How updates work
How the Manager updates itself, how you update the CLI, and how to check what version each is running.
Manager
The Manager updates through the normal WordPress plugin update path. includes/class-captaincore-manager-updater.php hooks plugins_api, site_transient_update_plugins and upgrader_pre_download and supplies the update itself.
The flow:
request()fetcheshttps://raw.githubusercontent.com/CaptainCore/captaincore-manager/master/manifest.jsonwith a 30 second timeout and caches the result in thecaptaincore_manager_updatertransient for one hour. If the fetch fails, the bundledmanifest.jsonshipped in the plugin is used and the failure is cached for five minutes.update()comparesCAPTAINCORE_VERSIONagainst the manifest’sversionwithversion_compare(). It refuses to offer the update at all unless the manifest’sdownload_urlpassesis_our_package_url()(https, host ingithub.com/objects.githubusercontent.com/codeload.github.com, path starting with/CaptainCore/captaincore-manager/) and the manifest publishes a non-emptysha256.verify_package()intercepts the download, fetches the zip withdownload_url( $package, 300 ), and compareshash_file( 'sha256', $file )to the manifest hash withhash_equals(). A mismatch deletes the file and returnscaptaincore_bad_package_hash. A manifest with no hash returnscaptaincore_missing_package_hash.purge()clears the transient after a successful plugin update.
Apply an update:
wp plugin update captaincore-manager
Force a fresh manifest read:
wp transient delete captaincore_manager_updater
The version lives in three places: the Version: plugin header, the CAPTAINCORE_VERSION constant in captaincore.php, and version in manifest.json. bin/build-zip.sh fails the build if they disagree, or if the manifest download_url does not point at the matching /v{version}/ release asset. A build whose header disagrees with its own manifest would either offer an update forever or never offer one.
Schema migrations ride along with the code. After an update, the next init or admin_init runs captaincore_maybe_upgrade_db(), which compares the captaincore_db_version site option against CaptainCore\DB::REQUIRED_VERSION and runs DB::upgrade() under a lock.
CLI
The CLI has no self-update command. Update it one of two ways.
Re-run the installer to replace the binary with the latest release:
curl -fsSL https://raw.githubusercontent.com/CaptainCore/captaincore/master/install.sh | bash
Or pull and rebuild in place on the CLI server:
cd ~/.captaincore
git pull
go build -o captaincore .
Rebuilding in place is the option that also refreshes the bash scripts under app/ and lib/remote-scripts/, which the binary shells out to. If you only replace the binary, those stay at whatever revision your clone is on, so pull either way.
Restart captaincore server after updating so the Manager talks to the new build.
Releases are cut with git tags and GoReleaser:
git tag -a v1.0.0 -m "v1.0.0"
git push origin v1.0.0
goreleaser release --snapshot --skip-publish --clean # preview
goreleaser release --skip-validate --clean # publish
The architecture notes in docs/architecture.md describe app/cli/install and app/cli/update scripts. Those no longer exist in the tree, and there is no captaincore cli command. Treat that section of the doc as stale.
Checking versions
For the CLI:
captaincore version
It prints the version, the Go version it was built with, and the platform:
captaincore 1.0.0
- go version: go1.25.0
- platform: linux/amd64
The value comes from the Version variable in version/version.go, which can be overridden at build time with -ldflags "-X github.com/CaptainCore/captaincore/version.Version=...". A binary built without that flag reports whatever the constant says, which is not necessarily the tag you built from. Check git describe in ~/.captaincore if you need the exact source revision.
For the Manager:
wp plugin list --name=captaincore-manager --fields=name,status,version
Or read the Version: header in wp-content/plugins/captaincore-manager/captaincore.php. The dashboard’s Settings section does not show a version number.