--- doc-schema-version: 1 summary: "CLI reference for `openclaw backup` (local and offsite archives, SQLite snapshots, Git history, and schedules)" read_when: - You want a first-class backup archive for local OpenClaw state - You need a compact, verified snapshot of one OpenClaw SQLite database - You want scheduled, versioned database backups in an operator-owned Git repository - You want encrypted offsite archives, retention, or external backup status - You want to preview which paths would be included before reset or uninstall - You want to restore from a `.tar.gz` archive previously created by `openclaw backup` title: "Backup" --- # `openclaw backup` Create backup archives for OpenClaw state, config, auth profiles, channel/provider credentials, sessions, and optionally workspaces. Save them locally or upload to a named [storage location](/concepts/storage-locations). SQLite snapshots and Git history provide database-focused alternatives. ```bash openclaw backup create openclaw backup create --output ~/Backups openclaw backup create --dry-run --json openclaw backup create --verify openclaw backup create --no-include-workspace openclaw backup create --only-config openclaw backup create --to offsite --keep-daily 7 --keep-weekly 4 --keep-monthly 12 openclaw backup list --from offsite openclaw backup verify --from offsite latest openclaw backup restore --from offsite latest --target ./restored-openclaw openclaw backup verify ./2026-03-09T08-00-00.000+08-00-openclaw-backup.tar.gz openclaw backup restore ./2026-03-09T08-00-00.000+08-00-openclaw-backup.tar.gz --target ./restored-openclaw openclaw backup sqlite create --global --repository ~/Backups/openclaw-sqlite openclaw backup sqlite create --agent main --repository ~/Backups/openclaw-sqlite openclaw backup sqlite list --repository ~/Backups/openclaw-sqlite openclaw backup sqlite verify ~/Backups/openclaw-sqlite/ openclaw backup sqlite verify ~/Backups/openclaw-sqlite/ --scratch ~/Private/openclaw-scratch openclaw backup sqlite restore ~/Backups/openclaw-sqlite/ --target ./restored/openclaw.sqlite openclaw backup git init --repository ~/Backups/openclaw-git --remote openclaw backup git create --repository ~/Backups/openclaw-git --all --push openclaw backup git log --repository ~/Backups/openclaw-git openclaw backup git verify --repository ~/Backups/openclaw-git --global openclaw backup git restore --repository ~/Backups/openclaw-git --agent main --target ./restored/agent.sqlite openclaw backup enable --repository ~/Backups/openclaw-git --every 24h --push openclaw backup enable --to offsite --every 24h --keep-daily 7 openclaw backup disable --offsite openclaw backup disable openclaw backup record --status ok --target host-restic --bytes 1048576 ``` Archive `create`, `list`, `verify`, and `restore`, external `record`, plus SQLite `create`, `list`, `verify`, and `restore`, accept `--json` for one machine-readable result on stdout. ## Notes - The archive embeds a schema-version-1 `manifest.json` with the resolved source paths and archive layout. Additive ownership metadata records configured agent ids and roots, including agent roots already covered by another asset; existing archive layout and older archives remain supported. New archives also record the canonical SQLite snapshots captured at creation; standalone verification rejects missing or mismatched inventory entries. Legacy archives without this inventory remain readable, but verification reports `sqliteInventoryVerified: false` because complete database coverage cannot be established. An empty inventory means no canonical databases were captured (for example, a config-only export), not a full database recovery point. - Without `--to`, default output is a timestamped `.tar.gz` archive in the current working directory. Local timestamped filenames use your machine's local timezone and include the UTC offset. If the current working directory is inside a backed-up source tree, OpenClaw falls back to your home directory for the default archive location. With `--to`, the default archive is temporary; pass `--output` as well to retain a local copy. - Existing archive files are never overwritten. Output paths inside the source state/workspace trees are rejected to avoid self-inclusion. - `openclaw backup verify ` checks that the archive contains exactly one root manifest, rejects traversal-style archive paths and unsafe symbolic links, confirms every manifest-declared payload exists, and validates the root SQLite snapshot and agent snapshots listed in the manifest or captured durable registry. It rejects sidecars for those snapshots and checks their integrity and database roles, including each agent's identity. Other files, including plugin snapshots already validated during creation, remain opaque during verification and restore. `openclaw backup create --verify` runs that validation immediately after writing the archive. - Full archives include the active config and its required `$include` files, including dependencies outside the state directory. They preserve authored bytes, comments, and environment placeholders; resolved secrets are not written into the config copy. These additional files may contain sensitive data, so protect the archive accordingly. - AppleDouble metadata named `._*.sqlite`, such as `._cron.sqlite`, is excluded from state and agent database roots only when its file signature confirms the format. Real SQLite files and hardlink aliases with these names follow the same ownership rules as other databases. - Full archives refuse unresolved include graphs, files that change during config capture, and include aliases that cannot be represented safely. Fix missing or unreadable files, use regular-file include paths, or pause concurrent edits and retry. `--no-include-workspace` still includes required config dependencies, even within an excluded workspace. - `openclaw backup create --only-config` backs up just the active JSON config file, **not** its `$include` dependencies. It is a root-file export, not a complete modular-config recovery point. - Config files are pinned before database capture. SQLite snapshots retain their existing per-database consistency and sanitization; the archive is not one atomic snapshot across config and all databases. Later writes remain live and may not appear in the archive. Archive members live beneath a timestamped root and `payload/`, with source paths encoded below it. Counting entries beginning `.openclaw/agents/` therefore returns zero even when the agent databases are present. Inspect the root `manifest.json` and its `sqliteSnapshots` inventory, then run `openclaw backup verify `. A path reported as `covered by` another asset is included through that parent; it has not been excluded from the archive. ## Offsite archives Configure a named [storage location](/concepts/storage-locations), initialize it, and test access before the first backup: ```bash openclaw storage init offsite openclaw storage test offsite openclaw backup create --to offsite ``` The built-in `filesystem` provider supports an existing disk or mounted directory. The [Cloudflare plugin](/plugins/cloudflare) provides R2 object storage. Storage configuration owns encryption and credentials; backup commands use the configured location without provider-specific flags. See [Storage CLI](/cli/storage). `create --to` opens and checks the location before archiving, creates the archive in managed scratch, verifies its manifest and payload, uploads it, and confirms the stored size. Verification is always enabled for offsite creation, even without `--verify`. The temporary local archive is removed afterward. To keep a local copy as well, add `--output `; that copy is an ordinary plaintext `.tar.gz`, even when storage encryption is enabled. An uninitialized location fails before archive creation and records a failed attempt with the next step. Reconnect a missing disk or check the bucket and prefix, or run `openclaw storage init ` only when the destination is new. Backups never initialize storage implicitly. Keep the encryption passphrase and root location marker available for recovery. | Option | Meaning | | ------------------------ | ------------------------------------------------------------------------------------- | | `--to ` | Upload the verified archive to a configured, initialized location. | | `--namespace ` | Backup namespace; defaults to the sanitized hostname. | | `--claim-namespace` | Deliberately replace the namespace ownership claim with this installation's identity. | | `--output ` | Also retain a local archive at a path or in a destination directory. | | `--no-include-workspace` | Omit workspace files while retaining state, config, credentials, and agent databases. | | `--only-config` | Archive only the active config file; storage configuration must still be readable. | | `--keep-daily ` | Retain the newest backup in each of the newest `n` nonempty UTC days. | | `--keep-weekly ` | Retain the newest backup in each of the newest `n` nonempty UTC weeks. | | `--keep-monthly ` | Retain the newest backup in each of the newest `n` nonempty UTC months. | Namespaces contain 1–128 letters, digits, dots, underscores, or hyphens and cannot be `.` or `..`. Objects live under `backups//` with keys such as `20260930T120000Z-a1b2c3d4.tar.gz`: a UTC timestamp plus eight random hexadecimal characters. The filename does not change when storage encryption is enabled. Choose a stable explicit namespace for a host that may be renamed, and use that same namespace when listing, verifying, or restoring from another host. The first upload creates `backups//owner.json` with the installation's durable Gateway device ID, hostname, and claim time. The claim uses the location's encryption settings. OpenClaw checks that the claim matches this installation before archiving, at archive publication, and before each retention deletion. An existing claim with a different device ID refuses the run before archiving and records a failed attempt naming the owner. Identical hostnames do not grant shared ownership. Use a different `--namespace` for a separate installation. To deliberately take over a stopped or retired installation's namespace, such as after moving to new hardware, pass `--claim-namespace` with `--to`. This also replaces a damaged ownership claim: ```bash openclaw backup create --to offsite --namespace gateway --claim-namespace ``` The displaced installation is rejected at its next publication or deletion. Object stores cannot make an object's write conditional on a separate ownership claim, so a residual provider round-trip window remains between the final check and the effect. Stop the old installation before taking over; use a separate namespace for installations that run concurrently. A restored installation retains its device identity and can continue using its namespace. A cloned copy running at the same time shares that identity and must use its own `--namespace` to avoid sharing retention. ### Offsite retention Retention runs after a successful upload and applies only within the selected namespace to keys matching `-<8 lowercase hex>.tar.gz` with a valid UTC timestamp. Other objects and namespaces, including the `owner.json` claim, are never deleted. Retention checks ownership again before pruning. The policies form a union: a backup retained by any policy stays. Each policy selects the newest backup in its most recent nonempty calendar buckets; days start at midnight UTC, weeks start Monday UTC, and months follow the UTC calendar. Missing periods do not consume a bucket. The newest backup is always kept, including when every supplied count is zero. Counts must be nonnegative integers. Without any `--keep-*` flags, retention deletes nothing. ```bash openclaw backup create --to offsite --namespace gateway --keep-daily 7 --keep-weekly 4 --keep-monthly 12 ``` ### List and verify remote archives ```bash openclaw backup list --from offsite openclaw backup list --from offsite --namespace gateway openclaw backup list --from offsite --namespace gateway --json openclaw backup verify --from offsite --namespace gateway latest openclaw backup verify --from offsite --namespace gateway 20260930T120000Z-a1b2c3d4.tar.gz ``` `list` requires `--from ` and accepts `--namespace `. It lists matching backup keys newest first, with plaintext and stored sizes. Without `--namespace`, it also lists available namespaces under `backups/` with their claim hostnames, helping you locate backups from another machine. `verify` accepts those same options and either a listed key or `latest`, which selects the newest timestamp in the key. Use the key relative to the namespace, without the `backups//` prefix. Remote verification downloads and decrypts into managed scratch, applies the same archive verification as a local file, and removes the scratch copy. Listing, verifying, and restoring remote archives are read-only at the location; they neither require nor replace the namespace claim, including on a new machine. Without `--from`, `verify` and `restore` continue to accept local archive paths. ## Restore a full archive Restore a complete archive into a fresh staging directory without touching the live state directory: ```bash openclaw backup restore --target openclaw backup restore --from offsite --namespace gateway latest --target ``` With `--from `, the archive argument is a listed key or `latest`. `--namespace ` defaults to the sanitized hostname. The command downloads and decrypts the selected archive into managed scratch before the same local verification and restore flow. The target must not exist or must be an empty directory, and it cannot be inside the live state directory or any configured live agent directory. Restore verifies the archive and its SQLite databases before creating or writing the target, refuses a non-empty target, and removes an incomplete extraction if anything fails. It never restores in place and has no `--force` mode. The extracted layout retains the archive root, manifest, and `payload/` paths exactly as recorded in the archive. Restoring an archive is time travel. Messaging-channel credentials with ratchet state, especially WhatsApp, may desynchronize after rollback and need relinking. Approvals and delivery/dedupe state also roll back, so review pending approvals before resuming the Gateway. Plugin `node_modules` trees are not archived; after activation, run `openclaw plugins update ` or reinstall with `openclaw plugins install --force`. The generated `plugin-skills/` symlink index is also omitted; run `openclaw skills list` or start an agent session after activation to rebuild it from plugin metadata. Activation is a separate offline operator step. Stop the Gateway, move the restored state asset into place or point `OPENCLAW_STATE_DIR` at that asset, then run `openclaw doctor` before restarting. Use `manifest.json` as the source of truth for the state, config, credentials, workspace, and configured agent paths. Restore custom agent roots to the locations configured by `agentDir`, or update those settings to their new locations before restarting. See [Restore a full archive](/install/backups#restore-a-full-archive) for the full disaster-recovery sequence. ## Private update captures The managed `.update-captures/` root is excluded from ordinary archives, SQLite snapshots, Git backups, and support exports. Selecting a containing or nested workspace does not override this rule. Selecting a capture file as config or as a database backup source refuses the backup. Other states' captures are recognized by the exact sibling layout: `/` beside `.update-captures/`, with an existing owner directory, including a resolved directory link. Unrelated similarly named workspace directories remain included; a suffix alone does not establish ownership. Marked private directories remain excluded after their owner is removed or renamed, or the marked directory is moved or copied. Keep the marker with the whole directory. Files copied out without it are not recognized by this rule. The fixed `.openclaw-private-update-capture` file contains exactly `openclaw-private-update-capture-v1` followed by a newline. Export checks inspect each path component with `lstat` and resolve symbolic links with cycle and depth limits. A resolved target's real ancestors receive the same marker checks as the selected path. Links to marked directories are omitted; malformed or unreadable real markers refuse export. Loops and dangling links have no resolved target and remain link entries, unless a real selected ancestor excludes them. Ordinary unmarked links keep their original targets without copying target contents through the link. Windows target separators are stored as forward slashes. Explicit content exports, including SQLite snapshots, check the selected archive path and actual content source through the same classifier. A support bundle reports refused inputs without including their contents. These checks do not parse workspace manifests or scan for other state roots. The marker is an exclusion instruction, not proof of artifact ownership or permission to reopen, adopt, or delete it. Producers must durably write it before raw data, including in each independently movable staging or capture directory. Cleanup must preserve it until private contents are gone. This exclusion does not create captures, change retention, or change ordinary backup sanitization. ## SQLite snapshots Use `openclaw backup sqlite` when you need a portable artifact for one OpenClaw-owned SQLite database instead of a broad state archive. Snapshot creation accepts exactly one named source. Agent sources always use the current configuration's resolved `/openclaw-agent.sqlite`, even when `agentDir` is outside the state directory: | Command | Database | | --------------------------------------------------------------- | ---------------------- | | `openclaw backup sqlite create --global --repository ` | Shared OpenClaw state | | `openclaw backup sqlite create --agent --repository ` | One per-agent database | The repository contains one directory per committed snapshot. Each snapshot directory contains exactly: - `manifest.json` - `database.sqlite` Snapshot creation verifies the live database before reading it, uses SQLite's online backup API to capture committed WAL state without holding one long read transaction, closes the live database, compacts the private copy with `VACUUM`, verifies the generated database again, and publishes the completed directory without overwriting existing paths. Global snapshots remove every delivery queue row before compaction, including pending work, failed ownership fences, and completion or idempotency receipts, so neither payload detail nor ownership tombstones are published or retained in free pages. Restoring this sanitized, portable snapshot is therefore not an exactly-once delivery continuation boundary. This is an intentional privacy and no-replay portability tradeoff. Do not copy live `.sqlite`, `-wal`, `-shm`, or `-journal` files as a portability artifact. Copy only completed snapshot directories. When a database contains cold transcripts, snapshot creation embeds each referenced compressed archive in its private database copy after checking the file's size and SHA-256, even if automatic archival is disabled. Full archives and Git backups use the same cold payload capture. A restored database needs no original cold directory; missing or corrupt source archives fail backup creation. See [Cold transcript backups](/install/backups#cold-transcript-backups). SQLite snapshots can contain auth profiles, session state, plugin state, and other sensitive records. Protect repositories with the same permissions, encryption, retention policy, and destination restrictions as the live OpenClaw state directory. ### Verify and restore ```bash openclaw backup sqlite verify openclaw backup sqlite restore --target ``` Verification checks the strict manifest shape, artifact size and SHA-256, SQLite integrity, foreign keys, schema version, database role and owner, and OpenClaw-owned index definitions. Verification validates a private content-pinned copy so pathname races cannot swap the bytes SQLite inspects. By default, that temporary copy is created beside the snapshot repository and removed before the command returns. The staging root and its ancestor chain must prevent other users from replacing it. POSIX roots must be current-user-owned and not group/world writable; sticky ancestors such as `/tmp` are accepted for user-owned children. macOS ACL grants that expose or make staging replaceable are rejected. Windows roots and ancestors must be owned by the current user or a trusted OS principal, with ACLs that deny untrusted staging access. For a read-only mount or network share, pass `--scratch ` on storage with equivalent encryption and destination controls. Snapshot creation applies the same owner, ACL, ancestor, and path-identity checks to the repository before staging or publishing database bytes. Newly created directory edges and final publication metadata are synchronized through the shared `fs-safe` durability boundary before success is reported on supported filesystems. Restore repeats verification and writes only to a fresh target. It refuses an existing target, `-wal`, `-shm`, or `-journal` sidecar and never performs an in-place replacement of a live OpenClaw database. The target parent has the same path-security requirements as verification scratch. Activating a restored database remains an explicit offline operator step. Snapshot repositories are local directories. Scheduling, upload, retention, incremental WAL bundles, failover, and restore-on-boot behavior are intentionally outside this command. ## Versioned Git backups `openclaw backup git` stores deterministic, per-table JSONL dumps in a plain Git repository owned by the operator. One repository can hold the shared database and every per-agent database: ```text global/manifest.json global/schema.sql global/tables/.jsonl agents//manifest.json agents//schema.sql agents//tables/
.jsonl ``` Initialize the repository, then create a snapshot of the shared database and all configured agent databases: ```bash openclaw backup git init --repository ~/Backups/openclaw-git --remote openclaw backup git create --repository ~/Backups/openclaw-git --all --push ``` The repository root must be owned by the current user and must not be group- or world-writable. OpenClaw checks this when initializing or adopting a repository and before every create. On POSIX systems, repair unsafe permissions with `chmod 700 ` after confirming its ownership. The repository must be dedicated to OpenClaw backups. An existing `global/` or `agents//` scope is backup-owned only when it is empty or contains a valid schema-version-1 `manifest.json`. OpenClaw refuses to replace any other scope. With `--all`, it validates every existing entry under `agents/` before removing stale backup-owned agent scopes, so an unowned entry aborts the cleanup before anything is deleted. With `--all`, only agents removed from the configuration have their scopes pruned. If a configured agent's database is missing or cannot pass snapshot validation, its previous backup scope stays unchanged while other agents are backed up. The command reports that agent as degraded in CLI warnings, JSON `warnings`, and the recorded backup outcome. No scope is created if that agent has never been backed up. Explicit `--agent ` selections still fail if the selected database cannot be copied, and a run with no copyable databases fails. You can also select `--global`, repeat `--agent `, or combine the shared database with selected agents. Explicit agent selections, `--all`, and scheduled backups resolve each database from its configured `agentDir`; historical artifact verification and restore use the artifact's recorded agent id without requiring that agent to remain in the current configuration. Snapshot creation uses the same online backup, sanitizer, `VACUUM`, owner validation, and integrity checks as `backup sqlite create`; it never reads live SQLite files directly. Rows and schema entries have deterministic ordering, and integers and blobs use lossless encodings. The command creates one commit named `openclaw backup `. If the database content is unchanged, it prints `no changes` and creates no commit. Git staging is restricted to the backup-owned `global` and `agents` paths; unrelated files elsewhere in an adopted repository are never staged. `--push` pushes the current branch to `origin`. A push failure after a successful local commit is a warning and does not discard or mark the local backup as failed. Git history is durable. Without `--exclude-secrets`, snapshots include credential material and any pushed remote must be private. `src/state/secret-state-tables.ts` is the source of truth for redaction. At this revision, `--exclude-secrets` omits these shared-state tables: - `audit_identity_keys` - `apns_registrations` - `channel_ingress_events` - `channel_pairing_requests` - `clawhub_promotion_claims` - `config_revision_keys` - `device_auth_tokens` - `device_bootstrap_tokens` - `device_identities` - `device_pairing_join_codes` - `device_pairing_paired` - `gateway_origin_device_tokens` - `mcp_oauth_pending_authorizations` - `mcp_oauth_stores` - `native_hook_relay_bridges` - `secret_store_entries` - `web_push_subscriptions` - `worker_environment_credentials` It also omits `config_machine_state` rows whose keys begin with `authProfiles.`, `nodeHost.`, or `webPush.vapidKeys`, while retaining other machine-state rows. It omits these per-agent tables: - `auth_profile_state` - `auth_profile_store` - `session_suggestions` The backup manifest records omitted tables in `excludedTables` and omitted machine-state prefixes in `excludedConfigStateKeyPrefixes`. Restore reports omitted tables and machine-state prefixes so a redacted snapshot cannot be mistaken for a complete credential backup. Inspect or verify history without changing the live databases: ```bash openclaw backup git log --repository ~/Backups/openclaw-git --limit 20 openclaw backup git verify --repository ~/Backups/openclaw-git --ref --global openclaw backup git verify --repository ~/Backups/openclaw-git --ref --agent main ``` Git history output must fit within a 16 MiB read. If a log request reports an output-limit error, retry with a smaller `--limit`. An oversized commit subject can exceed the limit even with `--limit 1`; inspect that history directly with Git. OpenClaw reports the failure without returning partial history entries. Verification restores the selected snapshot into private scratch space, checks each table's row count and SHA-256, runs `PRAGMA integrity_check` and `PRAGMA foreign_key_check`, and removes the scratch copy. Restore writes only to a fresh target and refuses existing `-wal`, `-shm`, and `-journal` sidecars: ```bash openclaw backup git restore --repository ~/Backups/openclaw-git --ref --global --target ./restored/openclaw.sqlite ``` Restore rebuilds content-backed FTS5 indexes after loading their content tables. It deliberately omits the derived `session_transcript_index_state` projection so Gateway startup reconciliation rebuilds transcript search. `vec0` virtual tables are not materialized because the extension is unavailable in the restore process; memory indexing recreates them and schedules a full reindex. Git backup creation, restore, and verification stream table data instead of retaining complete table dumps in memory. Restores still require space for the materialized Git files and the private SQLite staging copy; verification does not write a second set of table dumps. ## Schedule backups Provision one Gateway-owned automation per mode. Choose `--to ` for offsite archives or `--repository ` for Git database backups: ```bash openclaw backup enable --to offsite --every 24h --keep-daily 7 --keep-weekly 4 --keep-monthly 12 openclaw backup enable --repository ~/Backups/openclaw-git --every 24h --push ``` The interval defaults to `24h` when `--every` is omitted. An explicitly empty or whitespace-only interval is rejected before a schedule is created or updated. Offsite schedules accept `--namespace `, `--claim-namespace`, `--no-include-workspace`, and `--keep-daily`, `--keep-weekly`, and `--keep-monthly`. They use the same archive, encryption, and [retention rules](/cli/backup#offsite-retention) as `backup create --to`. The location and its secrets must be accessible to the Gateway process. There is no retained local archive from scheduled offsite runs. `--claim-namespace` is stored in the schedule's command only when explicitly passed to `backup enable --to`; each scheduled run can then take over the namespace. Omit it for normal ownership checks. Re-enable the schedule without the flag when continuing takeover authority is no longer needed. For Git schedules, the default scope is every database. Use `--global-only` or `--agent ` to narrow it, and add `--exclude-secrets` for a redacted history. Pushed schedules (`--push`) redact credential-bearing tables and secret-prefixed machine-state rows by default because an unattended recurring push retains them durably in remote history; pass `--include-secrets` for explicit full-fidelity remote backups. Restores from redacted history need device re-pairing and provider re-authentication. `--push` also requires the repository to already have an `origin` remote. Git-only flags cannot be combined with `--to`. Re-running `backup enable` updates the job for the selected mode instead of creating a duplicate. Offsite and Git jobs can coexist. Existing Git jobs retain their declaration key `openclaw-backup-scheduled`; offsite jobs use `openclaw-backup-offsite-scheduled`. ```bash openclaw backup disable --offsite openclaw backup disable --git openclaw backup disable ``` `--offsite` removes only the offsite job; `--git` removes only the Git job. Omitting the selector removes both. Disabling an already-missing job is a successful no-op. Enabling and disabling require a local Gateway because the command job runs on the Gateway host; for a remote Gateway, create the cron job manually with `openclaw cron add`. Disabling a schedule finds the managed automation across all list pages, even after renaming it. Unrelated automations with the same name are left in place. ## Recorded runs and freshness Every real archive, SQLite snapshot, and Git create attempt records a compact outcome in the existing shared state database. External jobs can also report their outcomes. Dry runs are not recorded. The log retains the newest 200 attempts plus the newest attempt and newest successful result for every backup kind and target, including the namespace for offsite backups. Frequent schedules cannot evict an infrequent destination's last attempt or last success; history stays bounded by the recent window and the number of distinct targets. Git history is grouped by repository. Local archives and SQLite snapshots without a named target share a bounded history group for their backup kind. Successful offsite outcomes include the location name, provider, location identity, key, namespace, plaintext archive bytes, and stored bytes. Runs with retention also record kept/deleted counts. Storage encryption can make stored bytes larger than plaintext bytes. Failed offsite attempts also record the namespace they tried. `openclaw status` shows the newest offsite result alongside the backup overview; `openclaw status --json` includes recorded freshness. `openclaw doctor` prints an informational hint when no successful backup is recorded or the newest success is more than 14 days old. It also flags an enabled offsite schedule whose newest attempt failed or whose newest success is older than three times its interval, naming the location and `openclaw storage test ` as the next check. Offsite health matches both the location and the schedule's namespace. Older records without a namespace remain readable but cannot satisfy a namespaced schedule. Gateway RPC `backup.status` requires operator read scope. It returns the newest attempt and success per backup kind, target, and offsite namespace from the whole retained ledger, configured backup schedules with their next run, and the configured storage locations. Local archives and SQLite snapshots without a named target use one status group per kind, displaying the newest attempt's archive path. Listing configuration does not probe storage. The Control UI's Backups section on the Systems landing and Gateway host views uses this status and provides a **Check** action per location through `storage.locations.probe`. Doctor uses the same retained history, so per-target health survives more than 200 newer outcomes from other jobs. Recording is best-effort: a record-write failure prints a warning but never changes a successful backup into a failed command. Recording uses an existing shared state database; it does not create a missing database. ### Record external backup jobs Use `backup record` after a host-level backup job, such as a restic timer, to include its outcome in backup status and Doctor freshness: ```bash openclaw backup record --status ok --target host-restic --bytes 1048576 openclaw backup record --status failed --target host-restic --error "Backup destination unavailable" ``` `--status ok|failed` and `--target