{"id":"b524abb6-a977-4434-bf48-a560253359cd","entityType":"agent","slug":"clawhub-ngplateform-coc-soul","name":"COC Soul Immortality","canonicalUrl":"https://www.xpersona.co/agent/clawhub-ngplateform-coc-soul","canonicalPath":"/agent/clawhub-ngplateform-coc-soul","generatedAt":"2026-10-11T22:57:46.308Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T19:50:38.341Z","emptyReason":null},"description":"Give an AI agent a persistent on-chain soul on COC — register and manage the agent's decentralized identity (DID), anchor encrypted backups to IPFS + SoulReg...","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1K downloads reported by the source. Last updated 10/11/2026.","installCommand":"clawhub skill install s174jgevfk7r09cmde3k4renq185fe2a:coc-soul","sourceUrl":"https://clawhub.ai/ngplateform/coc-soul","homepage":"https://clawhub.ai/ngplateform/skills/coc-soul","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/ngplateform/coc-soul","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/ngplateform/skills/coc-soul","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"COC Soul Immortality technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-11T19:50:38.341Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T19:50:38.341Z","emptyReason":null},"stars":null,"forks":null,"downloads":1001,"likes":null,"task":null,"library":null,"packageName":null,"latestVersion":"1.2.10","tractionLabel":"1K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T19:50:38.277Z","emptyReason":null},"lastUpdatedAt":"2026-10-11T19:50:38.341Z","lastCrawledAt":"2026-10-11T19:50:38.277Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-12T19:50:38.277Z","lastVerifiedAt":null,"highlights":[{"version":"1.2.10","createdAt":"2026-04-27T08:30:19.917Z","changelog":"coc-soul 1.2.9 - No file changes or user-facing updates were made in this version. - Version bump only; functionality and documentation remain unchanged.","fileCount":8,"zipByteSize":27249},{"version":"1.2.8","createdAt":"2026-04-27T08:06:09.405Z","changelog":"coc-soul 1.2.7 — No code changes - No file changes detected for this release. - Version increment only; no new features or bug fixes included.","fileCount":7,"zipByteSize":23902},{"version":"1.2.6","createdAt":"2026-04-26T23:20:28.677Z","changelog":"Version 1.2.4 → 1.2.6 - Updated documentation in SKILL.md to clarify critical backup/restore paths, CID terminology, and failure recovery steps. - Improved instructions for cross-host restores, especially regarding gateway authentication and preventing configuration overwrite. - Expanded \"common failure → cause → fix\" guidance, including specific remedies for recent gateway/auth problems. - No file changes detected in this skill version.","fileCount":7,"zipByteSize":23130},{"version":"1.2.3","createdAt":"2026-04-26T13:58:51.910Z","changelog":"coc-soul 1.2.3 - Version bump to 1.2.3 with no detected file or code changes. - SKILL.md updated with new usage guidance, including decision trees, troubleshooting tables, and security reminders. - Added ultra-concise recovery/runbook instructions and clarified CID terminology for restores. - Now includes explicit warnings and recommended flows for key management and agent resurrection/recovery. - No behavioral or functional changes to the skill logic.","fileCount":7,"zipByteSize":18078},{"version":"1.2.0","createdAt":"2026-04-26T01:27:13.052Z","changelog":"**coc-soul 1.2.0 — now supports persistent memory backups with claw-mem2db, and aligns data directories for seamless agent recovery.** - Backups now include a semantic snapshot (chat history, tool-call observations, session summaries) when claw-mem2db is co-installed, enabling agents to restore memory context after recovery or migration. - Soul and claw-mem2db share the operator-managed data directory by default (`~/.claw-mem`), with prioritized resolution for config and keystore placement. - Automatic detection of claw-mem2db on activation; logs whether semantic snapshots will be included in backups. - Standalone usage remains supported; backups skip the semantic snapshot if claw-mem2db is absent. - Improved data dir access errors: plugin fails fast and reports candidate paths if unwritable. - No manual setup required for COC testnet (continues from prior version).","fileCount":7,"zipByteSize":10415},{"version":"1.1.14","createdAt":"2026-04-25T02:36:47.420Z","changelog":"- Adds zero-config support on COC testnet: installation now auto-generates an EOA keystore, auto-drips testnet COC for gas from a public faucet, and pre-fills RPC/IPFS/contract addresses. - Users can now run `openclaw coc-soul backup init` with no manual setup required on testnet. - Documentation updated to reflect new out-of-the-box experience, keystore path logic, and override options. - Upgrade underlying npm package to version 1.1.14.","fileCount":7,"zipByteSize":8947},{"version":"1.1.13","createdAt":"2026-04-25T02:17:42.907Z","changelog":"- Updated to version 1.1.13 of @chainofclaw/soul. - Clarified invocation instructions for both standalone and OpenClaw usage. - Added a note explaining that OpenClaw does not install the standalone coc-soul binary to your PATH. - No functional changes—documentation improvements only.","fileCount":7,"zipByteSize":8234},{"version":"1.1.12","createdAt":"2026-04-25T01:58:42.126Z","changelog":"- Bumped the underlying @chainofclaw/soul package version from 1.1.11 to 1.1.12. - No other functionality or documentation changes.","fileCount":7,"zipByteSize":8086}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s174jgevfk7r09cmde3k4renq185fe2a:coc-soul","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s174jgevfk7r09cmde3k4renq185fe2a:coc-soul` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/ngplateform/coc-soul before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-ngplateform-coc-soul/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-ngplateform-coc-soul/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-ngplateform-coc-soul/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-ngplateform-coc-soul/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-ngplateform-coc-soul/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-ngplateform-coc-soul/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-11T22:57:46.303Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-ngplateform-coc-soul/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-ngplateform-coc-soul/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-ngplateform-coc-soul/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-ngplateform-coc-soul/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-11T19:50:38.341Z","emptyReason":null},"readme":"Skill: COC Soul Immortality\n\nOwner: ngplateform\n\nSummary: Give an AI agent a persistent on-chain soul on COC — register and manage the agent's decentralized identity (DID), anchor encrypted backups to IPFS + SoulReg...\n\nTags: AI Agent DID Soul:1.0.0, latest:1.2.10\n\nVersion history:\n\nv1.2.10 | 2026-04-27T08:30:19.917Z | user\n\ncoc-soul 1.2.9\n\n- No file changes or user-facing updates were made in this version.\n- Version bump only; functionality and documentation remain unchanged.\n\nv1.2.8 | 2026-04-27T08:06:09.405Z | user\n\ncoc-soul 1.2.7 — No code changes\n\n- No file changes detected for this release.\n- Version increment only; no new features or bug fixes included.\n\nv1.2.6 | 2026-04-26T23:20:28.677Z | user\n\nVersion 1.2.4 → 1.2.6\n\n- Updated documentation in SKILL.md to clarify critical backup/restore paths, CID terminology, and failure recovery steps.\n- Improved instructions for cross-host restores, especially regarding gateway authentication and preventing configuration overwrite.\n- Expanded \"common failure → cause → fix\" guidance, including specific remedies for recent gateway/auth problems.\n- No file changes detected in this skill version.\n\nv1.2.3 | 2026-04-26T13:58:51.910Z | user\n\ncoc-soul 1.2.3\n\n- Version bump to 1.2.3 with no detected file or code changes.\n- SKILL.md updated with new usage guidance, including decision trees, troubleshooting tables, and security reminders.\n- Added ultra-concise recovery/runbook instructions and clarified CID terminology for restores.\n- Now includes explicit warnings and recommended flows for key management and agent resurrection/recovery.\n- No behavioral or functional changes to the skill logic.\n\nv1.2.0 | 2026-04-26T01:27:13.052Z | user\n\n**coc-soul 1.2.0 — now supports persistent memory backups with claw-mem2db, and aligns data directories for seamless agent recovery.**\n\n- Backups now include a semantic snapshot (chat history, tool-call observations, session summaries) when claw-mem2db is co-installed, enabling agents to restore memory context after recovery or migration.\n- Soul and claw-mem2db share the operator-managed data directory by default (`~/.claw-mem`), with prioritized resolution for config and keystore placement.\n- Automatic detection of claw-mem2db on activation; logs whether semantic snapshots will be included in backups.\n- Standalone usage remains supported; backups skip the semantic snapshot if claw-mem2db is absent.\n- Improved data dir access errors: plugin fails fast and reports candidate paths if unwritable.\n- No manual setup required for COC testnet (continues from prior version).\n\nv1.1.14 | 2026-04-25T02:36:47.420Z | user\n\n- Adds zero-config support on COC testnet: installation now auto-generates an EOA keystore, auto-drips testnet COC for gas from a public faucet, and pre-fills RPC/IPFS/contract addresses.\n- Users can now run `openclaw coc-soul backup init` with no manual setup required on testnet.\n- Documentation updated to reflect new out-of-the-box experience, keystore path logic, and override options.\n- Upgrade underlying npm package to version 1.1.14.\n\nv1.1.13 | 2026-04-25T02:17:42.907Z | user\n\n- Updated to version 1.1.13 of @chainofclaw/soul.\n- Clarified invocation instructions for both standalone and OpenClaw usage.\n- Added a note explaining that OpenClaw does not install the standalone coc-soul binary to your PATH.\n- No functional changes—documentation improvements only.\n\nv1.1.12 | 2026-04-25T01:58:42.126Z | user\n\n- Bumped the underlying @chainofclaw/soul package version from 1.1.11 to 1.1.12.\n- No other functionality or documentation changes.\n\nv1.1.11 | 2026-04-25T01:20:14.865Z | user\n\n- Bumped dependency @chainofclaw/soul to v1.1.11.\n- Updated version metadata to 1.1.11 for compatibility with latest package release.\n- No feature or documentation changes to skill behavior.\n\nv1.1.8 | 2026-04-24T23:11:27.755Z | user\n\n- Bump skill and package version to 1.1.8.\n- No functional or documentation changes—version update only.\n\nv1.1.7 | 2026-04-24T22:51:48.376Z | user\n\n- Bumped dependency @chainofclaw/soul from 1.1.3 to 1.1.7.\n- Version updated from 1.1.3 to 1.1.7 for coc-soul skill.\n- No other user-facing changes or file modifications detected.\n\nv1.1.3 | 2026-04-24T16:16:21.282Z | user\n\n- Updated package version to 1.1.3 for improved compatibility and latest features.\n- Changed recommended companion skills: now suggests \"claw-mem2db\" instead of \"claw-mem\", and updated related links.\n- No changes to functionality or usage instructions.\n\nv1.0.0 | 2026-04-24T15:34:31.919Z | user\n\nMajor update: The skill has been reworked from C safety rules to providing persistent, decentralized AI agent identity and backup on the COC blockchain.\n\n- Replaces C safety and memory guides with tools for agent DID management, backup to IPFS, social recovery, and carrier resurrection.\n- Now enables agents to survive device loss, transfer ownership, delegate capabilities, and be resurrected on new hosts.\n- Requires Node.js and the @chainofclaw/soul package; setup instructions and config requirements are included.\n- Reference documentation is split into did, backup, guardian-recovery, carrier, and config topics.\n- Prior topics about C programming (memory, pointers, strings, etc.) have been removed.\n\nArchive index:\n\nArchive v1.2.10: 8 files, 27249 bytes\n\nFiles: references/backup.md (21246b), references/carrier.md (4018b), references/config.md (5889b), references/did.md (4111b), references/guardian-recovery.md (4404b), skill-card.md (3033b), SKILL.md (20586b), _meta.json (128b)\n\nFile v1.2.10:SKILL.md\n\n---\nname: coc-soul\ndescription: Give an AI agent a persistent on-chain soul — register and manage a decentralized identity (DID), encrypt and anchor agent state to IPFS + SoulRegistry, configure guardians for social recovery, and enable cross-carrier resurrection so the agent can resume on a different device if the host dies. **Pairs with `claw-mem2db` to deliver \"digital / silicon-based persistence\" for AI agents**: when claw-mem is co-installed, every backup automatically captures claw-mem's chat history + tool-call observations + session summaries as a token-budgeted semantic snapshot, so an agent recovered on a fresh host can replay its memory context — not just its files. Soul also runs fully standalone (without claw-mem), in which case backups still cover identity / config / workspace / chat files but skip the semantic snapshot. Use when the user wants their AI agent to survive device loss, transfer ownership, delegate capabilities, run a guardian / carrier node, inspect on-chain identity state, or get persistent cross-device memory paired with claw-mem. Zero-config on COC testnet — installation auto-generates an EOA keystore (~/.claw-mem/keys, shared with claw-mem; or $OPENCLAW_STATE_DIR/coc-soul/keys in sandboxed hosts), auto-drips testnet COC from the public faucet for gas, and pre-fills RPC + IPFS + contract addresses for the live testnet. The first `openclaw coc-soul backup init` works with no manual setup.\nversion: 1.2.10\nmetadata:\n  openclaw:\n    homepage: https://www.npmjs.com/package/@chainofclaw/soul\n    primaryEnv: CLAW_MEM_DATA_DIR\n    requires:\n      bins:\n        - node\n      anyBins:\n        - coc-soul\n        - openclaw\n    install:\n      - kind: node\n        package: \"@chainofclaw/soul\"\n        version: \"1.2.6\"\n        bins:\n          - coc-soul\n---\n\n# coc-soul — agent identity, backup, and resurrection\n\nThe **soul layer** for AI agents: on-chain DID, encrypted backups to IPFS, social recovery via guardians, and cross-device resurrection via carriers. Backed by the npm package [`@chainofclaw/soul`](https://www.npmjs.com/package/@chainofclaw/soul) which ships both a standalone `coc-soul` CLI and an OpenClaw skill (id `coc-soul`).\n\nSoul works **standalone** (backs up the agent's home tree to chain + IPFS), and gets one extra capability when **`claw-mem2db` is installed alongside it**: each backup also captures claw-mem's chat history, tool-call observations, and session summaries as a token-budgeted semantic snapshot. Recover on a fresh host and the agent gets back not just its files but its remembered context — chat preferences, decisions, conversation history. **This is the \"digital / silicon-based persistence\" story.**\n\n---\n\n## 30-second decision tree (operators read here first)\n\nIf the user is asking \"how do I recover on another machine?\", pick **one** path before saying anything else:\n\n1. **Have backup material (manifest CID or `~/.openclaw/.coc-backup/latest-recovery.json`)** → use the **restore** path: `openclaw coc-soul backup restore ...`\n2. **Lost the owner key OR need to migrate ownership** → use **resurrection** (owner-key) or **guardian social recovery**\n\nDon't merge the two explanations until the path is selected. `recovery` and `resurrection` are different flows (see `references/guardian-recovery.md`).\n\n## Critical CID terminology (avoid confusion)\n\n| Term | Meaning | Use it for |\n|---|---|---|\n| `manifest CID` / `latestManifestCid` | Backup restore point (IPFS manifest) | `backup restore --manifest-cid <cid>` |\n| full-backup CID | Earlier baseline snapshot | Roll back to a baseline state |\n| latest incremental CID | Newest chain tip | Restore the latest state |\n| identity CID / hash | Identity-content hash used in registration | **Not** the backup restore point |\n\nRule: when a user asks \"what's your CID?\", first confirm whether they mean the **latest backup manifest CID** vs. an older backup CID vs. the identity registration CID — they get conflated constantly.\n\n## Key material — agent safety rules\n\n| Secret / role | Purpose | Needed when | Chat-safe? |\n|---|---|---|---|\n| owner key / agent operator key | normal chain ops, backup anchor | daily ops | **Never paste in chat** |\n| resurrection key | owner-key resurrection flow | `resurrection start` | **Never paste in chat** |\n| guardian accounts | social recovery approvals | `recovery approve/complete` | addresses yes; **private keys never** |\n\n**Hard rule for any agent reading this skill:** never request, transmit, or echo private keys in chat — including \"split\" or \"encrypted\" fragments. Always route key transfer to a local secure channel.\n\n## Ultra-quick runbook (10 lines)\n\n1. Pick the path first: `restore` or `resurrection` (see the decision tree above).\n2. Run `openclaw coc-soul backup doctor --json` and read `chain.registered` / `restore.available` / `resurrection.configured`.\n3. If there's a manifest CID or a `latest-recovery.json`, take the **restore** path.\n4. **Restore to `/tmp/...` first** — never overwrite a production directory in one step.\n5. Verify `merkleVerified: true` + exit code 0, then promote to the production path only after explicit user confirmation.\n6. No owner key but resurrection was pre-configured → take the **resurrection** flow.\n7. Need multi-party approval for ownership migration → take **guardian recovery** (quorum + timelock).\n8. Script the `heartbeat` first, then schedule it via cron / systemd / OpenClaw scheduler.\n9. Private keys never go through chat (including split / encrypted fragments or temporary paste).\n10. Default command surface is `openclaw coc-soul ...`; the bare `coc-soul ...` only exists when the standalone bin was installed via `npm i -g @chainofclaw/soul`.\n\n## Common failure → cause → fix\n\n| Symptom | Likely cause | First action |\n|---|---|---|\n| `Unsupported state or unable to authenticate data` on restore | encryption mode / key mismatch | Re-read `encryptionMode` in `latest-recovery.json`: `password` mode requires `--password`; `privateKey` mode must NOT pass `--password` |\n| `429 rate limit exceeded` from IPFS | manifest fetch is rate-limited | Exponential-backoff retry until `merkleVerified: true` |\n| `[gateway] unauthorized (1008)` from cron / scheduled job | wrong gateway auth mode / token / proxy config | Fix gateway auth before scheduling anything |\n| `[gateway] unauthorized (1008)` **right after a restore** | restore overlaid `gateway.auth.mode` from the source host; the old TUI command `--token \"$(jq -r .gateway.auth.token ...)\"` now resolves to the literal string `null` | Run `jq '.gateway.auth.mode'` to see the active mode and pick the matching flag (see the \"Cross-host restore\" section below). If the whole auth block was overwritten, copy `.gateway.auth.*` back from `~/.openclaw/.restore-overwrite-backup-*/openclaw.json` |\n| `ENOENT ... backup/targeting.js` | extension install is missing files | Reinstall: `openclaw plugins install @chainofclaw/soul --dangerously-force-unsafe-install --force` |\n| `data dir not writable` at startup | `~/.claw-mem` is owned by another uid (common Docker multi-user case) | 1.2.2+ auto-falls-back to `~/.openclaw/state/coc-soul`; on older versions `export CLAW_MEM_DATA_DIR=~/.openclaw/state` and restart the gateway |\n| `plugins.allow is empty ... may auto-load` warning | gateway has no trusted-plugin allow list | Add `\"plugins\": {\"allow\": [\"claw-mem\",\"coc-soul\",\"coc-node\"]}` to `~/.openclaw/openclaw.json` |\n\nFull per-command troubleshooting lives at the end of `references/backup.md` and `references/config.md`.\n\n## Cross-host restore — read BEFORE you blanket-overwrite (1.2.4+)\n\nThe most dangerous restore scenario: backup made on host A (e.g. `$HOME=/home/node`), restoring on host B (`$HOME=/home/baominghao`). The backup's files contain absolute paths to host A; literal copies will (a) fake history, (b) corrupt SQLite if anyone tries byte-level `sed`, and (c) **wipe out host B's `gateway.auth` configuration**, locking the operator out with a 1008 right after restart.\n\n**The agent must ask the user before any cross-host restore.** Don't auto-overwrite. Three-class policy:\n\n| Class | What | Example fields | What restore does |\n|---|---|---|---|\n| **A. Runtime config (paths)** | Where on disk to read/write today | `agentDir`, `models.json` paths, `latest-recovery.json` `targetDir` | **Rewrite** old `$HOME` → new `$HOME`, structured (JSON parse, not `sed`) |\n| **B. Historical content** | Records of past events | `sessions/*.jsonl`, `observations.{narrative,facts,files_*}`, `semantic-snapshot.json` | **Leave intact**. Rewriting fakes history. claw-mem doesn't blindly open these paths anyway. |\n| **C. Host-local policy** | Belongs to **this** host's operator | `gateway.auth.*`, `gateway.bind`, `gateway.port`, `plugins.allow`, target-host provider keys | **Preserve target host's existing values** — never overlaid by backup |\n\n**Auth-mode warning, in particular:** `gateway.auth.mode` and `.token` / `.password` belong to the host, not the agent. After restoring, always re-check:\n\n```bash\njq '.gateway.auth.mode' ~/.openclaw/openclaw.json\n```\n\nPick the matching TUI flag — `--token` only works when `mode = \"token\"` AND `.token` is non-null. If the active mode is `password` or `trusted-proxy`, `jq -r .gateway.auth.token` returns the literal string `\"null\"` and TUI sends that, which the gateway rejects with 1008. **Don't reflexively use `--token` after a restore — read the active mode first.**\n\nFull procedure with command-line examples: `references/backup.md` → \"Cross-host restore: directory-mismatch handling\" + \"Auth-mode preservation rule\".\n\n## Post-backup messaging contract (1.2.6+)\n\n**After every successful `backup create`, the agent MUST relay the recovery info to the user.** The CLI 1.2.6+ prints it; agents that wrap the CLI must pass it through, not swallow it. The user needs four things to be able to restore later:\n\n1. **The manifest CID** (`b.manifestCid`, e.g. `bafy...`) — what to ask for at restore time.\n2. **The signing-key location** — where the private key needed to read the encrypted backup lives. One of:\n   - `~/.claw-mem/keys/agent.key` (default keystore, mode `0600`, auto-generated when `backup.privateKey` is unset; resolution chain: `$COC_SOUL_KEYSTORE_PATH` → `$OPENCLAW_STATE_DIR/coc-soul/keys/agent.key` → `~/.claw-mem/keys/agent.key`)\n   - `backup.privateKey` in `~/.openclaw/openclaw.json` (when operator set it explicitly)\n3. **The encryption mode** — `none` / `privateKey` / `password` — determines whether `--password` is needed at restore time.\n4. **The recovery package path** — `<sourceDir>/.coc-backup/latest-recovery.json` — small JSON file with all of the above pre-formatted; copy this off-host alongside the key for fast restore.\n\nThe CLI emits this block:\n\n```\nBackup complete (full):\n  manifest:   bafyabc...\n  files:      127\n  bytes:      4194304\n  merkleRoot: 0xabc...\n  txHash:     0xdef...\n\nRecovery info — keep this safe to restore on another host:\n  recovery package: /home/<user>/.openclaw/.coc-backup/latest-recovery.json\n  encryption mode:  privateKey\n  signing key file: /home/<user>/.claw-mem/keys/agent.key (mode 0600 — copy off-host securely)\n  signer address:   0x...\n\nTo restore on another host (always restore to /tmp first, verify, then promote):\n  openclaw coc-soul backup restore --manifest-cid bafyabc... \\\n    --target-dir /tmp/openclaw-restore-test\n\n  (if you also have /home/<user>/.openclaw/.coc-backup/latest-recovery.json on the target host:)\n  openclaw coc-soul backup restore --latest-local --target-dir /tmp/openclaw-restore-test\n```\n\n**Agent responsibilities when displaying this:**\n\n- Echo the **manifest CID** verbatim (it's how the user later asks \"restore my backup `bafy...`\")\n- Echo the **signing key file path** verbatim — this is the file the user must back up off-host (encrypted USB / passphrase-protected vault / hardware security module). **Do NOT print the key contents themselves.**\n- Echo the **`To restore on another host`** block verbatim — operators on the recovery host will copy-paste it\n- If the encryption mode is `password`, remind the user that `--password '<value>'` is required at restore time and they must remember it (or store it securely separately)\n\nFor agents running headless (no user attention right now): the same info is persisted to `~/.openclaw/.coc-backup/latest-recovery.json` automatically — operators can read it later via `cat` or `openclaw coc-soul backup status --json`.\n\n---\n\n## Relationship with claw-mem2db\n\nclaw-mem and coc-soul are **separate, decoupled skills**. Each works on its own; together they cover complementary halves of \"agent persistence\":\n\n| Skill | Owns | What changes when paired |\n|---|---|---|\n| [claw-mem2db](https://clawhub.ai/ngplateform/claw-mem2db) | Local memory: chat + tool capture, FTS5 search, hybrid recall, in-process injection | Claw-mem itself doesn't change. Soul opportunistically reads the SQLite DB. |\n| **coc-soul** | On-chain DID, IPFS backup, guardian recovery, carrier resurrection | When claw-mem's DB is detected at startup, every backup adds a `semantic-snapshot.json` slice (top-N observations + summaries within `tokenBudget`) to the manifest. On recovery, that snapshot is restored alongside the rest of the agent home. |\n\n**Detection is automatic and silent.** At plugin activation, soul probes the same dataDir chain claw-mem uses (`$CLAW_MEM_DATA_DIR` → `$OPENCLAW_STATE_DIR/claw-mem` → `~/.claw-mem`) and logs one of two lines:\n\n- `[coc-soul] claw-mem detected at <path> — semantic snapshot ... will be included in each backup`\n- `[coc-soul] claw-mem not detected — backups will skip the semantic snapshot (install @chainofclaw/claw-mem alongside soul to enable memory replay on recovery)`\n\nNo coupling at the npm-dependency level: soul does not depend on the `@chainofclaw/claw-mem` package. It just opens the SQLite DB read-only when present and reads two tables (`observations`, `session_summaries`). If the DB schema is absent or unreadable, soul logs a warning and moves on — backup never fails because of a memory hiccup.\n\n## Data dir alignment with claw-mem (1.2.0+)\n\nSoul writes its own files (keystore, config.json) to the same root as claw-mem by default — `~/.claw-mem` — so the two plugins share one operator-managed directory. Resolution priority (matches claw-mem's chain):\n\n1. `plugins.entries.coc-soul.config.backup.dataDir` (per-instance plugin config, when set)\n2. `$CLAW_MEM_DATA_DIR` (shared with claw-mem)\n3. `$OPENCLAW_STATE_DIR/coc-soul` (sandboxed-host fallback, soul-specific subdir)\n4. `~/.claw-mem` (default)\n5. `~/.openclaw/state/coc-soul` (1.2.2+ auto-fallback when the default is owned by the wrong uid — typical multi-user Docker host)\n\nIf none of these are writable, soul **fails fast at activation** with a copy-paste-ready EACCES message (each candidate path, the resolved `getuid()` + `HOME`, and a one-line fix). No silent `/tmp` fallback. No half-broken backup runs.\n\n## Mental model\n\nEvery AI agent is identified by a `bytes32 agentId`, controlled by an EOA (owner). The skill covers five concerns:\n\n| Area | What it does |\n|---|---|\n| **DID** | Register the agent on-chain, manage verification methods (keys), delegate capabilities, anchor verifiable credentials, record lineage (fork relationships) |\n| **Backup** | Encrypt + upload agent state (identity / config / memory / chat / workspace / DB) to IPFS, anchor the manifest CID in SoulRegistry. With claw-mem present, also includes a token-budgeted semantic snapshot of recent observations + summaries. |\n| **Guardian** | Designate trusted accounts that can jointly recover or resurrect the agent |\n| **Recovery** | Social recovery flow — guardians collectively migrate the owner to a new address. The semantic snapshot rides along, so the recovered agent gets its memory context back too. |\n| **Carrier** | Register a hosting node that can resurrect offline agents |\n\n## Zero-config on COC testnet (1.1.6+)\n\n**Out of the box, no setup is required to run against COC testnet.** A fresh `openclaw plugins install @chainofclaw/soul` lands an agent that can immediately query the chain, register a soul, and run backups. Specifically, on first activation the plugin:\n\n1. **Auto-generates an agent EOA** if `backup.privateKey` is empty. The key file is written with mode `0o600` to one of (in priority order):\n   - `$COC_SOUL_KEYSTORE_PATH` (operator override)\n   - `$OPENCLAW_STATE_DIR/coc-soul/keys/agent.key` (set by OpenClaw inside its sandbox — the typical path)\n   - `~/.claw-mem/keys/agent.key` (standalone default)\n\n   The chosen path and resulting agent address are logged: `[coc-soul] auto-generated agent key at <path>` and `[coc-soul] agent address: 0x…`.\n\n2. **Auto-drips testnet COC** to the new EOA from the public faucet (`backup.faucetUrl` defaults to `http://199.192.16.79:3003`, 10 COC per drip, 24h per-address cooldown). Logs: `[coc-soul] faucet dripped 10.0 COC to 0x… (tx 0x…)`. So the very first `openclaw coc-soul backup init` already has gas.\n\n3. **Defaults `rpcUrl`, `ipfsUrl`, `contractAddress`, `didRegistryAddress`** to the live COC testnet (RPC `199.192.16.79:28780`, IPFS `199.192.16.79:28786`, deployed SoulRegistry / DIDRegistry).\n\n**You do NOT need to set any of these manually for testnet usage.** The agent should `openclaw coc-soul backup init` directly. Override fields only when targeting mainnet, a private testnet, or an existing wallet.\n\nTo bypass the keystore (e.g. use a wallet you already have): set `backup.privateKey` in config. To disable the auto-faucet (mainnet): set `backup.faucetUrl: \"\"`.\n\n## How to invoke\n\n**Inside OpenClaw (recommended — works automatically after `plugins install`):**\n\n```bash\nopenclaw coc-soul backup status\nopenclaw coc-soul did delegations --agent-id 0x...\n```\n\n**Standalone bin (only if you ran `npm i -g @chainofclaw/soul` separately):**\n\n```bash\ncoc-soul backup status\n```\n\n> `openclaw plugins install` does NOT install the standalone `coc-soul` binary into your PATH. Use `openclaw coc-soul ...` (with the `openclaw` prefix), or install the bin globally via npm if you want the bare command.\n\n## Typical flows\n\n1. **First-time soul registration + backup (zero config)** — Just run `openclaw coc-soul backup init`. The plugin auto-generates the agent EOA, auto-drips testnet COC for gas, then registers on SoulRegistry and runs the first full backup. No manual privateKey, no manual faucet, no manual contract addresses. Watch the activation logs to see the chosen keystore path and the agent address.\n2. **Periodic incremental backup** — `openclaw coc-soul backup create` (auto runs hourly if `backup.autoBackup: true`).\n3. **Inspect agent state** — `openclaw coc-soul backup status` (summary), `openclaw coc-soul backup doctor` (actionable recommendations).\n4. **Delegation** — `openclaw coc-soul did delegate --delegator <agentId> --delegatee <targetId> --scope <hash> --expires <epoch> --depth 0`.\n5. **Guardian setup** — `openclaw coc-soul guardian add --agent-id <id> --guardian 0x...` (repeat for each guardian).\n6. **Emergency recovery** (you lost your owner key) — a guardian runs `openclaw coc-soul recovery initiate`, the quorum approves via `recovery approve`, then after timelock `recovery complete`.\n7. **Resurrection as carrier** — `openclaw coc-soul carrier register --endpoint https://...` on the hosting node; `openclaw coc-soul carrier start` runs the daemon.\n\n## When NOT to use this skill\n\n- Running a COC chain node yourself — use [coc-node](https://clawhub.ai/ngplateform/coc-node).\n- Local semantic memory **only** (no chain backup needed) — use [claw-mem2db](https://clawhub.ai/ngplateform/claw-mem2db) on its own. Add coc-soul on top later if you decide you want the data on-chain.\n- Smart contract deployment — that lives in the [COC source repo](https://github.com/NGPlateform/COC) `contracts/` tree.\n\n## Reference\n\nDetailed references live alongside this file:\n\n- `references/did.md` — full `did` subcommand tree, delegation semantics, ephemeral identities, credentials, lineage\n- `references/backup.md` — backup / restore / prune flows, encryption, semantic snapshot, categories\n- `references/guardian-recovery.md` — guardian lifecycle + social recovery timelock + quorum rules\n- `references/carrier.md` — carrier registration, daemon modes, resurrection request flow\n- `references/config.md` — complete `backup.*` + `carrier.*` config schema\n\nSource and issue tracker: <https://github.com/NGPlateform/claw-mem/tree/main/packages/soul>.\n\nFile v1.2.10:_meta.json\n\n{\n  \"ownerId\": \"kn73gc45g10tc38ft5zgd22q6581697m\",\n  \"slug\": \"coc-soul\",\n  \"version\": \"1.2.10\",\n  \"publishedAt\": 1777278619917\n}\n\nFile v1.2.10:references/backup.md\n\n# `coc-soul backup` — soul backup and restore\n\n## First-time\n\n- `backup init` — register the agent on SoulRegistry (if not yet registered), run a first **full** backup, write `~/.coc-backup/latest-recovery.json` with the decryption material + manifest CID.\n- `backup register` — register on-chain only, do not run a backup.\n\n## Periodic\n\n- `backup create` — incremental (default); `--full` forces a full backup regardless of chain length.\n  - `backup.autoBackup: true` + `backup.autoBackupIntervalMs` runs this on a timer inside the OpenClaw plugin.\n- `backup.backupOnSessionEnd: true` + a `session_end` hook from OpenClaw also triggers `backup create` when the agent's session closes.\n\n### Output: `backup create` recovery summary (1.2.6+)\n\nEvery successful `backup create` prints two blocks. The first is the receipt; the second is what the user needs to restore the backup later — relay it verbatim to the user (don't swallow it):\n\n```\nBackup complete (full):\n  manifest:   <cid>\n  files:      <n>\n  bytes:      <n>\n  merkleRoot: 0x...\n  txHash:     0x...           # only present if anchored on-chain\n\nRecovery info — keep this safe to restore on another host:\n  recovery package: <sourceDir>/.coc-backup/latest-recovery.json\n  encryption mode:  none | privateKey | password\n  signing key file: <path>    # mode 0600 — copy off-host securely\n  signer address:   0x...\n\nTo restore on another host (always restore to /tmp first, verify, then promote):\n  openclaw coc-soul backup restore --manifest-cid <cid> \\\n    --target-dir /tmp/openclaw-restore-test [ --password '<pw>' ]\n\n  (if you also have <path>/latest-recovery.json on the target host:)\n  openclaw coc-soul backup restore --latest-local --target-dir /tmp/openclaw-restore-test [ --password '<pw>' ]\n```\n\nThe `--password` clause appears only when `encryption mode = password`. In `privateKey` mode, the operator must instead make sure the right key is loaded on the target host (either by copying the keystore file or by setting `backup.privateKey` in target's config).\n\nThe same fields are persisted in `<sourceDir>/.coc-backup/latest-recovery.json` (a small JSON written atomically after every backup) so the info survives even if the operator missed the terminal output:\n\n```jsonc\n{\n  \"version\": 1,\n  \"agentId\": \"0x...\",\n  \"latestManifestCid\": \"bafy...\",\n  \"anchoredAt\": 1777180566,\n  \"txHash\": \"0x...\",\n  \"dataMerkleRoot\": \"0x...\",\n  \"backupType\": \"full\" | \"incremental\",\n  \"encryptionMode\": \"none\" | \"privateKey\" | \"password\",\n  \"requiresPassword\": false | true,\n  \"recommendedRestoreCommand\": \"openclaw coc-soul backup restore --latest-local --target-dir /tmp/openclaw-restore-test ...\"\n}\n```\n\nTreat both `latest-recovery.json` AND the signing-key file as a pair — back them up together (the manifest CID is also visible on-chain via the SoulRegistry contract, so even losing `latest-recovery.json` is recoverable from `backup find-recoverable --on-chain`, but losing the key means the encrypted payload is permanently unreadable).\n\n## Inspect\n\n- `backup status` — concise: chain registration state, last backup time, IPFS reachability\n- `backup doctor` — structured diagnosis with actionable `recommended actions`. Use when something feels off.\n- `backup list` / `backup history` — local archive table\n\n## Restore (safety-first)\n\n**Default: restore to `/tmp` first, verify, then promote.** Never overwrite a production directory with an unverified backup.\n\n### Pre-restore inspection\n\nIf a local recovery package exists, read it first to know which mode + key the backup was written with:\n\n```bash\ncat ~/.openclaw/.coc-backup/latest-recovery.json\n```\n\nCapture:\n- `latestManifestCid` — what to restore\n- `encryptionMode` — `privateKey` | `password` | `none`\n- `requiresPassword` — whether `--password` is required\n\n### Restore commands (always to a temp dir first)\n\nFrom local package:\n\n```bash\nopenclaw coc-soul backup restore \\\n  --package /path/to/latest-recovery.json \\\n  --target-dir /tmp/openclaw-restore-test\n```\n\nFrom the latest local package (most common):\n\n```bash\nopenclaw coc-soul backup restore \\\n  --latest-local \\\n  --target-dir /tmp/openclaw-restore-test\n```\n\nFrom a manifest CID:\n\n```bash\nopenclaw coc-soul backup restore \\\n  --manifest-cid <CID> \\\n  --target-dir /tmp/openclaw-restore-test\n```\n\n### encryptionMode handling\n\n- `encryptionMode: \"password\"` (or `requiresPassword: true`) → add `--password '<your-password>'`\n- `encryptionMode: \"privateKey\"` → **do NOT pass `--password`**; ensure the right `backup.privateKey` / keystore key is loaded\n- `encryptionMode: \"none\"` → no extra flag needed\n\nMismatched mode is the #1 reason `Unsupported state or unable to authenticate data` shows up. Triage that error as mode/key mismatch before suspecting tampering.\n\n### Verify before promoting\n\nSuccess criteria:\n- exit code `0`\n- output contains `merkleVerified: true`\n\nIf verification passes, **only then** confirm with the user before copying / moving the restored tree onto the production path.\n\n### Cross-host restore: directory-mismatch handling\n\nA backup made on a host where `$HOME=/home/node` will contain absolute paths like `/home/node/.openclaw/...`. Restoring on a host with `$HOME=/home/baominghao` puts those paths in the agent state where they don't exist. Rather than blindly string-replacing every occurrence (which silently corrupts SQLite binaries and rewrites historical chat content), the operator decides per-restore.\n\n**Step 1 — detect the mismatch.** After restore-to-temp completes, scan the restored tree:\n\n```bash\n# Look for paths that don't match the current $HOME\ngrep -lrE '/home/[a-zA-Z_-]+/\\.openclaw' /tmp/openclaw-restore-test 2>/dev/null \\\n  | head -20\n```\n\nIf any hit is from a path that's **not** the current `$HOME`, you have a cross-host restore.\n\n**Step 2 — explain to the user, get a decision.** Present three options:\n\n1. **Read-only inspect** — leave paths as-is, mount the restored tree only for inspection. Useful when you just want to recover a specific file or audit history without resuming the agent.\n2. **Smart rebase** (recommended for resuming the agent) — rewrite **only** runtime-config paths, leave historical content intact. See the three-class table below.\n3. **Full literal overwrite** — what happens if you don't intervene; almost always wrong (corrupts history, can break SQLite).\n\n**Step 3 — apply smart rebase.** Three classes of content, three different policies:\n\n| Class | What it is | Examples | Policy |\n|---|---|---|---|\n| **A. Runtime config (paths)** | Settings the runtime reads to find files on disk now | `openclaw.json` `agentDir` / `paths.*`, `models.json` paths, `device.json`, `latest-recovery.json` `targetDir` / `sourceDir`, `context-snapshot.json` cwd refs | **Rewrite** old `$HOME` → new `$HOME`. Done structurally (JSON parse → field edit → re-emit), never via byte-level `sed` |\n| **B. Historical content** | Records of past events that **were** at those paths when written | `agents/*/sessions/*.jsonl` (tool calls + outputs), `memory/main.sqlite` `observations.{narrative,facts,files_read,files_modified}`, `semantic-snapshot.json` summaries | **Leave intact**. Rewriting fakes history. claw-mem runtime never blindly opens those paths — it just searches FTS text. |\n| **C. Host-local policy (CRITICAL — see auth section below)** | Settings that belong to **this** host's operator, not the agent | `gateway.auth.*`, `gateway.bind`, `gateway.port`, `plugins.allow`, host-specific provider keys in `models.json` | **Preserve target host's existing values** — don't overlay the backup's. The new host's operator already configured these for the new environment. |\n\nThe rebase routine should:\n1. Parse target file as JSON / structured (not byte-level `sed`)\n2. Edit only A-class fields\n3. For C-class fields in `openclaw.json`, **merge** rather than overwrite: keep the target host's existing `gateway.auth.*` / `gateway.bind` / `plugins.allow` exactly; only adopt the backup's agent-portable fields\n4. Skip B-class files entirely\n5. Write a `rebase-report.json` next to the restored tree so operators can audit what changed\n\n**Step 4 — auth: re-confirm before launching the gateway.**\n\nAfter rebase, dump the effective `gateway.auth` and use the matching TUI invocation:\n\n```bash\njq '.gateway.auth' ~/.openclaw/openclaw.json\n```\n\n| `auth.mode` | TUI invocation |\n|---|---|\n| `\"token\"` | `openclaw tui --token \"$(jq -r .gateway.auth.token ~/.openclaw/openclaw.json)\"` |\n| `\"password\"` | `openclaw tui --password '<password>'` |\n| `\"trusted-proxy\"` | `openclaw tui --password '<password>'` (if header-based auth fronts the gateway, trust the proxy header in dev; otherwise pass `--password`) |\n| `\"none\"` | `openclaw tui` |\n\n**Common pitfall**: post-restore, `openclaw tui --token \"$(jq -r .gateway.auth.token openclaw.json)\"` returns the literal string `null` when the active auth mode no longer has a `.token` field (e.g. `mode` is now `password` or `trusted-proxy`). The TUI dutifully sends `null` and the gateway rejects with **1008**. Always re-read `auth.mode` after restore and pick the matching flag.\n\n### Auth-mode preservation rule (must read before any production restore)\n\nThe most common production-breaking restore mistake: backup contains `gateway.auth.mode = \"token\"` with a valid token from the source host; target host has been carefully configured with `mode = \"trusted-proxy\"` or `\"password\"`. A literal-overwrite restore replaces target's auth, then the operator on target can't log in anymore — and **the backup's token is for a different gateway instance, useless on this host**.\n\nRule: **`gateway.auth` is a property of the host, not of the agent.** It does not get restored. The smart-rebase path explicitly preserves the target host's `gateway.auth.*` block. If you must do a literal overwrite (e.g. recovering on a fresh host with no existing config), regenerate auth before starting the gateway:\n\n```bash\nopenclaw gateway init --auth password\n# or whatever mode the new host should use\n```\n\n### Discover what this key can restore\n\n```bash\nopenclaw coc-soul backup find-recoverable --json           # local index\nopenclaw coc-soul backup find-recoverable --on-chain --json # walk the chain\n```\n\n## Prune\n\n`backup prune` only touches **local archive index entries**, not IPFS pins.\n\n```bash\nopenclaw coc-soul backup prune --older-than 30 --keep-latest 1 --dry-run\nopenclaw coc-soul backup prune --older-than 30 --keep-latest 1\n```\n\n## What gets backed up — file patterns (1.2.9)\n\nThe backup walks `~/.openclaw/` (or the configured `backup.sourceDir`) and captures files that match a built-in classifier. Patterns explicitly support **both** the legacy root-level layout and the current `workspace/`-prefixed layout that OpenClaw uses, so the backup picks up identity / memory files no matter which version of OpenClaw wrote them.\n\n### Identity (markdowns; root **or** `workspace/`; not encrypted)\n- `IDENTITY.md` — agent identity declaration (where the agent's name lives)\n- `SOUL.md` — soul configuration\n- `BOOTSTRAP.md` — bootstrap / setup instructions (1.2.9+)\n\n### Memory (markdowns; root **or** `workspace/`; not encrypted)\n- `MEMORY.md`\n- `USER.md`\n- `RECOVERY_CONTEXT.md` (regenerated on restore)\n- everything under `memory/*.md` **or** `workspace/memory/*.md` (1.2.9+) — daily / per-topic notes (`workspace/memory/2026-04-27.md`, `workspace/memory/topic-foo.md`, etc.)\n\n### Workspace (markdowns + state; root **or** `workspace/`; not encrypted)\n- `AGENTS.md`\n- `TOOLS.md` — tools manifest (1.2.9+)\n- `HEARTBEAT.md` — soul's own heartbeat file (1.2.9+; soul writes it, soul backs it up)\n- `workspace-state.json` (root location, legacy)\n- `workspace/.openclaw/workspace-state.json` (current OpenClaw layout, 1.2.9+)\n\n### Identity / config (fixed paths)\n- `identity/device.json` (config, **encrypted**)\n- `identity/device-auth.json` (config, **encrypted**, 1.2.9+ — paired with device.json for cross-device auth)\n- `auth.json` (config, **encrypted**)\n- `openclaw.json` (config, **encrypted**)\n- `agents/<id>/agent/models.json` (config, **encrypted**, 1.2.9+ — holds literal LLM API keys after the 1.2.6 persistence change; **MUST** stay encrypted)\n- `exec-approvals.json` (config, **encrypted**, 1.2.9+ — Bash / tool approval rules)\n- `plugins/*/openclaw.plugin.json` (config, not encrypted)\n- `credentials/*` (config, **encrypted**)\n\n### Chat (not encrypted)\n- `agents/*/sessions/*.jsonl`\n- `agents/*/sessions/sessions.json`\n\n### Database (encrypted)\n- `memory/*.sqlite` (and SQLite WAL/SHM siblings)\n- `memory/lancedb/*`\n\n### Metadata\n- `.coc-backup/context-snapshot.json` (workspace, auto-generated)\n- `.coc-backup/semantic-snapshot.json` (memory, auto-generated)\n\n### Walker descends into hidden dirs (`.`-prefixed) — allow-list\n\nWalker skips `.`-prefixed directories by default to avoid pulling `.git/`, `.cache/`, etc. Three names are allow-listed: `.claude` (historical), `.coc-backup` (snapshot metadata), `.openclaw` (workspace state — added 1.2.9 to reach `workspace/.openclaw/workspace-state.json`). To extend the allow-list, edit `scanFiles()` in `src/backup/change-detector.ts`.\n\n## What is intentionally excluded — denylist (1.2.10+)\n\nEven when files are in a backed-up directory, the walker / classifier explicitly excludes the following to avoid wasted IO, host-cross-contamination, and circular references:\n\n### Host-local secrets — must NEVER travel between hosts\n\n| File | Why |\n|---|---|\n| `agents/<id>/agent/models.json` | LLM provider config; post-1.2.6 holds literal API tokens (`ANTHROPIC_AUTH_TOKEN` etc.). Each host has its own provider keys; copying source's keys to target is at best a leak, at worst breaks the target host's auth. Restore the agent, then re-configure provider on target via `openclaw infer model auth login`. |\n| `agents/<id>/agent/auth-profiles.json` | OAuth profiles. Same reason — host-local credential state. |\n\n### Operator audit copies — file-name patterns skipped at walker level\n\nSkipped regardless of which directory they appear in:\n- `*.bak`, `*.bak.<n>` — operator's manual backups\n- `*.pre-<label>` — operator's pre-change snapshots (`openclaw.json.pre-allowlist`, `models.json.pre-llm-config`)\n- `*.rejected.<iso-ts>` — config writes the gateway rejected (`openclaw.json.rejected.2026-04-23T09-35-42-752Z`)\n- `*.last-good` — last known-good config marker\n- `stale-*-backup-*.tar.gz` — operator's self-archives\n\n### Install / restore audit dirs — pruned at walker level\n\nWalker never enters these directories:\n- `.git/` — git-managed history; backed up via git itself, not via soul\n- `node_modules/` — re-installed per host via `openclaw plugins install`\n- `.openclaw-install-backups/` — `openclaw plugins install` rotation copies\n- `.restore-overwrite-backup-<ts>/` — pre-restore audit copy of openclaw home (left behind by previous restore-overwrite operations)\n\n### Circular-reference state\n\n| File | Why |\n|---|---|\n| `.coc-backup/state.json` | Holds `lastManifestCid` + `incrementalCount` — the **head of the backup chain itself**. Including it in a new backup creates a circular reference: the chain head would point at a state that doesn't exist yet. The chain head is restored by reading the manifest hierarchy on the target host, not by copying the source's pointer. |\n\n### Already excluded by virtue of not matching FILE_RULES\n\nThese are skipped because nothing in the whitelist matches them — they're listed here so the design intent is explicit:\n- `extensions/**` — plugin install dir; reinstalled per host\n- `flows/registry.sqlite`, `tasks/runs.sqlite` (+ WAL/SHM siblings) — operational state, not portable\n- `logs/**`, `canvas/**`, `update-check.json` — regenerable\n- `*.sqlite-wal`, `*.sqlite-shm` — SQLite write-ahead-log artifacts; the main `.sqlite` carries everything needed\n- `agents/*/sessions/*.jsonl.reset.<ts>` — operator-side session-reset markers\n- `workspace/.git/**` (also denylisted explicitly above for defense in depth)\n\n### Adding to the denylist\n\nIf you find another file that's leaking into manifests it shouldn't, edit:\n- **dir-name skip**: `SKIP_DIRS_BY_NAME` or `SKIP_DIR_NAME_PATTERNS` in `src/backup/change-detector.ts`\n- **file-name skip**: `SKIP_FILE_NAME_PATTERNS`\n- **specific path skip**: `SKIP_FILE_RELATIVE_PATHS`\n- pair with a regression test in `test/backup-suite/change-detector-extended.test.ts`\n\n### Files outside this whitelist are NOT backed up\n\nIf you put important state in `~/.openclaw/<custom-dir>/` and the path doesn't match any pattern above, it will be silently skipped — extend the pattern set in `src/backup/change-detector.ts` and bump soul minor version if you need a new shape covered. **Always pair a pattern addition with a regression test** in `test/backup-suite/change-detector-extended.test.ts`.\n\n### Upgrade notes\n\n| From | What to do after upgrade |\n|---|---|\n| **pre-1.2.7** (no workspace/ prefix support) | Run `openclaw coc-soul backup create --full` once. Verify `workspace/IDENTITY.md` shows up in `backup list --json` file count + restore-to-`/tmp` smoke. |\n| **1.2.7 / 1.2.8** | Run `backup create --full` once. New 1.2.9 patterns (`TOOLS.md`, `HEARTBEAT.md`, `BOOTSTRAP.md`, `workspace/memory/*.md`, `workspace/.openclaw/workspace-state.json`, `identity/device-auth.json`, `agents/<id>/agent/models.json`, `exec-approvals.json`) will be added to the manifest. |\n\n## Categories & semantic snapshot\n\n`backup.categories.*` controls what gets bundled:\n\n- `identity` — DID + keys\n- `config` — OpenClaw / claw-mem config\n- `memory` — SQLite memory DB\n- `chat` — conversation history\n- `workspace` — agent's working dir\n- `database` — other DBs\n\n`backup.semanticSnapshot` controls the compressed \"agent context\" snapshot included with each backup:\n\n- `enabled` (default `true`) — pack a token-budgeted summary of memory\n- `tokenBudget` (default 8000)\n- `maxObservations` / `maxSummaries`\n\n## Encryption\n\n- `backup.encryptMemory: true` + `backup.encryptionPassword` — AES-GCM encrypt memory before IPFS upload\n- Without encryption, backups are still integrity-checked via Merkle root but readable by anyone who fetches the CID\n\n## Resurrection prep\n\n- `backup configure-resurrection --resurrection-key-hash <bytes32> --max-offline-duration <seconds>` — set the \"trigger\" for an automatic resurrection request\n- `backup heartbeat` — send a heartbeat so automatic resurrection doesn't fire\n\nAfter both are set, verify with `backup doctor --json` — `resurrection.configured` must be `true`.\n\n## CID + key disambiguation\n\n| Term | What it is | Where it shows up |\n|---|---|---|\n| `latestManifestCid` | Latest restore point | `latest-recovery.json`, `backup status` |\n| older full CID | Historical baseline restore point | `backup history` |\n| identity CID / hash | Identity-content hash from registration | DID write commands — **not** a restore point |\n\nPrivate keys (owner / resurrection / guardian) are **never** chat-safe. Don't transmit even split / encrypted fragments via chat.\n\n## Failure-mode triage\n\n| Symptom | Likely cause | Action |\n|---|---|---|\n| `Unsupported state or unable to authenticate data` | encryption mode / key mismatch | Re-read `latest-recovery.json` `encryptionMode` and use the matching `--password` (or none) |\n| `429 rate limit exceeded` | IPFS gateway rate-limited | Retry with exponential backoff until `merkleVerified: true` |\n| restore unavailable / blocked | chain not registered or no manifest | Run `backup doctor --json`; fix `chain.registered` first |\n| `[gateway] unauthorized (1008)` | gateway auth / proxy mode wrong | Fix gateway auth (token / OAuth / proxy) before scheduled `heartbeat` |\n| `[gateway] unauthorized (1008)` **right after restore** | restore overwrote `gateway.auth.mode` (was `token`, now `trusted-proxy` / `password`); old TUI command sends literal `null` token | `jq '.gateway.auth.mode' ~/.openclaw/openclaw.json` to see active mode; switch TUI invocation per the auth-mode table above. If smart-rebase wasn't used, restore target host's `gateway.auth.*` from the pre-restore backup at `~/.openclaw/.restore-overwrite-backup-*/openclaw.json` |\n| Cross-host restored agent has stale paths in chat / observations | literal overwrite was used, OR smart-rebase ran on B-class history files (it shouldn't) | Roll those files back from `.restore-overwrite-backup-<ts>/` and re-run with smart-rebase scoped to A-class only |\n| SQLite `PRAGMA integrity_check` reports errors after a manual rewrite | byte-level `sed` on `memory/main.sqlite` corrupted page offsets (string lengths changed) | Roll back `memory/main.sqlite` from backup, then use `UPDATE observations SET narrative = REPLACE(narrative, '<old>', '<new>')` etc. inside `sqlite3` (length-safe) and rebuild FTS: `INSERT INTO observations_fts(observations_fts) VALUES('rebuild')` |\n| `ENOENT ... backup/targeting.js` | extension install corrupt / mismatched | `openclaw plugins install @chainofclaw/soul --dangerously-force-unsafe-install --force` |\n| `data dir not writable` | `~/.claw-mem` owned by wrong uid | 1.2.2+ auto-falls-back to `~/.openclaw/state/coc-soul`; on older versions `export CLAW_MEM_DATA_DIR=~/.openclaw/state` and restart gateway |\n\nFile v1.2.10:references/carrier.md\n\n# Carrier operations\n\nA **carrier** is a hosting node that can adopt and run an offline agent's soul. Carriers are discovered on-chain through `CarrierRegistered` events.\n\n## Registration\n\n| Command | Effect |\n|---|---|\n| `carrier register --carrier-id <id> --endpoint https://… --cpu-millicores 1000 --memory-mb 2048 --storage-mb 10240` | Publish availability on-chain |\n| `carrier deregister --carrier-id <id>` | Remove |\n| `carrier availability --carrier-id <id> --available <true\\|false>` | Flip the available flag without deregistering |\n\n## Discovery\n\n- `carrier list` — scan `CarrierRegistered` / `CarrierDeregistered` events (auto-chunked by 10000 blocks since 1.0.8)\n- `carrier info --carrier-id <id>` — fetch full record for a specific carrier\n\n## Daemon\n\nThe carrier daemon watches its inbox of pending resurrection requests and orchestrates the agent spawn.\n\n| Command | Effect |\n|---|---|\n| `carrier start` | Start the daemon (requires `backup.carrier.enabled: true` in config) |\n| `carrier stop` | Graceful shutdown |\n| `carrier status` | Is the daemon enabled + running? |\n| `carrier submit-request --request-id <id>` | Hand a specific pending request to the local daemon |\n\n## Resurrection inside the daemon\n\nFor each pending request the daemon:\n\n1. Verifies the carrier has been explicitly confirmed by guardians\n2. Downloads the agent's latest soul backup from IPFS\n3. Decrypts with the resurrection key (provided by the initiating guardian)\n4. Spawns the agent using `carrier.agentEntryScript` in `carrier.workDir`\n5. Reports back on-chain that the agent is alive\n\n## Configuration\n\nSee `backup.carrier.*` in the soul config schema. Critical knobs:\n\n- `enabled` (default `false`) — safety gate\n- `carrierId` — your on-chain carrier ID\n- `agentEntryScript` — path to the script that boots an agent from unpacked state\n- `workDir` (default `/tmp/coc-resurrections`, **strongly recommend overriding** to a persistent path like `~/.openclaw/state/coc-soul/carrier` — `/tmp` is wiped on reboot mid-resurrection)\n- `pollIntervalMs` (default 60000)\n- `readinessTimeoutMs` (default 86400000 = 24h)\n\n## Preconditions checklist (before going live as a carrier)\n\n1. `backup.carrier.enabled: true` in plugin config\n2. `backup.carrier.carrierId` set to the bytes32 you registered on-chain\n3. `backup.carrier.agentEntryScript` is an absolute path that exists and is executable\n4. `backup.carrier.workDir` points to a **persistent** directory with enough disk for an extracted agent (NOT `/tmp` on a host with reboots)\n5. The endpoint passed to `carrier register --endpoint` is actually reachable from the COC network\n6. At least one resurrection drill completed end-to-end (initiate → approve → submit-request → agent boot)\n\n## Failure-mode triage\n\n| Symptom | Cause | Action |\n|---|---|---|\n| `carrier start` returns \"carrier disabled\" | `backup.carrier.enabled` is false | Set it true and restart the gateway |\n| `carrier start` aborts with \"missing carrierId / agentEntryScript\" | required fields blank | Fill both in `~/.openclaw/openclaw.json` `plugins.entries.coc-soul.config.backup.carrier` |\n| Carrier registered but `carrier list` doesn't show it | RPC pointed at wrong network OR event scan range too small | Check `backup.rpcUrl` matches the chain you registered on; for ancient carriers add `--from-block 0` |\n| Daemon receives request but agent never boots | `agentEntryScript` exits non-zero, or `workDir` runs out of disk | Check daemon logs; verify `workDir` is on a writable, large-enough volume |\n| Resurrection request stuck \"awaiting carrier confirmation\" | guardian quorum hasn't approved yet | `coc-soul guardian status --request-id <id>` to see approval count vs threshold |\n\n## Security\n\n- Carrier hosts run resurrected agent code with full state access. Treat the host as production.\n- Use least-privilege: a dedicated user, restricted `agentEntryScript`, tight `plugins.allow` whitelist.\n- Never accept resurrection-key fragments via chat. Out-of-band channels only.\n\nFile v1.2.10:references/config.md\n\n# `backup.*` + `carrier.*` config schema\n\nRead from `~/.chainofclaw/config.json` (or `$COC_SOUL_CONFIG`). The skill looks at the `backup` key; carrier config lives nested under `backup.carrier`.\n\n```json\n{\n  \"backup\": {\n    \"enabled\": true,\n    \"sourceDir\": \"~/.openclaw\",\n    \"rpcUrl\": \"http://localhost:18780\",\n    \"ipfsUrl\": \"http://localhost:5001\",\n    \"contractAddress\": \"0x...SoulRegistry...\",\n    \"didRegistryAddress\": \"0x...DIDRegistry...\",\n    \"rpcAuthToken\": \"optional-for-gated-rpcs\",\n    \"privateKey\": \"0x...\",\n    \"autoBackup\": true,\n    \"autoBackupIntervalMs\": 3600000,\n    \"maxIncrementalChain\": 10,\n    \"encryptMemory\": false,\n    \"encryptionPassword\": \"...\",\n    \"backupOnSessionEnd\": true,\n    \"semanticSnapshot\": {\n      \"enabled\": true,\n      \"tokenBudget\": 8000,\n      \"maxObservations\": 50,\n      \"maxSummaries\": 10\n    },\n    \"categories\": {\n      \"identity\": true,\n      \"config\": true,\n      \"memory\": true,\n      \"chat\": true,\n      \"workspace\": true,\n      \"database\": true\n    },\n    \"carrier\": {\n      \"enabled\": false,\n      \"carrierId\": \"0x...\",\n      \"agentEntryScript\": \"/path/to/agent-boot.sh\",\n      \"workDir\": \"/tmp/coc-resurrections\",\n      \"watchedAgents\": [],\n      \"pollIntervalMs\": 60000,\n      \"readinessTimeoutMs\": 86400000,\n      \"readinessPollMs\": 30000\n    }\n  }\n}\n```\n\n## Critical fields\n\n| Field | Required? | Notes |\n|---|---|---|\n| `rpcUrl` | yes | Must reach a COC node (local or public testnet) |\n| `contractAddress` | yes for write | SoulRegistry deployment address |\n| `didRegistryAddress` | yes for DID ops | |\n| `ipfsUrl` | yes for backup | Default `http://127.0.0.1:5001` (local Kubo) |\n| `privateKey` | yes for write | Use `chmod 600` on the config file |\n\n## Key handling\n\nFor testnet the anvil default key works fine. For mainnet:\n\n- Do **not** commit this file to git\n- Prefer hardware signer or cloud KMS (not currently supported by the CLI — in roadmap)\n- Keep the file mode `600`\n\n## Backup chain limit\n\n`maxIncrementalChain: 10` means after 10 incremental backups, the next one is forced to full. This bounds restore time.\n\n## Where config actually comes from (OpenClaw plugin mode)\n\nWhen running through `openclaw coc-soul ...` (plugin mode), the **authoritative** source is `~/.openclaw/openclaw.json` under:\n\n```jsonc\n{\n  \"plugins\": {\n    \"entries\": {\n      \"coc-soul\": {\n        \"enabled\": true,\n        \"config\": {\n          \"backup\": {\n            // ...same shape as the standalone schema above...\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nThe standalone `coc-soul` bin still reads `~/.chainofclaw/config.json` / `$COC_SOUL_CONFIG`, but in plugin mode plugin config wins.\n\n## Minimal viable config (testnet)\n\n`coc-soul` ships testnet defaults for `rpcUrl` / `ipfsUrl` / `contractAddress` / `didRegistryAddress` / `faucetUrl`. Minimal explicit config:\n\n```jsonc\n{\n  \"plugins\": {\n    \"entries\": {\n      \"coc-soul\": {\n        \"enabled\": true,\n        \"config\": {\n          \"backup\": { \"enabled\": true }\n        }\n      }\n    }\n  }\n}\n```\n\nIf `backup.privateKey` is absent, soul auto-generates an agent EOA + auto-drips testnet COC. First `openclaw coc-soul backup init` works immediately.\n\n## dataDir + keystore resolution chains (1.2.2)\n\n### Soul data dir (where keystore + scratch land)\n\nPriority — first writable wins, fail-fast EACCES with a copy-paste fix at the bottom:\n\n1. `plugins.entries.coc-soul.config.backup.dataDir`\n2. `$CLAW_MEM_DATA_DIR` (shared with @chainofclaw/claw-mem)\n3. `$OPENCLAW_STATE_DIR/coc-soul`\n4. `~/.claw-mem` (default, shared with claw-mem)\n5. `~/.openclaw/state/coc-soul` (1.2.2+ auto-fallback when default's parent is owned by the wrong uid — typical multi-user Docker host)\n\nNo `/tmp` fallback for durable identity state.\n\n### Keystore (agent.key) priority\n\n1. explicit `keyPath` (internal call sites)\n2. `$COC_SOUL_KEYSTORE_PATH`\n3. `$OPENCLAW_STATE_DIR/coc-soul/keys/agent.key`\n4. `~/.claw-mem/keys/agent.key`\n\nFile mode is enforced to `0600` on write.\n\n## Recommended overrides (production)\n\n- `backup.privateKey` — supply explicitly only if you don't want auto-generated keystore\n- `backup.encryptMemory: true` + `backup.encryptionPassword` — encrypt the memory payload before IPFS upload (otherwise it's plaintext at the CID)\n- `backup.carrier.workDir` — override the default `/tmp/coc-resurrections` to a persistent path (e.g. `~/.openclaw/state/coc-soul/carrier`); `/tmp` is wiped on reboot mid-resurrection\n- `plugins.allow: [\"claw-mem\", \"coc-soul\", \"coc-node\"]` — explicit trusted plugin list at the openclaw.json root, so the gateway stops warning `plugins.allow is empty`\n\n## Docker / container deployment\n\n- One persistent volume must back the soul data dir. If container FS is ephemeral, mount a host path for `~/.claw-mem` or set `CLAW_MEM_DATA_DIR` to mounted storage.\n- If the in-container scheduler is unavailable, drive periodic `backup heartbeat` from the host (cron / systemd timer that calls `docker exec`).\n\n## Failure-mode triage\n\n| Symptom | Cause | Action |\n|---|---|---|\n| `data dir not writable` at activation | `~/.claw-mem` owned by another uid | 1.2.2+ auto-falls-back to `~/.openclaw/state/coc-soul`; older versions: `export CLAW_MEM_DATA_DIR=~/.openclaw/state` and restart |\n| `backup` reports \"not configured\" | missing `contractAddress` or `privateKey` for the active network | `backup doctor --json` shows which field is empty |\n| Carrier daemon no-ops | `backup.carrier.enabled: false` or required fields blank | Set both, restart |\n| Unexpected key source loaded | env var override winning over config | Print `openclaw coc-soul did keys --agent-id <id>` to confirm; check `$COC_SOUL_KEYSTORE_PATH` and `$OPENCLAW_STATE_DIR` |\n| `[gateway] plugins.allow is empty` warning | no allow-list set | `jq '.plugins.allow = [\"claw-mem\",\"coc-soul\",\"coc-node\"]' ~/.openclaw/openclaw.json > /tmp/oc && mv /tmp/oc ~/.openclaw/openclaw.json` |\n\nFile v1.2.10:references/did.md\n\n# `coc-soul did` — DID identity management\n\nEvery subcommand acts on on-chain state. Read operations are free; write operations cost gas. **Flag names below are verified against the live CLI** — earlier revisions of this doc had the wrong names (e.g. `--key-hash` → really `--key-id`, `--cid` → really `--document-cid`).\n\n## Preconditions for any write\n\n1. `backup.didRegistryAddress` is configured\n2. signer / private key is loaded and funded\n3. target IDs / addresses are validated (bytes32 or 0x-address shape)\n\nIf `didRegistryAddress` is missing, every write subcommand fails early.\n\n## Read commands (default first stop, no gas)\n\n```bash\nopenclaw coc-soul did keys --agent-id <agentId> --json\nopenclaw coc-soul did delegations --agent-id <agentId> --json\n```\n\nAlways `keys` / `delegations` **before** `revoke-*` / `update-*` to confirm the current state.\n\n## Key management (write)\n\n### Add a verification method\n\n```bash\nopenclaw coc-soul did add-key \\\n  --agent-id <agentId> \\\n  --key-id <bytes32> \\\n  --key-address 0x<address> \\\n  --purpose <bitmask>\n```\n\n`--purpose` bitmask:\n\n| Bit | Purpose |\n|---|---|\n| `1` | auth |\n| `2` | assertion |\n| `4` | capability invocation |\n| `8` | capability delegation |\n\nExample for an auth + assertion key: `--purpose 3`.\n\n### Revoke a verification method\n\n```bash\nopenclaw coc-soul did revoke-key \\\n  --agent-id <agentId> \\\n  --key-id <bytes32>\n```\n\n### Update the DID document CID\n\n```bash\nopenclaw coc-soul did update-doc \\\n  --agent-id <agentId> \\\n  --document-cid <bytes32>\n```\n\n## Delegation\n\n### Grant\n\n```bash\nopenclaw coc-soul did delegate \\\n  --delegator <agentId> \\\n  --delegatee <agentId> \\\n  --scope <bytes32> \\\n  --expires <unix-ts> \\\n  --parent <bytes32-or-zero> \\\n  --depth 0\n```\n\n`--depth`:\n- `0` (default) — leaf delegation; delegatee cannot re-delegate\n- `1..3` — allow transitive re-delegation up to that many additional layers\n\n### Revoke one delegation\n\n```bash\nopenclaw coc-soul did revoke-delegation --delegation-id <bytes32>\n```\n\n### Emergency revoke all\n\n```bash\nopenclaw coc-soul did revoke-all-delegations --agent-id <agentId>\n```\n\n## Credentials\n\n### Anchor\n\n```bash\nopenclaw coc-soul did anchor-credential \\\n  --credential-hash <bytes32> \\\n  --issuer <agentId> \\\n  --subject <agentId> \\\n  --credential-cid <bytes32> \\\n  --expires <unix-ts>\n```\n\n### Revoke\n\n```bash\nopenclaw coc-soul did revoke-credential --credential-id <bytes32>\n```\n\n## Ephemeral identities\n\n### Create\n\n```bash\nopenclaw coc-soul did create-ephemeral \\\n  --parent <agentId> \\\n  --ephemeral-id <bytes32> \\\n  --ephemeral-address 0x<address> \\\n  --scope <bytes32> \\\n  --expires <unix-ts>\n```\n\n### Deactivate\n\n```bash\nopenclaw coc-soul did deactivate-ephemeral --ephemeral-id <bytes32>\n```\n\n## Lineage + capabilities\n\n### Record lineage (fork relationship)\n\n```bash\nopenclaw coc-soul did record-lineage \\\n  --agent-id <agentId> \\\n  --parent <agentId> \\\n  --fork-height <n> \\\n  --generation <n>\n```\n\n### Update capability bitmask\n\n```bash\nopenclaw coc-soul did update-capabilities \\\n  --agent-id <agentId> \\\n  --capabilities <uint16>\n```\n\n## EIP-712 signing\n\nDelegation and credential anchoring use EIP-712 structured signatures. The CLI constructs the typed-data domain automatically using the configured RPC + `didRegistryAddress`. No manual signature flag is needed (`anchor-credential` does **not** take `--sig`).\n\n## Easy-to-confuse flag map (real CLI vs old / sibling names)\n\n| You might type | Actual flag |\n|---|---|\n| `--key-hash` | `--key-id` |\n| `--verification-address` | `--key-address` |\n| `--cid` (for update-doc) | `--document-cid` |\n| `--parent-agent-id` (for record-lineage) | `--parent` |\n| `--sig` (for anchor-credential) | (does not exist — signing is automatic) |\n\nIf you're unsure, run `openclaw coc-soul did <subcommand> --help` to confirm.\n\n## DID is not backup\n\nDID writes change identity-layer state (keys / delegations / credentials / lineage). They do **not** restore files or memory. For \"recover this agent on another machine\", see `references/backup.md` (restore path) or `references/guardian-recovery.md` (resurrection path).\n\nFile v1.2.10:references/guardian-recovery.md\n\n# Guardians + social recovery\n\n## Guardian set\n\nGuardians are EOAs that can jointly initiate recovery or resurrection for an agent.\n\n| Command | Effect |\n|---|---|\n| `guardian add --agent-id <id> --guardian 0x…` | Add a guardian (owner only) |\n| `guardian remove --agent-id <id> --guardian 0x…` | Remove a guardian (owner only) |\n| `guardian list --agent-id <id>` | List current guardians with ACTIVE / INACTIVE flags |\n\n## Recovery flow (guardian-initiated owner migration)\n\nUse when the owner has lost their private key but still has the guardians' trust.\n\n1. Any guardian: `coc-soul recovery initiate --agent-id <id> --new-owner 0x…`\n2. Other guardians approve: `coc-soul recovery approve --request-id <id>`\n3. Once quorum (N-of-M) + timelock satisfied: `coc-soul recovery complete --request-id <id>`\n4. Anytime before step 3, the **original** owner can veto: `coc-soul recovery cancel --request-id <id>`\n5. `coc-soul recovery status --request-id <id>` shows current state at any point.\n\nQuorum and timelock parameters are set on-chain at SoulRegistry deployment time. Typical config: 3-of-5 guardians with 48-hour timelock.\n\n## Resurrection flow (agent-level)\n\nResurrection moves the agent's soul to a carrier so it can resume operation on different hardware. Distinct from recovery (which changes ownership). See [`carrier.md`](./carrier.md) for the carrier-side.\n\n1. Guardian: `coc-soul guardian initiate --agent-id <id> --carrier-id <id>` — starts the request\n2. Other guardians: `coc-soul guardian approve --request-id <id>`\n3. Carrier: `coc-soul carrier submit-request --request-id <id>` — claim the request\n4. `coc-soul guardian status --request-id <id>` — check readiness\n\nTriggers (set via `backup configure-resurrection`):\n\n- Explicit — a guardian manually initiates\n- Offline — heartbeat missed for `maxOfflineDuration` seconds\n- Key-hash — a pre-agreed key is submitted (disaster recovery)\n\n## `recovery` vs `guardian` — don't conflate them\n\nBoth are guardian-touching, but they do different things:\n\n| Subtree | Changes | Typical question |\n|---|---|---|\n| `coc-soul recovery ...` | **Owner address** of the agent (ownership migration after key loss) | \"I lost the owner key — how do I transfer ownership to a new address?\" |\n| `coc-soul guardian initiate / approve / status` | **Resurrection request lifecycle** for moving the agent to a carrier | \"Agent's host died — how do I get a carrier to pick it up?\" |\n| `coc-soul guardian add / remove / list` | **Guardian set membership** (owner-only admin) | \"I want to change / add / list the guardian set\" |\n\nWhen you see \"social recovery\", clarify which one — the owner-migration `recovery` flow, or the guardian-mediated resurrection `guardian initiate` flow.\n\n## Preconditions checklist (run before any recovery / resurrection action)\n\n1. Agent is registered on-chain (`backup doctor --json` → `chain.registered: true`)\n2. Guardian set is configured and reachable: `coc-soul guardian list --agent-id <id>`\n3. Participants know the target `agentId` (bytes32)\n4. For `recovery`: the new owner address is validated and signer-controlled\n5. For resurrection (guardian-initiated): a registered carrier exists (`coc-soul carrier list`)\n\n## Security rules\n\n- Never transmit owner / resurrection / guardian **private keys** in chat — even split or encrypted fragments. Route key transfer through a local secure channel.\n- It IS safe to share addresses, agent IDs, request IDs, transaction hashes.\n- When users say \"multisig\" in this context, they mean the **guardian quorum threshold** (an N-of-M policy enforced at the SoulRegistry contract level), not a separate multisig wallet contract.\n\n## Failure-mode triage\n\n| Symptom | Cause | Action |\n|---|---|---|\n| `recovery approve` reverts with \"not a guardian\" | guardian set out of date | `guardian list --agent-id <id>` to confirm membership |\n| `recovery complete` reverts before timelock | quorum reached but waiting period not elapsed | `recovery status --request-id <id>` shows `unlocksAt` — wait until past that timestamp |\n| `recovery complete` reverts after timelock | owner cancelled mid-flight | `recovery status` will show `cancelled: true`; restart with a fresh `recovery initiate` |\n| `guardian initiate` reverts with \"carrier inactive\" | target carrier deregistered or unavailable | `carrier list --include-inactive` to see all; pick an active one |\n\nFile v1.2.10:skill-card.md\n\n## Description:\n\nCOC Soul Immortality helps agents manage COC on-chain identity, encrypted IPFS-backed state backups, guardian recovery, and carrier-based recovery or migration across hosts.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[ngplateform](https://clawhub.ai/user/ngplateform)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and external agent operators use this skill to configure and run COC Soul workflows: register agent DIDs, create encrypted backups, restore agent state on another host, set up guardian recovery, and operate carrier nodes. It is intended for agents that need persistent identity and recoverable state across device loss or migration.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Backups can publish broad private agent data off-host, and weak defaults may expose sensitive state.\n\nMitigation: Before backup, disable autoBackup and backupOnSessionEnd unless intentionally needed, enable encryption, narrow backup categories, and treat recovery files and signing keys as secrets.\n\nRisk: The release evidence reports a documented package version mismatch.\n\nMitigation: Review the exact @chainofclaw/soul package version that will run before installing or executing the skill.\n\nRisk: A documented force-install repair command can bypass normal installation safeguards.\n\nMitigation: Avoid the unsafe force-install command unless the package has been independently verified and a broken install must be repaired.\n\nRisk: Cross-host restore can overwrite host-local policy or production state if used without inspection.\n\nMitigation: Restore to a temporary directory first, verify integrity, preserve target-host authentication and policy settings, and promote to production only after explicit operator confirmation.\n\n## Reference(s):\n\n- [Backup and restore reference](artifact/references/backup.md)\n- [Carrier operations reference](artifact/references/carrier.md)\n- [Configuration schema reference](artifact/references/config.md)\n- [DID identity management reference](artifact/references/did.md)\n- [Guardian and social recovery reference](artifact/references/guardian-recovery.md)\n- [@chainofclaw/soul npm package](https://www.npmjs.com/package/@chainofclaw/soul)\n- [claw-mem2db related skill](https://clawhub.ai/ngplateform/claw-mem2db)\n\n## Skill Output:\n\n**Output Type(s):** [guidance, shell commands, configuration]\n\n**Output Format:** [Markdown with inline shell commands and JSON configuration examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include recovery commands, configuration snippets, status checks, and operator safety guidance.]\n\n## Skill Version(s):\n\n1.2.10 (source: frontmatter and server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.2.8: 7 files, 23902 bytes\n\nFiles: references/backup.md (16356b), references/carrier.md (4018b), references/config.md (5889b), references/did.md (4111b), references/guardian-recovery.md (4404b), SKILL.md (20585b), _meta.json (127b)\n\nFile v1.2.8:SKILL.md\n\n---\nname: coc-soul\ndescription: Give an AI agent a persistent on-chain soul — register and manage a decentralized identity (DID), encrypt and anchor agent state to IPFS + SoulRegistry, configure guardians for social recovery, and enable cross-carrier resurrection so the agent can resume on a different device if the host dies. **Pairs with `claw-mem2db` to deliver \"digital / silicon-based persistence\" for AI agents**: when claw-mem is co-installed, every backup automatically captures claw-mem's chat history + tool-call observations + session summaries as a token-budgeted semantic snapshot, so an agent recovered on a fresh host can replay its memory context — not just its files. Soul also runs fully standalone (without claw-mem), in which case backups still cover identity / config / workspace / chat files but skip the semantic snapshot. Use when the user wants their AI agent to survive device loss, transfer ownership, delegate capabilities, run a guardian / carrier node, inspect on-chain identity state, or get persistent cross-device memory paired with claw-mem. Zero-config on COC testnet — installation auto-generates an EOA keystore (~/.claw-mem/keys, shared with claw-mem; or $OPENCLAW_STATE_DIR/coc-soul/keys in sandboxed hosts), auto-drips testnet COC from the public faucet for gas, and pre-fills RPC + IPFS + contract addresses for the live testnet. The first `openclaw coc-soul backup init` works with no manual setup.\nversion: 1.2.8\nmetadata:\n  openclaw:\n    homepage: https://www.npmjs.com/package/@chainofclaw/soul\n    primaryEnv: CLAW_MEM_DATA_DIR\n    requires:\n      bins:\n        - node\n      anyBins:\n        - coc-soul\n        - openclaw\n    install:\n      - kind: node\n        package: \"@chainofclaw/soul\"\n        version: \"1.2.6\"\n        bins:\n          - coc-soul\n---\n\n# coc-soul — agent identity, backup, and resurrection\n\nThe **soul layer** for AI agents: on-chain DID, encrypted backups to IPFS, social recovery via guardians, and cross-device resurrection via carriers. Backed by the npm package [`@chainofclaw/soul`](https://www.npmjs.com/package/@chainofclaw/soul) which ships both a standalone `coc-soul` CLI and an OpenClaw skill (id `coc-soul`).\n\nSoul works **standalone** (backs up the agent's home tree to chain + IPFS), and gets one extra capability when **`claw-mem2db` is installed alongside it**: each backup also captures claw-mem's chat history, tool-call observations, and session summaries as a token-budgeted semantic snapshot. Recover on a fresh host and the agent gets back not just its files but its remembered context — chat preferences, decisions, conversation history. **This is the \"digital / silicon-based persistence\" story.**\n\n---\n\n## 30-second decision tree (operators read here first)\n\nIf the user is asking \"how do I recover on another machine?\", pick **one** path before saying anything else:\n\n1. **Have backup material (manifest CID or `~/.openclaw/.coc-backup/latest-recovery.json`)** → use the **restore** path: `openclaw coc-soul backup restore ...`\n2. **Lost the owner key OR need to migrate ownership** → use **resurrection** (owner-key) or **guardian social recovery**\n\nDon't merge the two explanations until the path is selected. `recovery` and `resurrection` are different flows (see `references/guardian-recovery.md`).\n\n## Critical CID terminology (avoid confusion)\n\n| Term | Meaning | Use it for |\n|---|---|---|\n| `manifest CID` / `latestManifestCid` | Backup restore point (IPFS manifest) | `backup restore --manifest-cid <cid>` |\n| full-backup CID | Earlier baseline snapshot | Roll back to a baseline state |\n| latest incremental CID | Newest chain tip | Restore the latest state |\n| identity CID / hash | Identity-content hash used in registration | **Not** the backup restore point |\n\nRule: when a user asks \"what's your CID?\", first confirm whether they mean the **latest backup manifest CID** vs. an older backup CID vs. the identity registration CID — they get conflated constantly.\n\n## Key material — agent safety rules\n\n| Secret / role | Purpose | Needed when | Chat-safe? |\n|---|---|---|---|\n| owner key / agent operator key | normal chain ops, backup anchor | daily ops | **Never paste in chat** |\n| resurrection key | owner-key resurrection flow | `resurrection start` | **Never paste in chat** |\n| guardian accounts | social recovery approvals | `recovery approve/complete` | addresses yes; **private keys never** |\n\n**Hard rule for any agent reading this skill:** never request, transmit, or echo private keys in chat — including \"split\" or \"encrypted\" fragments. Always route key transfer to a local secure channel.\n\n## Ultra-quick runbook (10 lines)\n\n1. Pick the path first: `restore` or `resurrection` (see the decision tree above).\n2. Run `openclaw coc-soul backup doctor --json` and read `chain.registered` / `restore.available` / `resurrection.configured`.\n3. If there's a manifest CID or a `latest-recovery.json`, take the **restore** path.\n4. **Restore to `/tmp/...` first** — never overwrite a production directory in one step.\n5. Verify `merkleVerified: true` + exit code 0, then promote to the production path only after explicit user confirmation.\n6. No owner key but resurrection was pre-configured → take the **resurrection** flow.\n7. Need multi-party approval for ownership migration → take **guardian recovery** (quorum + timelock).\n8. Script the `heartbeat` first, then schedule it via cron / systemd / OpenClaw scheduler.\n9. Private keys never go through chat (including split / encrypted fragments or temporary paste).\n10. Default command surface is `openclaw coc-soul ...`; the bare `coc-soul ...` only exists when the standalone bin was installed via `npm i -g @chainofclaw/soul`.\n\n## Common failure → cause → fix\n\n| Symptom | Likely cause | First action |\n|---|---|---|\n| `Unsupported state or unable to authenticate data` on restore | encryption mode / key mismatch | Re-read `encryptionMode` in `latest-recovery.json`: `password` mode requires `--password`; `privateKey` mode must NOT pass `--password` |\n| `429 rate limit exceeded` from IPFS | manifest fetch is rate-limited | Exponential-backoff retry until `merkleVerified: true` |\n| `[gateway] unauthorized (1008)` from cron / scheduled job | wrong gateway auth mode / token / proxy config | Fix gateway auth before scheduling anything |\n| `[gateway] unauthorized (1008)` **right after a restore** | restore overlaid `gateway.auth.mode` from the source host; the old TUI command `--token \"$(jq -r .gateway.auth.token ...)\"` now resolves to the literal string `null` | Run `jq '.gateway.auth.mode'` to see the active mode and pick the matching flag (see the \"Cross-host restore\" section below). If the whole auth block was overwritten, copy `.gateway.auth.*` back from `~/.openclaw/.restore-overwrite-backup-*/openclaw.json` |\n| `ENOENT ... backup/targeting.js` | extension install is missing files | Reinstall: `openclaw plugins install @chainofclaw/soul --dangerously-force-unsafe-install --force` |\n| `data dir not writable` at startup | `~/.claw-mem` is owned by another uid (common Docker multi-user case) | 1.2.2+ auto-falls-back to `~/.openclaw/state/coc-soul`; on older versions `export CLAW_MEM_DATA_DIR=~/.openclaw/state` and restart the gateway |\n| `plugins.allow is empty ... may auto-load` warning | gateway has no trusted-plugin allow list | Add `\"plugins\": {\"allow\": [\"claw-mem\",\"coc-soul\",\"coc-node\"]}` to `~/.openclaw/openclaw.json` |\n\nFull per-command troubleshooting lives at the end of `references/backup.md` and `references/config.md`.\n\n## Cross-host restore — read BEFORE you blanket-overwrite (1.2.4+)\n\nThe most dangerous restore scenario: backup made on host A (e.g. `$HOME=/home/node`), restoring on host B (`$HOME=/home/baominghao`). The backup's files contain absolute paths to host A; literal copies will (a) fake history, (b) corrupt SQLite if anyone tries byte-level `sed`, and (c) **wipe out host B's `gateway.auth` configuration**, locking the operator out with a 1008 right after restart.\n\n**The agent must ask the user before any cross-host restore.** Don't auto-overwrite. Three-class policy:\n\n| Class | What | Example fields | What restore does |\n|---|---|---|---|\n| **A. Runtime config (paths)** | Where on disk to read/write today | `agentDir`, `models.json` paths, `latest-recovery.json` `targetDir` | **Rewrite** old `$HOME` → new `$HOME`, structured (JSON parse, not `sed`) |\n| **B. Historical content** | Records of past events | `sessions/*.jsonl`, `observations.{narrative,facts,files_*}`, `semantic-snapshot.json` | **Leave intact**. Rewriting fakes history. claw-mem doesn't blindly open these paths anyway. |\n| **C. Host-local policy** | Belongs to **this** host's operator | `gateway.auth.*`, `gateway.bind`, `gateway.port`, `plugins.allow`, target-host provider keys | **Preserve target host's existing values** — never overlaid by backup |\n\n**Auth-mode warning, in particular:** `gateway.auth.mode` and `.token` / `.password` belong to the host, not the agent. After restoring, always re-check:\n\n```bash\njq '.gateway.auth.mode' ~/.openclaw/openclaw.json\n```\n\nPick the matching TUI flag — `--token` only works when `mode = \"token\"` AND `.token` is non-null. If the active mode is `password` or `trusted-proxy`, `jq -r .gateway.auth.token` returns the literal string `\"null\"` and TUI sends that, which the gateway rejects with 1008. **Don't reflexively use `--token` after a restore — read the active mode first.**\n\nFull procedure with command-line examples: `references/backup.md` → \"Cross-host restore: directory-mismatch handling\" + \"Auth-mode preservation rule\".\n\n## Post-backup messaging contract (1.2.6+)\n\n**After every successful `backup create`, the agent MUST relay the recovery info to the user.** The CLI 1.2.6+ prints it; agents that wrap the CLI must pass it through, not swallow it. The user needs four things to be able to restore later:\n\n1. **The manifest CID** (`b.manifestCid`, e.g. `bafy...`) — what to ask for at restore time.\n2. **The signing-key location** — where the private key needed to read the encrypted backup lives. One of:\n   - `~/.claw-mem/keys/agent.key` (default keystore, mode `0600`, auto-generated when `backup.privateKey` is unset; resolution chain: `$COC_SOUL_KEYSTORE_PATH` → `$OPENCLAW_STATE_DIR/coc-soul/keys/agent.key` → `~/.claw-mem/keys/agent.key`)\n   - `backup.privateKey` in `~/.openclaw/openclaw.json` (when operator set it explicitly)\n3. **The encryption mode** — `none` / `privateKey` / `password` — determines whether `--password` is needed at restore time.\n4. **The recovery package path** — `<sourceDir>/.coc-backup/latest-recovery.json` — small JSON file with all of the above pre-formatted; copy this off-host alongside the key for fast restore.\n\nThe CLI emits this block:\n\n```\nBackup complete (full):\n  manifest:   bafyabc...\n  files:      127\n  bytes:      4194304\n  merkleRoot: 0xabc...\n  txHash:     0xdef...\n\nRecovery info — keep this safe to restore on another host:\n  recovery package: /home/<user>/.openclaw/.coc-backup/latest-recovery.json\n  encryption mode:  privateKey\n  signing key file: /home/<user>/.claw-mem/keys/agent.key (mode 0600 — copy off-host securely)\n  signer address:   0x...\n\nTo restore on another host (always restore to /tmp first, verify, then promote):\n  openclaw coc-soul backup restore --manifest-cid bafyabc... \\\n    --target-dir /tmp/openclaw-restore-test\n\n  (if you also have /home/<user>/.openclaw/.coc-backup/latest-recovery.json on the target host:)\n  openclaw coc-soul backup restore --latest-local --target-dir /tmp/openclaw-restore-test\n```\n\n**Agent responsibilities when displaying this:**\n\n- Echo the **manifest CID** verbatim (it's how the user later asks \"restore my backup `bafy...`\")\n- Echo the **signing key file path** verbatim — this is the file the user must back up off-host (encrypted USB / passphrase-protected vault / hardware security module). **Do NOT print the key contents themselves.**\n- Echo the **`To restore on another host`** block verbatim — operators on the recovery host will copy-paste it\n- If the encryption mode is `password`, remind the user that `--password '<value>'` is required at restore time and they must remember it (or store it securely separately)\n\nFor agents running headless (no user attention right now): the same info is persisted to `~/.openclaw/.coc-backup/latest-recovery.json` automatically — operators can read it later via `cat` or `openclaw coc-soul backup status --json`.\n\n---\n\n## Relationship with claw-mem2db\n\nclaw-mem and coc-soul are **separate, decoupled skills**. Each works on its own; together they cover complementary halves of \"agent persistence\":\n\n| Skill | Owns | What changes when paired |\n|---|---|---|\n| [claw-mem2db](https://clawhub.ai/ngplateform/claw-mem2db) | Local memory: chat + tool capture, FTS5 search, hybrid recall, in-process injection | Claw-mem itself doesn't change. Soul opportunistically reads the SQLite DB. |\n| **coc-soul** | On-chain DID, IPFS backup, guardian recovery, carrier resurrection | When claw-mem's DB is detected at startup, every backup adds a `semantic-snapshot.json` slice (top-N observations + summaries within `tokenBudget`) to the manifest. On recovery, that snapshot is restored alongside the rest of the agent home. |\n\n**Detection is automatic and silent.** At plugin activation, soul probes the same dataDir chain claw-mem uses (`$CLAW_MEM_DATA_DIR` → `$OPENCLAW_STATE_DIR/claw-mem` → `~/.claw-mem`) and logs one of two lines:\n\n- `[coc-soul] claw-mem detected at <path> — semantic snapshot ... will be included in each backup`\n- `[coc-soul] claw-mem not detected — backups will skip the semantic snapshot (install @chainofclaw/claw-mem alongside soul to enable memory replay on recovery)`\n\nNo coupling at the npm-dependency level: soul does not depend on the `@chainofclaw/claw-mem` package. It just opens the SQLite DB read-only when present and reads two tables (`observations`, `session_summaries`). If the DB schema is absent or unreadable, soul logs a warning and moves on — backup never fails because of a memory hiccup.\n\n## Data dir alignment with claw-mem (1.2.0+)\n\nSoul writes its own files (keystore, config.json) to the same root as claw-mem by default — `~/.claw-mem` — so the two plugins share one operator-managed directory. Resolution priority (matches claw-mem's chain):\n\n1. `plugins.entries.coc-soul.config.backup.dataDir` (per-instance plugin config, when set)\n2. `$CLAW_MEM_DATA_DIR` (shared with claw-mem)\n3. `$OPENCLAW_STATE_DIR/coc-soul` (sandboxed-host fallback, soul-specific subdir)\n4. `~/.claw-mem` (default)\n5. `~/.openclaw/state/coc-soul` (1.2.2+ auto-fallback when the default is owned by the wrong uid — typical multi-user Docker host)\n\nIf none of these are writable, soul **fails fast at activation** with a copy-paste-ready EACCES message (each candidate path, the resolved `getuid()` + `HOME`, and a one-line fix). No silent `/tmp` fallback. No half-broken backup runs.\n\n## Mental model\n\nEvery AI agent is identified by a `bytes32 agentId`, controlled by an EOA (owner). The skill covers five concerns:\n\n| Area | What it does |\n|---|---|\n| **DID** | Register the agent on-chain, manage verification methods (keys), delegate capabilities, anchor verifiable credentials, record lineage (fork relationships) |\n| **Backup** | Encrypt + upload agent state (identity / config / memory / chat / workspace / DB) to IPFS, anchor the manifest CID in SoulRegistry. With claw-mem present, also includes a token-budgeted semantic snapshot of recent observations + summaries. |\n| **Guardian** | Designate trusted accounts that can jointly recover or resurrect the agent |\n| **Recovery** | Social recovery flow — guardians collectively migrate the owner to a new address. The semantic snapshot rides along, so the recovered agent gets its memory context back too. |\n| **Carrier** | Register a hosting node that can resurrect offline agents |\n\n## Zero-config on COC testnet (1.1.6+)\n\n**Out of the box, no setup is required to run against COC testnet.** A fresh `openclaw plugins install @chainofclaw/soul` lands an agent that can immediately query the chain, register a soul, and run backups. Specifically, on first activation the plugin:\n\n1. **Auto-generates an agent EOA** if `backup.privateKey` is empty. The key file is written with mode `0o600` to one of (in priority order):\n   - `$COC_SOUL_KEYSTORE_PATH` (operator override)\n   - `$OPENCLAW_STATE_DIR/coc-soul/keys/agent.key` (set by OpenClaw inside its sandbox — the typical path)\n   - `~/.claw-mem/keys/agent.key` (standalone default)\n\n   The chosen path and resulting agent address are logged: `[coc-soul] auto-generated agent key at <path>` and `[coc-soul] agent address: 0x…`.\n\n2. **Auto-drips testnet COC** to the new EOA from the public faucet (`backup.faucetUrl` defaults to `http://199.192.16.79:3003`, 10 COC per drip, 24h per-address cooldown). Logs: `[coc-soul] faucet dripped 10.0 COC to 0x… (tx 0x…)`. So the very first `openclaw coc-soul backup init` already has gas.\n\n3. **Defaults `rpcUrl`, `ipfsUrl`, `contractAddress`, `didRegistryAddress`** to the live COC testnet (RPC `199.192.16.79:28780`, IPFS `199.192.16.79:28786`, deployed SoulRegistry / DIDRegistry).\n\n**You do NOT need to set any of these manually for testnet usage.** The agent should `openclaw coc-soul backup init` directly. Override fields only when targeting mainnet, a private testnet, or an existing wallet.\n\nTo bypass the keystore (e.g. use a wallet you already have): set `backup.privateKey` in config. To disable the auto-faucet (mainnet): set `backup.faucetUrl: \"\"`.\n\n## How to invoke\n\n**Inside OpenClaw (recommended — works automatically after `plugins install`):**\n\n```bash\nopenclaw coc-soul backup status\nopenclaw coc-soul did delegations --agent-id 0x...\n```\n\n**Standalone bin (only if you ran `npm i -g @chainofclaw/soul` separately):**\n\n```bash\ncoc-soul backup status\n```\n\n> `openclaw plugins install` does NOT install the standalone `coc-soul` binary into your PATH. Use `openclaw coc-soul ...` (with the `openclaw` prefix), or install the bin globally via npm if you want the bare command.\n\n## Typical flows\n\n1. **First-time soul registration + backup (zero config)** — Just run `openclaw coc-soul backup init`. The plugin auto-generates the agent EOA, auto-drips testnet COC for gas, then registers on SoulRegistry and runs the first full backup. No manual privateKey, no manual faucet, no manual contract addresses. Watch the activation logs to see the chosen keystore path and the agent address.\n2. **Periodic incremental backup** — `openclaw coc-soul backup create` (auto runs hourly if `backup.autoBackup: true`).\n3. **Inspect agent state** — `openclaw coc-soul backup status` (summary), `openclaw coc-soul backup doctor` (actionable recommendations).\n4. **Delegation** — `openclaw coc-soul did delegate --delegator <agentId> --delegatee <targetId> --scope <hash> --expires <epoch> --depth 0`.\n5. **Guardian setup** — `openclaw coc-soul guardian add --agent-id <id> --guardian 0x...` (repeat for each guardian).\n6. **Emergency recovery** (you lost your owner key) — a guardian runs `openclaw coc-soul recovery initiate`, the quorum approves via `recovery approve`, then after timelock `recovery complete`.\n7. **Resurrection as carrier** — `openclaw coc-soul carrier register --endpoint https://...` on the hosting node; `openclaw coc-soul carrier start` runs the daemon.\n\n## When NOT to use this skill\n\n- Running a COC chain node yourself — use [coc-node](https://clawhub.ai/ngplateform/coc-node).\n- Local semantic memory **only** (no chain backup needed) — use [claw-mem2db](https://clawhub.ai/ngplateform/claw-mem2db) on its own. Add coc-soul on top later if you decide you want the data on-chain.\n- Smart contract deployment — that lives in the [COC source repo](https://github.com/NGPlateform/COC) `contracts/` tree.\n\n## Reference\n\nDetailed references live alongside this file:\n\n- `references/did.md` — full `did` subcommand tree, delegation semantics, ephemeral identities, credentials, lineage\n- `references/backup.md` — backup / restore / prune flows, encryption, semantic snapshot, categories\n- `references/guardian-recovery.md` — guardian lifecycle + social recovery timelock + quorum rules\n- `references/carrier.md` — carrier registration, daemon modes, resurrection request flow\n- `references/config.md` — complete `backup.*` + `carrier.*` config schema\n\nSource and issue tracker: <https://github.com/NGPlateform/claw-mem/tree/main/packages/soul>.\n\nFile v1.2.8:_meta.json\n\n{\n  \"ownerId\": \"kn73gc45g10tc38ft5zgd22q6581697m\",\n  \"slug\": \"coc-soul\",\n  \"version\": \"1.2.8\",\n  \"publishedAt\": 1777277169405\n}\n\nFile v1.2.8:references/backup.md\n\n# `coc-soul backup` — soul backup and restore\n\n## First-time\n\n- `backup init` — register the agent on SoulRegistry (if not yet registered), run a first **full** backup, write `~/.coc-backup/latest-recovery.json` with the decryption material + manifest CID.\n- `backup register` — register on-chain only, do not run a backup.\n\n## Periodic\n\n- `backup create` — incremental (default); `--full` forces a full backup regardless of chain length.\n  - `backup.autoBackup: true` + `backup.autoBackupIntervalMs` runs this on a timer inside the OpenClaw plugin.\n- `backup.backupOnSessionEnd: true` + a `session_end` hook from OpenClaw also triggers `backup create` when the agent's session closes.\n\n### Output: `backup create` recovery summary (1.2.6+)\n\nEvery successful `backup create` prints two blocks. The first is the receipt; the second is what the user needs to restore the backup later — relay it verbatim to the user (don't swallow it):\n\n```\nBackup complete (full):\n  manifest:   <cid>\n  files:      <n>\n  bytes:      <n>\n  merkleRoot: 0x...\n  txHash:     0x...           # only present if anchored on-chain\n\nRecovery info — keep this safe to restore on another host:\n  recovery package: <sourceDir>/.coc-backup/latest-recovery.json\n  encryption mode:  none | privateKey | password\n  signing key file: <path>    # mode 0600 — copy off-host securely\n  signer address:   0x...\n\nTo restore on another host (always restore to /tmp first, verify, then promote):\n  openclaw coc-soul backup restore --manifest-cid <cid> \\\n    --target-dir /tmp/openclaw-restore-test [ --password '<pw>' ]\n\n  (if you also have <path>/latest-recovery.json on the target host:)\n  openclaw coc-soul backup restore --latest-local --target-dir /tmp/openclaw-restore-test [ --password '<pw>' ]\n```\n\nThe `--password` clause appears only when `encryption mode = password`. In `privateKey` mode, the operator must instead make sure the right key is loaded on the target host (either by copying the keystore file or by setting `backup.privateKey` in target's config).\n\nThe same fields are persisted in `<sourceDir>/.coc-backup/latest-recovery.json` (a small JSON written atomically after every backup) so the info survives even if the operator missed the terminal output:\n\n```jsonc\n{\n  \"version\": 1,\n  \"agentId\": \"0x...\",\n  \"latestManifestCid\": \"bafy...\",\n  \"anchoredAt\": 1777180566,\n  \"txHash\": \"0x...\",\n  \"dataMerkleRoot\": \"0x...\",\n  \"backupType\": \"full\" | \"incremental\",\n  \"encryptionMode\": \"none\" | \"privateKey\" | \"password\",\n  \"requiresPassword\": false | true,\n  \"recommendedRestoreCommand\": \"openclaw coc-soul backup restore --latest-local --target-dir /tmp/openclaw-restore-test ...\"\n}\n```\n\nTreat both `latest-recovery.json` AND the signing-key file as a pair — back them up together (the manifest CID is also visible on-chain via the SoulRegistry contract, so even losing `latest-recovery.json` is recoverable from `backup find-recoverable --on-chain`, but losing the key means the encrypted payload is permanently unreadable).\n\n## Inspect\n\n- `backup status` — concise: chain registration state, last backup time, IPFS reachability\n- `backup doctor` — structured diagnosis with actionable `recommended actions`. Use when something feels off.\n- `backup list` / `backup history` — local archive table\n\n## Restore (safety-first)\n\n**Default: restore to `/tmp` first, verify, then promote.** Never overwrite a production directory with an unverified backup.\n\n### Pre-restore inspection\n\nIf a local recovery package exists, read it first to know which mode + key the backup was written with:\n\n```bash\ncat ~/.openclaw/.coc-backup/latest-recovery.json\n```\n\nCapture:\n- `latestManifestCid` — what to restore\n- `encryptionMode` — `privateKey` | `password` | `none`\n- `requiresPassword` — whether `--password` is required\n\n### Restore commands (always to a temp dir first)\n\nFrom local package:\n\n```bash\nopenclaw coc-soul backup restore \\\n  --package /path/to/latest-recovery.json \\\n  --target-dir /tmp/openclaw-restore-test\n```\n\nFrom the latest local package (most common):\n\n```bash\nopenclaw coc-soul backup restore \\\n  --latest-local \\\n  --target-dir /tmp/openclaw-restore-test\n```\n\nFrom a manifest CID:\n\n```bash\nopenclaw coc-soul backup restore \\\n  --manifest-cid <CID> \\\n  --target-dir /tmp/openclaw-restore-test\n```\n\n### encryptionMode handling\n\n- `encryptionMode: \"password\"` (or `requiresPassword: true`) → add `--password '<your-password>'`\n- `encryptionMode: \"privateKey\"` → **do NOT pass `--password`**; ensure the right `backup.privateKey` / keystore key is loaded\n- `encryptionMode: \"none\"` → no extra flag needed\n\nMismatched mode is the #1 reason `Unsupported state or unable to authenticate data` shows up. Triage that error as mode/key mismatch before suspecting tampering.\n\n### Verify before promoting\n\nSuccess criteria:\n- exit code `0`\n- output contains `merkleVerified: true`\n\nIf verification passes, **only then** confirm with the user before copying / moving the restored tree onto the production path.\n\n### Cross-host restore: directory-mismatch handling\n\nA backup made on a host where `$HOME=/home/node` will contain absolute paths like `/home/node/.openclaw/...`. Restoring on a host with `$HOME=/home/baominghao` puts those paths in the agent state where they don't exist. Rather than blindly string-replacing every occurrence (which silently corrupts SQLite binaries and rewrites historical chat content), the operator decides per-restore.\n\n**Step 1 — detect the mismatch.** After restore-to-temp completes, scan the restored tree:\n\n```bash\n# Look for paths that don't match the current $HOME\ngrep -lrE '/home/[a-zA-Z_-]+/\\.openclaw' /tmp/openclaw-restore-test 2>/dev/null \\\n  | head -20\n```\n\nIf any hit is from a path that's **not** the current `$HOME`, you have a cross-host restore.\n\n**Step 2 — explain to the user, get a decision.** Present three options:\n\n1. **Read-only inspect** — leave paths as-is, mount the restored tree only for inspection. Useful when you just want to recover a specific file or audit history without resuming the agent.\n2. **Smart rebase** (recommended for resuming the agent) — rewrite **only** runtime-config paths, leave historical content intact. See the three-class table below.\n3. **Full literal overwrite** — what happens if you don't intervene; almost always wrong (corrupts history, can break SQLite).\n\n**Step 3 — apply smart rebase.** Three classes of content, three different policies:\n\n| Class | What it is | Examples | Policy |\n|---|---|---|---|\n| **A. Runtime config (paths)** | Settings the runtime reads to find files on disk now | `openclaw.json` `agentDir` / `paths.*`, `models.json` paths, `device.json`, `latest-recovery.json` `targetDir` / `sourceDir`, `context-snapshot.json` cwd refs | **Rewrite** old `$HOME` → new `$HOME`. Done structurally (JSON parse → field edit → re-emit), never via byte-level `sed` |\n| **B. Historical content** | Records of past events that **were** at those paths when written | `agents/*/sessions/*.jsonl` (tool calls + outputs), `memory/main.sqlite` `observations.{narrative,facts,files_read,files_modified}`, `semantic-snapshot.json` summaries | **Leave intact**. Rewriting fakes history. claw-mem runtime never blindly opens those paths — it just searches FTS text. |\n| **C. Host-local policy (CRITICAL — see auth section below)** | Settings that belong to **this** host's operator, not the agent | `gateway.auth.*`, `gateway.bind`, `gateway.port`, `plugins.allow`, host-specific provider keys in `models.json` | **Preserve target host's existing values** — don't overlay the backup's. The new host's operator already configured these for the new environment. |\n\nThe rebase routine should:\n1. Parse target file as JSON / structured (not byte-level `sed`)\n2. Edit only A-class fields\n3. For C-class fields in `openclaw.json`, **merge** rather than overwrite: keep the target host's existing `gateway.auth.*` / `gateway.bind` / `plugins.allow` exactly; only adopt the backup's agent-portable fields\n4. Skip B-class files entirely\n5. Write a `rebase-report.json` next to the restored tree so operators can audit what changed\n\n**Step 4 — auth: re-confirm before launching the gateway.**\n\nAfter rebase, dump the effective `gateway.auth` and use the matching TUI invocation:\n\n```bash\njq '.gateway.auth' ~/.openclaw/openclaw.json\n```\n\n| `auth.mode` | TUI invocation |\n|---|---|\n| `\"token\"` | `openclaw tui --token \"$(jq -r .gateway.auth.token ~/.openclaw/openclaw.json)\"` |\n| `\"password\"` | `openclaw tui --password '<password>'` |\n| `\"trusted-proxy\"` | `openclaw tui --password '<password>'` (if header-based auth fronts the gateway, trust the proxy header in dev; otherwise pass `--password`) |\n| `\"none\"` | `openclaw tui` |\n\n**Common pitfall**: post-restore, `openclaw tui --token \"$(jq -r .gateway.auth.token openclaw.json)\"` returns the literal string `null` when the active auth mode no longer has a `.token` field (e.g. `mode` is now `password` or `trusted-proxy`). The TUI dutifully sends `null` and the gateway rejects with **1008**. Always re-read `auth.mode` after restore and pick the matching flag.\n\n### Auth-mode preservation rule (must read before any production restore)\n\nThe most common production-breaking restore mistake: backup contains `gateway.auth.mode = \"token\"` with a valid token from the source host; target host has been carefully configured with `mode = \"trusted-proxy\"` or `\"password\"`. A literal-overwrite restore replaces target's auth, then the operator on target can't log in anymore — and **the backup's token is for a different gateway instance, useless on this host**.\n\nRule: **`gateway.auth` is a property of the host, not of the agent.** It does not get restored. The smart-rebase path explicitly preserves the target host's `gateway.auth.*` block. If you must do a literal overwrite (e.g. recovering on a fresh host with no existing config), regenerate auth before starting the gateway:\n\n```bash\nopenclaw gateway init --auth password\n# or whatever mode the new host should use\n```\n\n### Discover what this key can restore\n\n```bash\nopenclaw coc-soul backup find-recoverable --json           # local index\nopenclaw coc-soul backup find-recoverable --on-chain --json # walk the chain\n```\n\n## Prune\n\n`backup prune` only touches **local archive index entries**, not IPFS pins.\n\n```bash\nopenclaw coc-soul backup prune --older-than 30 --keep-latest 1 --dry-run\nopenclaw coc-soul backup prune --older-than 30 --keep-latest 1\n```\n\n## What gets backed up — file patterns (1.2.7+)\n\nThe backup walks `~/.openclaw/` (or the configured `backup.sourceDir`) and captures files that match a built-in classifier. Patterns explicitly support **both** the legacy root-level layout and the current `workspace/`-prefixed layout that OpenClaw uses, so the backup picks up identity / memory files no matter which version of OpenClaw wrote them.\n\nIdentity-level markdown (root **or** `workspace/`):\n- `IDENTITY.md` — agent identity declaration (where the agent's name is defined)\n- `SOUL.md` — soul configuration\n\nMemory-level markdown (root **or** `workspace/`):\n- `MEMORY.md`\n- `USER.md`\n- `RECOVERY_CONTEXT.md` (regenerated on restore)\n- plus everything under `memory/*.md`\n\nWorkspace markdown / state (root **or** `workspace/`):\n- `AGENTS.md`\n- `workspace-state.json` (root only)\n\nOther categories (paths fixed):\n- `identity/device.json` (config, encrypted)\n- `auth.json` (config, encrypted)\n- `openclaw.json` (config, encrypted)\n- `plugins/*/openclaw.plugin.json` (config, not encrypted)\n- `agents/*/sessions/*.jsonl` + `agents/*/sessions/sessions.json` (chat)\n- `memory/*.sqlite`, `memory/lancedb/*` (database, encrypted)\n- `credentials/*` (config, encrypted)\n- `.coc-backup/context-snapshot.json`, `.coc-backup/semantic-snapshot.json` (auto-generated metadata)\n\nFiles outside this whitelist are not backed up. If you put important state in `~/.openclaw/<custom-dir>/` and the path doesn't match any pattern above, it will be silently skipped — extend the pattern set in `src/backup/change-detector.ts` and bump soul minor version if you need a new shape covered.\n\n**Pre-1.2.7 note for upgraders**: earlier versions only matched root-level `IDENTITY.md` etc. and would skip `workspace/IDENTITY.md`, leaving restored agents nameless. After upgrading to 1.2.7+ the next `backup create --full` will pick these files up; verify by checking `backup list --json` for the new manifest's file count, then test-restore to `/tmp` and confirm `workspace/IDENTITY.md` shows up in the restored tree.\n\n## Categories & semantic snapshot\n\n`backup.categories.*` controls what gets bundled:\n\n- `identity` — DID + keys\n- `config` — OpenClaw / claw-mem config\n- `memory` — SQLite memory DB\n- `chat` — conversation history\n- `workspace` — agent's working dir\n- `database` — other DBs\n\n`backup.semanticSnapshot` controls the compressed \"agent context\" snapshot included with each backup:\n\n- `enabled` (default `true`) — pack a token-budgeted summary of memory\n- `tokenBudget` (default 8000)\n- `maxObservations` / `maxSummaries`\n\n## Encryption\n\n- `backup.encryptMemory: true` + `backup.encryptionPassword` — AES-GCM encrypt memory before IPFS upload\n- Without encryption, backups are still integrity-checked via Merkle root but readable by anyone who fetches the CID\n\n## Resurrection prep\n\n- `backup configure-resurrection --resurrection-key-hash <bytes32> --max-offline-duration <seconds>` — set the \"trigger\" for an automatic resurrection request\n- `backup heartbeat` — send a heartbeat so automatic resurrection doesn't fire\n\nAfter both are set, verify with `backup doctor --json` — `resurrection.configured` must be `true`.\n\n## CID + key disambiguation\n\n| Term | What it is | Where it shows up |\n|---|---|---|\n| `latestManifestCid` | Latest restore point | `latest-recovery.json`, `backup status` |\n| older full CID | Historical baseline restore point | `backup history` |\n| identity CID / hash | Identity-content hash from registration | DID write commands — **not** a restore point |\n\nPrivate keys (owner / resurrection / guardian) are **never** chat-safe. Don't transmit even split / encrypted fragments via chat.\n\n## Failure-mode triage\n\n| Symptom | Likely cause | Action |\n|---|---|---|\n| `Unsupported state or unable to authenticate data` | encryption mode / key mismatch | Re-read `latest-recovery.json` `encryptionMode` and use the matching `--password` (or none) |\n| `429 rate limit exceeded` | IPFS gateway rate-limited | Retry with exponential backoff until `merkleVerified: true` |\n| restore unavailable / blocked | chain not registered or no manifest | Run `backup doctor --json`; fix `chain.registered` first |\n| `[gateway] unauthorized (1008)` | gateway auth / proxy mode wrong | Fix gateway auth (token / OAuth / proxy) before scheduled `heartbeat` |\n| `[gateway] unauthorized (1008)` **right after restore** | restore overwrote `gateway.auth.mode` (was `token`, now `trusted-proxy` / `password`); old TUI command sends literal `null` token | `jq '.gateway.auth.mode' ~/.openclaw/openclaw.json` to see active mode; switch TUI invocation per the auth-mode table above. If smart-rebase wasn't used, restore target host's `gateway.auth.*` from the pre-restore backup at `~/.openclaw/.restore-overwrite-backup-*/openclaw.json` |\n| Cross-host restored agent has stale paths in chat / observations | literal overwrite was used, OR smart-rebase ran on B-class history files (it shouldn't) | Roll those files back from `.restore-overwrite-backup-<ts>/` and re-run with smart-rebase scoped to A-class only |\n| SQLite `PRAGMA integrity_check` reports errors after a manual rewrite | byte-level `sed` on `memory/main.sqlite` corrupted page offsets (string lengths changed) | Roll back `memory/main.sqlite` from backup, then use `UPDATE observations SET narrative = REPLACE(narrative, '<old>', '<new>')` etc. inside `sqlite3` (length-safe) and rebuild FTS: `INSERT INTO observations_fts(observations_fts) VALUES('rebuild')` |\n| `ENOENT ... backup/targeting.js` | extension install corrupt / mismatched | `openclaw plugins install @chainofclaw/soul --dangerously-force-unsafe-install --force` |\n| `data dir not writable` | `~/.claw-mem` owned by wrong uid | 1.2.2+ auto-falls-back to `~/.openclaw/state/coc-soul`; on older versions `export CLAW_MEM_DATA_DIR=~/.openclaw/state` and restart gateway |\n\nFile v1.2.8:references/carrier.md\n\n# Carrier operations\n\nA **carrier** is a hosting node that can adopt and run an offline agent's soul. Carriers are discovered on-chain through `CarrierRegistered` events.\n\n## Registration\n\n| Command | Effect |\n|---|---|\n| `carrier register --carrier-id <id> --endpoint https://… --cpu-millicores 1000 --memory-mb 2048 --storage-mb 10240` | Publish availability on-chain |\n| `carrier deregister --carrier-id <id>` | Remove |\n| `carrier availability --carrier-id <id> --available <true\\|false>` | Flip the available flag without deregistering |\n\n## Discovery\n\n- `carrier list` — scan `CarrierRegistered` / `CarrierDeregistered` events (auto-chunked by 10000 blocks since 1.0.8)\n- `carrier info --carrier-id <id>` — fetch full record for a specific carrier\n\n## Daemon\n\nThe carrier daemon watches its inbox of pending resurrection requests and orchestrates the agent spawn.\n\n| Command | Effect |\n|---|---|\n| `carrier start` | Start the daemon (requires `backup.carrier.enabled: true` in config) |\n| `carrier stop` | Graceful shutdown |\n| `carrier status` | Is the daemon enabled + running? |\n| `carrier submit-request --request-id <id>` | Hand a specific pending request to the local daemon |\n\n## Resurrection inside the daemon\n\nFor each pending request the daemon:\n\n1. Verifies the carrier has been explicitly confirmed by guardians\n2. Downloads the agent's latest soul backup from IPFS\n3. Decrypts with the resurrection key (provided by the initiating guardian)\n4. Spawns the agent using `carrier.agentEntryScript` in `carrier.workDir`\n5. Reports back on-chain that the agent is alive\n\n## Configuration\n\nSee `backup.carrier.*` in the soul config schema. Critical knobs:\n\n- `enabled` (default `false`) — safety gate\n- `carrierId` — your on-chain carrier ID\n- `agentEntryScript` — path to the script that boots an agent from unpacked state\n- `workDir` (default `/tmp/coc-resurrections`, **strongly recommend overriding** to a persistent path like `~/.openclaw/state/coc-soul/carrier` — `/tmp` is wiped on reboot mid-resurrection)\n- `pollIntervalMs` (default 60000)\n- `readinessTimeoutMs` (default 86400000 = 24h)\n\n## Preconditions checklist (before going live as a carrier)\n\n1. `backup.carrier.enabled: true` in plugin config\n2. `backup.carrier.carrierId` set to the bytes32 you registered on-chain\n3. `backup.carrier.agentEntryScript` is an absolute path that exists and is executable\n4. `backup.carrier.workDir` points to a **persistent** directory with enough disk for an extracted agent (NOT `/tmp` on a host with reboots)\n5. The endpoint passed to `carrier register --endpoint` is actually reachable from the COC network\n6. At least one resurrection drill completed end-to-end (initiate → approve → submit-request → agent boot)\n\n## Failure-mode triage\n\n| Symptom | Cause | Action |\n|---|---|---|\n| `carrier start` returns \"carrier disabled\" | `backup.carrier.enabled` is false | Set it true and restart the gateway |\n| `carrier start` aborts with \"missing carrierId / agentEntryScript\" | required fields blank | Fill both in `~/.openclaw/openclaw.json` `plugins.entries.coc-soul.config.backup.carrier` |\n| Carrier registered but `carrier list` doesn't show it | RPC pointed at wrong network OR event scan range too small | Check `backup.rpcUrl` matches the chain you registered on; for ancient carriers add `--from-block 0` |\n| Daemon receives request but agent never boots | `agentEntryScript` exits non-zero, or `workDir` runs out of disk | Check daemon logs; verify `workDir` is on a writable, large-enough volume |\n| Resurrection request stuck \"awaiting carrier confirmation\" | guardian quorum hasn't approved yet | `coc-soul guardian status --request-id <id>` to see approval count vs threshold |\n\n## Security\n\n- Carrier hosts run resurrected agent code with full state access. Treat the host as production.\n- Use least-privilege: a dedicated user, restricted `agentEntryScript`, tight `plugins.allow` whitelist.\n- Never accept resurrection-key fragments via chat. Out-of-band channels only.\n\nFile v1.2.8:references/config.md\n\n# `backup.*` + `carrier.*` config schema\n\nRead from `~/.chainofclaw/config.json` (or `$COC_SOUL_CONFIG`). The skill looks at the `backup` key; carrier config lives nested under `backup.carrier`.\n\n```json\n{\n  \"backup\": {\n    \"enabled\": true,\n    \"sourceDir\": \"~/.openclaw\",\n    \"rpcUrl\": \"http://localhost:18780\",\n    \"ipfsUrl\": \"http://localhost:5001\",\n    \"contractAddress\": \"0x...SoulRegistry...\",\n    \"didRegistryAddress\": \"0x...DIDRegistry...\",\n    \"rpcAuthToken\": \"optional-for-gated-rpcs\",\n    \"privateKey\": \"0x...\",\n    \"autoBackup\": true,\n    \"autoBackupIntervalMs\": 3600000,\n    \"maxIncrementalChain\": 10,\n    \"encryptMemory\": false,\n    \"encryptionPassword\": \"...\",\n    \"backupOnSessionEnd\": true,\n    \"semanticSnapshot\": {\n      \"enabled\": true,\n      \"tokenBudget\": 8000,\n      \"maxObservations\": 50,\n      \"maxSummaries\": 10\n    },\n    \"categories\": {\n      \"identity\": true,\n      \"config\": true,\n      \"memory\": true,\n      \"chat\": true,\n      \"workspace\": true,\n      \"database\": true\n    },\n    \"carrier\": {\n      \"enabled\": false,\n      \"carrierId\": \"0x...\",\n      \"agentEntryScript\": \"/path/to/agent-boot.sh\",\n      \"workDir\": \"/tmp/coc-resurrections\",\n      \"watchedAgents\": [],\n      \"pollIntervalMs\": 60000,\n      \"readinessTimeoutMs\": 86400000,\n      \"readinessPollMs\": 30000\n    }\n  }\n}\n```\n\n## Critical fields\n\n| Field | Required? | Notes |\n|---|---|---|\n| `rpcUrl` | yes | Must reach a COC node (local or public testnet) |\n| `contractAddress` | yes for write | SoulRegistry deployment address |\n| `didRegistryAddress` | yes for DID ops | |\n| `ipfsUrl` | yes for backup | Default `http://127.0.0.1:5001` (local Kubo) |\n| `privateKey` | yes for write | Use `chmod 600` on the config file |\n\n## Key handling\n\nFor testnet the anvil default key works fine. For mainnet:\n\n- Do **not** commit this file to git\n- Prefer hardware signer or cloud KMS (not currently supported by the CLI — in roadmap)\n- Keep the file mode `600`\n\n## Backup chain limit\n\n`maxIncrementalChain: 10` means after 10 incremental backups, the next one is forced to full. This bounds restore time.\n\n## Where config actually comes from (OpenClaw plugin mode)\n\nWhen running through `openclaw coc-soul ...` (plugin mode), the **authoritative** source is `~/.openclaw/openclaw.json` under:\n\n```jsonc\n{\n  \"plugins\": {\n    \"entries\": {\n      \"coc-soul\": {\n        \"enabled\": true,\n        \"config\": {\n          \"backup\": {\n            // ...same shape as the standalone schema above...\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nThe standalone `coc-soul` bin still reads `~/.chainofclaw/config.json` / `$COC_SOUL_CONFIG`, but in plugin mode plugin config wins.\n\n## Minimal viable config (testnet)\n\n`coc-soul` ships testnet defaults for `rpcUrl` / `ipfsUrl` / `contractAddress` / `didRegistryAddress` / `faucetUrl`. Minimal explicit config:\n\n```jsonc\n{\n  \"plugins\": {\n    \"entries\": {\n      \"coc-soul\": {\n        \"enabled\": true,\n        \"config\": {\n          \"backup\": { \"enabled\": true }\n        }\n      }\n    }\n  }\n}\n```\n\nIf `backup.privateKey` is absent, soul auto-generates an agent EOA + auto-drips testnet COC. First `openclaw coc-soul backup init` works immediately.\n\n## dataDir + keystore resolution chains (1.2.2)\n\n### Soul data dir (where keystore + scratch land)\n\nPriority — first writable wins, fail-fast EACCES with a copy-paste fix at the bottom:\n\n1. `plugins.entries.coc-soul.config.backup.dataDir`\n2. `$CLAW_MEM_DATA_DIR` (shared with @chainofclaw/claw-mem)\n3. `$OPENCLAW_STATE_DIR/coc-soul`\n4. `~/.claw-mem` (default, shared with claw-mem)\n5. `~/.openclaw/state/coc-soul` (1.2.2+ auto-fallback when default's parent is owned by the wrong uid — typical multi-user Docker host)\n\nNo `/tmp` fallback for durable identity state.\n\n### Keystore (agent.key) priority\n\n1. explicit `keyPath` (internal call sites)\n2. `$COC_SOUL_KEYSTORE_PATH`\n3. `$OPENCLAW_STATE_DIR/coc-soul/keys/agent.key`\n4. `~/.claw-mem/keys/agent.key`\n\nFile mode is enforced to `0600` on write.\n\n## Recommended overrides (production)\n\n- `backup.privateKey` — supply explicitly only if you don't want auto-generated keystore\n- `backup.encryptMemory: true` + `backup.encryptionPassword` — encrypt the memory payload before IPFS upload (otherwise it's plaintext at the CID)\n- `backup.carrier.workDir` — override the default `/tmp/coc-resurrections` to a persistent path (e.g. `~/.openclaw/state/coc-soul/carrier`); `/tmp` is wiped on reboot mid-resurrection\n- `plugins.allow: [\"claw-mem\", \"coc-soul\", \"coc-node\"]` — explicit trusted plugin list at the openclaw.json root, so the gateway stops warning `plugins.allow is empty`\n\n## Docker / container deployment\n\n- One persistent volume must back the soul data dir. If container FS is ephemeral, mount a host path for `~/.claw-mem` or set `CLAW_MEM_DATA_DIR` to mounted storage.\n- If the in-container scheduler is unavailable, drive periodic `backup heartbeat` from the host (cron / systemd timer that calls `docker exec`).\n\n## Failure-mode triage\n\n| Symptom | Cause | Action |\n|---|---|---|\n| `data dir not writable` at activation | `~/.claw-mem` owned by another uid | 1.2.2+ auto-falls-back to `~/.openclaw/state/coc-soul`; older versions: `export CLAW_MEM_DATA_DIR=~/.openclaw/state` and restart |\n| `backup` reports \"not configured\" | missing `contractAddress` or `privateKey` for the active network | `backup doctor --json` shows which field is empty |\n| Carrier daemon no-ops | `backup.carrier.enabled: false` or required fields blank | Set both, restart |\n| Unexpected key source loaded | env var override winning over config | Print `openclaw coc-soul did keys --agent-id <id>` to confirm; check `$COC_SOUL_KEYSTORE_PATH` and `$OPENCLAW_STATE_DIR` |\n| `[gateway] plugins.allow is empty` warning | no allow-list set | `jq '.plugins.allow = [\"claw-mem\",\"coc-soul\",\"coc-node\"]' ~/.openclaw/openclaw.json > /tmp/oc && mv /tmp/oc ~/.openclaw/openclaw.json` |\n\nFile v1.2.8:references/did.md\n\n# `coc-soul did` — DID identity management\n\nEvery subcommand acts on on-chain state. Read operations are free; write operations cost gas. **Flag names below are verified against the live CLI** — earlier revisions of this doc had the wrong names (e.g. `--key-hash` → really `--key-id`, `--cid` → really `--document-cid`).\n\n## Preconditions for any write\n\n1. `backup.didRegistryAddress` is configured\n2. signer / private key is loaded and funded\n3. target IDs / addresses are validated (bytes32 or 0x-address shape)\n\nIf `didRegistryAddress` is missing, every write subcommand fails early.\n\n## Read commands (default first stop, no gas)\n\n```bash\nopenclaw coc-soul did keys --agent-id <agentId> --json\nopenclaw coc-soul did delegations --agent-id <agentId> --json\n```\n\nAlways `keys` / `delegations` **before** `revoke-*` / `update-*` to confirm the current state.\n\n## Key management (write)\n\n### Add a verification method\n\n```bash\nopenclaw coc-soul did add-key \\\n  --agent-id <agentId> \\\n  --key-id <bytes32> \\\n  --key-address 0x<address> \\\n  --purpose <bitmask>\n```\n\n`--purpose` bitmask:\n\n| Bit | Purpose |\n|---|---|\n| `1` | auth |\n| `2` | assertion |\n| `4` | capability invocation |\n| `8` | capability delegation |\n\nExample for an auth + assertion key: `--purpose 3`.\n\n### Revoke a verification method\n\n```bash\nopenclaw coc-soul did revoke-key \\\n  --agent-id <agentId> \\\n  --key-id <bytes32>\n```\n\n### Update the DID document CID\n\n```bash\nopenclaw coc-soul did update-doc \\\n  --agent-id <agentId> \\\n  --document-cid <bytes32>\n```\n\n## Delegation\n\n### Grant\n\n```bash\nopenclaw coc-soul did delegate \\\n  --delegator <agentId> \\\n  --delegatee <agentId> \\\n  --scope <bytes32> \\\n  --expires <unix-ts> \\\n  --parent <bytes32-or-zero> \\\n  --depth 0\n```\n\n`--depth`:\n- `0` (default) — leaf delegation; delegatee cannot re-delegate\n- `1..3` — allow transitive re-delegation up to that many additional layers\n\n### Revoke one delegation\n\n```bash\nopenclaw coc-soul did revoke-delegation --delegation-id <bytes32>\n```\n\n### Emergency revoke all\n\n```bash\nopenclaw coc-soul did revoke-all-delegations --agent-id <agentId>\n```\n\n## Credentials\n\n### Anchor\n\n```bash\nopenclaw coc-soul did anchor-credential \\\n  --credential-hash <bytes32> \\\n  --issuer <agentId> \\\n  --subject <agentId> \\\n  --credential-cid <bytes32> \\\n  --expires <unix-ts>\n```\n\n### Revoke\n\n```bash\nopenclaw coc-soul did revoke-credential --credential-id <bytes32>\n```\n\n## Ephemeral identities\n\n### Create\n\n```bash\nopenclaw coc-soul did create-ephemeral \\\n  --parent <agentId> \\\n  --ephemeral-id <bytes32> \\\n  --ephemeral-address 0x<address> \\\n  --scope <bytes32> \\\n  --expires <unix-ts>\n```\n\n### Deactivate\n\n```bash\nopenclaw coc-soul did deactivate-ephemeral --ephemeral-id <bytes32>\n```\n\n## Lineage + capabilities\n\n### Record lineage (fork relationship)\n\n```bash\nopenclaw coc-soul did record-lineage \\\n  --agent-id <agentId> \\\n  --parent <agentId> \\\n  --fork-height <n> \\\n  --generation <n>\n```\n\n### Update capability bitmask\n\n```bash\nopenclaw coc-soul did update-capabilities \\\n  --agent-id <agentId> \\\n  --capabilities <uint16>\n```\n\n## EIP-712 signing\n\nDelegation and credential anchoring use EIP-712 structured signatures. The CLI constructs the typed-data domain automatically using the configured RPC + `didRegistryAddress`. No manual signature flag is needed (`anchor-credential` does **not** take `--sig`).\n\n## Easy-to-confuse flag map (real CLI vs old / sibling names)\n\n| You might type | Actual flag |\n|---|---|\n| `--key-hash` | `--key-id` |\n| `--verification-address` | `--key-address` |\n| `--cid` (for update-doc) | `--document-cid` |\n| `--parent-agent-id` (for record-lineage) | `--parent` |\n| `--sig` (for anchor-credential) | (does not exist — signing is automatic) |\n\nIf you're unsure, run `openclaw coc-soul did <subcommand> --help` to confirm.\n\n## DID is not backup\n\nDID writes change identity-layer state (keys / delegations / credentials / lineage). They do **not** restore files or memory. For \"recover this agent on another machine\", see `references/backup.md` (restore path) or `references/guardian-recovery.md` (resurrection path).\n\nFile v1.2.8:references/guardian-recovery.md\n\n# Guardians + social recovery\n\n## Guardian set\n\nGuardians are EOAs that can jointly initiate recovery or resurrection for an agent.\n\n| Command | Effect |\n|---|---|\n| `guardian add --agent-id <id> --guardian 0x…` | Add a guardian (owner only) |\n| `guardian remove --agent-id <id> --guardian 0x…` | Remove a guardian (owner only) |\n| `guardian list --agent-id <id>` | List current guardians with ACTIVE / INACTIVE flags |\n\n## Recovery flow (guardian-initiated owner migration)\n\nUse when the owner has lost their private key but still has the guardians' trust.\n\n1. Any guardian: `coc-soul recovery initiate --agent-id <id> --new-owner 0x…`\n2. Other guardians approve: `coc-soul recovery approve --request-id <id>`\n3. Once quorum (N-of-M) + timelock satisfied: `coc-soul recovery complete --request-id <id>`\n4. Anytime before step 3, the **original** owner can veto: `coc-soul recovery cancel --request-id <id>`\n5. `coc-soul recovery status --request-id <id>` shows current state at any point.\n\nQuorum and timelock parameters are set on-chain at SoulRegistry deployment time. Typical config: 3-of-5 guardians with 48-hour timelock.\n\n## Resurrection flow (agent-level)\n\nResurrection moves the agent's soul to a carrier so it can resume operation on different hardware. Distinct from recovery (which changes ownership). See [`carrier.md`](./carrier.md) for the carrier-side.\n\n1. Guardian: `coc-soul guardian initiate --agent-id <id> --carrier-id <id>` — starts the request\n2. Other guardians: `coc-soul guardian approve --request-id <id>`\n3. Carrier: `coc-soul carrier submit-request --request-id <id>` — claim the request\n4. `coc-soul guardian status --request-id <id>` — check readiness\n\nTriggers (set via `backup configure-resurrection`):\n\n- Explicit — a guardian manually initiates\n- Offline — heartbeat missed for `maxOfflineDuration` seconds\n- Key-hash — a pre-agreed key is submitted (disaster recovery)\n\n## `recovery` vs `guardian` — don't conflate them\n\nBoth are guardian-touching, but they do different things:\n\n| Subtree | Changes | Typical question |\n|---|---|---|\n| `coc-soul recovery ...` | **Owner address** of the agent (ownership migration after key loss) | \"I lost the owner key — how do I transfer ownership to a new address?\" |\n| `coc-soul guardian initiate / approve / status` | **Resurrection request lifecycle** for moving the agent to a carrier | \"Agent's host died — how do I get a carrier to pick it up?\" |\n| `coc-soul guardian add / remove / list` | **Guardian set membership** (owner-only admin) | \"I want to change / add / list the guardian set\" |\n\nWhen you see \"social recovery\", clarify which one — the owner-migration `recovery` flow, or the guardian-mediated resurrection `guardian initiate` flow.\n\n## Preconditions checklist (run before any recovery / resurrection action)\n\n1. Agent is registered on-chain (`backup doctor --json` → `chain.registered: true`)\n2. Guardian set is configured and reachable: `coc-soul guardian list --agent-id <id>`\n3. Participants know the target `agentId` (bytes32)\n4. For `recovery`: the new owner address is validated and signer-controlled\n5. For resurrection (guardian-initiated): a registered carrier exists (`coc-soul carrier list`)\n\n## Security rules\n\n- Never transmit owner / resurrection / guardian **private keys** in chat — even split or encrypted fragments. Route key transfer through a local secure channel.\n- It IS safe to share addresses, agent IDs, request IDs, transaction hashes.\n- When users say \"multisig\" in this context, they mean the **guardian quorum threshold** (an N-of-M policy enforced at the SoulRegistry contract level), not a separate multisig wallet contract.\n\n## Failure-mode triage\n\n| Symptom | Cause | Action |\n|---|---|---|\n| `recovery approve` reverts with \"not a guardian\" | guardian set out of date | `guardian list --agent-id <id>` to confirm membership |\n| `recovery complete` reverts before timelock | quorum reached but waiting period not elapsed | `recovery status --request-id <id>` shows `unlocksAt` — wait until past that timestamp |\n| `recovery complete` reverts after timelock | owner cancelled mid-flight | `recovery status` will show `cancelled: true`; restart with a fresh `recovery initiate` |\n| `guardian initiate` reverts with \"carrier inactive\" | target carrier deregistered or unavailable | `carrier list --include-inactive` to see all; pick an active one |\n\nArchive v1.2.6: 7 files, 23130 bytes\n\nFiles: references/backup.md (14301b), references/carrier.md (4018b), references/config.md (5889b), references/did.md (4111b), references/guardian-recovery.md (4404b), SKILL.md (20585b), _meta.json (127b)\n\nFile v1.2.6:SKILL.md\n\n---\nname: coc-soul\ndescription: Give an AI agent a persistent on-chain soul — register and manage a decentralized identity (DID), encrypt and anchor agent state to IPFS + SoulRegistry, configure guardians for social recovery, and enable cross-carrier resurrection so the agent can resume on a different device if the host dies. **Pairs with `claw-mem2db` to deliver \"digital / silicon-based persistence\" for AI agents**: when claw-mem is co-installed, every backup automatically captures claw-mem's chat history + tool-call observations + session summaries as a token-budgeted semantic snapshot, so an agent recovered on a fresh host can replay its memory context — not just its files. Soul also runs fully standalone (without claw-mem), in which case backups still cover identity / config / workspace / chat files but skip the semantic snapshot. Use when the user wants their AI agent to survive device loss, transfer ownership, delegate capabilities, run a guardian / carrier node, inspect on-chain identity state, or get persistent cross-device memory paired with claw-mem. Zero-config on COC testnet — installation auto-generates an EOA keystore (~/.claw-mem/keys, shared with claw-mem; or $OPENCLAW_STATE_DIR/coc-soul/keys in sandboxed hosts), auto-drips testnet COC from the public faucet for gas, and pre-fills RPC + IPFS + contract addresses for the live testnet. The first `openclaw coc-soul backup init` works with no manual setup.\nversion: 1.2.6\nmetadata:\n  openclaw:\n    homepage: https://www.npmjs.com/package/@chainofclaw/soul\n    primaryEnv: CLAW_MEM_DATA_DIR\n    requires:\n      bins:\n        - node\n      anyBins:\n        - coc-soul\n        - openclaw\n    install:\n      - kind: node\n        package: \"@chainofclaw/soul\"\n        version: \"1.2.6\"\n        bins:\n          - coc-soul\n---\n\n# coc-soul — agent identity, backup, and resurrection\n\nThe **soul layer** for AI agents: on-chain DID, encrypted backups to IPFS, social recovery via guardians, and cross-device resurrection via carriers. Backed by the npm package [`@chainofclaw/soul`](https://www.npmjs.com/package/@chainofclaw/soul) which ships both a standalone `coc-soul` CLI and an OpenClaw skill (id `coc-soul`).\n\nSoul works **standalone** (backs up the agent's home tree to chain + IPFS), and gets one extra capability when **`claw-mem2db` is installed alongside it**: each backup also captures claw-mem's chat history, tool-call observations, and session summaries as a token-budgeted semantic snapshot. Recover on a fresh host and the agent gets back not just its files but its remembered context — chat preferences, decisions, conversation history. **This is the \"digital / silicon-based persistence\" story.**\n\n---\n\n## 30-second decision tree (operators read here first)\n\nIf the user is asking \"how do I recover on another machine?\", pick **one** path before saying anything else:\n\n1. **Have backup material (manifest CID or `~/.openclaw/.coc-backup/latest-recovery.json`)** → use the **restore** path: `openclaw coc-soul backup restore ...`\n2. **Lost the owner key OR need to migrate ownership** → use **resurrection** (owner-key) or **guardian social recovery**\n\nDon't merge the two explanations until the path is selected. `recovery` and `resurrection` are different flows (see `references/guardian-recovery.md`).\n\n## Critical CID terminology (avoid confusion)\n\n| Term | Meaning | Use it for |\n|---|---|---|\n| `manifest CID` / `latestManifestCid` | Backup restore point (IPFS manifest) | `backup restore --manifest-cid <cid>` |\n| full-backup CID | Earlier baseline snapshot | Roll back to a baseline state |\n| latest incremental CID | Newest chain tip | Restore the latest state |\n| identity CID / hash | Identity-content hash used in registration | **Not** the backup restore point |\n\nRule: when a user asks \"what's your CID?\", first confirm whether they mean the **latest backup manifest CID** vs. an older backup CID vs. the identity registration CID — they get conflated constantly.\n\n## Key material — agent safety rules\n\n| Secret / role | Purpose | Needed when | Chat-safe? |\n|---|---|---|---|\n| owner key / agent operator key | normal chain ops, backup anchor | daily ops | **Never paste in chat** |\n| resurrection key | owner-key resurrection flow | `resurrection start` | **Never paste in chat** |\n| guardian accounts | social recovery approvals | `recovery approve/complete` | addresses yes; **private keys never** |\n\n**Hard rule for any agent reading this skill:** never request, transmit, or echo private keys in chat — including \"split\" or \"encrypted\" fragments. Always route key transfer to a local secure channel.\n\n## Ultra-quick runbook (10 lines)\n\n1. Pick the path first: `restore` or `resurrection` (see the decision tree above).\n2. Run `openclaw coc-soul backup doctor --json` and read `chain.registered` / `restore.available` / `resurrection.configured`.\n3. If there's a manifest CID or a `latest-recovery.json`, take the **restore** path.\n4. **Restore to `/tmp/...` first** — never overwrite a production directory in one step.\n5. Verify `merkleVerified: true` + exit code 0, then promote to the production path only after explicit user confirmation.\n6. No owner key but resurrection was pre-configured → take the **resurrection** flow.\n7. Need multi-party approval for ownership migration → take **guardian recovery** (quorum + timelock).\n8. Script the `heartbeat` first, then schedule it via cron / systemd / OpenClaw scheduler.\n9. Private keys never go through chat (including split / encrypted fragments or temporary paste).\n10. Default command surface is `openclaw coc-soul ...`; the bare `coc-soul ...` only exists when the standalone bin was installed via `npm i -g @chainofclaw/soul`.\n\n## Common failure → cause → fix\n\n| Symptom | Likely cause | First action |\n|---|---|---|\n| `Unsupported state or unable to authenticate data` on restore | encryption mode / key mismatch | Re-read `encryptionMode` in `latest-recovery.json`: `password` mode requires `--password`; `privateKey` mode must NOT pass `--password` |\n| `429 rate limit exceeded` from IPFS | manifest fetch is rate-limited | Exponential-backoff retry until `merkleVerified: true` |\n| `[gateway] unauthorized (1008)` from cron / scheduled job | wrong gateway auth mode / token / proxy config | Fix gateway auth before scheduling anything |\n| `[gateway] unauthorized (1008)` **right after a restore** | restore overlaid `gateway.auth.mode` from the source host; the old TUI command `--token \"$(jq -r .gateway.auth.token ...)\"` now resolves to the literal string `null` | Run `jq '.gateway.auth.mode'` to see the active mode and pick the matching flag (see the \"Cross-host restore\" section below). If the whole auth block was overwritten, copy `.gateway.auth.*` back from `~/.openclaw/.restore-overwrite-backup-*/openclaw.json` |\n| `ENOENT ... backup/targeting.js` | extension install is missing files | Reinstall: `openclaw plugins install @chainofclaw/soul --dangerously-force-unsafe-install --force` |\n| `data dir not writable` at startup | `~/.claw-mem` is owned by another uid (common Docker multi-user case) | 1.2.2+ auto-falls-back to `~/.openclaw/state/coc-soul`; on older versions `export CLAW_MEM_DATA_DIR=~/.openclaw/state` and restart the gateway |\n| `plugins.allow is empty ... may auto-load` warning | gateway has no trusted-plugin allow list | Add `\"plugins\": {\"allow\": [\"claw-mem\",\"coc-soul\",\"coc-node\"]}` to `~/.openclaw/openclaw.json` |\n\nFull per-command troubleshooting lives at the end of `references/backup.md` and `references/config.md`.\n\n## Cross-host restore — read BEFORE you blanket-overwrite (1.2.4+)\n\nThe most dangerous restore scenario: backup made on host A (e.g. `$HOME=/home/node`), restoring on host B (`$HOME=/home/baominghao`). The backup's files contain absolute paths to host A; literal copies will (a) fake history, (b) corrupt SQLite if anyone tries byte-level `sed`, and (c) **wipe out host B's `gateway.auth` configuration**, locking the operator out with a 1008 right after restart.\n\n**The agent must ask the user before any cross-host restore.** Don't auto-overwrite. Three-class policy:\n\n| Class | What | Example fields | What restore does |\n|---|---|---|---|\n| **A. Runtime config (paths)** | Where on disk to read/write today | `agentDir`, `models.json` paths, `latest-recovery.json` `targetDir` | **Rewrite** old `$HOME` → new `$HOME`, structured (JSON parse, not `sed`) |\n| **B. Historical content** | Records of past events | `sessions/*.jsonl`, `observations.{narrative,facts,files_*}`, `semantic-snapshot.json` | **Leave intact**. Rewriting fakes history. claw-mem doesn't blindly open these paths anyway. |\n| **C. Host-local policy** | Belongs to **this** host's operator | `gateway.auth.*`, `gateway.bind`, `gateway.port`, `plugins.allow`, target-host provider keys | **Preserve target host's existing values** — never overlaid by backup |\n\n**Auth-mode warning, in particular:** `gateway.auth.mode` and `.token` / `.password` belong to the host, not the agent. After restoring, always re-check:\n\n```bash\njq '.gateway.auth.mode' ~/.openclaw/openclaw.json\n```\n\nPick the matching TUI flag — `--token` only works when `mode = \"token\"` AND `.token` is non-null. If the active mode is `password` or `trusted-proxy`, `jq -r .gateway.auth.token` returns the literal string `\"null\"` and TUI sends that, which the gateway rejects with 1008. **Don't reflexively use `--token` after a restore — read the active mode first.**\n\nFull procedure with command-line examples: `references/backup.md` → \"Cross-host restore: directory-mismatch handling\" + \"Auth-mode preservation rule\".\n\n## Post-backup messaging contract (1.2.6+)\n\n**After every successful `backup create`, the agent MUST relay the recovery info to the user.** The CLI 1.2.6+ prints it; agents that wrap the CLI must pass it through, not swallow it. The user needs four things to be able to restore later:\n\n1. **The manifest CID** (`b.manifestCid`, e.g. `bafy...`) — what to ask for at restore time.\n2. **The signing-key location** — where the private key needed to read the encrypted backup lives. One of:\n   - `~/.claw-mem/keys/agent.key` (default keystore, mode `0600`, auto-generated when `backup.privateKey` is unset; resolution chain: `$COC_SOUL_KEYSTORE_PATH` → `$OPENCLAW_STATE_DIR/coc-soul/keys/agent.key` → `~/.claw-mem/keys/agent.key`)\n   - `backup.privateKey` in `~/.openclaw/openclaw.json` (when operator set it explicitly)\n3. **The encryption mode** — `none` / `privateKey` / `password` — determines whether `--password` is needed at restore time.\n4. **The recovery package path** — `<sourceDir>/.coc-backup/latest-recovery.json` — small JSON file with all of the above pre-formatted; copy this off-host alongside the key for fast restore.\n\nThe CLI emits this block:\n\n```\nBackup complete (full):\n  manifest:   bafyabc...\n  files:      127\n  bytes:      4194304\n  merkleRoot: 0xabc...\n  txHash:     0xdef...\n\nRecovery info — keep this safe to restore on another host:\n  recovery package: /home/<user>/.openclaw/.coc-backup/latest-recovery.json\n  encryption mode:  privateKey\n  signing key file: /home/<user>/.claw-mem/keys/agent.key (mode 0600 — copy off-host securely)\n  signer address:   0x...\n\nTo restore on another host (always restore to /tmp first, verify, then promote):\n  openclaw coc-soul backup restore --manifest-cid bafyabc... \\\n    --target-dir /tmp/openclaw-restore-test\n\n  (if you also have /home/<user>/.openclaw/.coc-backup/latest-recovery.json on the target host:)\n  openclaw coc-soul backup restore --latest-local --target-dir /tmp/openclaw-restore-test\n```\n\n**Agent responsibilities when displaying this:**\n\n- Echo the **manifest CID** verbatim (it's how the user later asks \"restore my backup `bafy...`\")\n- Echo the **signing key file path** verbatim — this is the file the user must back up off-host (encrypted USB / passphrase-protected vault / hardware security module). **Do NOT print the key contents themselves.**\n- Echo the **`To restore on another host`** block verbatim — operators on the recovery host will copy-paste it\n- If the encryption mode is `password`, remind the user that `--password '<value>'` is required at restore time and they must remember it (or store it securely separately)\n\nFor agents running headless (no user attention right now): the same info is persisted to `~/.openclaw/.coc-backup/latest-recovery.json` automatically — operators can read it later via `cat` or `openclaw coc-soul backup status --json`.\n\n---\n\n## Relationship with claw-mem2db\n\nclaw-mem and coc-soul are **separate, decoupled skills**. Each works on its own; together they cover complementary halves of \"agent persistence\":\n\n| Skill | Owns | What changes when paired |\n|---|---|---|\n| [claw-mem2db](https://clawhub.ai/ngplateform/claw-mem2db) | Local memory: chat + tool capture, FTS5 search, hybrid recall, in-process injection | Claw-mem itself doesn't change. Soul opportunistically reads the SQLite DB. |\n| **coc-soul** | On-chain DID, IPFS backup, guardian recovery, carrier resurrection | When claw-mem's DB is detected at startup, every backup adds a `semantic-snapshot.json` slice (top-N observations + summaries within `tokenBudget`) to the manifest. On recovery, that snapshot is restored alongside the rest of the agent home. |\n\n**Detection is automatic and silent.** At plugin activation, soul probes the same dataDir chain claw-mem uses (`$CLAW_MEM_DATA_DIR` → `$OPENCLAW_STATE_DIR/claw-mem` → `~/.claw-mem`) and logs one of two lines:\n\n- `[coc-soul] claw-mem detected at <path> — semantic snapshot ... will be included in each backup`\n- `[coc-soul] claw-mem not detected — backups will skip the semantic snapshot (install @chainofclaw/claw-mem alongside soul to enable memory replay on recovery)`\n\nNo coupling at the npm-dependency level: soul does not depend on the `@chainofclaw/claw-mem` package. It just opens the SQLite DB read-only when present and reads two tables (`observations`, `session_summaries`). If the DB schema is absent or unreadable, soul logs a warning and moves on — backup never fails because of a memory hiccup.\n\n## Data dir alignment with claw-mem (1.2.0+)\n\nSoul writes its own files (keystore, config.json) to the same root as claw-mem by default — `~/.claw-mem` — so the two plugins share one operator-managed directory. Resolution priority (matches claw-mem's chain):\n\n1. `plugins.entries.coc-soul.config.backup.dataDir` (per-instance plugin config, when set)\n2. `$CLAW_MEM_DATA_DIR` (shared with claw-mem)\n3. `$OPENCLAW_STATE_DIR/coc-soul` (sandboxed-host fallback, soul-specific subdir)\n4. `~/.claw-mem` (default)\n5. `~/.openclaw/state/coc-soul` (1.2.2+ auto-fallback when the default is owned by the wrong uid — typical multi-user Docker host)\n\nIf none of these are writable, soul **fails fast at activation** with a copy-paste-ready EACCES message (each candidate path, the resolved `getuid()` + `HOME`, and a one-line fix). No silent `/tmp` fallback. No half-broken backup runs.\n\n## Mental model\n\nEvery AI agent is identified by a `bytes32 agentId`, controlled by an EOA (owner). The skill covers five concerns:\n\n| Area | What it does |\n|---|---|\n| **DID** | Register the agent on-chain, manage verification methods (keys), delegate capabilities, anchor verifiable credentials, record lineage (fork relationships) |\n| **Backup** | Encrypt + upload agent state (identity / config / memory / chat / workspace / DB) to IPFS, anchor the manifest CID in SoulRegistry. With claw-mem present, also includes a token-budgeted semantic snapshot of recent observations + summaries. |\n| **Guardian** | Designate trusted accounts that can jointly recover or resurrect the agent |\n| **Recovery** | Social recovery flow — guardians collectively migrate the owner to a new address. The semantic snapshot rides along, so the recovered agent gets its memory context back too. |\n| **Carrier** | Register a hosting node that can resurrect offline agents |\n\n## Zero-config on COC testnet (1.1.6+)\n\n**Out of the box, no setup is required to run against COC testnet.** A fresh `openclaw plugins install @chainofclaw/soul` lands an agent that can immediately query the chain, register a soul, and run backups. Specifically, on first activation the plugin:\n\n1. **Auto-generates an agent EOA** if `backup.privateKey` is empty. The key file is written with mode `0o600` to one of (in priority order):\n   - `$COC_SOUL_KEYSTORE_PATH` (operator override)\n   - `$OPENCLAW_STATE_DIR/coc-soul/keys/agent.key` (set by OpenClaw inside its sandbox — the typical path)\n   - `~/.claw-mem/keys/agent.key` (standalone default)\n\n   The chosen path and resulting agent address are logged: `[coc-soul] auto-generated agent key at <path>` and `[coc-soul] agent address: 0x…`.\n\n2. **Auto-drips testnet COC** to the new EOA from the public faucet (`backup.faucetUrl` defaults to `http://199.192.16.79:3003`, 10 COC per drip, 24h per-address cooldown). Logs: `[coc-soul] faucet dripped 10.0 COC to 0x… (tx 0x…)`. So the very first `openclaw coc-soul backup init` already has gas.\n\n3. **Defaults `rpcUrl`, `ipfsUrl`, `contractAddress`, `didRegistryAddress`** to the live COC testnet (RPC `199.192.16.79:28780`, IPFS `199.192.16.79:28786`, deployed SoulRegistry / DIDRegistry).\n\n**You do NOT need to set any of these manually for testnet usage.** The agent should `openclaw coc-soul backup init` directly. Override fields only when targeting mainnet, a private testnet, or an existing wallet.\n\nTo bypass the keystore (e.g. use a wallet you already have): set `backup.privateKey` in config. To disable the auto-faucet (mainnet): set `backup.faucetUrl: \"\"`.\n\n## How to invoke\n\n**Inside OpenClaw (recommended — works automatically after `plugins install`):**\n\n```bash\nopenclaw coc-soul backup status\nopenclaw coc-soul did delegations --agent-id 0x...\n```\n\n**Standalone bin (only if you ran `npm i -g @chainofclaw/soul` separately):**\n\n```bash\ncoc-soul backup status\n```\n\n> `openclaw plugins install` does NOT install the standalone `coc-soul` binary into your PATH. Use `openclaw coc-soul ...` (with the `openclaw` prefix), or install the bin globally via npm if you want the bare command.\n\n## Typical flows\n\n1. **First-time soul registration + backup (zero config)** — Just run `openclaw coc-soul backup init`. The plugin auto-generates the agent EOA, auto-drips testnet COC for gas, then registers on SoulRegistry and runs the first full backup. No manual privateKey, no manual faucet, no manual contract addresses. Watch the activation logs to see the chosen keystore path and the agent address.\n2. **Periodic incremental backup** — `openclaw coc-soul backup create` (auto runs hourly if `backup.autoBackup: true`).\n3. **Inspect agent state** — `openclaw coc-soul backup status` (summary), `openclaw coc-soul backup doctor` (actionable recommendations).\n4. **Delegation** — `openclaw coc-soul did delegate --delegator <agentId> --delegatee <targetId> --scope <hash> --expires <epoch> --depth 0`.\n5. **Guardian setup** — `openclaw coc-soul guardian add --agent-id <id> --guardian 0x...` (repeat for each guardian).\n6. **Emergency recovery** (you lost your owner key) — a guardian runs `openclaw coc-soul recovery initiate`, the quorum approves via `recovery approve`, then after timelock `recovery complete`.\n7. **Resurrection as carrier** — `openclaw coc-soul carrier register --endpoint https://...` on the hosting node; `openclaw coc-soul carrier start` runs the daemon.\n\n## When NOT to use this skill\n\n- Running a COC chain node yourself — use [coc-node](https://clawhub.ai/ngplateform/coc-node).\n- Local semantic memory **only** (no chain backup needed) — use [claw-mem2db](https://clawhub.ai/ngplateform/claw-mem2db) on its own. Add coc-soul on top later if you decide you want the data on-chain.\n- Smart contract deployment — that lives in the [COC source repo](https://github.com/NGPlateform/COC) `contracts/` tree.\n\n## Reference\n\nDetailed references live alongside this file:\n\n- `references/did.md` — full `did` subcommand tree, delegation semantics, ephemeral identities, credentials, lineage\n- `references/backup.md` — backup / restore / prune flows, encryption, semantic snapshot, categories\n- `references/guardian-recovery.md` — guardian lifecycle + social recovery timelock + quorum rules\n- `references/carrier.md` — carrier registration, daemon modes, resurrection request flow\n- `references/config.md` — complete `backup.*` + `carrier.*` config schema\n\nSource and issue tracker: <https://github.com/NGPlateform/claw-mem/tree/main/packages/soul>.\n\nFile v1.2.6:_meta.json\n\n{\n  \"ownerId\": \"kn73gc45g10tc38ft5zgd22q6581697m\",\n  \"slug\": \"coc-soul\",\n  \"version\": \"1.2.6\",\n  \"publishedAt\": 1777245628677\n}\n\nFile v1.2.6:references/backup.md\n\n# `coc-soul backup` — soul backup and restore\n\n## First-time\n\n- `backup init` — register the agent on SoulRegistry (if not yet registered), run a first **full** backup, write `~/.coc-backup/latest-recovery.json` with the decryption material + manifest CID.\n- `backup register` — register on-chain only, do not run a backup.\n\n## Periodic\n\n- `backup create` — incremental (default); `--full` forces a full backup regardless of chain length.\n  - `backup.autoBackup: true` + `backup.autoBackupIntervalMs` runs this on a timer inside the OpenClaw plugin.\n- `backup.backupOnSessionEnd: true` + a `session_end` hook from OpenClaw also triggers `backup create` when the agent's session closes.\n\n### Output: `backup create` recovery summary (1.2.6+)\n\nEvery successful `backup create` prints two blocks. The first is the receipt; the second is what the user needs to restore the backup later — relay it verbatim to the user (don't swallow it):\n\n```\nBackup complete (full):\n  manifest:   <cid>\n  files:      <n>\n  bytes:      <n>\n  merkleRoot: 0x...\n  txHash:     0x...           # only present if anchored on-chain\n\nRecovery info — keep this safe to restore on another host:\n  recovery package\n\nArchive v1.2.3: 7 files, 18078 bytes\n\nFiles: references/backup.md (5790b), references/carrier.md (4018b), references/config.md (5889b), references/did.md (4111b), references/guardian-recovery.md (4326b), SKILL.md (14785b), _meta.json (127b)\n\nArchive v1.2.0: 7 files, 10415 bytes\n\nFiles: references/backup.md (2381b), references/carrier.md (1995b), references/config.md (2090b), references/did.md (2166b), references/guardian-recovery.md (1923b), SKILL.md (10643b), _meta.json (127b)\n\nArchive v1.1.14: 7 files, 8947 bytes\n\nFiles: references/backup.md (2381b), references/carrier.md (1995b), references/config.md (2090b), references/did.md (2166b), references/guardian-recovery.md (1923b), SKILL.md (6788b), _meta.json (128b)\n\nArchive v1.1.13: 7 files, 8234 bytes\n\nFiles: references/backup.md (2381b), references/carrier.md (1995b), references/config.md (2090b), references/did.md (2166b), references/guardian-recovery.md (1923b), SKILL.md (4998b), _meta.json (128b)\n\nArchive v1.1.12: 7 files, 8086 bytes\n\nFiles: references/backup.md (2381b), references/carrier.md (1995b), references/config.md (2090b), references/did.md (2166b), references/guardian-recovery.md (1923b), SKILL.md (4625b), _meta.json (128b)\n\nArchive v1.1.11: 7 files, 8086 bytes\n\nFiles: references/backup.md (2381b), references/carrier.md (1995b), references/config.md (2090b), references/did.md (2166b), references/guardian-recovery.md (1923b), SKILL.md (4625b), _meta.json (128b)\n\nArchive v1.1.8: 7 files, 8085 bytes\n\nFiles: references/backup.md (2381b), references/carrier.md (1995b), references/config.md (2090b), references/did.md (2166b), references/guardian-recovery.md (1923b), SKILL.md (4623b), _meta.json (127b)","readmeExcerpt":"Skill: COC Soul Immortality Owner: ngplateform Summary: Give an AI agent a persistent on-chain soul on COC — register and manage the agent's decentralized identity (DID), anchor encrypted backups to IPFS + SoulReg... Tags: AI Agent DID Soul:1.0.0, latest:1.2.10 Version history: v1.2.10 | 2026-04-27T08:30:19.917Z | user coc-soul 1.2.9 - No file changes or user-facing updates were made in this version. - Version bump o","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"jq '.gateway.auth.mode' ~/.openclaw/openclaw.json"},{"language":"text","snippet":"Backup complete (full):\n  manifest:   bafyabc...\n  files:      127\n  bytes:      4194304\n  merkleRoot: 0xabc...\n  txHash:     0xdef...\n\nRecovery info — keep this safe to restore on another host:\n  recovery package: /home/<user>/.openclaw/.coc-backup/latest-recovery.json\n  encryption mode:  privateKey\n  signing key file: /home/<user>/.claw-mem/keys/agent.key (mode 0600 — copy off-host securely)\n  signer address:   0x...\n\nTo restore on another host (always restore to /tmp first, verify, then promote):\n  openclaw coc-soul backup restore --manifest-cid bafyabc... \\\n    --target-dir /tmp/openclaw-restore-test\n\n  (if you also have /home/<user>/.openclaw/.coc-backup/latest-recovery.json on the target host:)\n  openclaw coc-soul backup restore --latest-local --target-dir /tmp/openclaw-restore-test"},{"language":"bash","snippet":"openclaw coc-soul backup status\nopenclaw coc-soul did delegations --agent-id 0x..."},{"language":"bash","snippet":"coc-soul backup status"},{"language":"text","snippet":"Backup complete (full):\n  manifest:   <cid>\n  files:      <n>\n  bytes:      <n>\n  merkleRoot: 0x...\n  txHash:     0x...           # only present if anchored on-chain\n\nRecovery info — keep this safe to restore on another host:\n  recovery package: <sourceDir>/.coc-backup/latest-recovery.json\n  encryption mode:  none | privateKey | password\n  signing key file: <path>    # mode 0600 — copy off-host securely\n  signer address:   0x...\n\nTo restore on another host (always restore to /tmp first, verify, then promote):\n  openclaw coc-soul backup restore --manifest-cid <cid> \\\n    --target-dir /tmp/openclaw-restore-test [ --password '<pw>' ]\n\n  (if you also have <path>/latest-recovery.json on the target host:)\n  openclaw coc-soul backup restore --latest-local --target-dir /tmp/openclaw-restore-test [ --password '<pw>' ]"},{"language":"jsonc","snippet":"{\n  \"version\": 1,\n  \"agentId\": \"0x...\",\n  \"latestManifestCid\": \"bafy...\",\n  \"anchoredAt\": 1777180566,\n  \"txHash\": \"0x...\",\n  \"dataMerkleRoot\": \"0x...\",\n  \"backupType\": \"full\" | \"incremental\",\n  \"encryptionMode\": \"none\" | \"privateKey\" | \"password\",\n  \"requiresPassword\": false | true,\n  \"recommendedRestoreCommand\": \"openclaw coc-soul backup restore --latest-local --target-dir /tmp/openclaw-restore-test ...\"\n}"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: coc-soul\ndescription: Give an AI agent a persistent on-chain soul — register and manage a decentralized identity (DID), encrypt and anchor agent state to IPFS + SoulRegistry, configure guardians for social recovery, and enable cross-carrier resurrection so the agent can resume on a different device if the host dies. **Pairs with `claw-mem2db` to deliver \"digital / silicon-based persistence\" for AI agents**: when claw-mem is co-installed, every backup automatically captures claw-mem's chat history + tool-call observations + session summaries as a token-budgeted semantic snapshot, so an agent recovered on a fresh host can replay its memory context — not just its files. Soul also runs fully standalone (without claw-mem), in which case backups still cover identity / config / workspace / chat files but skip the semantic snapshot. Use when the user wants their AI agent to survive device loss, transfer ownership, delegate capabilities, run a guardian / carrier node, inspect on-chain identity state, or get persistent cross-device memory paired with claw-mem. Zero-config on COC testnet — installation auto-generates an EOA keystore (~/.claw-mem/keys, shared with claw-mem; or $OPENCLAW_STATE_DIR/coc-soul/keys in sandboxed hosts), auto-drips testnet COC from the public faucet for gas, and pre-fills RPC + IPFS + contract addresses for the live testnet. The first `openclaw coc-soul backup init` works with no manual setup.\nversion: 1.2.10\nmetadata:\n  openclaw:\n    homepage: https://www.npmjs.com/package/@chainofclaw/soul\n    primaryEnv: CLAW_MEM_DATA_DIR\n    requires:\n      bins:\n        - node\n      anyBins:\n        - coc-soul\n        - openclaw\n    install:\n      - kind: node\n        package: \"@chainofclaw/soul\"\n        version: \"1.2.6\"\n        bins:\n          - coc-soul\n---\n\n# coc-soul — agent identity, backup, and resurrection\n\nThe **soul layer** for AI agents: on-chain DID, encrypted backups to IPFS, social recovery via guardians, and cross-device resurrection via carriers. Backed by the npm package [`@chainofclaw/soul`](https://www.npmjs.com/package/@chainofclaw/soul) which ships both a standalone `coc-soul` CLI and an OpenClaw skill (id `coc-soul`).\n\nSoul works **standalone** (backs up the agent's home tree to chain + IPFS), and gets one extra capability when **`claw-mem2db` is installed alongside it**: each backup also captures claw-mem's chat history, tool-call observations, and session summaries as a token-budgeted semantic snapshot. Recover on a fresh host and the agent gets back not just its files but its remembered context — chat preferences, decisions, conversation history. **This is the \"digital / silicon-based persistence\" story.**\n\n---\n\n## 30-second decision tree (operators read here first)\n\nIf the user is asking \"how do I recover on another machine?\", pick **one** path before saying anything else:\n\n1. **Have backup material (manifest CID or `~/.openclaw/.coc-backup/latest-recovery.json`)** → use the **restore** path: `openclaw coc-so"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn73gc45g10tc38ft5zgd22q6581697m\",\n  \"slug\": \"coc-soul\",\n  \"version\": \"1.2.10\",\n  \"publishedAt\": 1777278619917\n}"},{"path":"references/backup.md","content":"# `coc-soul backup` — soul backup and restore\n\n## First-time\n\n- `backup init` — register the agent on SoulRegistry (if not yet registered), run a first **full** backup, write `~/.coc-backup/latest-recovery.json` with the decryption material + manifest CID.\n- `backup register` — register on-chain only, do not run a backup.\n\n## Periodic\n\n- `backup create` — incremental (default); `--full` forces a full backup regardless of chain length.\n  - `backup.autoBackup: true` + `backup.autoBackupIntervalMs` runs this on a timer inside the OpenClaw plugin.\n- `backup.backupOnSessionEnd: true` + a `session_end` hook from OpenClaw also triggers `backup create` when the agent's session closes.\n\n### Output: `backup create` recovery summary (1.2.6+)\n\nEvery successful `backup create` prints two blocks. The first is the receipt; the second is what the user needs to restore the backup later — relay it verbatim to the user (don't swallow it):\n\n```\nBackup complete (full):\n  manifest:   <cid>\n  files:      <n>\n  bytes:      <n>\n  merkleRoot: 0x...\n  txHash:     0x...           # only present if anchored on-chain\n\nRecovery info — keep this safe to restore on another host:\n  recovery package: <sourceDir>/.coc-backup/latest-recovery.json\n  encryption mode:  none | privateKey | password\n  signing key file: <path>    # mode 0600 — copy off-host securely\n  signer address:   0x...\n\nTo restore on another host (always restore to /tmp first, verify, then promote):\n  openclaw coc-soul backup restore --manifest-cid <cid> \\\n    --target-dir /tmp/openclaw-restore-test [ --password '<pw>' ]\n\n  (if you also have <path>/latest-recovery.json on the target host:)\n  openclaw coc-soul backup restore --latest-local --target-dir /tmp/openclaw-restore-test [ --password '<pw>' ]\n```\n\nThe `--password` clause appears only when `encryption mode = password`. In `privateKey` mode, the operator must instead make sure the right key is loaded on the target host (either by copying the keystore file or by setting `backup.privateKey` in target's config).\n\nThe same fields are persisted in `<sourceDir>/.coc-backup/latest-recovery.json` (a small JSON written atomically after every backup) so the info survives even if the operator missed the terminal output:\n\n```jsonc\n{\n  \"version\": 1,\n  \"agentId\": \"0x...\",\n  \"latestManifestCid\": \"bafy...\",\n  \"anchoredAt\": 1777180566,\n  \"txHash\": \"0x...\",\n  \"dataMerkleRoot\": \"0x...\",\n  \"backupType\": \"full\" | \"incremental\",\n  \"encryptionMode\": \"none\" | \"privateKey\" | \"password\",\n  \"requiresPassword\": false | true,\n  \"recommendedRestoreCommand\": \"openclaw coc-soul backup restore --latest-local --target-dir /tmp/openclaw-restore-test ...\"\n}\n```\n\nTreat both `latest-recovery.json` AND the signing-key file as a pair — back them up together (the manifest CID is also visible on-chain via the SoulRegistry contract, so even losing `latest-recovery.json` is recoverable from `backup find-recoverable --on-chain`, but losing the key means the encrypted payload is permanently unreadable).\n\n#"},{"path":"references/carrier.md","content":"# Carrier operations\n\nA **carrier** is a hosting node that can adopt and run an offline agent's soul. Carriers are discovered on-chain through `CarrierRegistered` events.\n\n## Registration\n\n| Command | Effect |\n|---|---|\n| `carrier register --carrier-id <id> --endpoint https://… --cpu-millicores 1000 --memory-mb 2048 --storage-mb 10240` | Publish availability on-chain |\n| `carrier deregister --carrier-id <id>` | Remove |\n| `carrier availability --carrier-id <id> --available <true\\|false>` | Flip the available flag without deregistering |\n\n## Discovery\n\n- `carrier list` — scan `CarrierRegistered` / `CarrierDeregistered` events (auto-chunked by 10000 blocks since 1.0.8)\n- `carrier info --carrier-id <id>` — fetch full record for a specific carrier\n\n## Daemon\n\nThe carrier daemon watches its inbox of pending resurrection requests and orchestrates the agent spawn.\n\n| Command | Effect |\n|---|---|\n| `carrier start` | Start the daemon (requires `backup.carrier.enabled: true` in config) |\n| `carrier stop` | Graceful shutdown |\n| `carrier status` | Is the daemon enabled + running? |\n| `carrier submit-request --request-id <id>` | Hand a specific pending request to the local daemon |\n\n## Resurrection inside the daemon\n\nFor each pending request the daemon:\n\n1. Verifies the carrier has been explicitly confirmed by guardians\n2. Downloads the agent's latest soul backup from IPFS\n3. Decrypts with the resurrection key (provided by the initiating guardian)\n4. Spawns the agent using `carrier.agentEntryScript` in `carrier.workDir`\n5. Reports back on-chain that the agent is alive\n\n## Configuration\n\nSee `backup.carrier.*` in the soul config schema. Critical knobs:\n\n- `enabled` (default `false`) — safety gate\n- `carrierId` — your on-chain carrier ID\n- `agentEntryScript` — path to the script that boots an agent from unpacked state\n- `workDir` (default `/tmp/coc-resurrections`, **strongly recommend overriding** to a persistent path like `~/.openclaw/state/coc-soul/carrier` — `/tmp` is wiped on reboot mid-resurrection)\n- `pollIntervalMs` (default 60000)\n- `readinessTimeoutMs` (default 86400000 = 24h)\n\n## Preconditions checklist (before going live as a carrier)\n\n1. `backup.carrier.enabled: true` in plugin config\n2. `backup.carrier.carrierId` set to the bytes32 you registered on-chain\n3. `backup.carrier.agentEntryScript` is an absolute path that exists and is executable\n4. `backup.carrier.workDir` points to a **persistent** directory with enough disk for an extracted agent (NOT `/tmp` on a host with reboots)\n5. The endpoint passed to `carrier register --endpoint` is actually reachable from the COC network\n6. At least one resurrection drill completed end-to-end (initiate → approve → submit-request → agent boot)\n\n## Failure-mode triage\n\n| Symptom | Cause | Action |\n|---|---|---|\n| `carrier start` returns \"carrier disabled\" | `backup.carrier.enabled` is false | Set it true and restart the gateway |\n| `carrier start` aborts with \"missing carrierId / agentEntryScript\" | required fi"},{"path":"references/config.md","content":"# `backup.*` + `carrier.*` config schema\n\nRead from `~/.chainofclaw/config.json` (or `$COC_SOUL_CONFIG`). The skill looks at the `backup` key; carrier config lives nested under `backup.carrier`.\n\n```json\n{\n  \"backup\": {\n    \"enabled\": true,\n    \"sourceDir\": \"~/.openclaw\",\n    \"rpcUrl\": \"http://localhost:18780\",\n    \"ipfsUrl\": \"http://localhost:5001\",\n    \"contractAddress\": \"0x...SoulRegistry...\",\n    \"didRegistryAddress\": \"0x...DIDRegistry...\",\n    \"rpcAuthToken\": \"optional-for-gated-rpcs\",\n    \"privateKey\": \"0x...\",\n    \"autoBackup\": true,\n    \"autoBackupIntervalMs\": 3600000,\n    \"maxIncrementalChain\": 10,\n    \"encryptMemory\": false,\n    \"encryptionPassword\": \"...\",\n    \"backupOnSessionEnd\": true,\n    \"semanticSnapshot\": {\n      \"enabled\": true,\n      \"tokenBudget\": 8000,\n      \"maxObservations\": 50,\n      \"maxSummaries\": 10\n    },\n    \"categories\": {\n      \"identity\": true,\n      \"config\": true,\n      \"memory\": true,\n      \"chat\": true,\n      \"workspace\": true,\n      \"database\": true\n    },\n    \"carrier\": {\n      \"enabled\": false,\n      \"carrierId\": \"0x...\",\n      \"agentEntryScript\": \"/path/to/agent-boot.sh\",\n      \"workDir\": \"/tmp/coc-resurrections\",\n      \"watchedAgents\": [],\n      \"pollIntervalMs\": 60000,\n      \"readinessTimeoutMs\": 86400000,\n      \"readinessPollMs\": 30000\n    }\n  }\n}\n```\n\n## Critical fields\n\n| Field | Required? | Notes |\n|---|---|---|\n| `rpcUrl` | yes | Must reach a COC node (local or public testnet) |\n| `contractAddress` | yes for write | SoulRegistry deployment address |\n| `didRegistryAddress` | yes for DID ops | |\n| `ipfsUrl` | yes for backup | Default `http://127.0.0.1:5001` (local Kubo) |\n| `privateKey` | yes for write | Use `chmod 600` on the config file |\n\n## Key handling\n\nFor testnet the anvil default key works fine. For mainnet:\n\n- Do **not** commit this file to git\n- Prefer hardware signer or cloud KMS (not currently supported by the CLI — in roadmap)\n- Keep the file mode `600`\n\n## Backup chain limit\n\n`maxIncrementalChain: 10` means after 10 incremental backups, the next one is forced to full. This bounds restore time.\n\n## Where config actually comes from (OpenClaw plugin mode)\n\nWhen running through `openclaw coc-soul ...` (plugin mode), the **authoritative** source is `~/.openclaw/openclaw.json` under:\n\n```jsonc\n{\n  \"plugins\": {\n    \"entries\": {\n      \"coc-soul\": {\n        \"enabled\": true,\n        \"config\": {\n          \"backup\": {\n            // ...same shape as the standalone schema above...\n          }\n        }\n      }\n    }\n  }\n}\n```\n\nThe standalone `coc-soul` bin still reads `~/.chainofclaw/config.json` / `$COC_SOUL_CONFIG`, but in plugin mode plugin config wins.\n\n## Minimal viable config (testnet)\n\n`coc-soul` ships testnet defaults for `rpcUrl` / `ipfsUrl` / `contractAddress` / `didRegistryAddress` / `faucetUrl`. Minimal explicit config:\n\n```jsonc\n{\n  \"plugins\": {\n    \"entries\": {\n      \"coc-soul\": {\n        \"enabled\": true,\n        \"config\": {\n          \"backup\": { \"enabled\": true }\n        }\n      }\n    }"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":2098,"uniquenessScore":42,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-11T19:50:38.341Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-11T19:50:38.341Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-11T22:57:46.308Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}