Back to Freedom.Tech Back
All NanoClaw releasesAll versions
Release Wed, Sep 23, 2026 9 min read

NanoClaw 2.4.0

Original release notes

NanoClaw 2.4.0 adds credential gateways installed through skills (OneCLI stays the default, Iron Proxy is new), community-portal setup for Echo's hardened image and a managed Slack app, install-wide and per-group model and speed controls, a Mattermost channel, and a reworked OpenCode provider. Agents now receive all of their capability instructions, replies stay in the thread they answer, and host restarts and /update-nanoclaw are more reliable. The default Claude model moves to Opus 5.5 and new Codex threads to gpt-6-astra, so check the section below before you update.

Before you update

  • [BREAKING] Custom source that composes agent instructions must move to the new module. CLAUDE.md was a list of @ imports into /app, and Claude Code silently drops imports that resolve outside the project directory, so eight of nine instruction sections never reached the model; it is now one flat file with every source inlined, shared with the Codex provider. src/claude-md-compose.ts is now src/project-doc-compose.ts, composeGroupClaudeMd(group) became composeGroupProjectDoc(group, groupDir, spec), and the /app/CLAUDE.md and /workspace/agent/.claude-fragments mounts are gone. Migration: run grep -rn --exclude='*.test.ts' "claude-md-compose\|composeGroupClaudeMd\|claude-fragments" src/ setup/ scripts/; no hits means nothing to do, otherwise repoint the import and pass DEFAULT_PROJECT_DOC as the third argument. Then clear the inert leftovers once with rm -rf groups/*/.claude-fragments groups/*/.claude-shared.md. Standard installations need no source edits; see docs/release-2.4-update.md.
  • [BREAKING] Forks that merge upstream by hand must install their credential gateway before restarting. Credential gateways now install through skills: /add-onecli supplies OneCLI and /add-iron-proxy adds optional Iron Proxy support, with a shared contract owning session lifecycle and human approvals. OneCLI remains the simple-setup default, gateway selection appears only in advanced setup, and upgrades preserve the existing selection. Setting NANOCLAW_GATEWAY_PROVIDER alone does not install its implementation, and the host refuses to start without a registered gateway. Migration: /update-nanoclaw materializes the selected gateway before cutover; a manual merge must apply /add-onecli (or the selected gateway's skill) before restarting. See gateway migration for detection, verification, and rollback.
  • Claude groups with no model set move to Opus 5.5, which changes cost and usage-limit burn. API-key installs move from Opus 5, and Pro and Team Standard installs from Sonnet. To keep a model, set NANOCLAW_DEFAULT_MODEL in .env or run ncl groups config update --id <group> --model <model> before updating.
  • Codex groups with no model set start new threads on gpt-6-astra. /add-codex now pins @openai/codex 0.155.1, whose default replaces 0.146.0's gpt-5.6-sol; existing threads keep the model they started on. To stay on the old model, run ncl groups config update --id <group-id> --model gpt-5.6-sol, then ncl groups restart --id <group-id>. NANOCLAW_DEFAULT_MODEL would also hold it but applies to Claude groups too. Existing Codex installs get the new pin and the provider fix below together from /update-nanoclaw, which rebuilds the agent image on installs that build their own.
  • Claude agents default to a concise tone. A Claude group whose settings do not set an output style now starts with Concise; the default is written once into the group's Claude settings and an explicit value is never overwritten, so groups that already set outputStyle are unaffected. To keep or change the tone, set outputStyle in data/v2-sessions/<agent-group-id>/.claude-shared/settings.json (the group's /home/node/.claude/settings.json); project and local settings still take precedence.
  • Existing OpenCode installs must refresh the skill payload. The optional /add-opencode skill now uses the native provider contracts and the new contract refuses the old payload: re-run /add-opencode, rebuild the agent image, and restart the host and the OpenCode groups.
  • Cutover stops this install's agent containers itself. /update-nanoclaw no longer times out while an idle agent container is running: it stops the containers with a 10-second grace inside a one-minute bound and names them as it goes, so no manual docker stop is needed. An agent in the middle of a turn loses that turn, as with ncl groups restart.

New

  • Iron Proxy is an alternative local gateway. /add-iron-proxy installs Iron Proxy and its Iron Control web console (Secrets, Credentials, OAuth Apps, Principals) on Docker; each request passes front identity and allowlist, then human approval, then stored credentials, before it reaches upstream. Codex works through Iron, including its WebSocket turns, setup can install Codex and pair it under Iron in one run, and a failed credential save names its cause on screen and in logs/setup.log. See .claude/skills/add-iron-proxy/SKILL.md.
  • OpenCode can authenticate through Iron Control. It can store API keys and native ChatGPT OAuth credentials there, including token refresh and reauthentication that preserves grants.
  • Echo's hardened image and a managed Slack app are set up through the community portal with one browser sign-in. Setup prints one link that covers sign-in, terminal approval and the perk choice, and the install token never passes through the browser. The running host stays linked to your account's cell, so a perk changed in the browser reaches the running agent and a Slack install approved days later finishes on its own. Setup asks each portal question once, including across a resumed or repeated run; Dial and Tavily are not offered. See docs/community-portal.md.
  • Two install-wide model knobs. NANOCLAW_DEFAULT_MODEL fills in the model for agent groups that have not set one of their own (a group's own model always wins), and NANOCLAW_FAST_MODE=1 turns on the API's fast serving tier for every agent, with faster output at a higher per-token price. Both are read from the host .env when container.json is materialized, so a change takes effect at the next container start with no host restart. Installs that set neither are unaffected: neither field is written to container.json and the provider sends exactly the options it sent before.
  • Per-group serving speed. ncl groups config update --id <group> --speed fast selects a serving tier the group's provider declares; Claude accepts standard and fast, fast mode costs more per token, and --speed "" clears it. Agent callers need approval, as with --timezone.
  • Agents run on Claude Code 2.1.280. A cd now carries over between turns, Monitor watches expire after 30 minutes, resumed agents keep seeing their current name and destinations, and claude.ai account skills and plugins are not synced into agent containers.
  • The OpenCode provider is reworked. /add-opencode now uses host-managed authentication and model selection, native tools and compaction, and reliable cancellation, and setup can install and authenticate it.
  • Mattermost is a channel. /add-mattermost installs it, can connect to a server you already run, validates and atomically saves its settings, verifies the running bot and server callback, and no longer needs a separately installed jq.
  • Host restarts keep approvals and delivery state. Approvals, delivery retry counts and session claims now live in the central database instead of host memory: an approval card sent before a restart still resolves after it (a late approve that can no longer be applied gets a follow-up card), overdue approvals expire as "no response" instead of being swept as "host restarted", and a message that keeps failing gives up after its retry limit even across a crash loop. A second host started in the same checkout no longer takes over a running host's ncl socket, and a host still draining during a restart keeps its sessions until it exits.
  • ncl status shows the running host process and its connected channel adapters. Setup uses it to confirm that the restarted host is the one it started.
  • The Slack agents companion skills ship on main. /slack-a2a-rooms and /slack-agent-flow now come with the core source.

Fixes

  • Codex turns no longer complete with nothing sent. From 0.147.0, Codex starts a turn after about one second without the tools of any MCP server still starting. The provider now waits for every MCP server to finish starting (Codex gives up on one after 30 seconds, as 0.146.0 did) and requires NanoClaw's own tool server: if that server cannot start, the message fails with an error instead of running without its tools.
  • Replies stay in the thread they answer. Replies, send_message, send_file, ask_user_question and send_card land in the thread of the message being answered, not the main channel or a thread that spoke more recently; this covers shared and agent-shared sessions, and replies from a turn longer than 30 minutes stay threaded.
  • Busy installs stay fast. The host sweep and delivery polls visit up to 8 sessions at a time at a fixed rate, and cross-session ambient context fans out only to a conversation's 8 most recently active threads (within 3 days) after the container wakes, so installs with many sessions or busy channels no longer see reply and task latency grow with size.
  • Quoted .env values read the same everywhere. Setup had its own parser that did not strip surrounding quotes, so a hand-edited TZ="America/New_York" or NANOCLAW_TEMPLATE_PATH="/opt/my templates" reached the wizard with the quotes attached and the template path was bridged into process.env unusable; both readers now share the host parser (envValue in src/env.ts, the single-key form of readEnvFile).
  • /update-nanoclaw loads its controller again. It crashed with MODULE_NOT_FOUND; it now also snapshots symlinked data roots by content and is correct on macOS hosts.
  • Setup is sturdier on Linux. No hang with a system-wide Node, a user-owned npm prefix instead of an invisible sudo, a nohup-started host verified and kept running when user systemd is missing, installers that run under /bin/sh and /bin/bash, a uvx-installed pnpm recovered, and the replacement host verified after a restart.
  • Concurrent SQLite migrations no longer fail setup or upgrade. Failed registry copies keep existing files, registry skills install from single-branch clones, and installing missing skill files keeps your customizations.
  • OneCLI certificate and credential-stub mounts survive host restarts and temp cleanup, and WEBHOOK_PORT is read from .env.
  • Conversations reach the right place and stop when asked. Cancelled questions stop promptly, failed provider turns keep partial replies, scheduled-task escalations default to the agent's own channel, and Slack group-DM and multi-instance approval cards name the right conversation and bot.
  • Task failures are easier to diagnose. ncl tasks update rejects an empty --prompt, and a timed-out pre-task script says so.
  • /add-dial handles more starting states. It installs the Dial tool on a first-ever install (before any agent exists), echoes what you type at its agent-scope question, and /add-dial-tool can re-register a rotated key with OneCLI.
  • Agents know their card options. They are told that send_card supports URL link buttons and that interactive choices need ask_user_question.

Security

  • Setup redacts resolved secrets in skill logs and commits related .env values atomically.
  • The agent image is repinned and the supply-chain gate is enforced. The image is hardened-2026-08-24 and runs Bun 1.4.0, and pnpm's 3-day minimumReleaseAge gate now takes effect. See docs/hardened-image.md.

For custom installations

  • Chat SDK channels can recover content the adapter left in the raw payload. The bridge drops message.raw before persisting, so anything a platform did not project into its message text was lost; Slack keeps pasted tables in attachments[].blocks[], and an agent saw only the sentence before the table. The optional extractRawText hook on ChatSdkBridgeConfig lets a channel rescue that content as text before raw is discarded; raw payloads still never reach the database, and a channel without the hook is unaffected. Slack uses it to recover pasted tables: refresh /add-slack to get it.
  • Custom OpenCode models can declare their limits. /add-opencode documents OPENCODE_MODEL_CONTEXT_LIMIT, OPENCODE_MODEL_OUTPUT_LIMIT and OPENCODE_MODEL_INPUT_MODALITIES, which set a custom model's context, output and input limits.

New Contributors

  • @tchopoorian made their first contribution in https://github.com/nanocoai/nanoclaw/pull/3655
  • @tahodev made their first contribution in https://github.com/nanocoai/nanoclaw/pull/3771
  • @linhongyu510 made their first contribution in https://github.com/nanocoai/nanoclaw/pull/3689
  • @DorZvulun made their first contribution in https://github.com/nanocoai/nanoclaw/pull/3844

Contributors

Thanks to everyone who landed work in this release:

  • versions: repin to hardened-2026-08-23 and let benign lock drift through by @gavrielc in https://github.com/nanocoai/nanoclaw/pull/3496
  • versions: repin the agent image to hardened-2026-08-24 by @amit-shafnir in https://github.com/nanocoai/nanoclaw/pull/3531
  • docs(add-opencode): document the OPENCODE_MODEL_* limit and modality env vars by @glifocat in https://github.com/nanocoai/nanoclaw/pull/3524
  • ci: handle branches without an old image pin by @glifocat in https://github.com/nanocoai/nanoclaw/pull/3534
  • fix(dial): post-merge follow-ups - credential re-run, step captions, registry CI by @glifocat in https://github.com/nanocoai/nanoclaw/pull/3432