DevOps
backup
Backup and restore openclaw configuration, skills, commands, and settings.
---
name: backup
description: Backup and restore openclaw configuration, skills, commands, and settings. Sync across devices, version control with git, automate backups, and migrate to new machines.
metadata: {"openclaw":{"emoji":"πΎ","requires":{"bins":["git","tar","rsync"],"env":[]}}}
---
# 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 [email protected]:username/openclaw-config.git
# Push
git push -u origin main
```
### Daily
... (truncated)
devops
By
Comments
Sign in to leave a comment