OpenClaw to Hermes Migration
This skill turns an OpenClaw installation into a verified Hermes Agent installation without losing identity, memory, skills, model settings, messaging access, or scheduled automation intent.
Use a conservative migration posture: freeze the source, dry-run first, migrate user data before secrets, validate each capability, then start Hermes gateway only after OpenClaw gateway is stopped.
Core Principles
- Treat migration as state transfer, not file copying. Preserve behavior: identity, memory, execution defaults, skills, messaging, model auth, and automation.
- Do not print secrets. Report secret presence as booleans or key names only.
- Keep OpenClaw available until Hermes passes acceptance checks.
- Do not run two gateways against the same bot/app/session token.
- Prefer
--preset user-datafirst. Migrate secrets only after the dry-run proves it will not duplicate or overwrite unrelated state. - Keep the original workspace path during cutover if memories, skills, or cron prompts reference it.
Inputs To Identify
Ask or infer:
- OpenClaw home, usually
~/.openclaw. - Hermes home, usually
~/.hermes. - Target workspace, often
~/.openclaw/workspaceduring initial cutover. - Required messaging platforms: Feishu/Lark, Weixin/WeChat, Telegram, Discord, etc.
- Desired model provider: z.ai/BigModel, OpenRouter, Gemini, Anthropic, custom OpenAI-compatible endpoint, or another supported provider.
- Whether secrets may be migrated or must be manually re-entered.
- Whether cron jobs should be recreated immediately, paused, or left archived.
Bundled Resources
- Read
references/migration-session-summary.mdonly when you need a concrete prior migration example, known Hermes/OpenClaw paths, Feishu/z.ai troubleshooting notes, or a record of commands that worked in one real migration. - Use
evals/evals.jsonwhen changing this skill to check that the SOP still covers safe migration, Feishu debugging, provider replacement, and cron generalization.
Phase 1: Freeze OpenClaw
Before migrating, stop active OpenClaw writers. Runtime files can otherwise change during checksum capture.
systemctl --user is-active openclaw-gateway.service || true
systemctl --user stop openclaw-gateway.service
lsof +D ~/.openclaw 2>/dev/null | head -80 || true
If OpenClaw is not systemd-managed, inspect processes:
ps -eo pid,ppid,etime,cmd | grep -Ei 'openclaw|weixin|wechat|feishu|hermes' | grep -v grep || true
Only stop confirmed OpenClaw runtime components. Do not kill generic node, python, or shell processes without proving they own OpenClaw files.
Capture a manifest:
mkdir -p /tmp/openclaw-migration
find ~/.openclaw -type f | sort > /tmp/openclaw-migration/source-files.txt
find ~/.openclaw -type f -print0 | sort -z | xargs -0 sha256sum > /tmp/openclaw-migration/source-sha256.txt
Capture a non-secret summary:
{
echo "date_utc=$(date -u +%Y-%m-%dT%H:%M:%SZ)"
echo "openclaw_size=$(du -sh ~/.openclaw | awk '{print $1}')"
echo "workspace_files=$(find ~/.openclaw/workspace -type f 2>/dev/null | wc -l)"
echo "main_sessions_glob=~/.openclaw/agents/main/sessions/*.jsonl"
echo "main_sessions=$(find ~/.openclaw/agents/main/sessions -type f -name '*.jsonl' 2>/dev/null | wc -l)"
echo "global_skills=$(find ~/.openclaw/skills -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l)"
echo "workspace_skills=$(find ~/.openclaw/workspace/skills -mindepth 1 -maxdepth 1 -type d 2>/dev/null | wc -l)"
echo "cron_jobs=$(jq '.jobs | length' ~/.openclaw/cron/jobs.json 2>/dev/null || echo 0)"
jq -c '{top_keys: keys, channels: (.channels // {} | keys), providers: (.models.providers // {} | keys), default_workspace: .agents.defaults.workspace}' ~/.openclaw/openclaw.json
} > /tmp/openclaw-migration/source-summary.txt
touch /tmp/openclaw-migration/source-summary.txt
find ~/.openclaw -type f -newer /tmp/openclaw-migration/source-summary.txt -print
Proceed only when the newer-file check is empty, or when the user explicitly accepts online migration risk.
Phase 2: Install Hermes
Install from the official script:
curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash
command -v hermes
hermes doctor
If the installer exits after creating Hermes because setup wizard cannot open /dev/tty, verify with command -v hermes and hermes doctor. A no-TTY wizard failure is not a blocker if the CLI, config, venv, and directories exist.
Phase 3: Dry-Run Migration
Run a safe preview:
hermes claw migrate \
--source ~/.openclaw \
--workspace-target ~/.openclaw/workspace \
--preset user-data \
--skill-conflict rename \
--overwrite \
--dry-run
Inspect:
Would migrate:soul,workspace-agents,memory,user-profile,model-config,agent-config, skills, custom providers.Skipped: messaging settings, raw config, sensitive runtime data, cron jobs, provider keys.Conflicts: should be resolved by--overwritefor template files and--skill-conflict renamefor duplicate skills.
If Hermes reports OpenClaw PIDs during dry-run, verify independently:
ps -fp <pid-list> || true
systemctl --user is-active openclaw-gateway.service || true
lsof +D ~/.openclaw 2>/dev/null | head -80 || true
Migration detector warnings can be transient if it matches command lines containing openclaw. Do not ignore the warning until service state and open files are checked.
Phase 4: Execute User-Data Migration
Execute only after dry-run is clean:
hermes claw migrate \
--source ~/.openclaw \
--workspace-target ~/.openclaw/workspace \
--preset user-data \
--skill-conflict rename \
--overwrite \
--yes
Validate:
test -s ~/.hermes/SOUL.md
test -s ~/.hermes/memories/MEMORY.md
test -s ~/.hermes/memories/USER.md
test -d ~/.hermes/skills/openclaw-imports
hermes skills list
hermes doctor
Review the migration report:
find ~/.hermes/migration/openclaw -maxdepth 3 -type f | sort | tail -80
sed -n '1,180p' ~/.hermes/migration/openclaw/<timestamp>/summary.md
Phase 5: Provider Migration
After user data is migrated, wire the desired provider. Avoid assuming the source has any particular provider, and avoid leaving obsolete provider entries that the user no longer wants.
General Provider Cleanup Pattern
Use this pattern when the user wants to replace one provider with another:
- Identify source providers and credentials without printing values.
- Confirm the target provider and model ID.
- Back up
~/.hermes/.envand~/.hermes/config.yaml. - Add the target provider key to
~/.hermes/.env. - Remove only provider env vars and
custom_providersentries that the user explicitly wants removed. - Update
model.default,model.provider,model.base_url, andmodel.api_keyto the target provider. - Validate with
hermes config check,hermes doctor, and a one-shothermes chatsmoke test.
Non-secret discovery commands:
jq '{default_model: .agents.defaults.model, provider_names: (.models.providers // {} | keys)}' ~/.openclaw/openclaw.json
python3 - <<'PY'
import json
from pathlib import Path
p = Path("~/.openclaw/agents/main/agent/auth-profiles.json").expanduser()
if p.exists():
data = json.loads(p.read_text())
print("auth_profiles=", sorted(data.get("profiles", {}).keys()))
PY
Generic OpenAI-Compatible Provider Template
Use this when the target provider exposes an OpenAI-compatible chat completions endpoint. Replace placeholder values and remove old providers only when explicitly requested:
TARGET_PROVIDER="provider-name"
TARGET_MODEL="provider-name/model-id"
TARGET_BASE_URL="https://provider.example.com/v1"
TARGET_API_KEY_ENV="PROVIDER_API_KEY"
export TARGET_PROVIDER TARGET_MODEL TARGET_BASE_URL TARGET_API_KEY_ENV
python3 - <<'PY'
import os
from pathlib import Path
import yaml
provider = os.environ["TARGE