Skip to content

Instantly share code, notes, and snippets.

@adhishthite
Created February 12, 2026 07:40
Show Gist options
  • Select an option

  • Save adhishthite/60e20ce509e73b3b04c26712739c327d to your computer and use it in GitHub Desktop.

Select an option

Save adhishthite/60e20ce509e73b3b04c26712739c327d to your computer and use it in GitHub Desktop.
OpenClaw Migration Guide - Moving your AI assistant setup to a new machine
#!/usr/bin/env bash
set -euo pipefail
# ============================================================================
# OpenClaw Migration Script
# Exports or imports your OpenClaw setup between machines.
# Usage:
# ./openclaw-migrate.sh export # Create migration bundle
# ./openclaw-migrate.sh import <bundle> # Restore from bundle
# ./openclaw-migrate.sh verify # Check current installation
# ============================================================================
# --- Colors & helpers -------------------------------------------------------
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
BOLD='\033[1m'
NC='\033[0m'
info() { echo -e "${BLUE}ℹ${NC} $*"; }
ok() { echo -e "${GREEN}✓${NC} $*"; }
warn() { echo -e "${YELLOW}⚠${NC} $*"; }
err() { echo -e "${RED}✗${NC} $*"; }
header(){ echo -e "\n${BOLD}${CYAN}═══ $* ═══${NC}\n"; }
OC_DIR="$HOME/.openclaw"
BUNDLE_NAME="openclaw-migration-bundle-$(date +%Y%m%d-%H%M%S).tar.gz"
BUNDLE_PATH="$HOME/$BUNDLE_NAME"
# --- Export -----------------------------------------------------------------
do_export() {
header "OpenClaw Migration Export"
if [[ ! -d "$OC_DIR" ]]; then
err "OpenClaw directory not found at $OC_DIR"
exit 1
fi
# Stop gateway if running
if command -v openclaw &>/dev/null; then
info "Stopping gateway..."
openclaw gateway stop 2>/dev/null || true
fi
# Show what we're bundling
info "Scanning OpenClaw directory..."
local size
size=$(du -sh "$OC_DIR" 2>/dev/null | cut -f1)
info "Total size: ${BOLD}$size${NC}"
echo ""
info "Contents to bundle:"
[[ -f "$OC_DIR/openclaw.json" ]] && ok " openclaw.json (gateway config)"
[[ -d "$OC_DIR/workspace" ]] && ok " workspace/ (SOUL.md, USER.md, MEMORY.md, memory/, etc.)"
[[ -d "$OC_DIR/agents" ]] && ok " agents/ (configs + session history)"
[[ -d "$OC_DIR/skills" ]] && ok " skills/ (user-installed skills)"
[[ -d "$OC_DIR/sessions" ]] && ok " sessions/"
[[ -d "$OC_DIR/logs" ]] && warn " logs/ (included but optional)"
echo ""
read -rp "$(echo -e "${YELLOW}Include session history? (can be large) [y/N]:${NC} ")" include_sessions
local exclude_args=()
if [[ "${include_sessions,,}" != "y" ]]; then
exclude_args+=(--exclude='agents/*/sessions')
exclude_args+=(--exclude='sessions')
info "Excluding session history"
fi
# Always exclude logs and temp files
exclude_args+=(--exclude='logs')
exclude_args+=(--exclude='*.tmp')
exclude_args+=(--exclude='.DS_Store')
exclude_args+=(--exclude='node_modules')
info "Creating bundle..."
tar czf "$BUNDLE_PATH" \
-C "$HOME" \
"${exclude_args[@]}" \
.openclaw
local bundle_size
bundle_size=$(du -sh "$BUNDLE_PATH" | cut -f1)
echo ""
header "Export Complete"
ok "Bundle created: ${BOLD}$BUNDLE_PATH${NC}"
ok "Bundle size: ${BOLD}$bundle_size${NC}"
echo ""
info "Next steps:"
echo " 1. Transfer the bundle to your new machine:"
echo " ${CYAN}scp $BUNDLE_PATH newmachine:~/${NC}"
echo " 2. On the new machine, run:"
echo " ${CYAN}./openclaw-migrate.sh import ~/$BUNDLE_NAME${NC}"
# Save cron jobs for reference
if command -v openclaw &>/dev/null; then
info "Saving cron job list..."
openclaw cron list > "$HOME/openclaw-cron-backup.txt" 2>/dev/null || true
ok "Cron backup: ~/openclaw-cron-backup.txt"
fi
}
# --- Import -----------------------------------------------------------------
do_import() {
local bundle="${1:-}"
header "OpenClaw Migration Import"
if [[ -z "$bundle" ]]; then
err "Usage: $0 import <path-to-bundle.tar.gz>"
exit 1
fi
if [[ ! -f "$bundle" ]]; then
err "Bundle not found: $bundle"
exit 1
fi
# Check if openclaw dir already exists
if [[ -d "$OC_DIR" ]]; then
warn "Existing OpenClaw directory found at $OC_DIR"
read -rp "$(echo -e "${YELLOW}Back it up and overwrite? [y/N]:${NC} ")" confirm
if [[ "${confirm,,}" != "y" ]]; then
err "Aborted."
exit 1
fi
local backup="$OC_DIR.backup-$(date +%Y%m%d-%H%M%S)"
info "Backing up existing directory to $backup"
mv "$OC_DIR" "$backup"
ok "Backup created"
fi
# Stop gateway if running
if command -v openclaw &>/dev/null; then
openclaw gateway stop 2>/dev/null || true
fi
info "Extracting bundle..."
tar xzf "$bundle" -C "$HOME"
ok "Files extracted to $OC_DIR"
# Verify extraction
echo ""
info "Verifying extracted files..."
[[ -f "$OC_DIR/openclaw.json" ]] && ok " openclaw.json" || warn " openclaw.json missing"
[[ -d "$OC_DIR/workspace" ]] && ok " workspace/" || warn " workspace/ missing"
[[ -d "$OC_DIR/agents" ]] && ok " agents/" || warn " agents/ missing"
[[ -d "$OC_DIR/skills" ]] && ok " skills/" || warn " skills/ missing"
# Install OpenClaw if not present
echo ""
if ! command -v openclaw &>/dev/null; then
warn "OpenClaw CLI not found. Install it:"
echo " ${CYAN}npm install -g openclaw@latest${NC}"
else
ok "OpenClaw CLI found: $(openclaw --version 2>/dev/null || echo 'unknown version')"
fi
# BWS check
echo ""
header "Secret Management"
if command -v bws &>/dev/null; then
ok "BWS CLI installed"
if [[ -n "${BWS_ACCESS_TOKEN:-}" ]]; then
ok "BWS_ACCESS_TOKEN is set"
else
warn "BWS_ACCESS_TOKEN not set — add to your shell profile:"
echo " ${CYAN}export BWS_ACCESS_TOKEN=\"your-token-here\"${NC}"
fi
else
warn "BWS CLI not installed. Install:"
echo " ${CYAN}brew install bitwarden/tap/bws${NC}"
fi
# QMD re-index
echo ""
header "QMD Re-indexing"
if command -v qmd &>/dev/null; then
info "Re-indexing workspace..."
qmd index "$OC_DIR/workspace" 2>/dev/null && ok "Workspace indexed" || warn "QMD indexing failed (run manually)"
else
warn "QMD not found — install it and run:"
echo " ${CYAN}qmd index ~/.openclaw/workspace${NC}"
fi
# Print re-auth checklist
echo ""
header "Manual Re-Authentication Required"
echo " The following tools need manual re-auth on this machine:"
echo ""
echo " ${BOLD}Tool Command${NC}"
echo " ──────────────── ─────────────────────────────"
echo " GitHub CLI ${CYAN}gh auth login${NC}"
echo " Google (gog) ${CYAN}gog auth login${NC}"
echo " WhatsApp (wacli) ${CYAN}wacli auth${NC} (QR scan)"
echo " Codex CLI ${CYAN}codex login${NC}"
echo " Claude Code ${CYAN}claude auth${NC}"
echo " Cursor Sign in via Cursor IDE UI"
echo " Tailscale ${CYAN}tailscale up${NC}"
echo ""
header "Import Complete"
ok "Files restored. Next steps:"
echo " 1. Set up BWS_ACCESS_TOKEN (if not done)"
echo " 2. Re-authenticate external tools (see above)"
echo " 3. Start the gateway: ${CYAN}openclaw gateway start${NC}"
echo " 4. Verify: ${CYAN}./openclaw-migrate.sh verify${NC}"
}
# --- Verify -----------------------------------------------------------------
do_verify() {
header "OpenClaw Installation Verification"
local pass=0
local fail=0
check() {
if eval "$2" &>/dev/null; then
ok "$1"
((pass++))
else
err "$1"
((fail++))
fi
}
# Core
info "Core:"
check " OpenClaw CLI installed" "command -v openclaw"
check " Config exists" "test -f $OC_DIR/openclaw.json"
check " Workspace exists" "test -d $OC_DIR/workspace"
check " SOUL.md exists" "test -f $OC_DIR/workspace/SOUL.md"
check " USER.md exists" "test -f $OC_DIR/workspace/USER.md"
check " MEMORY.md exists" "test -f $OC_DIR/workspace/MEMORY.md"
check " Agents directory exists" "test -d $OC_DIR/agents"
# Count agents
if [[ -d "$OC_DIR/agents" ]]; then
local agent_count
agent_count=$(find "$OC_DIR/agents" -maxdepth 1 -mindepth 1 -type d | wc -l | tr -d ' ')
info " Agents found: ${BOLD}$agent_count${NC}"
fi
# Tools
echo ""
info "External tools:"
check " BWS CLI" "command -v bws"
check " GitHub CLI" "command -v gh"
check " QMD" "command -v qmd"
check " Node.js" "command -v node"
check " Tailscale" "command -v tailscale"
# Auth status
echo ""
info "Auth status:"
if command -v gh &>/dev/null; then
check " GitHub authenticated" "gh auth status"
fi
if [[ -n "${BWS_ACCESS_TOKEN:-}" ]]; then
ok " BWS_ACCESS_TOKEN set"
((pass++))
else
warn " BWS_ACCESS_TOKEN not set"
((fail++))
fi
# Gateway
echo ""
info "Gateway:"
if command -v openclaw &>/dev/null; then
local gw_status
gw_status=$(openclaw gateway status 2>&1 || true)
if echo "$gw_status" | grep -qi "running"; then
ok " Gateway running"
((pass++))
else
warn " Gateway not running (start with: openclaw gateway start)"
((fail++))
fi
fi
# Cron jobs
if command -v openclaw &>/dev/null; then
local cron_count
cron_count=$(openclaw cron list 2>/dev/null | wc -l | tr -d ' ')
info " Cron jobs: ${BOLD}$cron_count${NC}"
fi
# Summary
echo ""
header "Summary"
ok "Passed: $pass"
[[ $fail -gt 0 ]] && err "Failed: $fail" || ok "Failed: $fail"
}
# --- Main -------------------------------------------------------------------
case "${1:-}" in
export) do_export ;;
import) do_import "${2:-}" ;;
verify) do_verify ;;
*)
echo -e "${BOLD}OpenClaw Migration Tool${NC}"
echo ""
echo "Usage:"
echo " $0 export Create migration bundle"
echo " $0 import <bundle> Restore from migration bundle"
echo " $0 verify Verify current installation"
echo ""
echo "Workflow:"
echo " 1. Old machine: ./openclaw-migrate.sh export"
echo " 2. Transfer: scp ~/openclaw-migration-bundle-*.tar.gz newmachine:~/"
echo " 3. New machine: ./openclaw-migrate.sh import ~/openclaw-migration-bundle-*.tar.gz"
echo " 4. Verify: ./openclaw-migrate.sh verify"
;;
esac

OpenClaw Migration Guide

Migrate your OpenClaw setup from one machine to another with minimal downtime.


Table of Contents

  1. Overview
  2. Pre-Migration Checklist
  3. Core Directories
  4. Secret Management (BWS)
  5. External Tool Re-Authentication
  6. QMD Semantic Search Index
  7. Cron Jobs
  8. Skills
  9. Agents
  10. Post-Migration Verification

Overview

OpenClaw stores all its data under ~/.openclaw/. This includes:

Path Contents
~/.openclaw/openclaw.json Gateway configuration (ports, channel configs, model settings)
~/.openclaw/workspace/ Your workspace files: SOUL.md, USER.md, MEMORY.md, AGENTS.md, TOOLS.md, memory/ directory
~/.openclaw/agents/ Agent configurations and session transcripts
~/.openclaw/skills/ User-installed skills
~/.openclaw/sessions/ Session data
~/.openclaw/logs/ Gateway and agent logs

The migration process is: export → transfer → import → re-auth → verify.


Pre-Migration Checklist

Before starting:

  • Stop the OpenClaw gateway: openclaw gateway stop
  • Note your current OpenClaw version: openclaw --version
  • List active cron jobs: openclaw cron list
  • List installed skills: check ~/.openclaw/skills/
  • List your agents: ls ~/.openclaw/agents/
  • Ensure you have your BWS (Bitwarden Secrets) access token stored somewhere safe
  • Back up any custom scripts or tools referenced by your agents
  • Check disk space — the migration bundle can be large if you have extensive session history

Core Directories

What to Copy

The entire ~/.openclaw/ directory is the migration target. Key subdirectories:

~/.openclaw/openclaw.json

The main gateway configuration file. Contains:

  • Gateway port and host settings
  • Channel configurations (Telegram bot tokens are referenced via BWS, not stored in plaintext)
  • Model provider settings
  • Agent routing rules

⚠️ Review before copying — some settings are machine-specific (e.g., paths, ports).

~/.openclaw/workspace/

Your agent's brain:

  • SOUL.md — Agent personality and identity
  • USER.md — Information about you (the user)
  • MEMORY.md — Long-term curated memory
  • AGENTS.md — Agent behavior rules and workflows
  • TOOLS.md — Tool configuration notes
  • memory/ — Daily memory files (YYYY-MM-DD.md), error logs, references

This is the most important directory to preserve.

~/.openclaw/skills/

User-installed skills (ClawHub or custom). System skills ship with the npm package and don't need copying.

~/.openclaw/agents/

Each agent has its own subdirectory:

~/.openclaw/agents/
├── myagent/
│   ├── agent.json          # Agent configuration
│   └── sessions/           # Session transcripts
└── anotheragent/
    ├── agent.json
    └── sessions/

Important: Agent IDs are permanent identifiers. Do not rename agent directories.


Secret Management (BWS)

OpenClaw integrates with Bitwarden Secrets Manager (BWS) for secure secret injection.

How It Works

  1. On gateway startup, OpenClaw reads secret references from openclaw.json
  2. It calls BWS to fetch the actual values
  3. Secrets are injected as environment variables for the gateway process
  4. Secrets are never stored on disk in plaintext

Migration Steps

  1. Install BWS CLI on the new machine:

    # macOS
    brew install bitwarden/tap/bws
    
    # Or download from https://bitwarden.com/help/secrets-manager-cli/
  2. Set your BWS access token:

    # Add to your shell profile (~/.zshrc, ~/.bashrc, etc.)
    export BWS_ACCESS_TOKEN="your-access-token-here"
  3. Verify access:

    bws secret list
  4. Secrets that OpenClaw typically pulls from BWS:

    • API keys for model providers (OpenAI, Anthropic, Azure, etc.)
    • Channel tokens (Telegram bot token, Discord bot token, etc.)
    • Third-party service credentials
    • Any custom secrets referenced in your openclaw.json

If You Don't Use BWS

If your secrets are set via environment variables directly, ensure they're added to your shell profile on the new machine.


External Tool Re-Authentication

These tools store auth locally and need re-authentication on the new machine:

gog (Google Workspace CLI)

# Re-authenticate for Gmail, Calendar, Drive access
gog auth login
# Follow the OAuth browser flow
# Verify:
gog gmail list --limit 1
gog calendar list --limit 1

gh (GitHub CLI)

gh auth login
# Choose: GitHub.com → HTTPS → Browser
# Verify:
gh auth status

wacli (WhatsApp CLI)

wacli auth
# Scan the QR code with WhatsApp on your phone
# This creates a new linked device
# Verify:
wacli status

codex (OpenAI Codex CLI)

codex login
# Or set OPENAI_API_KEY in your environment
# Verify:
codex --version

claude (Claude Code)

claude auth
# Follow the browser OAuth flow
# Or set ANTHROPIC_API_KEY in your environment
# Verify:
claude --version

Cursor Agent

# Open Cursor IDE and sign in via the UI
# Settings → Account → Sign In

Tailscale

# Re-join your tailnet
tailscale up
# Or on macOS, open the Tailscale app and sign in
# Verify:
tailscale status

QMD Semantic Search Index

QMD maintains a local semantic search index with embeddings. Embeddings are not portable — they must be regenerated on the new machine.

Migration Steps

  1. Install QMD on the new machine (if not already installed)

  2. List existing collections (on old machine, for reference):

    qmd collection list
  3. Re-index collections on the new machine:

    # Re-index your workspace
    qmd index ~/.openclaw/workspace
    
    # Re-index any other directories you had indexed
    qmd index /path/to/your/documents
    
    # List collections to verify
    qmd collection list
  4. Embeddings are regenerated automatically during indexing — no need to copy the old index database.


Cron Jobs

OpenClaw cron jobs handle scheduled tasks (heartbeats, reminders, workflow polling, etc.).

Export (Old Machine)

# List all cron jobs
openclaw cron list

# Save the output for reference
openclaw cron list > ~/openclaw-cron-backup.txt

Import (New Machine)

Cron jobs are stored in the agent configuration. After restoring ~/.openclaw/, they should be automatically available. Verify with:

openclaw cron list

If any are missing, re-create them:

openclaw cron add --agent myagent --schedule "*/15 * * * *" --task "your task description"

Skills

Types of Skills

Type Location Migration
System skills Inside the openclaw npm package Auto-installed with OpenClaw
User skills ~/.openclaw/skills/ Copied with migration bundle
ClawHub skills ~/.openclaw/skills/ (installed from ClawHub) Re-install from ClawHub if missing

After Migration

  1. Verify user skills are present:

    ls ~/.openclaw/skills/
  2. Re-install any ClawHub skills if needed:

    openclaw skill install <skill-name>
  3. System skills come with the OpenClaw package — just ensure you're on the same (or newer) version:

    npm install -g openclaw@latest

Agents

Agent Structure

~/.openclaw/agents/<agent-id>/
├── agent.json              # Agent identity, model, channel bindings
└── sessions/
    ├── <session-id>.jsonl   # Session transcripts
    └── ...

Important Notes

  • Agent IDs are permanent. The directory name IS the agent ID. Never rename these directories.
  • Session history can be large. You may choose to skip sessions/ directories to reduce bundle size if you don't need historical transcripts.
  • Agent configs (agent.json) contain the agent's model assignment, channel bindings, and behavior settings.

After Migration

# Verify agents are recognized
openclaw gateway start
# Check logs for agent loading
openclaw gateway logs

Post-Migration Verification

Run through this checklist after migration:

Core

  • OpenClaw installed: openclaw --version
  • Gateway starts: openclaw gateway start
  • Gateway status: openclaw gateway status
  • Config loaded: check openclaw gateway logs for errors

Secrets

  • BWS accessible: bws secret list
  • API keys injected (gateway starts without auth errors)

Agents

  • Agents listed and responsive
  • Send a test message through each configured channel
  • Workspace files intact: ls ~/.openclaw/workspace/
  • Memory files present: ls ~/.openclaw/workspace/memory/

Tools

  • gh auth status — GitHub authenticated
  • gog auth status — Google authenticated (if used)
  • wacli status — WhatsApp connected (if used)
  • tailscale status — Connected to tailnet (if used)

Scheduled Tasks

  • openclaw cron list — All cron jobs present
  • Wait for a scheduled task to fire and verify it works

Search

  • QMD re-indexed: qmd collection list
  • Test a search: qmd search "test query"

Optional

  • Session history accessible (if copied)
  • Skills loaded: check agent logs
  • Canvas/browser features working

Quick Reference: Migration Commands

# OLD MACHINE
openclaw gateway stop
./openclaw-migrate.sh export

# TRANSFER
scp ~/openclaw-migration-bundle.tar.gz newmachine:~/

# NEW MACHINE
npm install -g openclaw@latest
./openclaw-migrate.sh import ~/openclaw-migration-bundle.tar.gz
# Then re-auth external tools (see sections above)
openclaw gateway start

Troubleshooting

Issue Fix
Gateway won't start Check openclaw gateway logs — usually a missing secret or port conflict
Agent not responding Verify agent config in ~/.openclaw/agents/<id>/agent.json
BWS errors Ensure BWS_ACCESS_TOKEN is set and valid
Missing skills Re-install from ClawHub: openclaw skill install <name>
QMD search empty Re-index: qmd index ~/.openclaw/workspace
Cron jobs not firing Check openclaw cron list and gateway logs

Last updated: 2026-02-12

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment