Backup or restore your entire OpenClaw setup including config, agents, skills, credentials, and workspace as a timestamped portable .tar.gz archive.
---
name: openclaw-backup-restore
description: >
Backup or restore a complete OpenClaw installation (config, agents, flows, skills,
credentials, memory, workspace, telegram bots) as a single portable .tar.gz archive.
Use for backup: "backup my openclaw", "snapshot my openclaw setup".
Use for restore: "restore openclaw", "migrate openclaw to this machine".
On restore, any existing ~/.openclaw is automatically preserved with a timestamp before
being replaced, so the previous state is never lost.
license: Apache-2.0
compatibility: macOS, Linux, Windows (Git Bash or WSL). Requires bash, tar, gzip. Optional: gpg for encrypted backups.
metadata:
author: vbrunotech
version: "1.0.0"
category: devops
domain: configuration-management
openclaw:
emoji: "๐ฆ"
requires:
bins: ["bash", "tar", "gzip"]
install:
- id: brew-deps
kind: brew
formula: ["gnupg"]
bins: ["gpg"]
label: "Install gpg (optional, for encrypted backups)"
---
# OpenClaw Backup & Restore Skill
Snapshot and migrate your complete OpenClaw setup โ config, agents, flows, skills, credentials,
memory, and workspace โ as a single portable archive.
## What this skill does
- **Backup**: Archives the entire `~/.openclaw/` directory into a timestamped `.tar.gz`
(or `.tar.gz.gpg` if encrypted) โ no files excluded.
- **Restore**: Extracts an archive back into `~/.openclaw/`, preserving directory structure and
permissions, so OpenClaw works immediately after extraction.
- **List**: Shows available backup archives in the configured output directory.
- **Verify**: Validates a backup archive's integrity before restore.
Use this skill when the user says:
- "backup my openclaw setup"
- "migrate openclaw to my new machine"
- "snapshot my openclaw config"
- "restore openclaw from backup"
- "what backups do I have?"
## What is backed up
The entire `~/.openclaw` directory โ every file and subdirectory โ is included in the archive.
No exclusions. The restored machine gets an exact copy of the original, and OpenClaw works
immediately without any missing configuration, credentials, skills, or state.
See `references/paths.md` for details on sensitive paths and restore-time permissions.
## Workflow
### Backup
1. Resolve the OpenClaw home directory (`OPENCLAW_HOME`, defaults to `~/.openclaw`).
2. Resolve the output directory (`BACKUP_DIR`, defaults to `~/openclaw-backups`).
3. Archive the full `~/.openclaw` directory into a timestamped `.tar.gz`.
4. Optionally encrypt with GPG: `--encrypt` flag or `BACKUP_GPG_RECIPIENT` env var.
5. Print the archive path and size.
### Restore
1. Validate the archive (non-empty, valid gzip, no path traversal).
2. Warn if `~/.openclaw` already exists and prompt for confirmation (or use `--force`).
3. Optionally decrypt if `.gpg` extension detected.
4. Extract to `~/.openclaw/` with `--strip-components=0`.
5. Fix permissions on sensitive files (`credentials/`, `secrets/`, `identity/`).
6. Print a summary of restored paths.
### List
Print all `.tar.gz` and `.tar.gz.gpg` files in `BACKUP_DIR` with size and date.
### Verify
Run `gzip -t` on the archive and list its top-level contents without extracting.
## Scripts
| Script | Purpose |
|---|---|
| `scripts/backup.sh` | Create a backup archive |
| `scripts/restore.sh` | Restore from a backup archive |
## Usage examples
```bash
# Create a backup in ~/openclaw-backups/
bash scripts/backup.sh
# Backup to a custom directory
bash scripts/backup.sh --output /Volumes/USB/backups
# Backup with GPG encryption
bash scripts/backup.sh --encrypt you@example.com
# List available backups
bash scripts/backup.sh --list
# Verify a backup without restoring
bash scripts/restore.sh --verify openclaw-backup-2026-05-24_120000.tar.gz
# Restore (will prompt before overwriting)
bash scripts/restore.sh openclaw-backup-2026-05-24_120000.tar.gz
# Restore without confirmation prompt
bash scripts/restore.sh --force openclaw-backup-2026-05-24_120000.tar.gz
# Restore to a custom openclaw home
bash scripts/restore.sh --home /opt/openclaw openclaw-backup-2026-05-24_120000.tar.gz
```
## Migration workflow (old machine โ new machine)
1. On the **old machine**: run `bash scripts/backup.sh` โ copy the `.tar.gz` to the new machine.
2. On the **new machine**: install OpenClaw binary, then run `bash scripts/restore.sh <archive>`.
3. OpenClaw will start with your full config, agents, skills, credentials, and workspace intact.
## Security notes
- `credentials/` and `secrets/` contain sensitive API keys. Keep backups in a secure location.
- Use `--encrypt` with a GPG key for backups stored in cloud storage or on shared drives.
- The restore script sets `chmod 700` on sensitive directories automatically.
## Guardrails
- Never extract archives with path components that escape `~/.openclaw/` (path traversal check).
- Always show the archive size and file count after backup so the user can sanity-check completeness.
- If OpenClaw is running during backup, warn the user โ SQLite databases may be in a dirty state.
- Do not backup `identity/device-auth.json` without informing the user it contains auth tokens.
don't have the plugin yet? install it then click "run inline in claude" again.
added explicit inputs section with env vars and flags, structured procedure into four numbered workflows (backup, restore, list, verify) with clear inputs/outputs per step, expanded decision points to cover process detection, encryption, target overwrite, custom restore paths, and error states, and clarified output contract with specific file paths and exit codes.
snapshot and migrate your complete openclaw setup, config, agents, flows, skills, credentials, memory, and workspace as a single portable archive.
this skill backs up or restores your entire openclaw installation (~/.openclaw/) as a timestamped, portable .tar.gz archive. use it to snapshot your setup before major changes, migrate to a new machine, or recover from a broken installation. on restore, any existing ~/.openclaw is automatically timestamped and preserved, so you never lose the previous state.
environment variables and flags:
OPENCLAW_HOME: path to openclaw directory. defaults to ~/.openclaw. set this to back up a non-standard install location.BACKUP_DIR: output directory for archives. defaults to ~/openclaw-backups. create this directory if it doesn't exist.BACKUP_GPG_RECIPIENT: email or GPG key ID for encryption. if set, backups are encrypted automatically. requires gpg binary installed.--encrypt <recipient>: CLI flag to encrypt backup with gpg key. overrides BACKUP_GPG_RECIPIENT env var.--output <path>: CLI flag to set custom backup output directory.--force: skip confirmation prompt when restoring over existing ~/.openclaw.--home <path>: restore to custom openclaw directory instead of ~/.openclaw.--list: list all available backups in BACKUP_DIR.--verify <archive>: validate archive integrity without extracting.external dependencies:
bash, tar, gzip: required on all platforms. included in macOS and linux by default. on windows, use git bash or wsl.gpg: optional. install via brew install gnupg (macOS), apt-get install gnupg (debian/ubuntu), or chocolatey install gnupg (windows).archive naming convention:
backups are named openclaw-backup-YYYY-MM-DD_HHMMSS.tar.gz or .tar.gz.gpg if encrypted. restore commands accept the filename only (not full path).
resolve paths: determine OPENCLAW_HOME (from env var, flag, or ~/.openclaw default) and BACKUP_DIR (from env var, flag, or ~/openclaw-backups default). create BACKUP_DIR if missing.
check openclaw process: run pgrep -f openclaw (or tasklist | findstr openclaw on windows). if openclaw is running, warn the user that databases may be in a dirty state and offer to continue anyway.
validate source directory: confirm ~/.openclaw exists and is readable. exit with error if not.
generate timestamp: create timestamp in format YYYY-MM-DD_HHMMSS (e.g., 2026-05-24_120000).
create archive: run tar -czf BACKUP_DIR/openclaw-backup-TIMESTAMP.tar.gz -C ~ .openclaw/. this archives the entire directory with full paths and permissions intact.
encrypt (optional): if BACKUP_GPG_RECIPIENT is set or --encrypt flag passed, run gpg --encrypt --recipient <key_id> --output BACKUP_DIR/openclaw-backup-TIMESTAMP.tar.gz.gpg BACKUP_DIR/openclaw-backup-TIMESTAMP.tar.gz. then delete the unencrypted .tar.gz.
report success: print archive path, file size (in human-readable format), and file count. example output: "backup created: ~/openclaw-backups/openclaw-backup-2026-05-24_120000.tar.gz (2.3 MB, 1247 files)".
validate archive path: accept archive filename as argument. check that the file exists in BACKUP_DIR or as a full path. exit with error if not found.
check archive integrity: run gzip -t <archive> to test gzip validity. if gpg-encrypted, decrypt first (see step 5). exit with error if archive is corrupted.
check for path traversal: read archive contents with tar -tzf and verify no entries contain ../ or start with /. exit with error if detected.
warn if target exists: if ~/.openclaw already exists and --force not set, print warning with size and modification date. prompt user: "found existing ~/.openclaw. create timestamped backup before restore? (y/n)". if yes, backup existing dir to ~/.openclaw-TIMESTAMP. if user declines, exit.
decrypt (conditional): if archive ends in .gpg, run gpg --decrypt --output /tmp/openclaw-backup-temp.tar.gz <archive> and use /tmp/openclaw-backup-temp.tar.gz as source. handle gpg key passphrase interactively or via gpg-agent.
extract archive: run tar -xzf <archive> -C ~/ to extract. this restores ~/.openclaw/ with original structure and permissions.
fix permissions: run chmod 700 ~/.openclaw/credentials ~/.openclaw/secrets ~/.openclaw/identity 2>/dev/null (ignore errors if dirs don't exist). this ensures sensitive dirs are not readable by other users.
validate extraction: confirm ~/.openclaw directory now exists and contains expected subdirs (agents, skills, config, etc.). list top-level contents.
report success: print "restore complete. openclaw ready to start." and list restored top-level paths with sizes.
check BACKUP_DIR: if BACKUP_DIR doesn't exist or is empty, print "no backups found in BACKUP_DIR".
enumerate archives: find all .tar.gz and .tar.gz.gpg files in BACKUP_DIR. sort by modification date (newest first).
print table: for each file, print filename, size (human-readable), modification date, and encryption status. example:
openclaw-backup-2026-05-24_120000.tar.gz 2.3 MB 2026-05-24 12:00:00
openclaw-backup-2026-05-23_083000.tar.gz.gpg 2.2 MB 2026-05-23 08:30:00 (encrypted)
validate input: accept archive filename or full path as argument. check file exists.
test gzip integrity: run gzip -t <archive>. if encrypted, decrypt first using gpg (prompt for passphrase).
list contents: run tar -tzf <archive> | head -20 to show first 20 entries. print total entry count via tar -tzf <archive> | wc -l.
report results: print "archive is valid" or "archive is corrupted" and list top-level contents.
if openclaw process is running during backup: warn user that SQLite databases may be in a dirty state. offer to continue or abort. do not proceed without explicit user confirmation.
if BACKUP_GPG_RECIPIENT is set or --encrypt flag passed: encrypt archive with gpg. if gpg is not installed, error and exit. if gpg key is not found, error and exit.
if ~/.openclaw already exists on restore: if --force flag is set, skip prompt and proceed with extraction (overwriting in place). if --force not set, prompt user for confirmation. if user says no, abort restore.
if archive is encrypted (.tar.gz.gpg extension): automatically detect and prompt for gpg passphrase. do not try to extract as plain gzip.
if archive is corrupted or gzip test fails: abort restore and print error message. do not attempt extraction.
if path traversal detected in archive: abort restore and print security warning. do not extract.
if restore target is custom directory (--home flag set): create that directory if missing. restore to
on successful backup:
~/openclaw-backups/openclaw-backup-YYYY-MM-DD_HHMMSS.tar.gz (or .tar.gz.gpg if encrypted)on successful restore:
~/.openclaw/ (or custom --home path) with full contents~/.openclaw-YYYY-MM-DD_HHMMSS/on successful list:
on successful verify:
on error: