ncl on your PATH (or pnpm ncl from the checkout), and Docker up.
1
Create the agent group
An agent group is just a row in the central DB plus a folder under Now check the filesystem:
groups/ — both created in one step, as you’ll see.ncl prints the inserted row, including the generated UUID. Save it — every later command takes --id:ls groups/ — the scout/ folder is already there. Create does more than insert the DB row: it runs initGroupFilesystem() inline, so the folder and the container-config row exist before any message arrives. Re-running create with the same --folder returns the existing row. If the directory already exists but no database row owns it, creation is refused rather than adopting its files: choose another folder or move the old directory first. What does not exist yet: the composed CLAUDE.md (generated at first container spawn), instructions.prepend.md (you create that file yourself when you give the agent standing instructions), and any session state. An agent that has never been messaged still costs nothing at runtime — no container runs for it.2
Find the CLI messaging group
A messaging group is one chat on one platform, identified by a unique (Note the
channel_type, platform_id) pair. The CLI channel hardcodes its platform ID to local, and setup leaves the “Local CLI” messaging group in place, so it should already exist:id of the row with platform_id = local. If the list is empty (CLI-less install), create it exactly as the setup script does — unknown_sender_policy must be public because the terminal’s synthetic cli:local user holds no role:3
Wire them together
A wiring tells the router which agent handles messages from which chat, and when it engages:Two things matter here:
- CLI wirings are always pattern mode. The CLI adapter declares
patternwith a match-everything default, so omitting the engage flags would wire Scout to answer every message. An explicit--engage-mode mentionis rejected outright — the CLI channel never produces mentions, and wiring validation refuses a mode that can never engage. The explicit pattern above is what scopes Scout to its name. - The pattern is a JavaScript regex tested against the message text.
^[Ss]cout\bengages Scout only when a message starts with its name. Don’t use inline flags like(?i)— JS regexes reject them, and an invalid pattern fails open (the agent responds to everything).
4
Talk to it
data/cli.sock, the router matches your pattern, creates a session, and spawns a container. First contact is a cold start — expect 30–60 seconds before the reply prints. Follow-ups to a warm container are much faster, and the session persists server-side, so context carries across invocations.If nothing comes back after the cold start, check what the router did with the message:no_agent_engaged drop row only appears when no wiring on the chat matched at all — in this tutorial’s setup a catch-all (or complementary) pattern always engages one agent, so if the table is empty, check whether the other agent answered instead: your message probably didn’t start with “scout”.5
Inspect what was created
That first message triggered the first container spawn, which composed the one file creation left out:Look for It stays warm for a while after the conversation until the host’s sweep kills it — the runner never exits just for being idle — and the host respawns it on the next message. To force a fresh one (with an image rebuild, e.g. after adding packages):
CLAUDE.md is the composed instructions file the host regenerates on every spawn — don’t edit it. The agent’s editable standing instructions live in instructions.prepend.md, composed into the top of CLAUDE.md at every spawn. Groups created via ncl don’t have that file yet — create it to give Scout a personality and standing instructions (see customize an agent). Durable facts the agent accumulates over time live in its memory/ tree.The session — the runtime unit mapping this (agent, chat) pair to a container — is visible too:status = active and container_status = running. Current Docker container names start with ncl- and derive from the install and session IDs. List NanoClaw containers by label:What you built
Next steps
- Customize an agent — memory, container config, models, packages
- Multi-agent swarm — wire several agents that talk to each other
- Channels overview — wire Scout to WhatsApp, Telegram, Discord, and more