AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
SKILL verified MIT Self-run

Migrate From Openclaw

skill-nanocoai-nanoclaw-migrate-from-openclaw · by nanocoai

Migrate from OpenClaw to NanoClaw v2. Detects an existing OpenClaw installation, extracts identity, channel credentials, scheduled tasks, and other config, then guides interactive migration. Triggers on "migrate from openclaw", "openclaw migration", "import from openclaw".

No reviews yet
0 installs
2 views
0.0% view→install

Install

$ agentstack add skill-nanocoai-nanoclaw-migrate-from-openclaw

✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution No
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Verified badge

Passed review? Show it. Paste this badge into your README, it links to the public security report.

AgentStack Verified badge Links to your public security report.
[![AgentStack Verified](https://agentstack.voostack.com/badges/verified.svg)](https://agentstack.voostack.com/security/report/skill-nanocoai-nanoclaw-migrate-from-openclaw)

Reliability & compatibility

Security review passed
0 installs to date
no reviews yet
1mo ago

Declared compatibility

Claude CodeClaude Desktop

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Migrate From Openclaw? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

Migrate from OpenClaw

Guide the user through migrating their OpenClaw installation into NanoClaw v2. This is a conversation, not a batch job. Read OpenClaw state, discuss it with the user, decide together what to bring over and where it belongs in v2's entity model, and show proposed changes before applying.

Principle: Never silently copy data. Read it, explain it, place it, then apply. Credentials are masked when displayed (first 4 + ... + last 4). Make judgment calls about what's core vs. reference material.

UX: Use AskUserQuestion for multiple-choice only. Use plain text for free-form input. Don't dump raw data — summarize and explain conversationally.

What this skill changes (conformance)

This skill drives existing NanoClaw entry points (setup/index.ts --step register, scripts/init-first-agent.ts, the onecli CLI) and copies a few files in (workspace markdown, OpenClaw skills, and its own transform module + test). It makes no code-level reach-in into core. Its integration assumptions about v2 are guarded by scripts/transform.test.ts, which is copied into the project's scripts/ test tree on apply (Phase 8) so vitest runs it against the composed install. REMOVE.md reverses every file the skill copies.

v2 architecture the migration targets

OpenClaw and NanoClaw v2 differ structurally. Keep these in mind throughout:

  • Entity model. v2's central DB (data/v2.db) holds users,

user_roles, agent_groups, messaging_groups, and the messaging_group_agents wiring between them. There is no store/messages.db and no scheduled_tasks table.

  • Container isolation. Each agent group runs in its own Linux container.

An OpenClaw "agent" maps to a v2 agent group (workspace + memory + CLAUDE.md); an OpenClaw chat/group maps to a v2 messaging group; the wiring row connects them.

  • Shared vs per-group context. v2 has no groups/global/. Shared

instructions live in container/CLAUDE.md (mounted read-only into every container). Per-group memory is groups//CLAUDE.local.md; the CLAUDE.md in each group is composed at spawn — do not edit it.

  • Credentials. Container-facing API credentials (Anthropic, OpenAI, …) are

held in the OneCLI Agent Vault and injected per request — never in container env vars. Host-side channel tokens (Telegram/Discord/Slack bot tokens) stay in .env; the NanoClaw host process reads them to connect to the platform.

  • Access control. Per messaging group unknown_sender_policy plus

user_roles (owner/admin) and agent_group_members — not a JSON allowlist file.

  • Scheduled tasks. A task is a messages_in row (kind='task') in a

session's inbound.db, carrying a cron recurrence and a process_after timestamp. The agent creates them via its schedule_task MCP tool.

Migration State File

Create migration-state.md in the project root at the start of Phase 0. Update it after each phase. It's the single source of truth — if context is lost, re-read it to recover decisions and progress. Re-read it before starting any phase.

Sections to maintain:

  • Progress — checkbox list of phases (Phase 0–8)
  • Discovery — STATEDIR, IDENTITYNAME, channels, groups (with v2

platform_id mappings), workspace files, cron count, MCP servers

  • Decisions — assistant_name, shared-vs-separate, primary owner agent
  • Owner & Primary Agent — user id, role, agent group folder
  • Registered Groups — table: folder, platformid, channel, sessionmode
  • Credentials — table: credential, destination (vault / .env), status
  • Settings Migrated — timezone, container timeout
  • Identity & Memory — paths of files created, which CLAUDE.local.md edited
  • Scheduled Tasks — table: original_id, name, mapped schedule, status
  • Deferred / Not Applicable — unsupported channels, OpenClaw-only features

Keep it factual and terse. Delete it at the end of Phase 8 (or offer to keep it as a record).

Phase 0: Discovery

Run the discovery script to find and summarize the OpenClaw installation:

pnpm exec tsx ${CLAUDE_SKILL_DIR}/scripts/discover-openclaw.ts

If the user specifies a custom path, pass --state-dir .

Parse the status block. Key fields: STATUS, STATEDIR, CHANNELS, WORKSPACEFILES, DAILYMEMORYFILES, SKILLCOUNT, SKILLS, CRONJOBS, MCPSERVERS, IDENTITYNAME, AGENTCOUNT, AGENTIDS, GROUPS (each formatted channel:id(name)=>v2_platform_id — the right-hand value is what to pass as --platform-id to register).

Sanity-check the output. The script detects known structures but can miss data if OpenClaw's format changed. Check CONFIG_TOP_KEYS and CONFIG_CHANNEL_KEYS — if you see keys it didn't report on, read that section of the config with the Read tool. Check STATE_DIR_CONTENTS for directories it doesn't scan.

If STATUS=not_found: Tell the user no OpenClaw install was detected at the standard locations (~/.openclaw, ~/.clawdbot). Ask for a custom path; if none, exit.

If STATUS=found: Present a human-readable summary (identity name, workspace files, channels and which v2 supports, daily memory count, skills, cron count, MCP servers, agent count). Then paraphrase the key architectural differences from the section above — don't dump it as a table.

AskUserQuestion: "Ready to start migrating? I'll go through each area one at a time."

  1. Yes, let's go — proceed to Phase 1
  2. Tell me more — explain any area they ask about
  3. Skip migration — exit

Phase 1: Agents, Groups, and Shared vs Separate

Decide this before identity/memory — it determines where files go.

OpenClaw model: all groups routed to one agent share a workspace (SOUL/MEMORY/IDENTITY) and personality; only the session is per-group.

v2 model: each agent group is a separate container with its own filesystem, memory, and CLAUDE.local.md. Shared instructions are placed in container/CLAUDE.md (read-only in every container). There is no groups/global/.

AskUserQuestion: "In OpenClaw your groups shared one personality and memory. In v2 each agent group is separate. How do you want to handle this?"

  1. Shared base (recommended if it was one bot) — core personality/identity

goes in container/CLAUDE.md (every container sees it); each group adds its own CLAUDE.local.md on top.

  1. Fully separate — each group gets independent memory and instructions; no

shared base edit.

  1. Just the primary agent for now — set one agent up; add others later.

Remember this choice for Phase 3.

Confirm the assistant name

IDENTITY_NAME from discovery is the OpenClaw name. Ask: "Your OpenClaw assistant was named `. Keep it in v2?" If empty, ask them to choose (default: "Andy"). The chosen name is passed as --assistant-name` to register/init.

Seed the owner and the primary DM agent

The owner identity and the primary agent are created together by scripts/init-first-agent.ts. It upserts the user, grants the owner role, creates the agent group + filesystem, wires a DM messaging group, and queues a welcome DM over the running service's CLI socket — so the service must be running. If it isn't, tell the user to start it first.

Resolve the owner's channel identity and the DM platform id (use the channel's own terminology). Then:

pnpm exec tsx scripts/init-first-agent.ts \
  --channel  \
  --user-id : \
  --platform-id : \
  --display-name "" \
  --agent-name "" \
  [--role owner]      # default: owner

For direct-addressable channels (telegram, whatsapp) the --platform-id is usually the same handle as --user-id with the channel prefix. --role defaults to owner (global, cross-channel) — use admin (scoped to the agent group) or member only if intended.

Register the remaining groups

For each additional OpenClaw group the user wants to bring over, register a messaging group and wire it to an agent group:

pnpm exec tsx setup/index.ts --step register -- \
  --platform-id "" \
  --name "" \
  --folder "_" \
  --channel "" \
  --session-mode "" \
  [--trigger "@"] \
  [--no-trigger-required] \
  --assistant-name ""

Notes:

  • register namespaces the --platform-id the same way the adapter will at

runtime, so pass the => value discovery emitted (or the raw OpenClaw id).

  • Reuse a --folder to put a group on an existing agent (shared base/separate

conversations); use a new --folder for a fully separate agent.

  • Group chats default to mention-only; pass --trigger to set a regex, or

--no-trigger-required for respond-to-everything.

  • Register groups from channels v2 doesn't support yet too — the messaging

group and wiring persist and activate when that channel is installed.

Folder naming: _ (e.g. telegram_dev-team). Confirm each name and folder with the user.

Phase 2: Settings from Config

Read the config (/openclaw.json or clawdbot.json) for settings that map to v2 setup.

Timezone

Check agents.defaults.userTimezone. If it's a valid IANA zone, write it to .env as TZ=. v2 reads TZ from .env (src/config.ts) and uses it for cron/recurrence evaluation, so this matters for scheduled tasks.

Container timeout

Check agents.defaults.timeoutSeconds. v2's equivalent is CONTAINER_TIMEOUT (env var, default 30 min) or per-group ncl groups config update. If the OpenClaw value differs notably, note it; the user can set CONTAINER_TIMEOUT= in .env.

Access control (sender policies)

OpenClaw per-channel allowFrom / dmPolicy / groupPolicy map onto v2's model, which is not a JSON file. Each messaging group has an unknown_sender_policy; access is granted via user_roles (owner/admin) and agent_group_members. Map:

  • dmPolicy/groupPolicy: "open" → leave the default; no extra grants.
  • allowFrom / groupAllowFrom lists → for each allowed sender, upsert the

user and add them as a member of the relevant agent group via ncl:

``bash ncl users create --id ":" --kind --display-name "" ncl members add --user ":" --group "" ``

  • dmPolicy: "disabled" → don't wire that chat (or leave it registered but

unwired).

The messaging groups register / init-first-agent create already default to unknown_sender_policy = 'strict', so unknown senders are gated until you add them. Show the user the OpenClaw allowlist and confirm who to grant before running the commands.

Phase 3: Identity and Memory

Fully conversational — read files directly and discuss. Placement depends on the Phase 1 choice:

  • Shared base: core identity/personality → container/CLAUDE.md (seen by

all containers, read-only). Group specifics → that group's groups//CLAUDE.local.md.

  • Fully separate / primary only: everything → the primary agent's

groups//CLAUDE.local.md.

Never edit a group's composed CLAUDE.md — it's regenerated each spawn. Edit CLAUDE.local.md (or container/CLAUDE.md for the shared base).

Find workspace files at /workspace/. If AGENT_COUNT > 1, also check /agents/*/workspace/ and ask which agent maps to which v2 agent group.

IDENTITY.md / SOUL.md

Read them. Distinguish always-loaded vs reference:

  • Always loaded (core traits, communication style, key rules) → weave into

container/CLAUDE.md (shared) or the group's CLAUDE.local.md (separate).

  • Reference (backstory, extended guidelines) → a separate

groups//soul.md, with a one-line pointer in CLAUDE.local.md: "Extended personality is in soul.md."

Show proposed edits before applying — this is a thoughtful merge, not a paste.

USER.md

Create groups//user-context.md and add a pointer in CLAUDE.local.md. Ask whether any critical facts (name, timezone, key prefs) should go directly into CLAUDE.local.md for always-on awareness.

MEMORY.md and daily memory files

Show MEMORY.md; keep relevant items in groups//memories.md with a pointer. For daily files (workspace/memory/*.md, count = DAILYMEMORYFILES):

AskUserQuestion: "You have N daily memory files. How to handle them?"

  1. Copy as-iscp /memory/*.md /daily-memories/,

add a pointer in CLAUDE.local.md.

  1. Consolidate — read, extract durable facts, append to memories.md.
  2. Skip.

OpenClaw skills

If SKILL_COUNT > 0, the SKILL.md format is shared, so skills are portable. Present each (name + description from the front matter) and let the user pick. For each confirmed skill, copy the directory into the container skills tree:

cp -r  container/skills/

A container rebuild is needed afterward — note it for Phase 8.

Config-registered plugins (with API keys)

If CONFIG_PLUGINS is non-empty, OpenClaw had plugins/skills carrying keys. For each, read the config section and decide together:

  • Matching v2 skill → run that skill; route its credential per Phase 4.
  • An MCP server → install the exact configured package; wire via

ncl groups config add-mcp-server. Don't guess at packages.

  • An API key → route to the OneCLI vault if container-facing (Phase 4).

Don't install unknown packages or search for replacements — supply-chain risk.

Phase 4: Credentials

Two destinations, decided per credential. Channel tokens → .env (host reads them). Container-facing API credentials → the OneCLI vault (injected per request, never in container env).

Channel tokens (telegram, discord, slack)

Preview, then write to .env. The script emits only masked values:

pnpm exec tsx ${CLAUDE_SKILL_DIR}/scripts/extract-channel-credentials.ts \
  --state-dir  --channel 

Parse the status block. DESTINATION: env confirms a host-side token. Show CREDENTIAL_MASKED (and CREDENTIAL_MASKED_2 for Slack's app token).

AskUserQuestion:

  1. Use this credential — re-run with --write-env .env to save it.
  2. Enter a new one — ask in plain text, write to .env yourself.
  3. Skip this channel.
pnpm exec tsx ${CLAUDE_SKILL_DIR}/scripts/extract-channel-credentials.ts \
  --state-dir  --channel  --write-env .env

Check WRITTEN_TO / WRITTEN_COUNT. Slack writes both SLACK_BOT_TOKEN and SLACK_APP_TOKEN in one run.

If HAS_CREDENTIAL=false but a credential is expected: the config shape may be unrecognized, or it uses a file/exec SecretRef (CREDENTIAL_SOURCE ends in _ref with a NOTE) that can't be auto-extracted. Read the channel section of the config directly and ask the user to confirm or paste the value.

WhatsApp: authenticates via QR/pairing code — there's no token. Don't copy Baileys auth state (stale encryption sessions break decryption). Re-authenticate during /setup via /add-whatsapp. The extraction script reports DESTINATION: none for it.

Anthropic and other container-facing credentials → OneCLI vault

Find the agent's model credentials in OpenClaw. Check, in order:

  1. /auth-profiles.json (and

/agents//agent/auth-profiles.json) — a profiles map keyed provider:identifier. For an anthropic provider profile the value depends on type: api_keykey, tokentoken, oauthaccess.

  1. /.envANTHROPIC_API_KEY or CLAUDE_CODE_OAUTH_TOKEN.
  2. Config models.providers — Anthropic provider apiKey.

These are container-facing, so they go to the OneCLI vault. Do not write them to .env or thread them into a container. Register each in the vault:

onecli secrets create --name Anthropic --type anthropic \
  --value  --host-pattern api.anthropic.com

For other container-facing keys discovered in plugins (e.g. OpenAI):

onecli secrets create --name OpenAI --type api_key \
  --value  --host-pattern api.openai.com

Run the command on the user's behalf so the value never lands in the chat transcript; confirm with onecli secrets list.

Caveats: keyRef/tokenRef with source:"exec" or source:"file" can't be auto-extracted — ask the user to paste it. For an oauth profile with a past expiry,

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.