Skip to content

ClaudeClaw: A Composable Agent Orchestrator for Claude Code

Posted on:March 22, 2026

What Is ClaudeClaw

ClaudeClaw is a Claude Code plugin that turns Claude into a persistent, always-on agent orchestrator. It listens to messaging channels (Slack, WhatsApp, Telegram, Discord, Gmail), routes messages to isolated Claude agents, and manages conversations, memory, scheduled tasks, and webhooks — all from a single Node.js process.

It started as a fork of NanoClaw, a minimal agent orchestrator. The fork diverged significantly: ClaudeClaw was rebuilt as a Claude Code plugin with a pluggable extension system, structured memory, webhook triggers, per-group agent configuration, cost tracking, and native sandbox runtime support.

The core is ~8K lines of TypeScript with 355 tests. Channels and agents are installable extensions. The entire codebase fits in Claude’s context window.

Why Fork NanoClaw

NanoClaw is a good minimal base — single process, SQLite, channels that self-register. But it has limitations:

ClaudeClaw addresses all of these.

The Port: NanoClaw → ClaudeClaw

The port was done in a single day. Here’s what happened, commit by commit:

Phase 1: Plugin Architecture

The core was restructured into a Claude Code plugin layout:

.claude-plugin/plugin.json    # Plugin manifest
src/
  index.ts                    # Entrypoint
  orchestrator/               # Core (message-loop, queue, config, db, IPC)
  channels/                   # Channel implementations
  triage/                     # Triage extension
  webhook/                    # Webhook extension
  cost-tracking/              # Cost tracking extension
agent/
  runner/                     # Agent runner (Claude Agent SDK)
  skills/                     # Agent-side skills

Two key architectural changes:

Extension system. Extensions register capabilities without modifying core. Triage, webhook triggers, and cost tracking are all extensions — the orchestrator core doesn’t know about them.

Two entry points. The plugin entry (src/index.ts) loads via claude --plugin-dir and returns immediately — no side effects. The service entry (src/service.ts) runs the message loop as a persistent background process. They must never be conflated.

Phase 2: Sandbox Runtime

NanoClaw’s sandbox runtime was ported and made the default. Anthropic’s @anthropic-ai/sandbox-runtime provides OS-level process sandboxing — Seatbelt on macOS, bubblewrap on Linux. No containers, no VMs, sub-10ms cold starts.

The security model inverts Docker’s approach:

The agent runner is runtime-agnostic — CLAUDECLAW_*_DIR env vars resolve paths, falling back to /workspace/* for container mode. Same binary, both runtimes.

Phase 3: Directory Reorganization

The Docker-era container/ directory was split:

30 files updated across source, tests, docs, and 13 skills.

Phase 4: New Features

Three features inspired by 9to5:

Webhook Triggers. External systems trigger agent runs via HTTP POST with HMAC-SHA256 authentication. Per-group rate limiting, health check endpoint, response routes through the group’s channel. CI failures, GitHub events, monitoring alerts can all invoke agents.

Per-Group Agent Config. Each group can override model (sonnet/opus/haiku), reasoning effort (low/medium/high), system prompt, allowed/disallowed tools, max turns, and cost limits. Stored in the database, passed through to the agent runner.

Cost Tracking. Every agent run is logged with token usage (input, output, cache creation, cache read), estimated cost in USD, duration, turns, model, and trigger type. Query costs per group with a single SQL statement.

Phase 5: Memory System

Agents got structured memory tools via MCP:

Claude’s built-in auto-memory and our memory_save tool write to the same memory/ directory via autoMemoryDirectory — unified store.

Before context compaction, the PreCompact hook archives the conversation and writes a summary to the daily memory log. PostCompact verifies the flush. StopFailure notifies the user through their channel on API errors.

A /add-qmd skill stub is ready for upgrading to QMD’s hybrid BM25 + vector semantic search + LLM re-ranking — fully local, no API keys.

Phase 6: Claude Code Changelog Adoption

Recent Claude Code features (v2.1.76–81) were adopted:

FeatureVersionWhat We Did
PostCompact hookv2.1.76Verify memory flush after compaction
StopFailure hookv2.1.78Notify user on rate limits / auth errors
effort frontmatterv2.1.78Per-group reasoning effort control
disallowedToolsv2.1.78Per-group tool blacklisting
CLAUDE_PLUGIN_DATAv2.1.78Persistent store path survives plugin updates
autoMemoryDirectoryv2.1.80Unified SDK auto-memory + memory tools
SendMessage auto-resumev2.1.77Background agents auto-recover (zero code change)

Phase 7: Message Router Refactor

The monolithic message-loop.ts was split into two clean services:

MessageIngestion — single entry point for all inbound messages (channels, webhooks, cron, IPC). Extensions hook pre/post processing without touching core.

MessageRouter — single exit point for all outbound messages (agent responses, task results, extension output). Finds the right channel, formats, delivers.

Channels ──► MessageIngestion ──► GroupQueue ──► Agent
Webhooks ──►   (pre/post hooks)
Cron     ──►

Agent    ──► MessageRouter ──► Channel.sendMessage()
IPC      ──►   (pre/post hooks)
Extensions─►

Extensions register hooks on both services: pre-hooks can modify/drop envelopes, post-hooks observe. This eliminated five separate sendMessage closures scattered through main() and replaced them with router.route(envelope).

Phase 8: Composable Extension System

The biggest architectural change: channels and agents are now installable extensions, not bundled in core.

Slack and Triage+SWE were extracted into separate repos:

Each extension has a manifest.json declaring what it provides — channel, DB schema, env keys, skills, agent prompts, and lifecycle hooks:

{
  "name": "claudeclaw-slack",
  "type": "channel",
  "entry": "dist/index.js",
  "dependencies": { "@slack/bolt": "^4.6.0" },
  "skills": ["add-slack"],
  "hooks": { "postInstall": "hooks/install.sh" }
}

A manifest-based loader scans extensions/claudeclaw-*/ at startup, validates each manifest, and dynamically imports the entry point. Extensions self-register via registerChannel() or registerExtension() on import.

Install is a skill: /install-extension slack clones from GitHub, installs deps, compiles, copies skills into the host, and restarts the service. Uninstall reverses it. No merge conflicts — extensions are directories, not branches merged into your fork.

This solves NanoClaw’s biggest maintenance pain: upstream updates and extension conflicts. Core updates are git pull. Extension updates are git pull inside the extension directory. They never touch the same files.

Phase 9: Directory-as-Instance Model

Plugin mode was simplified: the current directory IS the instance. No hidden paths, no ~/.claude/plugin-data/, no instance manager.

~/assistants/personal/    ← one instance (cd here, run claude)
  .env, store/, groups/, logs/, .claudeclaw.json
~/assistants/work/        ← another instance

Multiple instances = multiple directories. cd is the instance switcher. Each directory gets its own launchd/systemd service (com.claudeclaw.<dirname>.plist).

Want to customize the code? Clone the repo INTO the data directory. .env, store/, groups/ are gitignored — they survive the clone. You’re now in developer mode with full self-improvement capability.

What ClaudeClaw Has Now

Agent Triggers

TriggerMechanism
Channel message@mention in Slack, WhatsApp, Telegram, Discord, Gmail
Scheduled taskCron, interval, or one-shot
WebhookHTTP POST with HMAC-SHA256

Per-Group Isolation

Each group gets its own:

24 Skills

/setup                    /add-slack              /add-telegram
/add-whatsapp             /add-discord            /add-gmail
/add-telegram-swarm       /add-parallel           /add-compact
/add-voice-transcription  /use-local-whisper      /add-image-vision
/add-pdf-reader           /add-ollama-tool        /add-reactions
/add-qmd                  /x-integration          /convert-to-apple-container
/customize                /debug                  /setup
/update-claudeclaw        /update-skills          /get-qodo-rules
/qodo-pr-resolver

Built-in Extensions (core)

Installable Extensions

What’s Next

Multi-Model Agent Routing

Support multiple LLM providers per agent. The agentConfig.model field expands to accept provider-prefixed strings (openai/gpt-4o, google/gemini-pro, ollama/llama3).

Phased approach:

  1. Provider-aware model field — agent runner switches SDK based on prefix
  2. Provider abstraction — unified Provider interface wrapping each SDK, tool schema translation
  3. Smart routing — pick provider/model by task complexity, cost budget, latency. Fallback chains.

QMD Semantic Memory

Replace grep-based memory_search with QMD’s hybrid BM25 + vector semantic search + LLM re-ranking. Fully local, no API keys. Automatic indexing of daily logs, topic files, CLAUDE.md, and archived conversations. /add-qmd skill handles installation and migration.

Future Extensions

ExtensionPurpose
claudeclaw-discordDiscord channel integration
claudeclaw-gmailGmail as a full channel
claudeclaw-memoryQMD-powered semantic memory
claudeclaw-tuiTerminal UI for instance management

Numbers

Try It

git clone https://github.com/sbusso/claudeclaw.git
cd claudeclaw
claude
# type: /setup

The full source is at github.com/sbusso/claudeclaw.

About the author

Stephane Busso
Stephane Busso

Software builder and engineering manager based in New Zealand 🇳🇿. HTDOCS.dev is a medium to share about ai, technologies and engineering.