add-anydoc
Add local office-document-to-Markdown conversion to NanoClaw agent containers with the pinned Firecrawl AnyDoc CLI. Use when agents need to read attached Word,…
Finish migrating a NanoClaw v1 install into v2. Run after `bash migrate-v2.sh` completes. Seeds the owner, migrates legacy memory, reconciles container configs, and helps port custom v1 code. Triggers on "migrate from v1", "finish migration", "v1 migration".
$ npx -y skills add nanocoai/nanoclaw --skill migrate-from-v1 --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/migrate-from-v1Context preview
The summary Claude sees to decide when to auto-load this skill.
Finish migrating a NanoClaw v1 install into v2. Run after `bash migrate-v2.sh` completes. Seeds the owner, migrates legacy memory, reconciles container configs, and helps port custom v1 code. Triggers on "migrate from v1", "finish migration", "v1 migration".
name: migrate-from-v1 description: Finish migrating a NanoClaw v1 install into v2. Run after `bash migrate-v2.sh` completes. Seeds the owner, migrates legacy memory, reconciles container configs, and helps port custom v1 code. Triggers on "migrate from v1", "finish migration", "v1 migration".
`bash migrate-v2.sh` already ran the deterministic migration. It handled:
Your job is the parts that need human judgment: triage failed steps, seed the owner, run the shared-memory migration, reconcile configs, and port fork customizations.
Read `logs/setup-migration/handoff.json` first — it has `overall_status`, per-step results in `steps`, and a `followups` list.
Before anything else, check that `logs/setup-migration/handoff.json` exists. If it doesn't, the user is invoking this skill before `migrate-v2.sh` ran. Stop and tell them, verbatim:
> This skill finishes a migration that `migrate-v2.sh` started. Run that first, in your terminal — not from inside Claude: > > ```bash > bash migrate-v2.sh > ``` > > It needs interactive prompts (channel selection, service switchover) and runs Node/pnpm bootstrap, Docker, OneCLI setup, and a container build that don't fit inside a Claude session. When it finishes, it'll hand control back to Claude automatically — at which point this skill picks up.
Do not attempt to run the script yourself, simulate its effects, or pick up the migration mid-stream. The deterministic side has dependencies on a real interactive shell.
Once `handoff.json` exists, proceed to Phase 0.
Before any deeper migration work, prove v2 actually answers messages on the user's real channels. v1 is paused, not touched — flipping back is a service restart.
Walk `handoff.steps`. Fix only the failures that would stop the bot from routing one message; defer the rest to its later phase.
Tell the user the switch is non-destructive (v1 is paused, not modified; reverting is one command). Help them stop v1's service unit and start v2's, tail the host log for a clean boot, and have them send a real test message. Use `AskUserQuestion` to confirm the bot responded.
If yes, continue to Phase 1. If no, diagnose from `logs/nanoclaw.log` and re-test — don't proceed to deeper work on a broken router.
Re-visit anything you skipped in 0a before declaring the migration done. Most surface naturally in later phases (`1c-groups` ↔ Phase 2, `1e-tasks` ↔ task verification).
v2 auto-creates a `users` row for every sender it sees (via `extractAndUpsertUser` in `src/modules/permissions/index.ts`). By the time this skill runs, the owner's row likely already exists — it just needs the `owner` role granted.
**User ID format**: always `<channel_type>:<platform_handle>`. Each channel populates this differently:
**Steps:**
1. Query `users` table: `SELECT id, kind, display_name FROM users`. 2. If exactly one user exists, confirm: `AskUserQuestion`: "Is `<display_name>` (`<id>`) you?" — Yes / No, let me type it. 3. If multiple users exist, present them as options in `AskUserQuestion`. 4. If no users exist yet (service hasn't received a message), ask the user to send a test message first, then re-query. 5. Once confirmed, check `user_roles` via `getUserRoles(userId)`. If an `owner` row already exists, skip. Otherwise grant it with `grantRole`. `grantRole` inserts a new row per call, so the `getUserRoles` check keeps this re-runnable.
Use the DB helpers in `src/modules/permissions/db/user-roles.ts` (`getUserRoles`, `grantRole`). Init the DB first, then call the helpers:
import { closeDb, initDb } from '../src/db/connection.js';
import { runMigrations } from '../src/db/migrations/index.js';
import { CENTRAL_DB_PATH } from '../src/config.js';
import { getUserRoles, grantRole } from '../src/modules/permissions/db/user-roles.js';
const db = await initDb(CENTRAL_DB_PATH);
try {
await runMigrations(db); // idempotent
const userId = '<user_id>';
if (!(await getUserRoles(userId)).some((r) => r.role === 'owner')) {
await grantRole({
user_id: userId,
role: 'owner',
agent_group_id: null, // owner role must be global
granted_by: null,
granted_at: new Date().toISOString(),
});
}
} finally {
await closeDb();
}After seeding the owner, discuss the access policy. v2's `messaging_groups.unknown_sender_policy` controls who can interact with the bot. `migrate-v2.sh` set it to `public` so the bot would respond during the switchover test, but the user may want to tighten it.
Present the options via `AskUserQuestion`:
1. **Public** (`public`, current) — anyone can message the bot. Good for personal DM bots. 2. **Known users only** (`strict`) — only users the access gate accepts (owner, admin, or `agent_group_members`) can trigger the bot. Others are silently dropped. 3. **Approval required** (`request_approval`) — unknown senders trigger an approval request to the owner. Good for group chats where you want to vet new members.
A lightweight alternative to OpenClaw that runs in containers for security. Connects to WhatsApp, Telegram, Slack, Discord, Gmail and other messaging apps,, has memory, scheduled jobs, and runs directly on Anthropic's Agents SDK
Repo: nanocoai/nanoclaw
Add local office-document-to-Markdown conversion to NanoClaw agent containers with the pinned Firecrawl AnyDoc CLI. Use when agents need to read attached Word,…
Convert an attached Word document, presentation, spreadsheet, OpenDocument file, RTF, EPUB, CSV, or text-based PDF into local Markdown. Use when a message…
Add Atomic Chat MCP server so the container agent can call local models served by the Atomic Chat desktop app via its OpenAI-compatible API.
Add clidash — a zero-dependency, read-only web dashboard that derives its tabs and tables at runtime from any CLI that lists resources as JSON. Ships pre-wired…
Use Codex (OpenAI's codex app-server) as a full agent provider — planning, tool orchestration, MCP tools, server-side history, session resume — alongside or…
Add a monitoring dashboard to NanoClaw. Installs @nanoco/nanoclaw-dashboard and a pusher that sends periodic JSON snapshots.