{"id":"migrate-from-openclaw","name":"migrate-from-openclaw","summary":"OpenClawからNanoClaw v2へ移行してください。既存のOpenClawインストールを検出し、アイデンティティ、チャネル認証情報、スケジュールされたタスク、その他の設定を抽出し、インタラクティブな移行を導きます。","body":"# Migrate from OpenClaw\n\nGuide the user through migrating their OpenClaw installation into NanoClaw v2.\nThis is a conversation, not a batch job. Read OpenClaw state, discuss it with\nthe user, decide together what to bring over and where it belongs in v2's\nentity model, and show proposed changes before applying.\n\n**Principle:** Never silently copy data. Read it, explain it, place it, then\napply. Credentials are masked when displayed (first 4 + `...` + last 4). Make\njudgment calls about what's core vs. reference material.\n\n**UX:** Use `AskUserQuestion` for multiple-choice only. Use plain text for\nfree-form input. Don't dump raw data — summarize and explain conversationally.\n\n## What this skill changes (conformance)\n\nThis skill drives existing NanoClaw entry points (`setup/index.ts --step\nregister`, `scripts/init-first-agent.ts`, the `onecli` CLI) and copies a few\nfiles in (workspace markdown, OpenClaw skills, and its own transform module +\ntest). It makes no code-level reach-in into core. Its integration assumptions\nabout v2 are guarded by `scripts/transform.test.ts`, which is copied into the\nproject's `scripts/` test tree on apply (Phase 8) so vitest runs it against the\ncomposed install. `REMOVE.md` reverses every file the skill copies.\n\n## v2 architecture the migration targets\n\nOpenClaw and NanoClaw v2 differ structurally. Keep these in mind throughout:\n\n- **Entity model.** v2's central DB (`data/v2.db`) holds `users`,\n  `user_roles`, `agent_groups`, `messaging_groups`, and the\n  `messaging_group_agents` wiring between them. There is no `store/messages.db`\n  and no `scheduled_tasks` table.\n- **Container isolation.** Each agent group runs in its own Linux container.\n  An OpenClaw \"agent\" maps to a v2 *agent group* (workspace + memory +\n  CLAUDE.md); an OpenClaw chat/group maps to a v2 *messaging group*; the wiring\n  row connects them.\n- **Standing instructions vs memory.** Per-group role, personality, and\n  behavior live in `groups/<folder>/instructions.prepend.md`. Durable facts\n  live under `groups/<folder>/memory/`. The provider project document is\n  composed at spawn and must not be edited.\n- **Credentials.** Container-facing API credentials (Anthropic, OpenAI, …) are\n  held in the OneCLI Agent Vault and injected per request — never in container\n  env vars. Host-side channel tokens (Telegram/Discord/Slack bot tokens) stay\n  in `.env`; the NanoClaw host process reads them to connect to the platform.\n- **Access control.** Per messaging group `unknown_sender_policy` plus\n  `user_roles` (owner/admin) and `agent_group_members` — not a JSON allowlist\n  file.\n- **Scheduled tasks.** A task is a `messages_in` row (`kind='task'`) in a\n  session's `inbound.db`, carrying a cron `recurrence` and a `process_after`\n  timestamp. The agent creates them via its `schedule_task` MCP tool.\n\n## Migration State File\n\nCreate `migration-state.md` in the project root at the start of Phase 0. Update\nit after each phase. It's the single source of truth — if context is lost,\nre-read it to recover decisions and progress. Re-read it before starting any\nphase.\n\nSections to maintain:\n\n- **Progress** — checkbox list of phases (Phase 0–8)\n- **Discovery** — STATE_DIR, IDENTITY_NAME, channels, groups (with v2\n  platform_id mappings), workspace files, cron count, MCP servers\n- **Decisions** — assistant_name, shared-vs-separate, primary owner agent\n- **Owner & Primary Agent** — user id, role, agent group folder\n- **Registered Groups** — table: folder, platform_id, channel, session_mode\n- **Credentials** — table: credential, destination (vault / .env), status\n- **Settings Migrated** — timezone, container timeout\n- **Identity & Memory** — prepend and memory paths created for each group\n- **Scheduled Tasks** — table: original_id, name, mapped schedule, status\n- **Deferred / Not Applicable** — unsupported channels, OpenClaw-only features\n\nKeep it factual and terse. Delete it at the end of Phase 8 (or offer to keep it\nas a record).\n\n## Phase 0: Discovery\n\nRun the discovery script to find and summarize the OpenClaw installation:\n\n```bash\npnpm exec tsx ${CLAUDE_SKILL_DIR}/scripts/discover-openclaw.ts\n```\n\nIf the user specifies a custom path, pass `--state-dir <path>`.\n\nParse the status block. Key fields: STATUS, STATE_DIR, CHANNELS,\nWORKSPACE_FILES, DAILY_MEMORY_FILES, SKILL_COUNT, SKILLS, CRON_JOBS,\nMCP_SERVERS, IDENTITY_NAME, AGENT_COUNT, AGENT_IDS, GROUPS (each formatted\n`channel:id(name)=>v2_platform_id` — the right-hand value is what to pass as\n`--platform-id` to register).\n\n**Sanity-check the output.** The script detects known structures but can miss\ndata if OpenClaw's format changed. Check `CONFIG_TOP_KEYS` and\n`CONFIG_CHANNEL_KEYS` — if you see keys it didn't report on, read that section\nof the config with the Read tool. Check `STATE_DIR_CONTENTS` for directories it\ndoesn't scan.\n\n**If STATUS=not_found:** Tell the user no OpenClaw install was detected at the\nstandard locations (`~/.openclaw`, `~/.clawdbot`). Ask for a custom path; if\nnone, exit.\n\n**If STATUS=found:** Present a human-readable summary (identity name, workspace\nfiles, channels and which v2 supports, daily memory count, skills, cron count,\nMCP servers, agent count). Then paraphrase the key architectural differences\nfrom the section above — don't dump it as a table.\n\nAskUserQuestion: \"Ready to start migrating? I'll go through each area one at a\ntime.\"\n1. **Yes, let's go** — proceed to Phase 1\n2. **Tell me more** — explain any area they ask about\n3. **Skip migration** — exit\n\n## Phase 1: Agents, Groups, and Shared vs Separate\n\n**Decide this before identity/memory** — it determines where files go.\n\n**OpenClaw model:** all groups routed to one agent share a workspace\n(SOUL/MEMORY/IDENTITY) and personality; only the session is per-group.\n\n**v2 model:** each agent group is a separate container with its own filesystem,\nstanding instructions, and `memory/` tree. Multiple messaging groups wired to\nthe same agent group share that state. There is no `groups/global/`.\n\nAskUserQuestion: \"In OpenClaw your groups shared one personality and memory. In\nv2 each agent group is separate. How do you want to handle this?\"\n\n1. **Shared identity (recommended if it was one bot)** — apply the same core\n   identity to each selected group's `instructions.prepend.md`; keep group\n   facts in each group's memory tree.\n2. **Fully separate** — each group gets independent memory and instructions; no\n   shared base edit.\n3. **Just the primary agent for now** — set one agent up; add others later.\n\nRemember this choice for Phase 3.\n\n### Confirm the assistant name\n\n`IDENTITY_NAME` from discovery is the OpenClaw name. Ask: \"Your OpenClaw\nassistant was named `<IDENTITY_NAME>`. Keep it in v2?\" If empty, ask them to\nchoose (default: \"Andy\"). The chosen name is passed as `--assistant-name` to\nregister/init.\n\n### Seed the owner and the primary DM agent\n\nThe owner identity and the primary agent are created together by\n`scripts/init-first-agent.ts`. It upserts the user, grants the owner role,\ncreates the agent group + filesystem, wires a DM messaging group, and queues a\nwelcome DM over the running service's CLI socket — **so the service must be\nrunning.** If it isn't, tell the user to start it first.\n\nResolve the owner's channel identity and the DM platform id (use the channel's\nown terminology). Then:\n\n```bash\npnpm exec tsx scripts/init-first-agent.ts \\\n  --channel <channel> \\\n  --user-id <channel>:<handle> \\\n  --platform-id <channel>:<dm-id> \\\n  --display-name \"<Owner Name>\" \\\n  --agent-name \"<confirmed assistant name>\" \\\n  [--role owner]      # default: owner\n```\n\nFor direct-addressable channels (telegram, whatsapp) the `--platform-id` is\nusually the same handle as `--user-id` with the channel prefix. `--role`\ndefaults to `owner` (global, cross-channel) — use `admin` (scoped to the agent\ngroup) or `member` only if intended.\n\n### Register the remaining groups\n\nFor each additional OpenClaw group the user wants to bring over, register a\nmessaging group and wire it to an agent group:\n\n```bash\npnpm exec tsx setup/index.ts --step register -- \\\n  --platform-id \"<v2_platform_id from discovery>\" \\\n  --name \"<group name>\" \\\n  --folder \"<channel>_<name-slug>\" \\\n  --channel \"<channel>\" \\\n  --session-mode \"<shared|agent-shared|per-thread>\" \\\n  [--trigger \"@<assistant name>\"] \\\n  [--no-trigger-required] \\\n  --assistant-name \"<assistant name>\"\n```\n\nNotes:\n- `register` namespaces the `--platform-id` the same way the adapter will at\n  runtime, so pass the `=>` value discovery emitted (or the raw OpenClaw id).\n- Reuse a `--folder` to put a group on an existing agent (shared base/separate\n  conversations); use a new `--folder` for a fully separate agent.\n- Engage defaults come from the channel adapter's declaration (most group\n  chats default to mention-based engagement; channels without a mention\n  signal default to a name pattern). Pass `--trigger` to set an explicit\n  regex, or `--no-trigger-required` for respond-to-everything.\n- Register groups from channels v2 doesn't support yet too — the messaging\n  group and wiring persist and activate when that channel is installed.\n\nFolder naming: `<channel>_<name-slug>` (e.g. `telegram_dev-team`). Confirm each\nname and folder with the user.\n\n## Phase 2: Settings from Config\n\nRead the config (`<STATE_DIR>/openclaw.json` or `clawdbot.json`) for settings\nthat map to v2 setup.\n\n### Timezone\n\nCheck `agents.defaults.userTimezone`. If it's a valid IANA zone, write it to\n`.env` as `TZ=<timezone>`. v2 reads `TZ` from `.env` (`src/config.ts`) and uses\nit for cron/recurrence evaluation, so this matters for scheduled tasks.\n\n### Container timeout\n\nCheck `agents.defaults.timeoutSeconds`. v2's equivalent is `CONTAINER_TIMEOUT`\n(env var, default 30 min) or per-group `ncl groups config update`. If the\nOpenClaw value differs notably, note it; the user can set\n`CONTAINER_TIMEOUT=<ms>` in `.env`.\n\n### Access control (sender policies)\n\nOpenClaw per-channel `allowFrom` / `dmPolicy` / `groupPolicy` map onto v2's\nmodel, which is **not** a JSON file. Each messaging group has an\n`unknown_sender_policy`; access is granted via `user_roles` (owner/admin) and\n`agent_group_members`. Map:\n\n- `dmPolicy`/`groupPolicy: \"open\"` → leave the default; no extra grants.\n- `allowFrom` / `groupAllowFrom` lists → for each allowed sender, upsert the\n  user and add them as a member of the relevant agent group via `ncl`:\n\n  ```bash\n  ncl users create --id \"<channel>:<handle>\" --kind <channel> --display-name \"<name>\"\n  ncl members add --user \"<channel>:<handle>\" --group \"<ag-id>\"\n  ```\n- `dmPolicy: \"disabled\"` → don't wire that chat (or leave it registered but\n  unwired).\n\nThe messaging groups `register` / `init-first-agent` create default their\n`unknown_sender_policy` to whatever the channel adapter declares for that\ncontext (DM vs group) — `strict` when the channel has no declaration — so\nunknown senders are gated until you add them (or an admin approves the\nadapter-declared approval card). Pass `--unknown-sender-policy` to `register`\nto override. Show the user the OpenClaw allowlist and confirm who to grant\nbefore running the commands.\n\n## Phase 3: Identity and Memory\n\nFully conversational — read files directly and discuss. **Placement depends on\nthe Phase 1 choice:**\n\n- **Shared identity:** merge the same core identity/personality into every\n  selected group's `instructions.prepend.md`.\n- **Fully separate / primary only:** merge identity/personality only into the\n  corresponding group's `instructions.prepend.md`.\n\nNever edit a composed `CLAUDE.md` or `AGENTS.md`; it is regenerated each spawn.\nPut standing behavior in `instructions.prepend.md` and facts in `memory/`.\n\nFind workspace files at `<STATE_DIR>/workspace/`. If `AGENT_COUNT > 1`, also\ncheck `<STATE_DIR>/agents/*/workspace/` and ask which agent maps to which v2\nagent group.\n\n### IDENTITY.md / SOUL.md\n\nRead them. Distinguish always-loaded vs reference:\n- **Standing behavior** (core traits, communication style, key rules) → weave\n  into the group's `instructions.prepend.md`.\n- **Reference** (backstory, extended guidelines) → a separate durable concept\n  in an appropriate folder under `groups/<folder>/memory/`, linked from that\n  folder's `index.md` and the root Map.\n\nChoose each memory folder based on which related information will be easiest to\nfind together; a folder may contain different concept types. Before writing the\nfirst concept into a new folder, create the folder and its `index.md`. Follow\n`memory/system/definition.md`, including its YAML frontmatter rules, for every\nnew concept.\n\nShow proposed edits before applying — this is a thoughtful merge, not a paste.\n\n### USER.md\n\nCreate a focused user-context concept in an appropriate memory folder and link\nit through that folder's index and the root Map. Put only facts relevant in\nnearly every conversation (for example name or timezone) into `## Core Memory`;\nkeep all other details in the linked file.\n\n### MEMORY.md and daily memory files\n\nShow `MEMORY.md`; keep relevant items in focused concepts under the chosen\nmemory folders, with links through each folder index and the root Map. For\ndaily files (`workspace/memory/*.md`, count = DAILY_MEMORY_FILES):\n\nAskUserQuestion: \"You have N daily memory files. How to handle them?\"\n1. **Copy as-is** — agree on a descriptive folder, create it and its `index.md`,\n   then copy with `cp <workspace>/memory/*.md <group_dir>/memory/<chosen-folder>/`\n   and link the retained files through its index and the root Map.\n2. **Consolidate** — read, extract durable facts, and place them in focused\n   linked memory files.\n3. **Skip.**\n\n### OpenClaw skills\n\nIf `SKILL_COUNT > 0`, the SKILL.md format is shared, so skills are portable.\nPresent each (name + description from the front matter) and let the user pick.\nFor each confirmed skill, copy the directory into the container skills tree:\n\n```bash\ncp -r <skill_source_dir> container/skills/<skill_name>\n```\n\nA container rebuild is needed afterward — note it for Phase 8.\n\n### Config-registered plugins (with API keys)\n\nIf `CONFIG_PLUGINS` is non-empty, OpenClaw had plugins/skills carrying keys.\nFor each, read the config section and decide together:\n- **Matching v2 skill** → run that skill; route its credential per Phase 4.\n- **An MCP server** → install the exact configured package; wire via\n  `ncl groups config add-mcp-server`. Don't guess at packages.\n- **An API key** → route to the OneCLI vault if container-facing (Phase 4).\n\nDon't install unknown packages or search for replacements — supply-chain risk.\n\n## Phase 4: Credentials\n\nTwo destinations, decided per credential. **Channel tokens → `.env`** (host\nreads them). **Container-facing API credentials → the OneCLI vault** (injected\nper request, never in container env).\n\n### Channel tokens (telegram, discord, slack)\n\nPreview, then write to `.env`. The script emits only masked values:\n\n```bash\npnpm exec tsx ${CLAUDE_SKILL_DIR}/scripts/extract-channel-credentials.ts \\\n  --state-dir <STATE_DIR> --channel <name>\n```\n\nParse the status block. `DESTINATION: env` confirms a host-side token. Show\n`CREDENTIAL_MASKED` (and `CREDENTIAL_MASKED_2` for Slack's app token).\n\nAskUserQuestion:\n1. **Use this credential** — re-run with `--write-env .env` to save it.\n2. **Enter a new one** — ask in plain text, write to `.env` yourself.\n3. **Skip this channel.**\n\n```bash\npnpm exec tsx ${CLAUDE_SKILL_DIR}/scripts/extract-channel-credentials.ts \\\n  --state-dir <STATE_DIR> --channel <name> --write-env .env\n```\n\nCheck `WRITTEN_TO` / `WRITTEN_COUNT`. Slack writes both `SLACK_BOT_TOKEN` and\n`SLACK_APP_TOKEN` in one run.\n\n**If `HAS_CREDENTIAL=false` but a credential is expected:** the config shape may\nbe unrecognized, or it uses a `file`/`exec` SecretRef (`CREDENTIAL_SOURCE`\nends in `_ref` with a NOTE) that can't be auto-extracted. Read the channel\nsection of the config directly and ask the user to confirm or paste the value.\n\n**WhatsApp:** authenticates via QR/pairing code — there's no token. Don't copy\nBaileys auth state (stale encryption sessions break decryption).\nRe-authenticate during `/setup` via `/add-whatsapp`. The extraction script\nreports `DESTINATION: none` for it.\n\n### Anthropic and other container-facing credentials → OneCLI vault\n\nFind the agent's model credentials in OpenClaw. Check, in order:\n1. `<STATE_DIR>/auth-profiles.json` (and\n   `<STATE_DIR>/agents/<id>/agent/auth-profiles.json`) — a `profiles` map keyed\n   `provider:identifier`. For an `anthropic` provider profile the value depends\n   on `type`: `api_key` → `key`, `token` → `token`, `oauth` → `access`.\n2. `<STATE_DIR>/.env` — `ANTHROPIC_API_KEY` or `CLAUDE_CODE_OAUTH_TOKEN`.\n3. Config `models.providers` — Anthropic provider `apiKey`.\n\nThese are container-facing, so they go to the OneCLI vault. Do **not** write\nthem to `.env` or thread them into a container. Register each in the vault:\n\n```bash\nonecli secrets create --name Anthropic --type anthropic \\\n  --value <key-or-token> --host-pattern api.anthropic.com\n```\n\nFor other container-facing keys discovered in plugins (e.g. OpenAI):\n\n```bash\nonecli secrets create --name OpenAI --type api_key \\\n  --value <key> --host-pattern api.openai.com\n```\n\nRun the command on the user's behalf so the value never lands in the chat\ntranscript; confirm with `onecli secrets list`.\n\n**Caveats:** `keyRef`/`tokenRef` with `source:\"exec\"` or `source:\"file\"` can't\nbe auto-extracted — ask the user to paste it. For an `oauth` profile with a\npast expiry, warn that the token may need refreshing; the user can run\n`claude setup-token` and register the fresh token.\n\nIf OneCLI isn't installed yet, defer this: tell the user that during `/setup`\n(or `/init-onecli`) they'll register the Anthropic credential, and note the\ndiscovered profile in `migration-state.md` so it isn't lost.\n\n> There is no supported `.env`-credentials opt-out anymore: the session spec's\n> admission rules refuse credential values in container env on every lane, by\n> design (the retired `/use-native-credential-proxy` skill would be denied at\n> every spawn). Credentials go through the OneCLI vault; custom Anthropic\n> endpoints use `ANTHROPIC_BASE_URL` plus the placeholder-token pattern from\n> setup, with the gateway rewriting the header on the wire.\n\n## Phase 5: Scheduled Tasks\n\nRead `<STATE_DIR>/cron/jobs.json`. If absent or empty, skip.\n\nIf jobs exist, read `${CLAUDE_SKILL_DIR}/MIGRATE_CRONS.md` for the v2 task\nmodel, the `mapCronToRecurrence` transform, the full field mapping, and how\ntasks are created (the agent's `schedule_task` MCP tool, since tasks live in a\nper-session `inbound.db` the host owns). Follow it for each enabled job.\n\n## Phase 6: MCP, Webhooks, Other Config\n\nRead the relevant config sections directly. Conversational.\n\n### MCP servers\n\nIf `MCP_SERVERS` is non-empty, v2 supports per-agent-group MCP servers via the\ncontainer config. Read each server's `command`/`args`/`env`/`url` from\n`mcp.servers`. For each one the user wants:\n\n```bash\nncl groups config add-mcp-server --id <agent-group-id> \\\n  --name <server-name> --command <cmd> \\\n  [--args '<json-array>'] [--env '<json-object>']\n```\n\nstdio servers must be runnable inside the container (Node/npx-based work;\ncustom binaries need a Dockerfile addition). Secrets referenced by a server's\n`env` should go to the OneCLI vault (Phase 4), not be inlined. The config\nchange takes effect on restart: `ncl groups restart --id <agent-group-id>`\n(add `--rebuild` only if a custom binary was added to the Dockerfile).\n\n### Webhooks\n\nOpenClaw `cron.webhook` / `failureDestination` / channel webhooks don't map to\na v2 primitive. For a notification webhook, fold it into a scheduled task's\nprompt or a pre-agent `script` that `curl`s the endpoint. Discuss the use case.\n\n### Other config (mention and move on)\n\n- **Exec approvals / command allowlist** → v2 uses container isolation; the\n  agent runs sandboxed.\n- **Human delay / TTS / compaction / model config** → not v2 task/group fields\n  (per-group model is in the container config).\n\n## Phase 7: Welcome and First Run\n\n`init-first-agent` (Phase 1) already queued a welcome DM for the primary owner\nagent. If the service was up, the owner should have received it. For groups\nregistered via `setup --step register`, the wiring also queues a `/welcome`\nonboarding message on first wiring.\n\nTell the user which agents are live now and which await channel installation\n(unsupported channels registered for the future).\n\n## Phase 8: Validate and Summarize\n\n### Run the shipped test\n\nCopy the transform module and its test into the project so vitest runs them\nagainst the composed install, then build and test:\n\n```bash\ncp ${CLAUDE_SKILL_DIR}/scripts/transform.ts        scripts/openclaw-transform.ts\ncp ${CLAUDE_SKILL_DIR}/scripts/transform.test.ts   scripts/openclaw-transform.test.ts\n# Point the copied test at the copied module name:\nsed -i.bak \"s#from './transform.js'#from './openclaw-transform.js'#\" scripts/openclaw-transform.test.ts && rm -f scripts/openclaw-transform.test.ts.bak\n\npnpm run build\npnpm exec vitest run scripts/openclaw-transform.test.ts\n```\n\nThe test guards the skill's two v2 integration assumptions: credential routing\n(container-facing → vault, channel tokens → `.env`) and the cron → v2\nrecurrence mapping. It imports the real `cron-parser` (the same parser the host\nrecurrence sweep uses), so a missing/renamed dependency turns it red. `build`\ntypechecks the transform module against the project.\n\nThese copied files are the only files the skill installs into the project tree;\n`REMOVE.md` deletes them.\n\n### If a container rebuild is needed\n\nIf OpenClaw skills were copied or MCP servers added: `./container/build.sh`,\nthen restart the service.\n\n### Summary\n\nPrint what was migrated:\n- Owner + primary agent → `users` / `user_roles` / agent group + welcome DM\n- Additional groups → messaging groups + wiring (folders + session modes)\n- Timezone → `.env TZ`; container timeout → noted\n- Access grants → members/roles for OpenClaw allowlist senders\n- Identity/personality → per-group `instructions.prepend.md` + linked memory concepts\n- User context / memories → Core Memory only for universal facts; otherwise\n  linked concepts in content-based folders under `memory/`\n- OpenClaw skills → `container/skills/`\n- Channel tokens → `.env` (list channels)\n- Container-facing credentials → OneCLI vault (list)\n- Scheduled tasks → mapped and scheduled via the agent (or noted for first run)\n- MCP servers → wired into agent group container configs\n\nNoted for later: channel installs during `/setup`; container rebuild if needed;\ntasks deferred until a session exists.\n\nNot applicable: unsupported channels (registered for the future); OpenClaw-only\nfeatures (exec approvals, human delay, TTS, model/thinking config).\n\nRemind: \"Run `/setup` next to finish your NanoClaw install. Channel tokens are\nin `.env`; container-facing credentials are in the OneCLI vault. Select the\nchannels we configured when setup asks.\"\n\nThen delete `migration-state.md` (or offer to keep it as a record), and remove\nthe copied transform files if you don't want them lingering (see `REMOVE.md`).\n\n## Troubleshooting\n\n- **Config parse error:** the JSON5 parser may not handle unusual syntax. Read\n  the file directly and work with it manually.\n- **Credential not found:** likely a `file`/`exec` SecretRef — ask the user to\n  paste the value.\n- **`init-first-agent` can't reach the CLI socket:** the service isn't running.\n  Start it, then re-run.\n- **Multi-agent complexity:** do the primary/default agent first; add others as\n  separate agent groups later.","author":"@nanocoai","ownerProfile":null,"authorContacts":null,"sourceUrl":"https://github.com/nanocoai/nanoclaw/tree/main/.claude/skills/migrate-from-openclaw","license":"MIT","category":"writing","lang":"en","tokens":5819,"stars":0,"calls30d":2,"claimed":false,"visibility":"public","origin":"crawler","version":"0.1.0","createdAt":"2026-08-22","updatedAt":"2026-08-22","files":[{"path":"MIGRATE_CRONS.md","size":6212,"sha256":"4b7ce0941f9090703dcba91eac68729c896f1bc3c261deb5973ee6ced14c70b4"},{"path":"REMOVE.md","size":2935,"sha256":"39820ef88af0a1fd94a668629e210d95f00ee28dded16367839edfb97f1231d5"},{"path":"scripts/discover-openclaw.ts","size":23701,"sha256":"540443333d1ba871165c6a1145afe253ce660f4877c60bae8c362f74630238fa"},{"path":"scripts/extract-channel-credentials.ts","size":10097,"sha256":"1c9ff9a270e387156b0fc61784d30847bce6b6a2de084b2e45619a7c9c8a38f3"},{"path":"scripts/transform.test.ts","size":7512,"sha256":"88cb8e5c61237c5c4c2b45b735b50fc83558a41b46ca4dc34cedb9a3300a2605"},{"path":"scripts/transform.ts","size":11543,"sha256":"fccc2571c382c50fc381b8727623c3e5c56f28c59f02b1770f750584dd0d9df3"}],"requires":{"mcp":[],"tools":[]},"safety":{"flags":[],"scannedAt":"2026-08-22","hasScripts":true,"networkEndpoints":[]}}