Skill: mayueanyou/self-backup (version 1.0.0)

--- name: self-backup description: Backup important OpenClaw workspace files to a GitHub repository. Use when: (1) user wants to backup workspace configuration, (2) sync OpenClaw settings to GitHub, (3) preserve automation scripts and personal configuration, (4) create remote backup of AGENTS.md, SOUL.md, MEMORY.md, and other workspace files. Configurable for any GitHub repository. --- # Self Backup Backup critical OpenClaw workspace files to your GitHub repository for safe keeping and version control. ## Setup ### 1. Install GitHub CLI (if not already installed) ```bash # Ubuntu/Debian sudo apt install gh # macOS brew install gh # Other platforms: https://cli.github.com/ ``` ### 2. Login to GitHub ```bash gh auth login ``` ### 3. Configure your backup repository Edit the configuration in the backup script or set environment variables: ```bash # Set your repository URL (replace with your repo) export BACKUP_REPO_URL="https://github.com/YOUR_USERNAME/YOUR_BACKUP_REPO.git" # Or edit the script directly nano scripts/backup.sh ``` ### 4. Create your backup repository ```bash # Create a private repository for your backups gh repo create YOUR_USERNAME/openclaw-backup --private --description "OpenClaw workspace backup" ``` ## What Gets Backed Up ### Core Configuration Files - `AGENTS.md` - Workflow documentation and procedures - `SOUL.md` - Personal assistant personality and behavior - `USER.md` - Personal profile and preferences - `MEMORY.md` - Long-term memory and important context - `IDENTITY.md` - Assistant identity and emoji - `TOOLS.md` - Tool configuration and local notes - `AUTOMATION.md` - Cron and scheduling documentation - `openclaw.json` - OpenClaw system settings (tokens sanitized for security) ### Scripts & Automation - `scripts/` directory - All automation scripts - `memory/` directory - Daily memory logs (last 30 days) - Custom configuration files ### Skills Configuration - `skills/` directory - Local skill installations (metadata only) - Skill customizations ## Repository Structure Files are organized in the backup repository as: ``` / ├── config/ # Core configuration files ├── scripts/ # Automation scripts ├── memory/ # Daily memory logs ├── skills/ # Skill configurations └── backup-info.md # Backup metadata ``` ## Usage ### First-time setup: ```bash scripts/setup.sh ``` ### Regular backups: ```bash scripts/backup.sh ``` ### Options: ```bash scripts/backup.sh --force # Force push even with conflicts scripts/backup.sh --dry-run # Show what would be backed up ``` ## Security Features - **Automatic token sanitization**: All sensitive tokens (Discord, Telegram, API keys) are automatically redacted - **Private repository recommended**: Keep your configuration private - **Structure preservation**: All settings preserved, only sensitive data redacted - **Safe restore**: Easy to restore and re-enter tokens ## Configuration Edit these variables in `scripts/backup.sh`: ```bash # Your GitHub repository URL REPO_URL="https://github.com/YOUR_USERNAME/YOUR_BACKUP_REPO.git" # Workspace directory (usually auto-detected) WORKSPACE_DIR="$HOME/.openclaw/workspace" ``` ## Manual Backup To backup specific files manually: ```bash # Clone your backup repository git clone https://github.com/YOUR_USERNAME/YOUR_BACKUP_REPO.git /tmp/backup cd /tmp/backup # Copy important files cp ~/.openclaw/workspace/AGENTS.md config/ cp ~/.openclaw/workspace/SOUL.md config/ # ... etc # Commit and push git add . git commit -m "Manual backup $(date)" git push origin main ``` ## Restore Process To restore from backup: ```bash # Clone the backup git clone https://github.com/YOUR_USERNAME/YOUR_BACKUP_REPO.git # Copy files back to workspace cp backup/config/* ~/.openclaw/workspace/ cp -r backup/scripts/* ~/.openclaw/workspace/scripts/ # ... etc # Re-enter your actual tokens in openclaw.json nano ~/.openclaw/openclaw.json ``` ## Troubleshooting ### GitHub Authentication Issues ```bash # Re-login to GitHub gh auth logout gh auth login ``` ### Permission Denied ```bash # Check repository exists and you have access gh repo view YOUR_USERNAME/YOUR_BACKUP_REPO ``` ### Git Configuration ```bash # Set git identity if needed git config --global user.name "Your Name" git config --global user.email "[REDACTED_SECRET]" ```

path: scripts/sanitize-config.sh
content: #!/bin/bash

# Sanitize OpenClaw config for backup
# Removes sensitive tokens/keys while preserving structure

CONFIG_FILE="$1"
OUTPUT_FILE="$2"

if [ ! -f "$CONFIG_FILE" ]; then
    echo "Error: Config file not found: $CONFIG_FILE"
    exit 1
fi

if ! command -v jq &> /dev/null; then
    echo "Error: jq is required for config sanitization"
    echo "Install with: sudo apt install jq  OR  brew install jq"
    exit 1
fi

# Use jq to sanitize sensitive fields
jq '
# Remove all tokens and sensitive keys
(.channels.telegram.botToken // empty) = "TELEGRAM_BOT_TOKEN_REDACTED" |
(.channels.discord.token // empty) = "DISCORD_BOT_TOKEN_REDACTED" |
(.gateway.auth.token // empty) = "GATEWAY_AUTH_TOKEN_REDACTED" |

# Remove any API keys in auth profiles
.auth.profiles = (.auth.profiles | with_entries(
  .value |= (
    if has("apiKey") then .[REDACTED_SECRET]"
    elif has("token") then .[REDACTED_SECRET]"
    else . end
  )
)) |

# Remove sensitive model provider keys
.models.providers = (.models.providers | with_entries(
  .value |= (
    if has("apiKey") then .[REDACTED_SECRET]"
    else . end
  )
))
' "$CONFIG_FILE" > "$OUTPUT_FILE"

if [ $? -eq 0 ]; then
    echo "Config sanitized: $OUTPUT_FILE"
else
    echo "Error: Failed to sanitize config"
    exit 1
fi

path: scripts/setup.sh
content: #!/bin/bash

# OpenClaw Self-Backup Setup Script
# Helps users configure their backup repository

set -e

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

log "OpenClaw Self-Backup Setup"
log "=========================="

# Check if GitHub CLI is available
if ! command -v gh &> /dev/null; then
    log "GitHub CLI not found."
    log ""
    log "To install GitHub CLI:"
    log "  Ubuntu/Debian: sudo apt install gh"
    log "  macOS: brew install gh"
    log "  Other: https://cli.github.com/"
    log ""
    echo -n "Do you want to continue with manual setup? (y/n): "
    read -r response
    if [[ ! "$response" =~ ^[Yy]$ ]]; then
        exit 0
    fi
    MANUAL_SETUP=true
else
    log "GitHub CLI found ✓"
    MANUAL_SETUP=false
fi

# Check authentication
if [ "$MANUAL_SETUP" = false ]; then
    if ! gh auth status &>/dev/null; then
        log "Please login to GitHub CLI first:"
        log "  gh auth login"
        log ""
        echo -n "Would you like to login now? (y/n): "
        read -r response
        if [[ "$response" =~ ^[Yy]$ ]]; then
            gh auth login
        else
            log "Please run 'gh auth login' then run this setup again"
            exit 1
        fi
    else
        log "GitHub authentication verified ✓"
    fi
fi

# Get user information
if [ "$MANUAL_SETUP" = false ]; then
    USERNAME=$(gh api user --jq '.login' 2>/dev/null || echo "")
    if [ -n "$USERNAME" ]; then
        log "GitHub username: $USERNAME"
        SUGGESTED_REPO="$USERNAME/openclaw-backup"
    else
        log "Warning: Could not detect GitHub username"
        SUGGESTED_REPO="YOUR_USERNAME/openclaw-backup"
    fi
else
    log "Manual setup mode"
    echo -n "Enter your GitHub username: "
    read -r USERNAME
    SUGGESTED_REPO="$USERNAME/openclaw-backup"
fi

# Ask about repository
log ""
log "Repository Configuration"
log "------------------------"
echo -n "Repository name (default: $SUGGESTED_REPO): "
read -r REPO_NAME

if [ -z "$REPO_NAME" ]; then
    REPO_NAME="$SUGGESTED_REPO"
fi

REPO_URL="https://github.com/$REPO_NAME.git"

# Create repository
if [ "$MANUAL_SETUP" = false ]; then
    log "Checking if repository exists..."
    
    # Extract owner and repo from REPO_NAME
    IFS='/' read -r OWNER REPO <<< "$REPO_NAME"
    
    if gh repo view "$REPO_NAME" &>/dev/null; then
        log "Repository already exists: $REPO_URL"
    else
        echo -n "Create private repository '$REPO_NAME'? (y/n): "
        read -r response
        if [[ "$response" =~ ^[Yy]$ ]]; then
            log "Creating repository..."
            gh repo create "$REPO_NAME" --private --description "OpenClaw workspace backup repository"
            log "✓ Repository created: $REPO_URL"
        else
            log "Please create the repository manually at: https://github.com/new"
            log "Repository name: $REPO"
            log "Make it private for security!"
        fi
    fi
else
    log "Please create your repository manually:"
    log "  1. Go to: https://github.com/new"
    log "  2. Repository name: ${REPO_NAME##*/}"
    log "  3. Make it PRIVATE (important for security)"
    log "  4. Click 'Create repository'"
fi

# Configure backup script
log ""
log "Configuring backup script..."

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
BACKUP_SCRIPT="$SCRIPT_DIR/backup.sh"

# Create a configuration file for the user
cat > "$SCRIPT_DIR/../backup-config.sh" << EOF
#!/bin/bash
# Self-Backup Configuration
# Source this file or export these variables before running backup.sh

export BACKUP_REPO_URL="$REPO_URL"
export OPENCLAW_WORKSPACE="\$HOME/.openclaw/workspace"

echo "Self-backup configured for repository: $REPO_URL"
EOF

chmod +x "$SCRIPT_DIR/../backup-config.sh"

log "✓ Configuration saved to: backup-config.sh"

# Test the backup script
log ""
log "Testing backup script..."

# Set the environment variable for testing
export BACKUP_REPO_URL="$REPO_URL"

if "$BACKUP_SCRIPT" --dry-run; then
    log "✓ Backup script test completed successfully"
else
    log "✗ Backup script test failed"
    exit 1
fi

log ""
log "Setup completed successfully!"
log ""
log "Next steps:"
log "1. Test backup: source backup-config.sh && scripts/backup.sh --dry-run"
log "2. Run actual backup: source backup-config.sh && scripts/backup.sh"
log "3. View your backups at: $REPO_URL"
log ""
log "Configuration file: backup-config.sh"
log "Repository: $REPO_URL"

path: scripts/backup.sh
content: #!/bin/bash

# OpenClaw Self-Backup Script (Generic Version)
# Backs up important workspace files to any GitHub repository

set -e

# CONFIGURATION - Edit these variables for your setup
REPO_URL="${BACKUP_REPO_URL:-https://github.com/YOUR_USERNAME/YOUR_BACKUP_REPO.git}"
WORKSPACE_DIR="${OPENCLAW_WORKSPACE:-$HOME/.openclaw/workspace}"

# Runtime variables
BACKUP_DIR="/tmp/openclaw_backup_$(date +%s)"
DRY_RUN=false
FORCE=false

# Check if repository URL is configured
if [[ "$REPO_URL" == *"YOUR_USERNAME"* ]]; then
    echo "ERROR: Please configure your repository URL first!"
    echo ""
    echo "Option 1: Set environment variable:"
    echo "  export BACKUP_REPO_URL=\"https://github.com/yourusername/your-backup-repo.git\""
    echo ""
    echo "Option 2: Edit this script and change REPO_URL variable"
    echo ""
    echo "Option 3: Create repository with:"
    echo "  gh repo create yourusername/openclaw-backup --private"
    exit 1
fi

# Parse arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        --dry-run)
            DRY_RUN=true
            shift
            ;;
        --force)
            FORCE=true
            shift
            ;;
        -h|--help)
            echo "Usage: $0 [--dry-run] [--force] [--help]"
            echo "  --dry-run  Show what would be backed up without doing it"
            echo "  --force    Force push even with conflicts"
            echo "  --help     Show this help message"
            echo ""
            echo "Configuration:"
            echo "  Set BACKUP_REPO_URL environment variable or edit REPO_URL in script"
            echo "  Current repository: $REPO_URL"
            exit 0
            ;;
        *)
            echo "Unknown option: $1"
            exit 1
            ;;
    esac
done

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

log "Starting OpenClaw self-backup..."
log "Repository: $REPO_URL"

if [ "$DRY_RUN" = true ]; then
    log "DRY RUN MODE - No changes will be made"
fi

# Check if workspace exists
if [ ! -d "$WORKSPACE_DIR" ]; then
    log "ERROR: Workspace directory not found: $WORKSPACE_DIR"
    log "Set OPENCLAW_WORKSPACE environment variable if using custom location"
    exit 1
fi

# Check if git is available
if ! command -v git &> /dev/null; then
    log "ERROR: git is not installed"
    exit 1
fi

# Check if gh CLI is available for authentication
if ! command -v gh &> /dev/null; then
    log "WARNING: GitHub CLI (gh) not found. Using HTTPS authentication."
    log "Install with: sudo apt install gh   OR   brew install gh"
fi

if [ "$DRY_RUN" = false ]; then
    # Clone or update the backup repository
    log "Setting up backup repository..."
    git clone "$REPO_URL" "$BACKUP_DIR" 2>/dev/null || {
        log "ERROR: Failed to clone repository. Check:"
        log "  1. Repository exists: $REPO_URL"
        log "  2. You have access to it"
        log "  3. GitHub authentication is working"
        exit 1
    }
    
    cd "$BACKUP_DIR"
else
    log "Would clone repository to: $BACKUP_DIR"
fi

# Create directory structure
DIRS=("config" "scripts" "memory" "skills")
for dir in "${DIRS[@]}"; do
    if [ "$DRY_RUN" = false ]; then
        mkdir -p "$dir"
    else
        log "Would create directory: $dir"
    fi
done

# Core configuration files to backup
CONFIG_FILES=(
    "AGENTS.md"
    "SOUL.md" 
    "USER.md"
    "MEMORY.md"
    "IDENTITY.md"
    "TOOLS.md"
    "AUTOMATION.md"
    "HEARTBEAT.md"
)

# OpenClaw system configuration file
OPENCLAW_CONFIG="$HOME/.openclaw/openclaw.json"

log "Backing up core configuration files..."
for file in "${CONFIG_FILES[@]}"; do
    if [ -f "$WORKSPACE_DIR/$file" ]; then
        if [ "$DRY_RUN" = false ]; then
            cp "$WORKSPACE_DIR/$file" "config/"
            log "  ✓ Backed up: $file"
        else
            log "  Would backup: $file"
        fi
    else
        log "  ⚠ Skipping missing file: $file"
    fi
done

# Backup OpenClaw system configuration
log "Backing up OpenClaw system configuration..."
if [ -f "$OPENCLAW_CONFIG" ]; then
    if [ "$DRY_RUN" = false ]; then
        # Sanitize the config file to remove sensitive tokens
        if command -v jq &> /dev/null; then
            log "  Sanitizing openclaw.json (removing sensitive tokens)..."
            
            # Get script directory relative to this script
            SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)"
            
            if [ -f "$SCRIPT_DIR/sanitize-config.sh" ]; then
                "$SCRIPT_DIR/sanitize-config.sh" "$OPENCLAW_CONFIG" "config/openclaw.json"
                log "  ✓ Backed up: openclaw.json (sanitized)"
            else
                log "  ⚠ Sanitizer script not found, skipping openclaw.json"
            fi
        else
            log "  ⚠ jq not found, skipping openclaw.json (contains sensitive data)"
            log "    Install jq: sudo apt install jq  OR  brew install jq"
        fi
    else
        log "  Would backup: openclaw.json (sanitized)"
    fi
else
    log "  ⚠ Skipping missing file: openclaw.json"
fi

# Backup scripts directory
if [ -d "$WORKSPACE_DIR/scripts" ]; then
    log "Backing up scripts directory..."
    if [ "$DRY_RUN" = false ]; then
        cp -r "$WORKSPACE_DIR/scripts/"* "scripts/" 2>/dev/null || log "  No scripts to backup"
    else
        log "  Would backup scripts directory"
    fi
else
    log "  No scripts directory found"
fi

# Backup memory directory (last 30 days)
if [ -d "$WORKSPACE_DIR/memory" ]; then
    log "Backing up recent memory files..."
    if [ "$DRY_RUN" = false ]; then
        find "$WORKSPACE_DIR/memory" -name "*.md" -mtime -30 -exec cp {} "memory/" \; 2>/dev/null || log "  No recent memory files"
    else
        log "  Would backup recent memory files (last 30 days)"
    fi
else
    log "  No memory directory found"
fi

# Backup skills configurations (metadata only)
if [ -d "$WORKSPACE_DIR/skills" ]; then
    log "Backing up skills metadata..."
    if [ "$DRY_RUN" = false ]; then
        mkdir -p "skills"
        find "$WORKSPACE_DIR/skills" -name "SKILL.md" -exec dirname {} \; | while read skilldir; do
            skillname=$(basename "$skilldir")
            mkdir -p "skills/$skillname"
            cp "$skilldir/SKILL.md" "skills/$skillname/" 2>/dev/null || true
        done
    else
        log "  Would backup skills metadata"
    fi
else
    log "  No skills directory found"
fi

# Create backup info file
BACKUP_INFO="backup-info.md"
if [ "$DRY_RUN" = false ]; then
    cat > "$BACKUP_INFO" << EOF
# OpenClaw Self-Backup Information

**Backup Date:** $(date)
**Hostname:** $(hostname)
**OpenClaw Version:** $(openclaw --version 2>/dev/null || echo "Unknown")
**Workspace:** $WORKSPACE_DIR
**Repository:** $REPO_URL

## Backup Contents

### Configuration Files
$(cd config 2>/dev/null && ls -la | tail -n +4 | awk '{print "- " $9 " (" $5 " bytes)"}' || echo "None")

**OpenClaw Settings:** $([ -f config/openclaw.json ] && echo "✓ openclaw.json (sanitized)" || echo "✗ Not backed up")

### Scripts
$(cd scripts 2>/dev/null && find . -type f | sed 's|^\./|- |' || echo "None")

### Memory Files
$(cd memory 2>/dev/null && ls -1 *.md 2>/dev/null | sed 's/^/- /' || echo "None")

### Skills
$(cd skills 2>/dev/null && find . -name "SKILL.md" | sed 's|/SKILL.md||' | sed 's|^\./|- |' || echo "None")

## Notes

This backup was created automatically by the self-backup skill.

**Security:** All sensitive tokens have been redacted from openclaw.json.
To restore, copy files back and re-enter your actual tokens.

**Repository:** $REPO_URL
EOF
    log "Created backup information file"
else
    log "Would create backup-info.md with metadata"
fi

if [ "$DRY_RUN" = false ]; then
    # Commit and push changes
    log "Committing changes..."
    git add .
    
    if git diff --staged --quiet; then
        log "No changes to commit"
    else
        git commit -m "Automated OpenClaw backup - $(date)"
        
        if [ "$FORCE" = true ]; then
            log "Force pushing to repository..."
            git push origin main --force
        else
            log "Pushing to repository..."
            git push origin main || {
                log "ERROR: Push failed. Use --force if you want to overwrite remote changes."
                exit 1
            }
        fi
        
        log "✓ Backup completed successfully!"
        log "Repository: $REPO_URL"
    fi
    
    # Cleanup
    cd /tmp
    rm -rf "$BACKUP_DIR"
    log "Cleanup completed"
else
    log "DRY RUN COMPLETE - No actual backup was performed"
fi

log "Backup process finished"

Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)