The half that does the work
A Go binary that lives on a server, connects to every managed site over SSH, collects data with WP-CLI and bash remote scripts, and posts the results back to the Manager's token-authenticated API. Backups with restic, change tracking with git, uptime checks in parallel.
$ captaincore update @production --parallel=3
[captaincore.io] Creating quicksave before update…
[captaincore.io] ✓ Quicksave 8f3c21a
[captaincore.io] Updating gravityforms 2.9.1 → 2.9.4
[minnadmin.com] Updating woocommerce 9.8.2 → 9.9.0
[disembark.host] Updating theme kadence 1.2.14 → 1.2.15
[captaincore.io] ✓ gravityforms updated
[minnadmin.com] ✓ woocommerce updated
[disembark.host] Verifying checksums…
[disembark.host] ✓ Done · 3 sites · 41s
One line on Linux or macOS
The installer drops the binary and the runtime scripts into ~/.captaincore. Copy the sample config, point it at your Manager, and the CLI takes it from there. Building from source needs Go 1.25 or later.
curl -fsSL https://raw.githubusercontent.com/CaptainCore/captaincore/master/install.sh | bash
cp ~/.captaincore/config-sample.json ~/.captaincore/config.json
captaincore connect https://your-manager.example.com
captaincore site list
captaincore backup generate @all
captaincore quicksave show-changes disembark
Fifty-odd commands, grouped by what they touch
Any site argument is the site slug, the domain without its TLD. Targets like @all and @production fan out across the fleet, and --fleet switches to multi-tenant mode.
Sites and data
site- List, add, edit and remove sites
environment- Production and staging environments
sync-data- Sync website data for one or more sites
usage-update- Generate storage and visit stats for a site
screenshot- Take a screenshot of one or more sites
stats- Fetch stats from Fathom Analytics or Fathom Lite
drift- Show version distribution across sites
Backups and history
backup- Incremental restic backups to B2 and restores
quicksave- Git-based change tracking for plugins, themes and config
snapshot- Full site zips, on demand or scheduled
store-snapshot- Move a zip to cold storage over rclone
archive- Long-term archive of removed sites
capture- Visual captures for a site over time
Running things
ssh- SSH connection to a site
run- Run arbitrary bash or WP-CLI on a site
bulk- Run a command concurrently on many sites
recipe- Run a cookbook recipe
script- Manage and run remote scripts
update- Theme, plugin and core updates with before and after diffs
upload- Upload a file to a site over SSH
migrate- Migrate a site in from a backup URL
Monitoring and health
monitor- Parallel uptime checks with SQLite-backed stats and alerts
performance-monitor- Background performance monitoring on sites
scan-errors- Scan for JavaScript errors on a site
email-health- Email deliverability checks
logs- Fetch and archive logs
ssh-verify- Verify a valid SSH connection
Providers and the server
provider- Kinsta and GridPane provider APIs
account- Account commands
account-portal- White-labelled customer portals
connect- Connect the CLI to a CaptainCore Manager
server- Start the REST + WebSocket server for remote dispatch
task- View and manage server tasks
cron- Trigger cron tasks
Run captaincore --help for the complete list, or captaincore <command> --help for its flags.
Plain bash, piped over SSH
Anything that runs on a site is a bash script in lib/remote-scripts. The CLI pipes it over stdin, so complex PHP dodges quoting and editing a script needs no rebuild. A sample of the sixty-plus that ship:
fetch-site-data
db-backup
plugin-diff
quicksave-fingerprint
update-core
malware-hunt
detect-seo-spam
detect-fake-dates
detect-web3-injection
detect-user-enumeration
find-nulled-components
php-in-uploads
inventory-compromised-passwords
component-hashes
reset-permissions
deploy-fathom
deploy-mailgun
email-health-check
apply-https
db-convert-to-innodb
archive-logs
vault
all of them →
One endpoint, one token
The CLI authenticates to the Manager with a shared token and POSTs JSON to a single endpoint. The handler validates the token, resolves the site and environment, and dispatches on the command name.
POST /wp-json/captaincore/v1/api
{ "token": "…", "command": "sync-data", "site_id": 84, "environment": "Production", "data": { … } }
Every ingest is one token-authed POST. Add a command on the CLI, add a branch in the Manager, done.