Skip to main content
NanoClaw has two configuration layers:
  1. Install-wide environment variables — identity, container limits, logging, credentials. They apply to the whole install.
  2. Per-group container config in the database — each agent group has a row in the container_configs table controlling its provider, model, mounts, packages, and MCP servers.

Environment variables

Variables come from two sources, and the distinction matters:
  • A small set is read from .env at the project root by NanoClaw’s own parser. These work with a plain “edit .env, restart” flow. Values are not loaded into process.env, so secrets don’t leak to child processes; a value already in the process environment takes precedence.
  • Everything else is read from process.env only. The launchd plist, systemd unit, and nohup wrapper that setup generates set just PATH and HOME — they do not source .env. Putting these variables in .env has no effect; you have to set them in the service environment (see Applying changes).

Read from .env

Some channels run in containers and can’t see the host’s .env. For those, setup mirrors .env to data/env/env, which is mounted into the channel container. Keep the two in sync — the set-env setup step handles both:
You can also edit .env by hand and copy it yourself: cp .env data/env/env.

Process environment only

These are read from process.env at startup. Set them in the service definition or export them in your shell before pnpm run dev.env won’t work. Containers
CONTAINER_TIMEOUT, IDLE_TIMEOUT, MAX_CONCURRENT_CONTAINERS, CONTAINER_MAX_OUTPUT_SIZE, and MAX_MESSAGES_PER_PROMPT were removed from the code and are no longer read — setting any of them has no effect. Container idle/stuck detection is now handled by the periodic host-sweep loop (src/host-sweep.ts), not a per-container timeout env var.
Network and logging See Hardening for the full egress lockdown and sandboxing story.

Per-group container config

Each agent group has a row in the container_configs table (the central SQLite database). At spawn time NanoClaw materializes it to groups/<folder>/container.json — don’t edit that file by hand, it’s overwritten on every spawn. The full per-field reference, including the variable tables for the whole install, lives in the environment variables and container configuration references. Fields per group: To change a group’s config, ask the agent in that group, or use ncl. For adding MCP servers, mounts, and providers, see Extending NanoClaw and Ollama integration.

Applying changes

.env-read variables: edit .env, sync the container copy if any channel runs in a container (cp .env data/env/env), then restart the service:
Process-environment variables: add them to the service definition, then reload it.
  • macOS: edit ~/Library/LaunchAgents/com.nanoclaw-v2-<slug>.plist, add a key to the EnvironmentVariables dict, then launchctl unload + launchctl load the plist.
  • Linux (systemd): add an Environment=KEY=value line to the unit, then systemctl --user daemon-reload && systemctl --user restart nanoclaw-v2-<slug>.
  • Dev shell: export LOG_LEVEL=debug before pnpm run dev.
Re-running the service setup step regenerates the plist or unit file, wiping manual Environment edits — re-apply them afterwards.
Per-group container config applies at the next container spawn — it’s read fresh from the database each time. A running container keeps its old config until it’s restarted, and package changes need an image rebuild (ncl groups restart --id <group-id> --rebuild). See the container configuration reference for per-field semantics. See Installation for service management details and finding your install slug.
Last modified on July 16, 2026