Releases: nanocoai/nanoclaw
Release list
v2.2.0
- Stamped plugins update in place through
ncl groups create --template <ref>. When a group already carries the template's plugin, the same command becomes an in-place update instead of minting a duplicate agent: a dry run prints a plan of every plugin-owned surface (plugin files, skills, MCP servers, persona, context files, tasks), flagging locally customized files whose edits would be lost;--yesapplies,--idpicks among several stamped groups,--newdeliberately stamps another agent. Agent state the plugin does not own (memory,plugin-data/, user-added MCP servers, task pause/resume state, wiring) is never touched. Plugin-stamped MCP servers now carry an ownership marker and refuse direct edits viancl groups config add-mcp-server/remove-mcp-serveror the agent'sadd_mcp_servertool: update the plugin and restamp instead. - [BREAKING] Agent templates are now Agent Plugins 1.0.0 directories.
plugin.jsonreplacescontext/instructions.mdas the required file; MCP servers move to a spec-shapedmcp.json; persona, extra context, and tasks move under theai.nanoco.nanoclaw/extension dir. Templates become portable to other plugin clients, and any conformant third-party plugin stamps as a NanoClaw agent. Migration: re-fetch templates from the registry (the pre-plugin layout fails with a migration error); to convert a local custom template, see docs/templates.md. - Plugin MCP servers may declare a working directory.
cwdinmcp.json(fixed forms./p,${PLUGIN_ROOT}[/p],${PLUGIN_DATA}[/p]) now launches the server in that directory instead of being skipped: resolved to an absolute container path at runtime, consumed natively by providers that support it and via acd-then-execlaunch shim on Claude. A stdio server that omitscwdruns from the plugin root (the spec default). - Setup can stamp the first agent from a template. The wizard offers the NanoClaw template library (or local
templates/) when creating the first agent;--template-path <ref>or the advanced screen presets the pick. A rerun over a partial install updates the stamped agent in place (dry-run plan + confirm) instead of duplicating it, the pick persists across wizard re-execs and reruns, and a template failure warns and continues instead of aborting setup. - Remote MCP servers can use Streamable HTTP. Register them with
ncl groups config add-mcp-server --name <name> --url <url>or the existing admin-approvedadd_mcp_servertool. Local stdio MCP commands keep their currentcommand/args/envbehavior; remote credentials remain OneCLI-managed: URLs with userinfo, fragments, or credential-looking query parameters are rejected. HTTPS is required except forlocalhost/host.docker.internal. - [BREAKING] Host modules now use one lifecycle registry. Custom modules that import
onShutdown()orgetShutdownCallbacks()fromresponse-registry.tsmust move to the host lifecycle API. Migration: follow the host lifecycle migration guide to detect affected code, update it, verify the cutover, or roll back. - Agent-to-agent messaging no longer loses to Claude Code's built-in
SendMessage. That built-in addresses the SDK's own in-session subagents, so an agent that had just runcreate_agentreached for it by name and gotNo agent named 'x' is currently addressable— reading as "the group was never provisioned" whilemcp__nanoclaw__send_message(the real path) was never called.SendMessagejoinsAskUserQuestioninSDK_DISALLOWED_TOOLS, so the PreToolUse hook now blocks it and points at the nanoclaw equivalent. - [BREAKING] Existing Claude installs should review the hardened agent image. Local builds remain supported, but the Echo-built image is recommended for patched sandbox components. Migration: follow the hardened-image guide to detect your current image source, switch, verify, or roll back.
- Release publication tolerates GitHub API propagation. The Release workflow now retries bounded post-publication read-backs when the new Release is not listed yet or its immutable state is not visible yet. Exact title, body, tag, or SHA mismatches still fail immediately.
- The
add-tavily-toolskill adds Tavily Search and Extract as keyless remote MCP tools for selected agent groups, bridged through a pinnedmcp-remote. - Scheduled tasks now run with their effective scheduled occurrence as the task time, plus a task-only
current_time(weekday included, in the agent group's timezone) instead of the creation timestamp. - Accumulated messages stay available as context without spuriously triggering warm-container follow-up turns; group-scoped agents can inspect their wirings and request approved engagement-policy updates; invalid engagement regexes are rejected.
- Hosted iMessage setup now provisions the line's user row directly and prints the assigned number to text once; that first message is the opt-in the delivery plane checks, and re-runs reuse the existing row.
- Resolved approval cards keep their title and request details, replace buttons with the decision and actor (or a timeout status), and survive host restarts and delayed resolution.
- Setup failure assist now offers diagnosis through the provider the operator picked instead of always offering to install Claude.
ensureUserDmgains an opt-in privacy-safe logging mode for security-sensitive flows: user IDs, handles, messaging-group IDs, and raw adapter errors are omitted while non-identifying channel context is kept.- The stale
add-gcal-tool,add-gmail-tool, andget-qodo-rulesskills were removed. - The recommended hardened agent image is repinned to
hardened-2026-08-13. - The package description now says personal AI assistant: NanoClaw is provider-agnostic, not Claude-only.
- Docs: skills define a single-responsibility integration rule, and the hardened-image guide states that
install_packagescovers apt and npm packages only.
New Contributors
- @dim0627 made their first contribution in #3187
- @zvi-fried made their first contribution in #3211
- @stumpjumper made their first contribution in #3216
- @manisrinivasan2k1 made their first contribution in #3190
Contributors
Thanks to everyone who landed work in this release:
- fix(setup): dispatch failure assist to the picked provider by @glifocat in #3170
- fix(release): retry post-publish readback by @glifocat in #3176
- Preserve resolved approval card content by @Koshkoshinsk in #3143
- fix(imessage): opt in via first message to the assigned line by @glifocat in #3181
- Fix engagement consistency and expose self-serve wiring controls by @Koshkoshinsk in #3137
- fix(update): surface hardened image migration by @gabi-simons in #3180
- versions: repin the agent image to hardened-2026-08-02 by @gavrielc in #3182
- fix(agent-runner): give scheduled tasks current run time by @Koshkoshinsk in #3154
- fix(agent-runner): disallow built-in SendMessage so agent-to-agent messaging works by @dim0627 in #3187
- chore(skills): remove stale qodo and Google MCP skills by @glifocat in #3172
- docs(skills): define single-responsibility integration rule by @zvi-fried in #3211
- refactor(db): add module migration registry by @zvi-fried in #3212
- refactor(host): unify module lifecycle hooks by @zvi-fried in #3214
- refactor(channels): register question renderers by @zvi-fried in #3213
- feat(permissions): add opt-in privacy-safe DM logs by @zvi-fried in #3222
- docs(hardened-image): note that install_packages covers apt and npm only by @stumpjumper in #3216
- feat: support remote Streamable HTTP MCP servers by @amit-shafnir in #3092
- feat: add Tavily MCP tool skill by @manisrinivasan2k1 in #3190
- feat!: agent templates become Agent Plugins 1.0.0 directories by @amit-shafnir in #3220
- feat(setup): template setup flow in the wizard and first-agent stamping by @amit-shafnir in #2909
- versions: repin the agent image to hardened-2026-08-13 by @gavrielc in #3236
- chore(release): v2.2.0 by @glifocat in #3237
Full Changelog: v2.1.54...v2.2.0
v2.1.54
Rollup release covering v2.1.18 through v2.1.54 — everything merged since the v2.1.17 tag.
- [BREAKING] iMessage unified into one
imessagechannel with two backends via/add-imessage: Local (this Mac'schat.dbvia the Chat SDK) or Hosted (native Photon viaspectrum-ts, no Mac relay). Backend chosen at install or viaIMESSAGE_BACKEND=local|hosted. The legacy Chat-SDK remote mode (IMESSAGE_SERVER_URL/IMESSAGE_API_KEY) and the separateimessage-cloudchannel +/add-imessage-cloudskill are removed. See docs/imessage.md. - [BREAKING] Provider-agnostic memory. All providers now share one OKF v0.1-compatible
memory/tree, while persona lives ininstructions.prepend.md; startup, clear, and compact reload memory automatically. Existing groups with legacy memory must run/migrate-memorybefore use. See memory and provider migration. - New groups can inherit an instance-wide default provider.
DEFAULT_AGENT_PROVIDERsets the provider used when a new agent group is created without an explicit provider. Each group's stored provider still overrides it, and existing groups are unchanged. - [BREAKING] Channel install skills are now the single source of truth. The setup wizard installs channels by applying the same
/add-<channel>SKILL.md a coding agent would follow — a deterministic engine executes the skill's mechanical steps directly from the document, so wizard and skill cannot drift, and anything the engine cannot do falls back to an agent reading the prose. Migration: the bespoke non-interactive channel installers (setup/add-<channel>.sh,setup/install-<channel>.sh) and per-channel wizard flows (setup/channels/<channel>.ts) are deleted. Anything that invoked them should apply the skill instead: interactively via/add-<channel>or the setup wizard, or programmatically via skill directives. - One guard for privileged actions. Every privileged action crossing the container or channel boundary now passes through
guard()before execution:allow,hold, ordeny. Approved replays carry the approval row as a grant and re-run checks against current state; forged, consumed, mismatched, or newly unauthorized grants fail closed. Guarded delivery actions can no longer be re-registered without their guard specification. - [BREAKING]
whatsapp-formattingandslack-formattingmoved from trunk to thechannelsbranch. They now install with their channel, so installations without those channels no longer carry channel-specific formatting instructions in every agent's context. Migration — only if the channel is installed: re-run/add-whatsappor/add-slackafter updating. Do not run an add-skill preemptively; it installs the full adapter. - [BREAKING] Scheduled tasks moved from MCP tools to
ncl tasks. Agents and operators now manage tasks withncl tasks list/get/create/update/cancel/pause/resume/delete/run/append-log; task sessions are isolated from the chat session that created them. Migration: follow the scheduled-task migration guide. - [BREAKING] Task delivery is explicit and uses one door. Every
send_messageandsend_filecall requires a namedtodestination; task-session final output becomes the run summary, while only explicitly addressed tool calls deliver. Migration: rebuild the agent image, restart NanoClaw, update custom instructions that omitto, and clear or compact existing sessions. Failed pre-task scripts now back their recurring series off and auto-pause after eight consecutive failures instead of spinning. - [BREAKING] Chat SDK and channel adapters are pinned to
4.29.0. The bridge and adapter must use the sameChatInstancetype, so exact pins replace caret ranges. Core installations without a channel are unaffected. Migration: if a channel is installed, re-run its/add-<channel>skill after updating. - Hardened agent images are available as an opt-in setup path. A digest-pinned, multi-architecture image can be fetched from the NanoClaw registry and retagged to the same local name used by builds; architecture, lockfile, provenance, size, and optional publisher-signature checks fail closed. Local builds remain the default and require no account. See hardened images.
- Agent containers now start with safer defaults. New spawns always drop all Linux capabilities, set
no-new-privileges, and use Docker's init process; these controls have no per-group override. A PID limit defaults to 2048 and can be changed installation-wide withCONTAINER_PIDS_LIMIT(0disables it). The Vercel CLI is now opt-in instead of being baked into every image. - Agent containers can have installation-wide resource caps.
CONTAINER_CPU_LIMITandCONTAINER_MEMORY_LIMITpass--cpusand--memoryto Docker for every agent container. Both remain empty by default, so existing installations keep their current behavior. - Per-agent-group timezones.
ncl groups config update --timezone <IANA>overrides the install timezone for that group's scheduling, run-log display, and containerTZ;""clears the override. Host-side operator display remains in the install timezone. - Agent templates and reusable skills expanded. Local templates can stamp persona, context, MCP configuration, and skills through
ncl groups create --template; templates can also seed scheduled tasks and timezone./learndistills a reusable skill from an existing workflow, and/add-clidashinstalls a read-only CLI-derived dashboard. - A clearer, safer
nclcontrol plane. Verbs now declare and validate their arguments, generate deep help, preserve dashed IDs, render human-readable output on the host, and flush large responses before exit. Creating groups and wirings now provisions their required companion rows transactionally, fixing first-spawn failures and silently dropped replies. - Approval and agent-to-agent controls are more expressive. Connected agents can require per-message approval; rejection reasons reach the requester; OneCLI approval cards use the gateway's structured summary; and shared-channel cards retain who approved or rejected an action.
- Delivery and provider failures stop disappearing. Missing adapters route messages into retry instead of marking them delivered, agent image builds no longer block the host, and Claude rate-limit telemetry only aborts a turn when the SDK reports a rejection. Billing exhaustion and transient rate limits remain distinct.
- Setup and update recovery improved. Setup can parse wrapped Claude OAuth captures, offer Slack Socket Mode, and reap dead peer-service registrations. Re-applying an updated skill rebuilds the container when needed, and a missing session folder is re-provisioned so the documented reset path works.
- Security fixes. Inbox attachment writes reject symlink escapes, approved CLI calls preserve the original caller context, command-gate checks no longer fail open, mount allowlists honor
readOnly, and stale v1 secret/config mirrors were removed. - Documentation was refreshed across architecture, database schemas, security boundaries, provider configuration, SDK behavior, skills, and registry-branch maintenance. A Korean README is now available.
New Contributors
- @arkjun made their first contribution in #2806
- @sturdy4days made their first contribution in #2803
- @moshe-nanoco made their first contribution in #2793
- @cben0ist made their first contribution in #2859
- @johnmathews made their first contribution in #2880
- @thisdotrob made their first contribution in #2885
- @leetwito made their first contribution in #2795
- @Shufel83 made their first contribution in #3003
- @boazdori made their first contribution in #2748
Contributors
Thanks to everyone who landed work in this release:
- fix(setup): parse Claude OAuth token from wrapped PTY capture by @amit-shafnir in #2805
- docs: add Korean README by @arkjun in #2806
- refactor: remove dead resolveGroupIpcPath by @sturdy4days in #2803
- refactor: mirror .claude skills + CLAUDE.md into .agents via symlinks by @Koshkoshinsk in #2810
- feat(agent-to-agent): per-message approval policies on connected agents by @moshe-nanoco in #2793
- fix(setup): allow env-selected agent provider by @amit-shafnir in #2811
- chore(deps): move chat SDK + channel-adapter pins to 4.29.0 by @gabi-simons in #2834
- fix(update-skills): nudge into skill updates, rebuild container on re-apply by @Koshkoshinsk in #2826
- fix(setup): reap dead peer service registrations whose binary is gone by @amit-shafnir in #2830
- feat(container): per-container CPU/memory limits (opt-in) by @omri-maya in #2856
- feat: add /learn skill — distill or refine a reusable skill from anything by @robbyczgw-cla in #2843
- feat(approvals): reject with reason by @moshe-nanoco in #2832
- fix(migrate-v2): don't SELECT is_main from v1 registered_groups by @cben0ist in https://github.com/nanocoai/nano...
v2.1.17
Rollup release covering v2.1.1 through v2.1.17 — every package.json bump merged since the v2.1.0 tag.
Changes
- [BREAKING]
@onecli-sh/sdk0.5.0 → 2.2.1 — requires a OneCLI server with the/v1API. Older servers 404 every SDK call. The sanctioned gateway and CLI versions are now pinned inversions.json, and theoneclisetup step enforces them. The gateway is a separate component — updating NanoClaw does not upgrade it for you:/update-nanoclawupgrades the gateway when its pin moves, otherwise upgrade manually. See docs/onecli-upgrades.md. - New agent provider: Codex (OpenAI) — run
/add-codex. Full runtime viacodex app-server(planning, MCP tools, server-side history, resume). Trunk ships the seams and the skill; the payload installs from theprovidersbranch — via the skill, the setup picker, or--step provider-auth codex. Auth is vault-only; no credential ever enters a container. - Setup can now select, install, and authenticate a non-default agent provider. A provider registry feeds the setup picker, an installer pulls the provider's payload from its branch, a vault auth walkthrough runs (
--step provider-auth), and the picked provider is set on the first agent — a DB property — before its first spawn. Default Claude installs are unaffected: picking Claude changes nothing. - Provider choice is explicit per group — no install-wide default. Provider is a DB property set via
ncl groups config update --providerplus a restart; group creation is provider-agnostic. /migrate-memoryruns the cross-provider memory move; runtime never touches it. Each provider keeps its own memory store, so fresh groups on a surfaces-owning provider see no staleCLAUDE.*files left over from another provider's writes. See docs/provider-migration.md./update-nanoclawnow upgrades the OneCLI gateway when its pinned version moves. Pairs with the OneCLI SDK 2.2.1 BREAKING above: the gateway upgrade that used to require a manual step is folded into the standard/update-nanoclawflow when the pin inversions.jsonshifts. Hosts whose gateway pin hasn't moved are unaffected.- Budget/billing-exhausted turns now reach the user instead of being silently dropped. When a turn ends in a non-retryable provider error — for example an Anthropic
403 billing_error— with no<message>wrapping, the agent-runner now delivers the provider's notice to the originating channel and stops re-nudging the failing gateway.providers/claude.tssurfaces the SDK'sis_errorflag and the error subtype'serrors[]text;poll-loop.tsdelivers that text and skips the re-wrap retry. Fixes the case where a spend-limit notice produced silence plus a turn-after-turn retry loop. - Command-gate denials now reach the sender.
writeOutboundDirectwas opening the session's outbound DB through the readonly opener, so the INSERT it ran threwSQLITE_READONLYon every call — the router'sPermission deniedresponse never delivered and the throw aborted further routing for that inbound event. Switched to the read-write opener (openOutboundDbRw, DELETE journal, busy_timeout); the host-side write stays even-seq, the container stays odd-seq, no contention. - Slash commands now interrupt an in-flight turn. A runner-handled command (
/clear,/compact,/cost, …) arriving mid-turn aborts the active stream and runs immediately instead of waiting for the turn to finish. - Container boot failures now say why. A 10-line stderr tail is kept per spawn and surfaced at
warnlevel on a non-zero exit (code !== null && code !== 0). Previously, a container that died at boot — unknown provider, missing binary, bad config — logged only atdebug, which is below the default level, so the failure vanished into a silent crash loop. - Egress lockdown (opt-in). Containers can be pinned to an allowlisted egress set via
ncl groups config update --egress-lockdown; outbound network calls outside the allowlist fail closed. Off by default. See docs/egress-lockdown.md. - Channel instances as a first-class dimension. A single channel kind — WhatsApp, Slack, … — can now run multiple independent instances per install, each with its own credentials, Chat SDK state, and webhook routes. Existing single-instance installs are preserved; the dispatcher falls back to
channelTypewhen noinstanceis set. - Native uninstaller.
bash uninstall.shfrom a checkout, ornanoclaw.sh --uninstallfrom the installed launcher, removes the service, the data directory, and the host registration in one step — no more manuallaunchctl bootout/systemctl --user disable. Includes--dry-runand a confirmation prompt; OneCLI agent registration is cleaned up alongside. - Interactive setup handoffs auto-submit context as Claude's first prompt. Mid-flow
?escapes and on-failure handoffs used to drop their context into--append-system-promptwith no user message, leaving Claude at an empty REPL while the operator re-explained themselves. Context now goes in as the first user message; handoffs in a single setup run also share a session-id (--session-idon the first spawn,--resumeon the next), so the conversation thread survives across mid-flow escapes. - Raw-route webhook registry. Channels register raw HTTP routes through a registry instead of patching the host's route table directly, so a new channel can be added without touching core. The non-Chat-SDK webhook suite kept its own file path to make the diff reviewable.
- Delivery-action getter. Channels expose a typed
getDeliveryActionso the host can route a message to the right send / edit / react path without channel-side branching at the call site. Read side of the action registry; the write side stays in the channel adapters. - Approval-resolved callback registry. Channels can register a callback that fires when an approval resolves — approved or rejected — used for in-channel acknowledgment cards and audit-trail edits.
- Per-exchange archiving is provider-owned. The
onExchangeCompletehook fires per turn; the markdown writer ships with the provider that needs it (codex payload), and the runner stops archiving on a provider's behalf. Dormant for the default Claude provider. - [security] A2A symlink guard. Inbound A2A payload resolution now fails closed on any symlink escape from the per-group sandbox — the resolver rejects forwarded attachments that traverse out via a symlink.
- [security] Approval admin authorization tightened. Approval response endpoints now require admin status and check the approver's scope against the request's group before executing — no cross-scope approvals.
- [security]
create_agenthost-side authorization. Agent creation is now authorized on the host side as well as the API edge: for confined groups, host-side approval is required, so a compromised channel can't spawn agents it isn't entitled to. host-sweepnow respects a per-group wake grace so it doesn't tear down a container that just woke and still has a stale processing claim.- Global agent-container CLI installs are data-driven via
container/cli-tools.json— skills add a CLI by appending a{name, version}JSON entry instead of patching the Dockerfile.agent-browseris now pinned to 0.27.1 (whatlatestlast resolved to); the rest is byte-for-byte unchanged. - Four skills retired (broken on v2 architecture):
claw,x-integration,add-parallel,convert-to-apple-container. References cleaned up inREADME.md,docs/SPEC.md,CONTRIBUTING.md, andCLAUDE.md. - Skills install model documented; see docs/skills-as-branches.md.
- Twelve skills retrofitted to the current skill contract:
add-dashboard,add-atomic-chat-tool,add-deltachat,add-slack,add-ollama-tool,migrate-from-openclaw,channel-family,opencodeprovider,codexprovider,mcp,capability,use-native-credential-proxy. - Ollama docs guide added for making the Ollama prompt cache hit on the Claude-Code → Ollama path: a small proxy filters the per-request
cch=<hash>the Claude Agent SDK prepends; in a 31B-on-Apple-Silicon setup, follow-up replies went ~80 s → ~4 s. Numbers vary by model. See docs/ollama.md. chat-sdk-bridgerecords the acting user on resolved approval/question cards in shared channels — appends a— <userName>byline to the edited card so the audit trail of who clicked Approve or Reject survives the button removal.@anthropic-ai/claude-code2.1.170 and@anthropic-ai/claude-agent-sdk0.3.170.
New Contributors
First NanoClaw PRs from @omri-maya, @markbala, @amit-shafnir, and @assapin landed in this release — welcome all four:
- @omri-maya — #2713
- @markbala — #2710
- @amit-shafnir — #2719
- @assapin — #2759
Want to be in the next one? Anyone can open a PR — pick up a good first issue or propose your own change directly. Discord is there if you want a hand getting started.
Contributors
Thanks to everyone who landed work in this release:
v2.1.0
Rollup release covering v2.0.65 through v2.1.0 — every package.json bump merged since the v2.0.64 tag.
Changes
- [BREAKING] Startup now requires an upgrade marker. The host refuses to boot unless
data/upgrade-state.jsonrecords that this install reached the current version through a sanctioned path (/setup,/update-nanoclaw,/migrate-nanoclaw). After this update completes — and before restarting the service — stamp the marker by runningpnpm exec tsx scripts/upgrade-state.ts set. If the host has already tripped on restart with "update did not go through the supported path", that same command clears it. (The tripwire code actually shipped in v2.1.1; v2.1.0 is the meaningful release boundary because the version bump and the feature merge sequenced in that order — every install on v2.1.1 or higher carries the tripwire.) See docs/upgrade-recovery.md. /upload-traceships the session transcript to Hugging Face. A runner-handled slash command (admin-gated, like/clear) pushes the current session's Claude Code transcript to the user's own private{hf_user}/nanoclaw-tracesdataset, browsable in the HF Agent Trace Viewer. Auth runs through the OneCLI gateway: the HF token is injected byHTTPS_PROXYand never touches agent code; a missing or unassigned token returns a clear setup message pointing at the gateway URL.- New
/add-rtkskill. Installs rtk into agent containers via host binary mount + a Claude CodePreToolUsehook, routing dev-loop commands through an output-summarizing proxy that saves 60–90% of tokens on compile/test/lint turns. Off by default — the skill opts a group in. - New
whatsapp-formattingcontainer skill. Inlined into every group'sCLAUDE.mdon container spawn (viaclaude-md-compose.ts) so agents see WhatsApp's mention syntax —@<phone-digits>sourced fromcontent.sender, never display names — on every reply. Without this, agents defaulted to@<displayName>, which WhatsApp can't tag: the @ rendered as plain text with no notification. Mirrors the existingcontainer/skills/slack-formatting/layout; pairs with the channels-branch fix that wiresmentionsthrough to Baileys'contextInfo. ncl groups deletenow cascades cleanly. Sessions, destinations, members, wirings, scheduled tasks, and dropped messages tied to a deleted group are removed in the same transaction — no orphan rows, no follow-up sweep needed.- Long-lived hub sessions now rotate their transcript before resume. The Claude provider checks the on-disk
.jsonlbacking the stored continuation before each--resume; if it exceeds 12 MB or its first entry is older than 14 days, an archived markdown summary is written toconversations/and a fresh session starts. Caps are operator-overridable viaCLAUDE_TRANSCRIPT_ROTATE_BYTESandCLAUDE_TRANSCRIPT_ROTATE_AGE_DAYS; both honor a zero/negative value as "disabled". Fixes the symptom where a hub that was responsive for days goes silent on a heavy turn because the SDK reloads the full transcript on every resume and the first turn alone exceeds the host's 30-min idle ceiling. - Outbound
<messages>envelope dropped — fixes the N>1 pending-message retry loop. When 2+ pending messages were bundled into<messages>...</messages>, the Claude Agent SDK returned a synthetic stub (model="<synthetic>",content="No response requested.") instead of calling the real API. The poll loop never marked the inbound row complete, the container exited, host-sweep respawned it with the same batch, and the transcript ballooned untiltries=5→ failed. Single-message turns were unaffected because they skipped the wrapper. Each<message id=... from=...>block is already self-contained, so dropping the outer envelope lets N>1 turns work the same way N=1 always has. - Persistent
inbound.dbcorruption now exits the container so host-sweep can respawn with a fresh mount. On Docker Desktop macOS, the kernel page cache for the bind-mountedinbound.dbcan latch a torn snapshot mid-host-write (a known virtiofs / gRPC-FUSE coherency issue); every fresh handle in the same process then sees the same broken view and emitsdatabase disk image is malformedat the poll rate. Reopening the handle inside the container does not recover — only a fresh container mount does. After ~5s of consecutive corruption errors (CORRUPTION_STREAK_EXIT), the runner exits with code 75 and host-sweep respawns it. Transient single torn reads are still tolerated. - Bumped
@anthropic-ai/claude-codeto 2.1.154 and@anthropic-ai/claude-agent-sdkto 0.3.154. - WhatsApp QR rendering wrapped so the QR block stays intact when piped through line-wrapping terminals.
- OneCLI base URL moved from
app.toapi.to match the new gateway DNS. setup-registerscope tightened so it can't register a group outside the operator's scope.- Channel approval targets are now authorized against the approving admin's scope — no cross-group approvals via crafted payloads.
signal-cli0.13+ identity field accepted; earlier versions kept working./add-teamsCLI docs corrected — previous version referenced flags that had been renamed.- Photon integration URL corrected from
photon.imtophoton.codesto match the new authoritative domain. CLAUDE.local.mdwrites now go through the SDK'ssettingSourcesplumbing so they survive a session reset.
New Contributors
First NanoClaw PRs from @claudiopostinghel, @snymanpaul, @mmahmed, @kartast, and @jonnychesthair-crypto landed in this release — welcome all five:
- @claudiopostinghel — #2551
- @snymanpaul — #2584
- @mmahmed — #2592
- @kartast — #2597
- @jonnychesthair-crypto — #2598
Want to be in the next one? Anyone can open a PR — pick up a good first issue or propose your own change directly. Discord is there if you want a hand getting started.
Contributors
Thanks to everyone who landed work in this release:
- @IamAdamJowett — #2553, #2556, #2586, #2595, #2596
- @gavrielc — #2637, #2648, #2690, #2691
- @glifocat — #2526
- @claudiopostinghel — #2551
- @guyb1 — #2558
- @kky — #2563
- @Hinotoi-agent — #2566
- @ira-at-work — #2571
- @snymanpaul — #2584
- @mmahmed — #2592
- @kartast — #2597
- @jonnychesthair-crypto — #2598
Full Changelog: v2.0.64...v2.1.0
v2.0.64
Changes
ncl destinations addandremovethrough the approval flow now reach the receiver immediately. Approved destinations weren't being projected into the receiving agent's local session state, so a freshly-added destination silently failed atsend_messagewithunknown destination, and a removed destination stayed resolvable until the next container restart. Both now take effect the moment the approval executes. Direct (non-approval) calls were unaffected.
Contributors
Full Changelog: v2.0.63...v2.0.64
v2.0.63
First properly published release. Starting with v2.0.63, the goal is to publish a GitHub Release for every
package.jsonversion bump that lands onmain— releases are cut manually by a maintainer, so there can be lag. Until now only the bumps landed and tags were sporadic, which made it hard for packagers and users to pin to a known version. See RELEASING.md for the policy.
Rollup release covering v2.0.55 through v2.0.63 — everything merged since the v2.0.54 tag.
Changes
- [BREAKING] Service names are now per-install. On v2 installs the launchd label and systemd unit are slugged to your project root:
com.nanoclaw.<sha1(projectRoot)[:8]>andnanoclaw-<slug>.service. The oldcom.nanoclaw/nanoclaw.servicenames no longer match a real service — update any copy-pasted restart or status commands. Find your install's names withsource setup/lib/install-slug.sh && launchd_label(macOS) orsystemd_unit(Linux). Thencltransport-error help text and 26 skill files now use the canonical helper-driven pattern; seesetup/lib/install-slug.sh. - Compaction destination reminder placement fixed. The reminder injected after SDK auto-compaction now appears at the end of the compaction summary so it isn't stripped during truncation. Replaces the placement shipped in v2.0.54.
- Stronger message-wrapping enforcement. The poll loop nudges the agent when its output lacks
<message>wrapping, andCLAUDE.mdcore instructions now require wrapping even for single-destination agents. The welcome flow no longer double-greets. - OneCLI credentials after MCP install. MCP servers added through
add_mcp_servernow inherit OneCLI gateway routing — fixes the case where the agent kept asking for API keys after installing a new server. - CLI scope hardening.
scopeFieldnow fails closed when scope is missing, andsessions getis guarded against cross-group oracle access from group-scoped agents. - gmail/gcal skills aligned with v2.
/add-gmail-tooland/add-gcal-toolnow reflect the v2 container-config model — DB-backed mounts, no deadTOOL_ALLOWLISTedits, nocontainer.jsonwrites that get clobbered on next spawn. Manual sqlite3/JSON1 invocations corrected. - Repo-rename cleanup. Remaining
qwibitai/nanoclawreferences swept tonanocoai/nanoclawacross code and docs; CI workflow guards updated so they no longer no-op after the rename. - Slack scope checklist now includes
files:readandfiles:writefor skills that read or post attachments. - The internal-tag description in destination instructions no longer mentions scratchpads (which confused agents into routing them incorrectly).
- Container startup is now graceful when the
on_wakecolumn is missing on older sessions DBs.
New Contributors
First NanoClaw PRs from @dvirarad and @intentionaleva landed in this release — welcome both:
Want to be in the next one? Anyone can open a PR — pick up a good first issue or propose your own change directly. Discord is there if you want a hand getting started.
Contributors
Thanks to everyone who landed work in this release:
- @johnnyfish — #2384
- @glifocat — #2392, #2402, #2408, #2489, #2493
- @dvirarad — #2400
- @gavrielc — #2410, #2412, #2413, #2414
- @Koshkoshinsk — #2442, #2467, #2473
- @intentionaleva — #2460
Full Changelog: v2.0.54...v2.0.63