On this page

On this page

CLI commands

Backup

openclaw backup

Create a local backup archive for OpenClaw state, config, auth profiles, channel/provider credentials, sessions, and optionally workspaces.

bash
openclaw backup createopenclaw backup create --output ~/Backupsopenclaw backup create --dry-run --jsonopenclaw backup create --verifyopenclaw backup create --no-include-workspaceopenclaw backup create --only-configopenclaw backup verify ./2026-03-09T08-00-00.000+08-00-openclaw-backup.tar.gzopenclaw backup restore ./2026-03-09T08-00-00.000+08-00-openclaw-backup.tar.gz --target ./restored-openclawopenclaw backup sqlite create --global --repository ~/Backups/openclaw-sqliteopenclaw backup sqlite create --agent main --repository ~/Backups/openclaw-sqliteopenclaw backup sqlite list --repository ~/Backups/openclaw-sqliteopenclaw backup sqlite verify ~/Backups/openclaw-sqlite/<snapshot-id>openclaw backup sqlite verify ~/Backups/openclaw-sqlite/<snapshot-id> --scratch ~/Private/openclaw-scratchopenclaw backup sqlite restore ~/Backups/openclaw-sqlite/<snapshot-id> --target ./restored/openclaw.sqliteopenclaw backup git init --repository ~/Backups/openclaw-git --remote <private-git-url>openclaw backup git create --repository ~/Backups/openclaw-git --all --pushopenclaw backup git log --repository ~/Backups/openclaw-gitopenclaw backup git verify --repository ~/Backups/openclaw-git --globalopenclaw backup git restore --repository ~/Backups/openclaw-git --agent main --target ./restored/agent.sqliteopenclaw backup enable --repository ~/Backups/openclaw-git --every 24h --pushopenclaw backup disable

Archive create, verify, and restore, 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.
  • Default output is a timestamped .tar.gz archive in the current working directory. 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.
  • Existing archive files are never overwritten. Output paths inside the source state/workspace trees are rejected to avoid self-inclusion.
  • openclaw backup verify <archive> 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 <archive>. A path reported as covered by another asset is included through that parent; it has not been excluded from the archive.

Restore a full archive

Restore a complete archive into a fresh staging directory without touching the live state directory:

bash
openclaw backup restore <archive.tar.gz> --target <fresh-directory>

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.

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 for the full disaster-recovery sequence.

Private update captures

The managed <stateDir>.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: <owner>/ beside <owner>.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 <agentDir>/openclaw-agent.sqlite, even when agentDir is outside the state directory:

Command Database
openclaw backup sqlite create --global --repository <dir> Shared OpenClaw state
openclaw backup sqlite create --agent <id> --repository <dir> 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.

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 <snapshot-directory>openclaw backup sqlite restore <snapshot-directory> --target <new-database-path>

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 <existing-private-directory> 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.jsonglobal/schema.sqlglobal/tables/<table>.jsonlagents/<agentId>/manifest.jsonagents/<agentId>/schema.sqlagents/<agentId>/tables/<table>.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 <private-git-url>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 <repository> after confirming its ownership.

The repository must be dedicated to OpenClaw backups. An existing global/ or agents/<agentId>/ 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 <id> 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 <id>, 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 <ISO8601>. 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.

Inspect or verify history without changing the live databases:

bash
openclaw backup git log --repository ~/Backups/openclaw-git --limit 20openclaw backup git verify --repository ~/Backups/openclaw-git --ref <commit> --globalopenclaw backup git verify --repository ~/Backups/openclaw-git --ref <commit> --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 <commit> --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 with a fixed name:

bash
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.

The default scope is every database. Use --global-only or --agent <id> 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. Re-running backup enable updates the existing automation instead of creating a duplicate. openclaw backup disable removes it; disabling an already-missing job is a successful no-op. Backup scheduling currently requires 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. Dry runs are not recorded. The log retains the newest 200 attempts, so frequent schedules remain bounded.

openclaw status shows one Backups overview row, and openclaw status --json includes the latest attempt and latest successful run. openclaw doctor prints an informational hint when no successful backup is recorded or the newest successful backup is more than 14 days old. Recording is best-effort: a record-write failure prints a warning but never changes a successful backup into a failed command.

What gets backed up

openclaw backup create plans sources from your local OpenClaw install:

  • The state directory (usually ~/.openclaw)
  • The active config file path
  • The resolved credentials/ directory when it exists outside the state directory
  • Every configured agent directory, including custom agentDir roots outside the state directory
  • Workspace directories discovered from the current config, unless you pass --no-include-workspace
  • Durable resources declared by effectively activated, loadable plugin manifests

Auth profiles and other per-agent runtime state live in <agentDir>/openclaw-agent.sqlite. The default agent root is <stateDir>/agents/<agentId>/agent, but a custom root remains authoritative whether it is outside the state directory, inside a workspace, or nested under an otherwise regenerable managed state root. --no-include-workspace omits ordinary workspace sources, not configured agent directories.

--only-config skips state, agent, credentials-directory, workspace, and plugin-resource discovery and archives only the active config file path.

OpenClaw first plans resources from configuration. It captures the root SQLite database online, then derives and freezes registered-agent ownership from that private snapshot for database discovery and archive traversal. Paths are canonicalized: config, credentials, workspaces, and agents already covered by another included root are not duplicated as top-level sources. A custom agent root becomes a distinct agent asset only when no existing asset covers it; the manifest still records its agent id and root when another asset contains it. Missing paths are reported as skipped.

A workspace can contain the state directory, including when the workspace is your home directory. A covered skip means that the enclosing asset includes those files. Repeated registrations of the same agent database resolve to one physical owner; distinct owners sharing one database still refuse the backup. This also applies with --no-include-workspace.

Legacy audit raw archives, import claims, and scrub journals are excluded as raw files; recoverable audit sources receive sanitized backup replacements. Their .quarantined-* variants remain excluded and are retained locally without being imported or rewritten. Sanitized .migrated companions and retained SQLite audit history remain included in the backup.

During archive creation, OpenClaw excludes known live-mutation paths before tar reads them. This avoids races between a file's recorded size and concurrent writes. The filter applies these state-relative rules under each backed-up state directory:

State-relative scope Skipped entries
sessions/** .jsonl, .log
agents/<agentId>/sessions/** .jsonl, .log
cron/runs/** .jsonl, .log
logs/** .jsonl, .log
delivery-queue/** .json, .delivered, .tmp
session-delivery-queue/** .json, .delivered, .tmp
browser/<profile>/user-data/ SingletonCookie, SingletonLock, SingletonSocket
sandbox/skills-workspaces/** All entries
Any archived root, including agent workspaces .sock, .pid, .tmp, and .tmp.*

Explicitly selected asset roots stay included even when their names match a transient filename rule. The active config file remains included even when its name or location matches a rule above. This exception keeps only the selected config file; neighboring files under excluded directories stay out of the archive.

Transient filename rules apply across all selected roots, including every agent workspace. State-specific log, queue, and browser rules remain scoped to state. They also omit completed transcript and log files that match the table, so retain those records separately when needed. The JSON result's skippedVolatileCount reports intentionally omitted volatile entries, each listed in skipped with reason volatile; regenerable agent temporary roots are listed separately and are not included in that count.

If an entry disappears during traversal or before it can be opened, the archive continues with the surviving entries. Each omitted path appears in the result's skipped list with reason vanished, and in the result's warnings and text summary. Required source roots and staged captures must still exist; permission and I/O errors still fail the archive. Changes that could redirect a read outside the selected roots also fail. Files are opened before their archive headers are written, so a vanished file cannot leave a partial entry.

Chromium singleton entries coordinate one running browser on one host and are recreated when that profile starts; the rest of the profile's user-data/ remains in the archive. Sandbox skills workspaces are generated copies of current skill sources and are materialized again when OpenClaw prepares the next sandbox context after restore; adjacent sandbox registry and other durable state remain included.

Managed SQLite snapshots cover the shared OpenClaw database, the quarantine and integrity-verification store, and per-agent databases declared by configuration, recorded in the captured durable agent registry, or discovered at <stateDir>/agents/<agentId>/agent/openclaw-agent.sqlite. This includes configured custom agentDir locations and databases left in the default location after an agent moves or is removed from configuration. Distinct databases belonging to the same agent are captured separately. --no-include-workspace preserves this database coverage.

SQLite files under activated plugins' declared backupResources with disposition: "include" also receive managed snapshots. Other filenames under the state directory or an agent directory alone do not establish SQLite ownership.

Managed databases are captured with SQLite's online backup API and compacted offline with VACUUM. Committed write-ahead log (WAL) changes are included, deleted-page remnants are removed, and sidecars are omitted. Shared and agent databases also receive their existing transient-state sanitization and must match their expected role and agent owner. Unsafe aliasing or an owner mismatch fails closed. A declared plugin database that requires unavailable SQLite capabilities also fails closed rather than falling back to a direct file copy.

Other SQLite files under state and configured agent roots, including their sidecars, are copied as opaque bytes. Creation reports each filename in warnings with an opaque label. Unmanaged SQLite symbolic links that exceed the link-resolution limit (ELOOP), including loops, are skipped with a warning naming the link. Other links keep their existing handling. Verification and restore preserve those bytes without opening, compacting, or validating the database. These copies do not have a live-database consistency or deleted-data removal guarantee. Use the owning application's backup procedure when you need those guarantees.

Hardlinks to a managed SQLite database share one captured image, stored as a separate regular archive entry for each name. Every hardlink must be an included SQLite file owned by the core inventory or declared plugin backup resources. If exactly one name has a nonempty write-ahead log (WAL), that name supplies the committed data. Closed databases without a nonempty WAL remain supported. Multiple nonempty WALs, a nonempty rollback journal, or hardlinks outside the backup inventory cause an explicit refusal with no archive. Close the database writers cleanly and include every hardlink in those resources before retrying. Changes to the shared database file during capture also refuse the backup, including a concurrent alias checkpoint that truncates its WAL before the journal checks repeat. Canonical OpenClaw database aliases retain their existing owner validation and sanitization.

Installed plugin source and manifest files under the state directory's extensions/ tree are included, but their nested node_modules/ dependency trees are skipped as rebuildable install artifacts. After restoring an archive, use openclaw plugins update <id> or reinstall with openclaw plugins install <spec> --force if a restored plugin reports missing dependencies.

The state directory's plugin-skills/ root is a generated, OpenClaw-owned symlink index, not authoritative state. Backup creation reports and omits that root because its absolute targets are specific to the source installation. After activating restored state, run openclaw skills list or start an agent session to rebuild the links from current plugin metadata.

Agent-scoped temporary trees under agents/<agentId>/agent/**/{tmp,.tmp}/ are also omitted and reported as regenerable. This includes temporary files directly below an agent directory and temporary trees inside agent runtime homes; durable sibling directories remain included. An explicitly configured config file, credentials directory, or workspace nested below an omitted temporary root remains included.

Symbolic links are archived as link entries, including absolute and dangling targets. Windows target separators are stored as forward slashes to match tar's reader; POSIX target text, including literal backslashes, is preserved. Creation never follows a link to copy its target. Targets outside the state directory, including separately backed-up config, credentials, or workspace targets, are recorded in the manifest and JSON result's externalSymbolicLinks list and reported in the text summary. Restore recreates the links after extracting the file content; it never writes through a restored link. Verification rejects archive entries nested beneath a symbolic link.

Absolute links retain their original location after restore, including links to separately backed-up config or credentials. They are no longer rewritten to relative targets. Review these links before activating a restored tree on another host or at another path. Older releases, including v2026.9.4, reject archives with absolute or escaping link targets; use the current release to restore those archives. Existing archives remain readable.

Installer-managed and rebuildable runtime roots under the state directory are also skipped: dev/, git/, npm/, legacy npm-runtime/, tmp/, and tools/. These contain managed checkouts, package trees, compiler caches, temporary files, and downloaded runtimes rather than authoritative user state; reinstall or update the corresponding runtime or plugin after restore. Effectively activated, loadable plugins can declare additional durable or regenerable state- or agent-relative roots through backupResources. Disabled or unloadable plugins cannot exclude data. Explicit config, credentials, workspace, agent, and plugin-included paths override exclusions, and any excluded parent remains traversable to reach those protected descendants. Names such as tmp and .tmp are not blanket exclusions in custom agent directories; only an applicable owner declaration can omit their durable-looking siblings.

Local edits inside a managed dev/ checkout are developer source, not OpenClaw product state, and are not included. Commit and push those edits or copy the checkout separately before relying on a state backup.

Invalid config behavior

openclaw backup bypasses the normal config preflight so it can still help during recovery. State archives require resolved agent and plugin ownership. If discovery fails, backup create reports the underlying error and refuses to publish an archive. --no-include-workspace excludes workspace files; it does not bypass ownership discovery.

Discovery reads shared state through an online SQLite snapshot so concurrent writers do not make a valid config appear invalid. If the state cannot be read, resolve the reported error and retry backup.

--only-config still works when the config is malformed or state discovery fails. It saves the active JSON config file alone, without parsing it or including its dependencies.

Size and performance

OpenClaw does not enforce a built-in maximum backup size or per-file size limit. An archive write that produces no data for five minutes fails and removes its partial temporary file instead of hanging indefinitely. Practical limits otherwise come from:

  • Available space for the temporary archive write plus the final archive
  • Time to walk large workspace trees and compress them into a .tar.gz
  • Time to rescan the archive with --verify or openclaw backup verify
  • Destination filesystem behavior: OpenClaw requires no-overwrite hard-link publication so a final archive path never exposes an in-progress copy; unsupported filesystems fail with an actionable error

If final-directory durability confirmation fails after publication, the command reports failure but preserves the complete final entry rather than risk deleting a concurrent replacement.

Large workspaces are usually the main driver of archive size. Use --no-include-workspace for a smaller/faster backup, or --only-config for the smallest archive.

Archive creation holds a SQLite lifetime transaction for its temporary openclaw-backup-owned-* scratch directory. The next backup run removes abandoned scratch only after acquiring exclusive custody; a running backup keeps its scratch even when it is old. Cleanup failures preserve the published archive and appear as warnings with the scratch path in both text and JSON output. The owned prefix also lets cleanup coordinate with a new creator before its token exists, without mistaking that allocation for legacy scratch. If cleanup wins before the creator claims its directory, creation retries with a fresh directory. A changed directory identity is still rejected. Scratch observed by the scan that disappears before cleanup is recorded as already reclaimed, without a warning or a claim that this pass removed it.

openclaw doctor reports scratch in the active temporary directory and recorded archive destination directories. openclaw doctor --fix removes recognized scratch whose lifetime transaction has ended. Unknown contents, symbolic links, and legacy directories without a lifetime token are preserved with guidance for inspection. Older releases do not create these tokens, so stop older backup processes before manually removing their reported scratch directories. Published archives and package rollback backups are outside this cleanup. Retired scratch is renamed to openclaw-backup-retired-* before deletion so a later pass can finish partial cleanup even after the lifetime token is gone.

Was this useful?