bash nanoclaw.sh and follow the wizard — quick start covers that flow end to end.
Requirements
| Requirement | |
|---|---|
| Platform | macOS or Linux. Windows works through WSL2 — the installer detects WSL and treats it as Linux. |
| RAM | 4 GB+. The installer warns below 3,700 MB (a “4 GB” VM typically reports 3,700–3,900 MB after kernel reserves) and lets you override. |
| Node.js | 20 or newer on the host (engines in package.json). Installed for you if missing. |
| git | To clone the repository. Not auto-installed. |
| Claude credential | A Claude subscription (sign-in via browser), an OAuth token (sk-ant-oat…), or an Anthropic API key (sk-ant-api…). |
- Google Compute Engine VMs — GCE blocks the sudo commands setup needs, so NanoClaw is unlikely to run there. The installer detects GCE via DMI and warns before doing anything. Use a different provider.
- Root on Linux — discouraged. The installer offers instructions for creating a regular user instead. If you insist, it installs a system-level systemd unit rather than a user one.
What’s installed for you
nanoclaw.sh installs everything below if it’s missing. You don’t need to pre-install any of it.
| Dependency | Where it runs | How it’s installed |
|---|---|---|
| Homebrew (macOS only) | Host | Official installer, after a prompt. Pulls in Apple’s Command Line Tools (can take 5–10 minutes on a factory Mac). |
| Node 22 | Host | uvx nodeenv -n lts if uvx is present; otherwise brew install node@22 (macOS) or NodeSource + apt-get (Linux). Skipped if you already have Node 20+. |
| pnpm 10 | Host | corepack enable, falling back to npm install -g pnpm@<pinned> at the version from packageManager. |
| Docker | Host | brew install --cask docker (macOS) or get.docker.com + usermod -aG docker (Linux/WSL). Setup also starts the daemon and works around stale group membership (sg docker re-exec, or a temporary ACL on the socket) so you don’t have to log out and back in. |
| OneCLI vault | Host | Installed by the wizard, or reuses an existing healthy OneCLI instance if it finds one. |
| Bun 1.3.12 | Container | Baked into the agent container image. Never touches the host. |
gcc/make on Linux) are checked and reported but not installed. They only matter if better-sqlite3 has to compile from source — setup verifies the native binding loads and fails loudly if it doesn’t.
What the installer does under the hood
bash nanoclaw.sh is a three-stage chain:
nanoclaw.sh— pre-flight checks (RAM floor, GCE detection, root warning, Homebrew prompt on macOS), then runs the bootstrap under a spinner. Bash only — nothing else exists on the machine yet.setup.sh— detects the platform (macOS / Linux / WSL), installs Node 22 viasetup/install-node.shif Node 20+ isn’t present, gets pnpm onto the PATH, runspnpm install --frozen-lockfile, and verifies thebetter-sqlite3native module loads.pnpm run setup:auto— the interactive wizard (setup/auto.ts). This is where the container build, OneCLI vault, provider auth, service install, and channel pairing happen. Quick start walks through every wizard step.
logs/setup.log (one entry per step) and verbatim per-step output under logs/setup-steps/NN-name.log. When something fails, start there.
One runtime on the host, another in the container
NanoClaw deliberately splits runtimes:- Host: Node 20+ and pnpm. The wizard compiles TypeScript with
tscand the service runsnode dist/index.js. - Agent container: Bun 1.3.12 runs the agent-runner TypeScript directly — no build step. The image (from
container/Dockerfile) is based onnode:22-slimwith Chromium for browser automation and globally installed CLIs —@anthropic-ai/claude-code,agent-browser, andvercel, each pinned to an exact version for reproducibility. The versions live incontainer/cli-tools.json(installed byinstall-cli-tools.sh).
- Agent source is never baked into the image. The host bind-mounts
container/agent-runner/srcread-only at/app/src, so agent-runner changes take effect on the next container spawn without a rebuild. The host’s ownsrc/is different: the service runs the compileddist/, so host changes needpnpm run buildand a service restart. - The image is per-checkout:
nanoclaw-agent-v2-<slug>:latest, where the slug is the first 8 hex chars ofsha1(projectRoot). Two NanoClaw installs on one host never clobber each other’s image, service, or containers.
src/container-runtime.ts hardcodes the binary (CONTAINER_RUNTIME_BIN = 'docker') behind a single-file abstraction — all runtime-specific logic lives in that one file, but nothing else is wired up today.
If you render Chinese, Japanese, or Korean text, set INSTALL_CJK_FONTS=true in .env before the container build — it adds Noto CJK fonts (~200 MB) to the image.
Manual installation
If you’d rather not runnanoclaw.sh (or it failed partway), the pieces compose by hand:
setup:auto is the same wizard the one-liner hands off to — it builds the container image, sets up credentials, and installs the background service. Without it, you can run the host in the foreground:
Re-running individual steps
pnpm run setup is a step runner, not a second wizard. Use it to re-run one piece of setup without going through the whole flow:
timezone, set-env, environment, container, register, pair-telegram, groups, whatsapp-auth, signal-auth, mounts, service, verify, onecli, auth, provider-auth, cli-agent.
Scripting the wizard
setup:auto reads environment variables for unattended or partial runs:
| Env var | Use |
|---|---|
NANOCLAW_SKIP | Comma-separated wizard steps to skip: environment, container, onecli, auth, mounts, service, cli-agent, first-chat, timezone, channel, verify |
NANOCLAW_DISPLAY_NAME | Skip the “what should the assistant call you” prompt |
NANOCLAW_AGENT_NAME | Set the messaging-channel agent name |
SECRET_NAME | OneCLI secret name (default: Anthropic) |
HOST_PATTERN | OneCLI host pattern (default: api.anthropic.com) |
ANTHROPIC_BASE_URL in .env — the host passes it through to the agent SDK inside the container.
Running as a service
The wizard’s service step compiles TypeScript (pnpm run build), writes a service definition that runs node dist/index.js from the project root, starts it, and symlinks bin/ncl into ~/.local/bin so the ncl CLI works from anywhere. Service names embed the per-checkout slug, so look yours up rather than guessing.
- macOS (launchd)
- Linux (systemd)
- No systemd (WSL fallback)
The plist lands at
~/Library/LaunchAgents/com.nanoclaw-v2-<slug>.plist with RunAtLoad and KeepAlive — it starts at login and restarts on crash.Where files live
Everything stateful lives inside the checkout, with two exceptions: security allowlists in~/.config/nanoclaw/ (kept outside the project so they’re never mounted into containers) and the service definition.
nanoclaw
src
dist
container
groups
main
CLAUDE.local.md
CLAUDE.md
container.json
data
v2.db
v2-sessions
{agent_group_id}
{session_id}
.claude-shared
env
ipc
cli.sock
logs
bin
.env
nanoclaw.sh
| Path | Purpose |
|---|---|
groups/<folder>/CLAUDE.local.md | Per-group agent instructions — this is the file you edit. |
groups/<folder>/CLAUDE.md | Regenerated at every container spawn from the shared base plus enabled skills. Don’t edit it — your changes get overwritten. |
groups/<folder>/container.json | Per-group container overrides. |
container/CLAUDE.md | Shared base instructions for all agents, mounted read-only into every container. |
data/v2.db | Host state database (registered groups, tasks, sessions). |
data/v2-sessions/ | Per-session message queues — inbound.db (host writes) and outbound.db (container writes). |
data/env/env | Container-mounted copy of .env, synced by setup. |
~/.config/nanoclaw/mount-allowlist.json | Which host directories agents may mount. Never mounted into containers. |
~/.config/nanoclaw/sender-allowlist.json | Optional per-channel sender access control. |
~/.local/bin/ncl | Symlink to bin/ncl so the CLI works from any directory. |
~/Library/LaunchAgents/com.nanoclaw-v2-<slug>.plist | launchd service (macOS). |
~/.config/systemd/user/nanoclaw-v2-<slug>.service | systemd user service (Linux). |
Next steps
Quick start
The one-command flow and the wizard, step by step.
Architecture
How the host, containers, and the two-DB session model fit together.
The ncl CLI
Inspect agents, groups, and sessions from the command line.
Troubleshooting
Setup failures start at
logs/setup.log; runtime issues at logs/nanoclaw.log.