openclaw/docs/cli/storage.md
Peter Steinberger 37ffe3ce94
feat: back up to external disks and Cloudflare R2 with storage locations (#161913)
Adds named storage locations as a generic, pluggable capability, with backup as its first consumer.

- Core storage owner (src/storage): storage.locations config, a location marker that binds identity (runtime never creates it, so unplugged disks and different disks at the same path are refused), client-side streaming encryption (scrypt key from a SecretRef passphrase, per-object HKDF keys, AES-256-GCM segments), and a built-in filesystem provider for external disks and mounts.
- Plugin SDK: api.registerStorageProvider plus manifest contracts.storageProviders; providers move opaque bytes only.
- Bundled cloudflare plugin: an r2 provider over the S3 API with conditional writes and bounded multipart uploads; auto-enabled when a location uses provider "r2".
- Backups: backup create --to <location> with verified archives, UTC retention, list/verify/restore --from, Gateway-owned offsite schedules (installed Git schedules unchanged), per-installation namespace claims fenced at publication and deletion, backup record for external jobs, backup.status RPC, Doctor/status hints, and a Systems page Backups section.

No config or state migration; the storage section is new and optional. Proof: live R2 and mounted-disk round trips, namespace takeover trace, and a published 2026.9.7 upgrade cell with an existing Git backup schedule.
2026-10-01 02:05:44 -07:00

2.7 KiB

summary title read_when
List, initialize, and test configured storage locations storage
You are connecting a disk or object store as a storage location
You need to check storage access or encryption keys

openclaw storage

Manage named destinations configured under storage.locations. See Storage locations for configuration, encryption, and provider contracts.

openclaw storage list
openclaw storage init archive
openclaw storage test archive

All three commands accept --json, including before the subcommand:

openclaw storage list --json
openclaw storage --json init archive
openclaw storage test archive --json

List

storage list shows each configured location, its provider, its display target when available, and its probe state. Probing reads the location marker and checks access and the encryption key. It does not initialize locations or write test objects. Providers that report capacity include free and total bytes in JSON output.

Initialize

storage init <name> writes the location's identity and encryption marker with a create-only operation. Repeating it with the same encryption configuration verifies the existing marker; it does not replace it. A wrong passphrase fails.

For a filesystem location, the configured absolute path must already exist and be a directory. OpenClaw never creates this root directory. Confirm that an external disk is mounted before initializing its location.

Initialization is explicit so a disconnected disk or an empty mount point cannot silently become a new destination. If a runtime operation reports a missing marker, reconnect the disk or check the bucket and prefix. Initialize the location only if it is new. For example:

Storage location "r2test" (r2://bucket/prefix) has no initialization marker. If this is a new location, run openclaw storage init r2test; otherwise reconnect the disk or check the bucket and prefix.

Test

storage test <name> writes a small, unique .openclaw-probe-<uuid> object at the location root, reads it back through the configured encryption layer, verifies every byte, and deletes the object. It requires an initialized location and never initializes one. No probe directory is created on filesystem locations.

A successful JSON result includes state: "ok" and sizeBytes. A failed write, read-back verification, or cleanup fails the command. If a provider is unreachable during cleanup, reconnect it before removing any leftover probe objects.

Storage locations can contain credentials and private conversations. Use encryption unless the destination is already protected and you deliberately choose encryption: "none".