Skip to main content
This page is the depth companion to Quick start: what the installer actually does, how to install by hand, how the background service works, and where everything lands on disk. If you just want a running assistant, run bash nanoclaw.sh and follow the wizard — quick start covers that flow end to end.

Requirements

Requirement
PlatformmacOS or Linux. Windows works through WSL2 — the installer detects WSL and treats it as Linux.
RAM4 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.js20 or newer on the host (engines in package.json). Installed for you if missing.
gitTo clone the repository. Not auto-installed.
Claude credentialA Claude subscription (sign-in via browser), an OAuth token (sk-ant-oat…), or an Anthropic API key (sk-ant-api…).
Two hosts the installer explicitly flags in pre-flight:
  • 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.
DependencyWhere it runsHow it’s installed
Homebrew (macOS only)HostOfficial installer, after a prompt. Pulls in Apple’s Command Line Tools (can take 5–10 minutes on a factory Mac).
Node 22Hostuvx 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 10Hostcorepack enable, falling back to npm install -g pnpm@<pinned> at the version from packageManager.
DockerHostbrew 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 vaultHostInstalled by the wizard, or reuses an existing healthy OneCLI instance if it finds one.
Bun 1.3.12ContainerBaked into the agent container image. Never touches the host.
Build tools (Xcode Command Line Tools on macOS, 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:
  1. 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.
  2. setup.sh — detects the platform (macOS / Linux / WSL), installs Node 22 via setup/install-node.sh if Node 20+ isn’t present, gets pnpm onto the PATH, runs pnpm install --frozen-lockfile, and verifies the better-sqlite3 native module loads.
  3. 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.
Every run writes two logs: a progression log at 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 tsc and the service runs node 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 on node:22-slim with Chromium for browser automation and globally installed CLIs — @anthropic-ai/claude-code, agent-browser, and vercel, each pinned to an exact version for reproducibility. The versions live in container/cli-tools.json (installed by install-cli-tools.sh).
Two consequences worth knowing:
  • Agent source is never baked into the image. The host bind-mounts container/agent-runner/src read-only at /app/src, so agent-runner changes take effect on the next container spawn without a rebuild. The host’s own src/ is different: the service runs the compiled dist/, so host changes need pnpm run build and a service restart.
  • The image is per-checkout: nanoclaw-agent-v2-<slug>:latest, where the slug is the first 8 hex chars of sha1(projectRoot). Two NanoClaw installs on one host never clobber each other’s image, service, or containers.
Docker is the only supported runtime. 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 run nanoclaw.sh (or it failed partway), the pieces compose by hand:
git clone https://github.com/nanocoai/nanoclaw.git
cd nanoclaw
pnpm install
pnpm run setup:auto
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:
pnpm run build && pnpm start   # compiled, what the service runs
pnpm run dev                   # tsx, no build step

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:
pnpm run setup -- --step container   # rebuild and re-test the agent image
pnpm run setup -- --step service     # rebuild TypeScript and reinstall the service
pnpm run setup -- --step verify      # end-to-end health check
Available steps: 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 varUse
NANOCLAW_SKIPComma-separated wizard steps to skip: environment, container, onecli, auth, mounts, service, cli-agent, first-chat, timezone, channel, verify
NANOCLAW_DISPLAY_NAMESkip the “what should the assistant call you” prompt
NANOCLAW_AGENT_NAMESet the messaging-channel agent name
SECRET_NAMEOneCLI secret name (default: Anthropic)
HOST_PATTERNOneCLI host pattern (default: api.anthropic.com)
For Anthropic-compatible custom endpoints, set 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.
The plist lands at ~/Library/LaunchAgents/com.nanoclaw-v2-<slug>.plist with RunAtLoad and KeepAlive — it starts at login and restarts on crash.
# Find your label
launchctl list | grep nanoclaw

# Restart
launchctl kickstart -k gui/$(id -u)/com.nanoclaw-v2-<slug>

# Stop / start
launchctl unload ~/Library/LaunchAgents/com.nanoclaw-v2-<slug>.plist
launchctl load   ~/Library/LaunchAgents/com.nanoclaw-v2-<slug>.plist

# Logs (stdout and stderr go to files, not the system log)
tail -f logs/nanoclaw.log logs/nanoclaw.error.log

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
groups
main
CLAUDE.local.md
CLAUDE.md
container.json
data
v2.db
v2-sessions
{agent_group_id}
.claude-shared
ipc
cli.sock
.env
nanoclaw.sh
The highlights:
PathPurpose
groups/<folder>/CLAUDE.local.mdPer-group agent instructions — this is the file you edit.
groups/<folder>/CLAUDE.mdRegenerated at every container spawn from the shared base plus enabled skills. Don’t edit it — your changes get overwritten.
groups/<folder>/container.jsonPer-group container overrides.
container/CLAUDE.mdShared base instructions for all agents, mounted read-only into every container.
data/v2.dbHost state database (registered groups, tasks, sessions).
data/v2-sessions/Per-session message queues — inbound.db (host writes) and outbound.db (container writes).
data/env/envContainer-mounted copy of .env, synced by setup.
~/.config/nanoclaw/mount-allowlist.jsonWhich host directories agents may mount. Never mounted into containers.
~/.config/nanoclaw/sender-allowlist.jsonOptional per-channel sender access control.
~/.local/bin/nclSymlink to bin/ncl so the CLI works from any directory.
~/Library/LaunchAgents/com.nanoclaw-v2-<slug>.plistlaunchd service (macOS).
~/.config/systemd/user/nanoclaw-v2-<slug>.servicesystemd 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.
Last modified on June 15, 2026