🦞 Clawdie — Architecture & Implementation Status

NanoClaw v1.1.3 codebase overview • 07.03.2026

What this document covers:
The NanoClaw codebase as it actually exists — architecture, key subsystems, and what is implemented vs. still planned. Clawdie is the bot persona running on top of NanoClaw.

1. What Clawdie Is

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.

1.1 System Architecture

┌─────────────────────────────────────────────────────────────┐ │ WhatsApp Groups │ │ (via @whiskeysockets/baileys) │ └────────────────────────┬────────────────────────────────────┘ │ messages / events ▼ ┌─────────────────────────────────────────────────────────────┐ │ NanoClaw Orchestrator (Node.js / TypeScript) │ │ │ │ ┌──────────────┐ ┌─────────────────┐ ┌───────────────┐ │ │ │ MessageLoop │ │ TaskScheduler │ │ IPC Watcher │ │ │ │ (poll+route) │ │ (cron/interval │ │ (filesystem) │ │ │ └──────┬───────┘ │ /once tasks) │ └───────┬───────┘ │ │ │ └────────┬────────┘ │ │ │ ▼ ▼ ▼ │ │ ┌──────────────────────────────────────────────────────┐ │ │ │ GroupQueue │ │ │ │ • per-group serialization (one jail at a time) │ │ │ │ • global concurrency cap (MAX_CONCURRENT_JAILS) │ │ │ │ • retry with exponential backoff on failure │ │ │ │ • idle preemption for priority tasks │ │ │ └──────────────────────┬───────────────────────────────┘ │ │ │ jexec │ └─────────────────────────┼───────────────────────────────────┘ │ ┌───────────────┼───────────────┐ ▼ ▼ ▼ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ Jail: │ │ Jail: │ │ Jail: │ │ group-A │ │ group-B │ │ task-X │ │ │ │ │ │ │ │ Claude Code │ │ Claude Code │ │ Claude Code │ │ agent │ │ agent │ │ agent │ └──────┬──────┘ └─────────────┘ └─────────────┘ │ IPC (filesystem) ▼ ┌─────────────┐ │ SQLite DB │ │ (messages, │ │ sessions, │ │ tasks) │ └─────────────┘

1.2 Codebase Structure

nanoclaw/ ← project root (v1.1.3) ├── src/ ← TypeScript source — orchestrator │ ├── index.ts ← entry: message loop, startup, shutdown │ ├── config.ts ← all env-based configuration │ ├── types.ts ← shared types (Channel, RegisteredGroup, …) │ ├── group-queue.ts ← concurrency manager (jails + tasks) │ ├── jail-runner.ts ← spawn agent via jexec, parse output │ ├── jail-ops.ts ← jail lifecycle (start, stop, cleanup) │ ├── jail-config.ts ← FreeBSD jail.conf generation │ ├── jail-runtime.ts ← nullfs mount setup + jail boot │ ├── task-scheduler.ts ← cron/interval/once task runner │ ├── ipc.ts ← IPC filesystem watcher │ ├── db.ts ← SQLite (messages, sessions, tasks, groups) │ ├── router.ts ← message formatting + channel routing │ ├── mount-security.ts ← validated nullfs mount allowlist │ ├── group-folder.ts ← group folder path resolution + validation │ ├── logger.ts ← pino structured logging │ └── channels/ │ └── whatsapp.ts ← WhatsApp channel (@whiskeysockets/baileys) │ ├── container/ ← jail image + agent runner │ ├── agent-runner/src/index.ts ← stdin prompt → Claude → stdout JSON │ └── skills/ ← skills bundled into jail image │ ├── setup/ ← provisioning scripts │ ├── register.ts ← group registration workflow │ ├── service.ts ← launchd / rc.d service management │ ├── container.ts ← jail provisioning │ ├── mounts.ts ← nullfs mount configuration │ └── verify.ts ← post-setup verification │ ├── skills-engine/ ← skill package manager │ ├── replay.ts ← apply skill file patches │ ├── rebase.ts ← rebase skills after NanoClaw update │ └── uninstall.ts ← clean skill removal │ ├── .agent/skills/ ← installed skill packages │ ├── setup/ ← initial Clawdie setup skill │ ├── customize/ ← per-group agent customization │ ├── debug/ ← diagnostic skill │ ├── update/ ← NanoClaw self-update skill │ ├── add-telegram/ ← Telegram channel integration │ ├── add-discord/ ← Discord channel integration │ ├── add-slack/ ← Slack channel integration │ ├── add-gmail/ ← Gmail channel integration │ ├── add-voice-transcription/ ← WhatsApp voice note → text │ ├── add-parallel/ ← parallel sub-agent execution │ ├── coding-agent/ ← coding-agent TUI integration │ ├── clawdie-freebsd/ ← FreeBSD jail management tools │ ├── x-integration/ ← X (Twitter) posting │ ├── tmux-screenshot/ ← terminal screenshot → color PNG │ └── get-qodo-rules/ ← Qodo AI code review rules │ └── groups/ ← per-group agent configuration ├── global/AGENT.md ← shared instructions (all groups) └── main/AGENT.md ← main group instructions

2. Tech Stack

ConcernTechnology
LanguageTypeScript (ESM, strict mode), Node.js
Package managernpm
Test frameworkVitest
Loggingpino + pino-pretty
DatabaseSQLite via better-sqlite3
WhatsApp@whiskeysockets/baileys
IsolationFreeBSD jails — jexec, nullfs, service jail
AI agentClaude Code (runs inside jail via agent-runner)
Schedulingcron-parser (cron / interval / once tasks)
Config / validationzod + yaml

3. Implemented Subsystems

3.1 FreeBSD Jail Isolation

Implemented. All Docker and Apple Container references removed. Jail-only.

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---
FileResponsibility
src/jail-runner.tsSpawn agent via jexec JAIL_NAME node agent-runner, stream + parse output
src/jail-ops.tsstopJail(), ensureJailRunning(), cleanupStaleJails()
src/jail-config.tsGenerate jail.conf entries per registered group
src/jail-runtime.tsnullfs mount orchestration and jail boot sequence
src/mount-security.tsValidate mounts against allowlist, block sensitive patterns

3.2 Group Queue

Implemented. Fully covered by Vitest tests.

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:

3.3 Message Loop

Implemented.

src/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.

3.4 IPC — Agent ↔ Orchestrator

Implemented.

Agents write JSON files to a watched directory. The IPC watcher processes them atomically with authorization enforcement:

DATA_DIR/ipc/ ├── {group-folder}/ │ ├── messages/ ← agent → send WhatsApp message │ └── tasks/ ← agent → schedule/pause/resume/cancel task └── errors/ ← failed IPC files moved here for inspection

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.

3.5 Task Scheduler

Implemented.
Schedule typeValue formatNotes
cronstandard cron expressionNext run computed after each execution
intervalmilliseconds as stringOffset from completion time
onceISO 8601 timestampRuns 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.

3.6 WhatsApp Channel

Implemented.

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.

3.7 Skills Engine

Implemented. 15 skill packages installed.

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).

SkillWhat it adds
setupInitial Clawdie provisioning workflow
customizePer-group AGENT.md editor
debugDiagnostic commands
updateNanoClaw self-update from upstream
add-telegramTelegram channel support
add-discordDiscord channel support
add-slackSlack channel support
add-gmailGmail integration
add-voice-transcriptionWhatsApp voice note → text
add-parallelParallel sub-agent execution
coding-agentcoding-agent TUI as alternative to Claude Code
clawdie-freebsdFreeBSD jail management tools for agents
x-integrationX (Twitter) posting, retweeting, replies
tmux-screenshotCapture tmux session → color PNG (ANSI renderer)
get-qodo-rulesFetch Qodo AI code review rules

3.8 tmux-screenshot

Implemented. At .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/.

4. Configuration Reference

VariableDefaultPurpose
DATA_DIR./dataSQLite DB, IPC dirs, session files
GROUPS_DIR./groupsPer-group AGENT.md and logs
JAIL_NAMEclawdieFreeBSD jail name passed to jexec
MAX_CONCURRENT_JAILS5Global jail concurrency limit
JAIL_TIMEOUT1800000 (30 min)Hard timeout per jail run
IDLE_TIMEOUT1800000 (30 min)Close stdin after idle period
POLL_INTERVAL1000 msMessage loop poll frequency
ASSISTANT_NAMEClawdieTrigger name in group messages (@Clawdie)
MAIN_GROUP_FOLDERmainMain group folder (no trigger required)
TIMEZONEEurope/LjubljanaCron task scheduling timezone

5. What Remains To Build

5.1 coding-agent TUI Integration

Skill installed, integration pending.

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.

5.2 Stripe Agents

Not started.

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.

5.3 Additional Channels

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.