backup

Backup and restore openclaw configuration, skills, commands, and settings. Sync across devices, version control with git, automate backups, and migrate to new machines.

170 stars

Best use case

backup is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Backup and restore openclaw configuration, skills, commands, and settings. Sync across devices, version control with git, automate backups, and migrate to new machines.

Teams using backup should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/backup/SKILL.md --create-dirs "https://raw.githubusercontent.com/adoresever/AGI_Ananas/main/26.2.06OpenClaw检索、审查执行与备份Skills/backup/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/backup/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How backup Compares

Feature / AgentbackupStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Backup and restore openclaw configuration, skills, commands, and settings. Sync across devices, version control with git, automate backups, and migrate to new machines.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# OpenClaw Backup Skill

Backup, restore, and sync your OpenClaw configuration across devices directly from openclaw.

## Overview

This skill helps you:
- Backup all openclaw data and settings
- Restore from backups
- Sync between multiple machines
- Version control your configuration
- Automate backup routines
- Migrate to new devices

## openclaw Directory Structure

### Key Locations

```
~/.claude/                    # Main openclaw directory
├── settings.json             # Global settings
├── settings.local.json       # Local overrides (machine-specific)
├── projects.json             # Project configurations
├── skills/                   # Your custom skills
│   ├── skill-name/
│   │   ├── SKILL.md
│   │   └── supporting-files/
│   └── another-skill/
├── commands/                 # Custom slash commands (legacy)
│   └── command-name.md
├── contexts/                 # Saved contexts
├── templates/                # Response templates
└── mcp/                      # MCP server configurations
    └── servers.json

~/projects/                   # Your projects (optional backup)
├── project-1/
│   └── .claude/              # Project-specific config
│       ├── settings.json
│       └── skills/
└── project-2/
```

### What to Backup

```
ESSENTIAL (Always backup):
✓ ~/.claude/skills/           # Custom skills
✓ ~/.claude/commands/         # Custom commands
✓ ~/.claude/settings.json     # Global settings
✓ ~/.claude/mcp/              # MCP configurations

RECOMMENDED (Usually backup):
✓ ~/.claude/contexts/         # Saved contexts
✓ ~/.claude/templates/        # Templates
✓ Project .claude/ folders    # Project configs

OPTIONAL (Case by case):
○ ~/.claude/settings.local.json  # Machine-specific
○ Cache directories              # Can be rebuilt
○ Log files                      # Usually not needed
```

## Quick Backup Commands

### Full Backup

```bash
# Create timestamped backup
BACKUP_DIR="$HOME/openclaw-backups"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="openclaw_backup_$TIMESTAMP"

mkdir -p "$BACKUP_DIR"

tar -czvf "$BACKUP_DIR/$BACKUP_NAME.tar.gz" \
  -C "$HOME" \
  .claude/skills \
  .claude/commands \
  .claude/settings.json \
  .claude/mcp \
  .claude/contexts \
  .claude/templates \
  2>/dev/null

echo "Backup created: $BACKUP_DIR/$BACKUP_NAME.tar.gz"
```

### Quick Skills-Only Backup

```bash
# Backup just skills
tar -czvf ~/openclaw_skills_$(date +%Y%m%d).tar.gz \
  -C "$HOME" .claude/skills .claude/commands
```

### Restore from Backup

```bash
# Restore full backup
BACKUP_FILE="$HOME/openclaw-backups/openclaw_backup_20260129.tar.gz"

# Preview contents first
tar -tzvf "$BACKUP_FILE"

# Restore (will overwrite existing)
tar -xzvf "$BACKUP_FILE" -C "$HOME"

echo "Restore complete!"
```

## Backup Script

### Full-Featured Backup Script

```bash
#!/bin/bash
# openclaw-backup.sh - Comprehensive openclaw backup tool

set -e

# Configuration
BACKUP_ROOT="${openclaw_BACKUP_DIR:-$HOME/openclaw-backups}"
CLAUDE_DIR="$HOME/.claude"
MAX_BACKUPS=10  # Keep last N backups
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'

log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; }
log_error() { echo -e "${RED}[ERROR]${NC} $1"; }

# Check if openclaw directory exists
check_claude_dir() {
    if [ ! -d "$CLAUDE_DIR" ]; then
        log_error "openclaw directory not found: $CLAUDE_DIR"
        exit 1
    fi
}

# Create backup
create_backup() {
    local backup_type="${1:-full}"
    local backup_name="openclaw_${backup_type}_${TIMESTAMP}"
    local backup_path="$BACKUP_ROOT/$backup_name.tar.gz"
    
    mkdir -p "$BACKUP_ROOT"
    
    log_info "Creating $backup_type backup..."
    
    case $backup_type in
        full)
            tar -czvf "$backup_path" \
                -C "$HOME" \
                .claude/skills \
                .claude/commands \
                .claude/settings.json \
                .claude/settings.local.json \
                .claude/projects.json \
                .claude/mcp \
                .claude/contexts \
                .claude/templates \
                2>/dev/null || true
            ;;
        skills)
            tar -czvf "$backup_path" \
                -C "$HOME" \
                .claude/skills \
                .claude/commands \
                2>/dev/null || true
            ;;
        settings)
            tar -czvf "$backup_path" \
                -C "$HOME" \
                .claude/settings.json \
                .claude/settings.local.json \
                .claude/mcp \
                2>/dev/null || true
            ;;
        *)
            log_error "Unknown backup type: $backup_type"
            exit 1
            ;;
    esac
    
    if [ -f "$backup_path" ]; then
        local size=$(du -h "$backup_path" | cut -f1)
        log_info "Backup created: $backup_path ($size)"
    else
        log_error "Backup failed!"
        exit 1
    fi
}

# List backups
list_backups() {
    log_info "Available backups in $BACKUP_ROOT:"
    echo ""
    
    if [ -d "$BACKUP_ROOT" ]; then
        ls -lh "$BACKUP_ROOT"/*.tar.gz 2>/dev/null | \
            awk '{print $9, $5, $6, $7, $8}' || \
            echo "No backups found."
    else
        echo "Backup directory doesn't exist."
    fi
}

# Restore backup
restore_backup() {
    local backup_file="$1"
    
    if [ -z "$backup_file" ]; then
        log_error "Please specify backup file"
        list_backups
        exit 1
    fi
    
    if [ ! -f "$backup_file" ]; then
        # Try relative path in backup dir
        backup_file="$BACKUP_ROOT/$backup_file"
    fi
    
    if [ ! -f "$backup_file" ]; then
        log_error "Backup file not found: $backup_file"
        exit 1
    fi
    
    log_warn "This will overwrite existing configuration!"
    read -p "Continue? (y/N) " confirm
    
    if [ "$confirm" != "y" ] && [ "$confirm" != "Y" ]; then
        log_info "Restore cancelled."
        exit 0
    fi
    
    log_info "Restoring from: $backup_file"
    tar -xzvf "$backup_file" -C "$HOME"
    log_info "Restore complete!"
}

# Clean old backups
cleanup_backups() {
    log_info "Cleaning old backups (keeping last $MAX_BACKUPS)..."
    
    cd "$BACKUP_ROOT" 2>/dev/null || return
    
    local count=$(ls -1 *.tar.gz 2>/dev/null | wc -l)
    
    if [ "$count" -gt "$MAX_BACKUPS" ]; then
        local to_delete=$((count - MAX_BACKUPS))
        ls -1t *.tar.gz | tail -n "$to_delete" | xargs rm -v
        log_info "Removed $to_delete old backup(s)"
    else
        log_info "No cleanup needed ($count backups)"
    fi
}

# Show backup stats
show_stats() {
    log_info "openclaw Backup Statistics"
    echo ""
    
    echo "=== Directory Sizes ==="
    du -sh "$CLAUDE_DIR"/skills 2>/dev/null || echo "Skills: N/A"
    du -sh "$CLAUDE_DIR"/commands 2>/dev/null || echo "Commands: N/A"
    du -sh "$CLAUDE_DIR"/mcp 2>/dev/null || echo "MCP: N/A"
    du -sh "$CLAUDE_DIR" 2>/dev/null || echo "Total: N/A"
    
    echo ""
    echo "=== Skills Count ==="
    find "$CLAUDE_DIR/skills" -name "SKILL.md" 2>/dev/null | wc -l | xargs echo "Skills:"
    find "$CLAUDE_DIR/commands" -name "*.md" 2>/dev/null | wc -l | xargs echo "Commands:"
    
    echo ""
    echo "=== Backup Directory ==="
    if [ -d "$BACKUP_ROOT" ]; then
        du -sh "$BACKUP_ROOT"
        ls -1 "$BACKUP_ROOT"/*.tar.gz 2>/dev/null | wc -l | xargs echo "Backup files:"
    else
        echo "No backups yet"
    fi
}

# Usage
usage() {
    cat << EOF
openclaw Backup Tool

Usage: $(basename $0) <command> [options]

Commands:
    backup [type]   Create backup (types: full, skills, settings)
    restore <file>  Restore from backup file
    list            List available backups
    cleanup         Remove old backups (keep last $MAX_BACKUPS)
    stats           Show backup statistics
    help            Show this help

Examples:
    $(basename $0) backup              # Full backup
    $(basename $0) backup skills       # Skills only
    $(basename $0) restore latest.tar.gz
    $(basename $0) list
    $(basename $0) cleanup

Environment:
    openclaw_BACKUP_DIR    Backup directory (default: ~/openclaw-backups)

EOF
}

# Main
main() {
    check_claude_dir
    
    case "${1:-help}" in
        backup)
            create_backup "${2:-full}"
            ;;
        restore)
            restore_backup "$2"
            ;;
        list)
            list_backups
            ;;
        cleanup)
            cleanup_backups
            ;;
        stats)
            show_stats
            ;;
        help|--help|-h)
            usage
            ;;
        *)
            log_error "Unknown command: $1"
            usage
            exit 1
            ;;
    esac
}

main "$@"
```

### Save and Use

```bash
# Save script
cat > ~/.local/bin/openclaw-backup << 'SCRIPT'
# Paste script content here
SCRIPT

chmod +x ~/.local/bin/openclaw-backup

# Usage
openclaw-backup backup          # Full backup
openclaw-backup backup skills   # Skills only
openclaw-backup list            # List backups
openclaw-backup restore <file>  # Restore
```

## Git Version Control

### Initialize Git Repo

```bash
cd ~/.claude

# Initialize git
git init

# Create .gitignore
cat > .gitignore << 'EOF'
# Machine-specific settings
settings.local.json

# Cache and temp files
cache/
*.tmp
*.log

# Large files
*.tar.gz
*.zip

# Sensitive data (if any)
*.pem
*.key
credentials/
EOF

# Initial commit
git add .
git commit -m "Initial openclaw configuration backup"
```

### Push to Remote

```bash
# Add remote (GitHub, GitLab, etc)
git remote add origin git@github.com:username/openclaw-config.git

# Push
git push -u origin main
```

### Daily Workflow

```bash
# After making changes to skills/settings
cd ~/.claude
git add .
git commit -m "Updated skill: trading-bot"
git push
```

### Auto-Commit Script

```bash
#!/bin/bash
# auto-commit-claude.sh - Auto commit changes

cd ~/.claude || exit 1

# Check for changes
if git diff --quiet && git diff --staged --quiet; then
    echo "No changes to commit"
    exit 0
fi

# Get changed files for commit message
CHANGED=$(git status --short | head -5 | awk '{print $2}' | tr '\n' ', ')

git add .
git commit -m "Auto-backup: $CHANGED ($(date +%Y-%m-%d))"
git push 2>/dev/null || echo "Push failed (offline?)"
```

## Sync Between Devices

### Method 1: Git Sync

```bash
# On new device
git clone git@github.com:username/openclaw-config.git ~/.claude

# Pull latest changes
cd ~/.claude && git pull

# Push local changes
cd ~/.claude && git add . && git commit -m "Update" && git push
```

### Method 2: Rsync

```bash
# Sync to remote server
rsync -avz --delete \
    ~/.claude/ \
    user@server:~/openclaw-backup/

# Sync from remote server
rsync -avz --delete \
    user@server:~/openclaw-backup/ \
    ~/.claude/
```

### Method 3: Cloud Storage

```bash
# Backup to cloud folder (Dropbox, Google Drive, etc)
CLOUD_DIR="$HOME/Dropbox/openclaw"

# Sync skills
rsync -avz ~/.claude/skills/ "$CLOUD_DIR/skills/"
rsync -avz ~/.claude/commands/ "$CLOUD_DIR/commands/"

# Copy settings
cp ~/.claude/settings.json "$CLOUD_DIR/"
```

### Sync Script

```bash
#!/bin/bash
# sync-openclaw.sh - Sync openclaw config between devices

SYNC_DIR="${openclaw_SYNC_DIR:-$HOME/Dropbox/openclaw}"
CLAUDE_DIR="$HOME/.claude"

sync_to_cloud() {
    echo "Syncing to cloud..."
    mkdir -p "$SYNC_DIR"
    
    rsync -avz --delete "$CLAUDE_DIR/skills/" "$SYNC_DIR/skills/"
    rsync -avz --delete "$CLAUDE_DIR/commands/" "$SYNC_DIR/commands/"
    rsync -avz "$CLAUDE_DIR/mcp/" "$SYNC_DIR/mcp/" 2>/dev/null
    cp "$CLAUDE_DIR/settings.json" "$SYNC_DIR/" 2>/dev/null
    
    echo "Sync complete!"
}

sync_from_cloud() {
    echo "Syncing from cloud..."
    
    rsync -avz "$SYNC_DIR/skills/" "$CLAUDE_DIR/skills/"
    rsync -avz "$SYNC_DIR/commands/" "$CLAUDE_DIR/commands/"
    rsync -avz "$SYNC_DIR/mcp/" "$CLAUDE_DIR/mcp/" 2>/dev/null
    
    # Don't overwrite local settings by default
    if [ ! -f "$CLAUDE_DIR/settings.json" ]; then
        cp "$SYNC_DIR/settings.json" "$CLAUDE_DIR/" 2>/dev/null
    fi
    
    echo "Sync complete!"
}

case "$1" in
    push) sync_to_cloud ;;
    pull) sync_from_cloud ;;
    *)
        echo "Usage: $0 {push|pull}"
        echo "  push - Upload local config to cloud"
        echo "  pull - Download cloud config to local"
        ;;
esac
```

## Automated Backups

### Cron Job (Linux/Mac)

```bash
# Edit crontab
crontab -e

# Add daily backup at 2 AM
0 2 * * * /home/user/.local/bin/openclaw-backup backup full

# Add weekly cleanup on Sundays
0 3 * * 0 /home/user/.local/bin/openclaw-backup cleanup

# Add git auto-commit every 6 hours
0 */6 * * * cd ~/.claude && git add . && git commit -m "Auto-backup $(date +\%Y-\%m-\%d)" && git push 2>/dev/null
```

### Systemd Timer (Linux)

```bash
# Create service: ~/.config/systemd/user/openclaw-backup.service
cat > ~/.config/systemd/user/openclaw-backup.service << 'EOF'
[Unit]
Description=openclaw Backup

[Service]
Type=oneshot
ExecStart=/home/user/.local/bin/openclaw-backup backup full
EOF

# Create timer: ~/.config/systemd/user/openclaw-backup.timer
cat > ~/.config/systemd/user/openclaw-backup.timer << 'EOF'
[Unit]
Description=Daily openclaw Backup

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target
EOF

# Enable
systemctl --user enable openclaw-backup.timer
systemctl --user start openclaw-backup.timer
```

### Launchd (macOS)

```bash
# Create plist: ~/Library/LaunchAgents/com.openclaw.backup.plist
cat > ~/Library/LaunchAgents/com.openclaw.backup.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>com.openclaw.backup</string>
    <key>ProgramArguments</key>
    <array>
        <string>/Users/username/.local/bin/openclaw-backup</string>
        <string>backup</string>
        <string>full</string>
    </array>
    <key>StartCalendarInterval</key>
    <dict>
        <key>Hour</key>
        <integer>2</integer>
        <key>Minute</key>
        <integer>0</integer>
    </dict>
</dict>
</plist>
EOF

# Load
launchctl load ~/Library/LaunchAgents/com.openclaw.backup.plist
```

## Migration Guide

### Migrate to New Machine

```bash
# === On OLD machine ===

# 1. Create full backup
openclaw-backup backup full

# 2. Copy backup file to new machine
scp ~/openclaw-backups/openclaw_full_*.tar.gz newmachine:~/

# Or use git
cd ~/.claude
git add . && git commit -m "Pre-migration backup"
git push


# === On NEW machine ===

# Method A: From backup file
tar -xzvf ~/openclaw_full_*.tar.gz -C ~

# Method B: From git
git clone git@github.com:username/openclaw-config.git ~/.claude

# 3. Verify
ls -la ~/.claude/skills/
```

### Export Single Skill

```bash
# Export one skill for sharing
SKILL_NAME="my-awesome-skill"
tar -czvf "${SKILL_NAME}.tar.gz" -C ~/.claude/skills "$SKILL_NAME"

# Import skill
tar -xzvf "${SKILL_NAME}.tar.gz" -C ~/.claude/skills/
```

### Export All Skills for Sharing

```bash
# Create shareable skills bundle (no personal settings)
tar -czvf openclaw-skills-share.tar.gz \
    -C ~/.claude \
    skills \
    --exclude='*.local*' \
    --exclude='*personal*'
```

## Backup Verification

### Verify Backup Integrity

```bash
# Test backup without extracting
tar -tzvf backup.tar.gz > /dev/null && echo "Backup OK" || echo "Backup CORRUPT"

# List contents
tar -tzvf backup.tar.gz

# Verify specific file exists
tar -tzvf backup.tar.gz | grep "skills/my-skill/SKILL.md"
```

### Compare Backup to Current

```bash
# Extract to temp dir
TEMP_DIR=$(mktemp -d)
tar -xzf backup.tar.gz -C "$TEMP_DIR"

# Compare
diff -rq ~/.claude/skills "$TEMP_DIR/.claude/skills"

# Cleanup
rm -rf "$TEMP_DIR"
```

## Troubleshooting

### Common Issues

```bash
# Issue: Permission denied
chmod -R u+rw ~/.claude

# Issue: Backup too large
# Exclude cache and logs
tar --exclude='cache' --exclude='*.log' -czvf backup.tar.gz ~/.claude

# Issue: Restore overwrote settings
# Keep settings.local.json for machine-specific config
# It won't be overwritten if using proper backup

# Issue: Git conflicts after sync
cd ~/.claude
git stash
git pull
git stash pop
# Resolve conflicts manually if needed
```

### Recovery from Corruption

```bash
# If ~/.claude is corrupted

# 1. Move corrupted dir
mv ~/.claude ~/.claude.corrupted

# 2. Restore from backup
openclaw-backup restore latest.tar.gz

# 3. Or restore from git
git clone git@github.com:username/openclaw-config.git ~/.claude

# 4. Compare and recover anything missing
diff -rq ~/.claude ~/.claude.corrupted/
```

## Quick Reference

### Essential Commands

```bash
# Backup
tar -czvf ~/openclaw-backup.tar.gz -C ~ .claude/skills .claude/commands .claude/settings.json

# Restore
tar -xzvf ~/openclaw-backup.tar.gz -C ~

# List backup contents
tar -tzvf ~/openclaw-backup.tar.gz

# Git backup
cd ~/.claude && git add . && git commit -m "Backup" && git push

# Git restore
cd ~/.claude && git pull
```

### Backup Checklist

```
Before major changes:
□ Create backup
□ Verify backup integrity
□ Note what you're changing

Regular maintenance:
□ Weekly full backup
□ Daily git commits (if using)
□ Monthly cleanup of old backups
□ Test restore procedure quarterly
```

## Resources

### Related Skills
```
- skill-creator - Create new skills
- mcp-builder - Configure MCP servers
- dotfiles - General dotfile management
```

### Documentation
```
- openclaw Docs: docs.openclaw.com
- Skills Guide: docs.openclaw.com/skills
- MCP Setup: docs.openclaw.com/mcp
```

---

**Tip:** Always test your backup restoration process before you actually need it. A backup you can't restore is worthless!

Related Skills

opentwitter

170
from adoresever/AGI_Ananas

Twitter/X data via the 6551 API. Supports user profiles, tweet search, user tweets, follower events, deleted tweets, and KOL followers.

opennews

170
from adoresever/AGI_Ananas

Crypto news search, AI ratings, trading signals, and real-time updates via the OpenNews 6551 API. Supports keyword search, coin filtering, source filtering, AI score ranking, and WebSocket live feeds.

agent-reach

170
from adoresever/AGI_Ananas

Give your AI agent eyes to see the entire internet. Read and search across Twitter/X, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu, Instagram, LinkedIn, Boss直聘, RSS, and any web page — all from a single CLI. Use when: (1) reading content from URLs (tweets, Reddit posts, articles, videos), (2) searching across platforms (web, Twitter, Reddit, GitHub, YouTube, Bilibili, XiaoHongShu, Instagram, LinkedIn, Boss直聘), (3) user asks to configure/enable a platform channel, (4) checking channel health or updating Agent Reach. Triggers: "search Twitter/Reddit/YouTube", "read this URL", "find posts about", "搜索", "读取", "查一下", "看看这个链接", "帮我配", "帮我添加", "帮我安装".

searxng-search

170
from adoresever/AGI_Ananas

使用自建SearXNG搜索引擎搜索互联网内容。触发词:搜索、查一下、帮我查、查找、搜一下、帮我搜索。

multi-search-engine

170
from adoresever/AGI_Ananas

Multi search engine integration with 17 engines (8 CN + 9 Global). Supports advanced search operators, time filters, site search, privacy engines, and WolframAlpha knowledge queries. No API keys required.

weather

170
from adoresever/AGI_Ananas

Get current weather and forecasts via wttr.in or Open-Meteo. Use when: user asks about weather, temperature, or forecasts for any location. NOT for: historical weather data, severe weather alerts, or detailed meteorological analysis. No API key needed.

wacli

170
from adoresever/AGI_Ananas

Send WhatsApp messages to other people or search/sync WhatsApp history via the wacli CLI (not for normal user chats).

voice-call

170
from adoresever/AGI_Ananas

Start voice calls via the OpenClaw voice-call plugin.

video-frames

170
from adoresever/AGI_Ananas

Extract frames or short clips from videos using ffmpeg.

trello

170
from adoresever/AGI_Ananas

Manage Trello boards, lists, and cards via the Trello REST API.

tmux

170
from adoresever/AGI_Ananas

Remote-control tmux sessions for interactive CLIs by sending keystrokes and scraping pane output.

things-mac

170
from adoresever/AGI_Ananas

Manage Things 3 via the `things` CLI on macOS (add/update projects+todos via URL scheme; read/search/list from the local Things database). Use when a user asks OpenClaw to add a task to Things, list inbox/today/upcoming, search tasks, or inspect projects/areas/tags.