NanoClaw v1.1.3 codebase overview • 07.03.2026
Clawdie is a WhatsApp AI assistant that routes group messages to Claude Code agents running inside FreeBSD jails. Each registered group gets its own isolated jail environment. The orchestrator (NanoClaw) handles all coordination: message polling, group queuing, agent lifecycle, task scheduling, and inter-process communication.
| Concern | Technology |
|---|---|
| Language | TypeScript (ESM, strict mode), Node.js |
| Package manager | npm |
| Test framework | Vitest |
| Logging | pino + pino-pretty |
| Database | SQLite via better-sqlite3 |
| @whiskeysockets/baileys | |
| Isolation | FreeBSD jails — jexec, nullfs, service jail |
| AI agent | Claude Code (runs inside jail via agent-runner) |
| Scheduling | cron-parser (cron / interval / once tasks) |
| Config / validation | zod + yaml |
Each Claude Code agent runs inside a FreeBSD jail. The orchestrator uses jexec to enter the jail and run the agent-runner. Filesystem mounts are via nullfs (read-only by default, allowlist-controlled via mount-security.ts).
The agent communicates results back to the orchestrator via structured JSON between sentinel markers on stdout:
---NANOCLAW_OUTPUT_START---
{"status": "success", "result": "...", "newSessionId": "session-abc"}
---NANOCLAW_OUTPUT_END---
| File | Responsibility |
|---|---|
src/jail-runner.ts | Spawn agent via jexec JAIL_NAME node agent-runner, stream + parse output |
src/jail-ops.ts | stopJail(), ensureJailRunning(), cleanupStaleJails() |
src/jail-config.ts | Generate jail.conf entries per registered group |
src/jail-runtime.ts | nullfs mount orchestration and jail boot sequence |
src/mount-security.ts | Validate mounts against allowlist, block sensitive patterns |
src/group-queue.ts enforces two invariants: only one jail runs per group at a time, and a global cap (MAX_CONCURRENT_JAILS) limits simultaneous jails across all groups. Additional behaviours:
queue.shutdown(ms) drains active jails before process exitsrc/index.ts polls SQLite every POLL_INTERVAL ms for new messages across registered groups. For each group with messages: checks trigger pattern, pipes to active jail if idle (hot path), otherwise enqueues via GroupQueue. Startup recovery re-queues any messages that arrived while the process was down.
Agents write JSON files to a watched directory. The IPC watcher processes them atomically with authorization enforcement:
Supported operations: message, schedule_task, pause_task, resume_task, cancel_task, refresh_groups, register_group. Non-main groups are restricted to their own JID and tasks.
| Schedule type | Value format | Notes |
|---|---|---|
cron | standard cron expression | Next run computed after each execution |
interval | milliseconds as string | Offset from completion time |
once | ISO 8601 timestamp | Runs once, no next_run |
Tasks run in their own jail, separate from the group's message-handling jail. Context mode isolated gives a fresh session; group inherits the group's current Claude session ID.
QR code pairing, reconnection, message receipt, typing indicators, group metadata sync via @whiskeysockets/baileys. All messages stored to SQLite — the message loop polls the DB, decoupling the channel from the agent lifecycle and surviving reconnects cleanly.
Skills are installable packages that modify the NanoClaw codebase via a patch-replay system (skills-engine/). Handles install, update, uninstall, and rebase (re-apply patches after a NanoClaw upstream update).
| Skill | What it adds |
|---|---|
setup | Initial Clawdie provisioning workflow |
customize | Per-group AGENT.md editor |
debug | Diagnostic commands |
update | NanoClaw self-update from upstream |
add-telegram | Telegram channel support |
add-discord | Discord channel support |
add-slack | Slack channel support |
add-gmail | Gmail integration |
add-voice-transcription | WhatsApp voice note → text |
add-parallel | Parallel sub-agent execution |
coding-agent | coding-agent TUI as alternative to Claude Code |
clawdie-freebsd | FreeBSD jail management tools for agents |
x-integration | X (Twitter) posting, retweeting, replies |
tmux-screenshot | Capture tmux session → color PNG (ANSI renderer) |
get-qodo-rules | Fetch Qodo AI code review rules |
.agent/skills/tmux-screenshot/tmux-screenshot.py.Captures the clawdie tmux session to PNG. UUID derived from SHA256 of stripped content — same state always produces same filename (deduplication + self-verification). Features: correct double-width character column calculation, full ANSI color support (basic 16, 256-color, 24-bit truecolor). Output: ai.clawdie.si/screenshots/.
| Variable | Default | Purpose |
|---|---|---|
DATA_DIR | ./data | SQLite DB, IPC dirs, session files |
GROUPS_DIR | ./groups | Per-group AGENT.md and logs |
JAIL_NAME | clawdie | FreeBSD jail name passed to jexec |
MAX_CONCURRENT_JAILS | 5 | Global jail concurrency limit |
JAIL_TIMEOUT | 1800000 (30 min) | Hard timeout per jail run |
IDLE_TIMEOUT | 1800000 (30 min) | Close stdin after idle period |
POLL_INTERVAL | 1000 ms | Message loop poll frequency |
ASSISTANT_NAME | Clawdie | Trigger name in group messages (@Clawdie) |
MAIN_GROUP_FOLDER | main | Main group folder (no trigger required) |
TIMEZONE | Europe/Ljubljana | Cron task scheduling timezone |
The coding-agent skill package is present but the actual swap of Claude Code for the coding-agent TUI inside the jail is not implemented. Needed: verify it runs on FreeBSD, wire agent-runner to launch it, adapt stdout JSON protocol, test session continuity.
Phase 1: configure Stripe MCP Server with a restricted read-only API key, expose to agents via jail MCP tool list. Gives agents read access to payments and customers without write risk.
Skills for Telegram, Discord, Slack, and Gmail are installed but not activated — each requires its own credentials and registering the channel alongside WhatsApp in src/index.ts.