Docs CLI

Backups and History

Restic backups, git-based quicksaves, downloadable snapshots, archives, visual captures and update logs.

CaptainCore keeps four separate kinds of history per site environment: Restic backups of files and database, git-based quicksaves of the plugin and theme tree, zipped snapshots for download, and visual captures of rendered pages. Update logs tie a pair of quicksaves together to describe what an update run changed.

Storage layout

Backups are written with Restic through an Rclone backend. The repository path for a site environment is:

rclone:<rclone_backup>/<site>_<site_id>/<environment>/restic-repo

Quicksaves use a sibling repo at quicksave-repo, and archived server logs land in a logs folder next to them. The Restic password comes from ~/.captaincore/data/restic.key. Long-running repo operations set TMPDIR from the system path_tmp value, because repacking a large repo needs hundreds of gigabytes of scratch space.

Restic is invoked with an explicit rclone serve line so B2 deletes are hard deletes and the timeouts are generous:

restic ... -o "rclone.args=serve restic --stdio --b2-hard-delete --timeout=300s --contimeout=60s" -o rclone.timeout=600s

Remotes read from config.json

The system block supplies paths and default remotes; the per-captain block can override them.

Config key Block Used for
rclone_backup system or captain remotes Restic backup and quicksave repos, and archived logs
rclone_snapshot system Destination for generated snapshot zips
b2_snapshots captain remotes B2 bucket for snapshot links. Derived from rclone_snapshot when unset
rclone_archive captain remotes Archive listing, sharing and cold storage
rclone_logs captain remotes Log storage
rclone_upload system or captain remotes Upload remote for generated files and thumbnails
path system Local site data path, <path>/<site>_<site_id>/<environment>/
path_tmp system TMPDIR for repo migrations and prune
logs system Local log output path

The captain remotes.rclone_backup wins over the system rclone_backup. In fleet mode the captain ID is appended to the backup remote and to the local site path, so tenants never share a repo.

The excludes files

Two exclusion lists ship in lib/.

  • lib/excludes is passed to rclone sync as --exclude-from when files are pulled down from the site. It skips error_log, /tmp, .DS_Store, node_modules/, the local database-backup.sql, and the backup and cache directories of the common backup plugins: UpdraftPlus, All-in-One WP Migration, Duplicator, BackWPup, BackupBuddy, Akeeba, Envato, Divi’s et-cache and et_temp, WP Super Cache and friends.
  • lib/restic-excludes is passed to restic backup as --exclude-file. It covers the same plugin backup and cache directories, plus debug.log, error_log and phperror_log.

backup

captaincore backup <subcommand> <site>

Everyday use

Subcommand Usage
generate backup generate <site> [--parallel=] [--skip-db] [--skip-remote] [--skip-if-recent=] [--dry-run]
list backup list <site> [--format=json]
list-generate backup list-generate <site> [--from-file=]
list-missing backup list-missing <site>
snapshots backup snapshots <site> [snapshot-id] [--sizes] [--format=json]
download backup download <site> <backup-id> [<payload>] [--payload=] [--email=]
get backup get <site> <backup-id>
get-generate backup get-generate <site> <backup-id>
show backup show <site> <backup-id> <file-id>
find backup find <site> <pattern> [--long] [--pack=] [--snapshot=]
fetch-link backup fetch-link --site= --site-id= --zip-name=
runtime backup runtime <site>
verify backup verify <site> [--from-file=]
repo-info backup repo-info <site> [--stats]

backup generate defaults to -p, --parallel 3. --skip-if-recent=24h skips an environment backed up within that window, which is what makes a nightly @all run cheap to re-run.

captaincore backup generate @all --parallel=5 --skip-if-recent=20h

--payload on backup download names a token identifying which files and directories to include. The captaincore server writes large payload blobs to ~/.captaincore/data/payload/<token>.txt and passes the token on the command line rather than the blob.

Repository maintenance

Subcommand Usage
check backup check <site> [--init] [--read-data]
prune backup prune <site> [--dry-run] [--repack-uncompressed]
forget backup forget <site> <snapshot-id> [--confirm] [--prune]
unlock backup unlock <site> [--remove-all]
repair backup repair <site> [pack-ids...] [--packs] [--snapshots] [--forget]
upgrade backup upgrade <site>
migrate-v2 backup migrate-v2 <site> [--force] [--skip-repack] [--skip-cache-cleanup]
key-backup backup key-backup <site> [--type=backup|quicksave]
key-restore backup key-restore <site> [--type=backup|quicksave]
cleanup backup cleanup <site> [--dry-run]
storage-cleanup backup storage-cleanup [--confirm]

backup migrate-v2 is the orchestrated version-1 to version-2 migration: it checks whether the repo is already v2, runs restic migrate upgrade_repo_v2, repacks uncompressed data with restic prune --repack-uncompressed, clears the remote Restic cache over SSH, then verifies the final state.

backup key-backup copies the Restic repo key out of B2 to a local backup-repo-key.txt (or quicksave-repo-key.txt) so a B2 data loss does not cost you the repo. key-restore puts it back.

backup forget and backup storage-cleanup preview by default; --confirm is required to actually delete.

captaincore backup check mysite-production --read-data

quicksave

Quicksaves are per-site git repositories tracking plugin, theme and configuration changes, with the git repo itself backed up into Restic.

Subcommand Usage
generate quicksave generate <site> [--force] [--parallel=] [--skip-if-recent=] [--dry-run] [--debug]
add quicksave add <site> [--force]
list quicksave list <site> [--field=]
latest quicksave latest <site> [--field=]
list-generate quicksave list-generate <site>
list-missing quicksave list-missing <site>
get quicksave get <site> <hash>
get-generate quicksave get-generate <site> <hash>
show-changes quicksave show-changes <site> <commit-hash> [<match>]
file-diff quicksave file-diff <site> <commit> <file> [--plugin=] [--theme=] [--html]
search quicksave search <site> <theme|plugin:title|name:search>
rollback quicksave rollback <site> <commit> [--plugin=] [--theme=] [--file=] [--all] [--version=this|previous]
archive quicksave archive <site> <hash> [--plugin=] [--theme=]
database quicksave database <site> <hash>
malware-scan quicksave malware-scan <site> [--full] [--format=json] [--label]
backup quicksave backup <site> [--parallel=] [--skip-if-recent=]
restore-git quicksave restore-git <site>
sync quicksave sync <site>
update-usage quicksave update-usage <site>
cache-check quicksave cache-check <site> [--format=json]
cache-purge quicksave cache-purge <site> [--dry-run]
unlock quicksave unlock <site>
migrate-v2 quicksave migrate-v2 <site> [--force] [--skip-repack] [--skip-cache-cleanup]

quicksave database extracts and sanitizes the database SQL from the nearest backup snapshot for a given quicksave, which is how a quicksave can be paired with the data of its moment. quicksave malware-scan --full runs a Wordfence CLI scan over the whole quicksave directory rather than the signature list.

captaincore quicksave generate @all --parallel=10 --skip-if-recent=24h

snapshot

Snapshots are one-off downloadable zips, distinct from Restic snapshots.

Subcommand Usage
generate snapshot generate <site> [--email=] [--notes=] [--filter=] [--user-id=] [--skip-remote] [--delete-after-snapshot]
list snapshot list <site-id> [--environment=] [--limit=] [--field=] [--format=json]
add snapshot add --site-id= --archive= --storage= [--environment=] [--email=] [--notes=] [--user-id=]
fetch-link snapshot fetch-link <snapshot-id>

--filter takes one or more of database, themes, plugins, uploads, everything-else. Without a filter the snapshot includes everything. --delete-after-snapshot deletes the site after the final snapshot is made. The generated zip is moved to the rclone_snapshot remote unless --skip-remote is given.

captaincore snapshot generate mysite-production --filter=database,themes,plugins [email protected]

store-snapshot

captaincore store-snapshot <url|file>

Moves a zip to the rclone_archive remote for cold storage.

captaincore store-snapshot https://example.com/mysite-2026-09-04.zip

archive

captaincore archive list
captaincore archive share <file>

archive list runs rclone lsjson against rclone_archive. archive share runs rclone link with --expire 168h, so the public link lasts seven days.

captaincore archive share mysite-2026-09-04.zip

capture

Captures render the site’s pages and store the HTML and screenshots, so injected scripts can be detected by comparison over time.

Subcommand Usage
generate `capture generate <site
scan capture scan <site|@target> [--filter=] [--format=json] [--malware]
check capture check <site>

--pages overrides the pages to check, otherwise the site’s stored capture_pages configuration is used. capture scan --filter accepts critical, warning or external; --malware narrows to scripts only and hides ok results. Signatures come from lib/capture-signatures.json.

captaincore capture scan @production --malware --format=json

update-log

An update log describes what changed between a pair of quicksaves.

Subcommand Usage
generate update-log generate <site> <quicksave-hash-before> <quicksave-hash-after>
get update-log get <site> <quicksave-hash-before> <quicksave-hash-after>
list update-log list <site>
list-generate update-log list-generate <site>
captaincore update-log list mysite-production

Archived server logs

Rotated access and error logs are streamed to B2 alongside the backup repos. See monitoring and health for logs archive, logs archive-list and logs archive-get.