github nanocoai/nanoclaw v2.3.0

3 hours ago
  • [BREAKING] A new Slack experience — per-agent provisioned Slack apps, agent spawning from Slack, and UX improvements — is available to classic single-bot Slack installs. Classic Slack keeps working unchanged; this gate asks for a decision, not a forced migration. New installs and non-Slack installs are unaffected. Migration: run /migrate-slack-agents — it detects classic state (exits cleanly otherwise) and either walks the upgrade or records the choice to stay on classic; both outcomes satisfy this requirement.
  • /add-codex now pins @openai/codex 0.146.0. The previous pin (0.138.0) defaults to GPT-5.4, which OpenAI retires from Codex on 2026-08-31 — codex-provider agents ride the CLI default model, so stock installs stop completing turns at retirement — and it rejects the newer GPT-5.6 models with a 400 asking for a newer Codex CLI. Existing codex installs are not re-pinned by re-running /add-codex (the manifest merge is keyed on package name): edit the @openai/codex entry in container/cli-tools.json to 0.146.0, rebuild the agent image (./container/build.sh), and restart.
  • [BREAKING] Agent mailbox access now goes through storage-neutral host and runner registries. The built-in SQLite implementation preserves existing session data and runtime behavior, but custom source may need to replace raw session-database access, await mailbox writes, update moved runner state/heartbeat helpers, drop DeliveryActionHandler's database argument, use booleans for trigger/onWake, and use the closed inbound-kind set. Migration: follow the agent mailbox seam migration guide for the complete detect grep, old→new symbol map, verification, and rollback.
  • Scheduled-task lifecycle semantics are stricter. Deleting an isolated task cascades its session state, updates refuse already-due runs, recurring selection uses the active series snapshot, and generated task timestamps retain millisecond precision.
  • [BREAKING] The container runtime moves behind the session driver seam. Session containers are composed as a validated, admission-checked spec and realized by a selectable driver (src/drivers/; Docker ships built-in and stays the default). Three surfaces break: (1) group folder names align to the runtime label grammar — at most 63 characters of [A-Za-z0-9_-], alphanumeric at both ends — so previously-legal 64-character names, trailing -/_, and unvalidated legacy imports refuse to spawn; (2) container names and invocation change from nanoclaw-v2-<folder>-<timestamp> to key-derived ncl-… names (the old human-readable name survives as the nanoclaw-container-name label) and from docker run to create + start --attach — name-based tooling, Docker-command allowlists, wrappers, and audit rules should match by label instead (docker ps --filter label=nanoclaw-session, or --filter label=nanoclaw-group-folder=<folder>); (3) internal container helpers moved into the driver module — customized installs importing hostGatewayArgs, readonlyMountArgs, stopContainer, ensureContainerRuntimeRunning, cleanupOrphans, or patching buildContainerArgs stop compiling. The use-native-credential-proxy skill is retired: the spec's admission rules refuse credential values in container env on every lane, by design — credentials ride the OneCLI vault, and custom Anthropic endpoints use the ANTHROPIC_BASE_URL + placeholder-token pattern from setup. Migration: run bun scripts/detect-driver-migration.ts — it detects all three surfaces in your install and prints one finding per line with a minimal fix instruction; hand the output to your coding agent. Nothing detected means nothing to do.
  • Host restarts now adopt running sessions instead of restarting them. A service restart no longer kills in-flight agent work; to apply image or runtime changes to a group, restart it deliberately with ncl groups restart. Pre-seam containers (spawned before this release) cannot be adopted and are removed at first upgraded startup, exactly as the old startup cleanup did.
  • Container gateway wiring is typed and admission-checked. The gateway's per-session contribution (proxy env, trust anchors, credential-stub mounts) merges into the session spec before validation instead of riding raw docker flags around it, and gateway selection becomes a registry (NANOCLAW_GATEWAY_PROVIDER, default onecli — an install that never sets it behaves as it always has).
  • Non-root hosts get an explicit container identity. Every non-root host now passes --user <uid>:<gid> and HOME=/home/node (previously uid-1000 hosts relied on the image's node user). On uid-1000 systems whose primary gid is not 1000, files the agent writes into mounted workspaces now carry the host's gid — which is the intended behavior.
  • CONTAINER_MEMORY_LIMIT is validated at spawn. Invalid values refuse the spawn with a named error instead of surfacing as a raw Docker error; blank and 0 still mean uncapped.
  • An unknown NANOCLAW_RUNTIME_DRIVER aborts startup (new variable — installs that never set it are unaffected), and drivers that cannot rebuild images in place deny install_packages and --rebuild at request time instead of failing later.
  • [BREAKING] The host runtime now requires Node.js 22 or newer. Node 20 is not supported by the upgraded better-sqlite3 release used for current Node runtimes. Migration: run bash setup/install-node.sh, verify node --version reports v22 or newer, then rerun /update-nanoclaw; stay on the previous NanoClaw release if Node cannot yet be upgraded.
  • New NanoClaw installs now use OneCLI gateway 1.41.0. Existing 1.36.0 gateways remain compatible because NanoClaw does not depend on any 1.41-only behavior. See the OneCLI upgrade guide to upgrade an existing gateway.
  • [BREAKING] Central database access is now asynchronous behind DbDriver. SQLite remains the default and existing data/v2.db files are unchanged, but custom source and installed channel/provider extensions must await central reads and writes and adopt the retyped host seams. Migration: follow the central database async migration guide to find affected calls, preserve transaction boundaries, update extensions, verify SQLite behavior, or roll back.
  • Central DB composition and migrations are backend-ready. A one-slot driver registry keeps backend selection in src/db/compose.ts; pnpm run migrate is the explicit schema-change path, host validation can fail closed without DDL, and a shared conformance suite pins transaction, parameter, ordering, and timestamp behavior. SQLite remains the installed default.

New Contributors

Contributors

Thanks to everyone who landed work in this release:

  • ci: let verify-agent-image run on every PR so it can gate by @gavrielc in #3238
  • ci: open the agent-image bump PR from a dispatch by @gavrielc in #3240
  • verify-agent-image: pin the publisher identity, and check attestations per arch by @gavrielc in #3158
  • ci: let a verified signature be the approving review by @gavrielc in #3241
  • verify-agent-image: arming auto-merge is not a verdict by @gavrielc in #3243
  • fix(poll-loop): stopped loops leaked their active query's follow-up poller by @gavrielc in #3268
  • engine: bump OneCLI gateway pin to 1.41.0 by @amit-shafnir in #3277
  • Permissions: registerChannelCardInterceptor seam before registration cards (A4) by @gavrielc in #3266
  • Agent-to-agent: CreateAgentOptions.suppressCreatedNotify (A3) by @gavrielc in #3265
  • Delivery: registerDeliveryBatchPreview hook over each undelivered batch (A2) by @gavrielc in #3264
  • Channel registry: hot-start a registered adapter after boot (A1) by @gavrielc in #3263
  • channels: Chat SDK bridge agent-mode DM surface — app-context capture, DM-thread normalization, dm-opened hook (A8 + C4) by @gavrielc in #3262
  • channels: optional adapter capabilities — status-bearing setTyping, setThreadTitle, setSuggestedPrompts + registry passthroughs by @gavrielc in #3261
  • permissions: 'decline_notify' unknown-sender policy — polite decline + one-line owner FYI, no approval card by @gavrielc in #3260
  • setup/tooling: skill-apply heading-ordinal strip, headless browser URL surfacing, inherit-script extraction by @gavrielc in #3259
  • container: mid-turn streaming is the single delivery door — cross-segment assembly, DB-backed echo suppression, no result-door sends by @gavrielc in #3284
  • Preserve structured chat links by @Koshkoshinsk in #3283
  • fix: idle container with no heartbeat file is exempt from the absolute-ceiling kill forever by @gavrielc in #3252
  • fix(skills): stop removal docs pointing at the retired data/env mirror by @teran13 in #3230
  • docs(container): tell the agent where received attachments land by @brentkearney in #3210
  • fix(container): bump pnpm and npm past fixable-critical tar CVE by @gabi-simons in #3207
  • Add AnyDoc document conversion skill by @amit-shafnir in #3198
  • Cross-session context for multi-session agent groups (batching, delivery-resolution, and detached-state prerequisites included) by @gavrielc in #3285
  • channels: generic membership-event hook on the Chat SDK bridge by @gavrielc in #3295
  • agent-runner: extendTool — additive MCP tool schema and description extension by @gavrielc in #3296
  • delivery: post-delivery hook with first-delivery context by @gavrielc in #3294
  • router: session-created hook for brand-new engaged sessions by @gavrielc in #3293
  • setup: per-channel pre-step and companion-skill declarations for the wizard by @gavrielc in #3297
  • channels: bridge inbound-policy registration seam by @gavrielc in #3292
  • channels: adapter-declared session-mode context defaults (threads stamp derived) by @gavrielc in #3304
  • fix(update): make NanoClaw upgrades transactional by @glifocat in #3195
  • cross-session context: extend new-session backfill to group conversations by @gavrielc in #3312
  • skills: channel welcome addenda, matched host-side (zero cost when absent) by @gavrielc in #3313
  • setup: optional automatic Slack app provisioning behind an opt-in flag by @gavrielc in #3314
  • Fix Telegram skill copy list by @Koshkoshinsk in #3316
  • ci: add zvi-fried to core team roster by @gabi-simons in #3348
  • drivers: a session-runtime driver seam, with Docker as the built-in realization by @gavrielc in #3306
  • host: route session lifecycle through the driver seam by @gavrielc in #3307
  • groups: refuse to create a group over a folder that already exists undisposed by @gavrielc in #3308
  • refactor(db): prepare the central database for portable drivers by @moshe-nanoco in #3332
  • refactor(db): add async central database seam by @moshe-nanoco in #3333
  • [BREAKING] refactor(db): adopt async central database safely by @moshe-nanoco in #3334
  • refactor(db): add backend composition and portable tests by @moshe-nanoco in #3335
  • fix setup ping folder compatibility by @amit-shafnir in #3350
  • docs(telegram): document approved group connection flow by @amit-shafnir in #3352
  • setup: --slack-agents installs the whole Slack agents feature by @Koshkoshinsk in #3357
  • fix(setup): fail closed when a stored sign-in cannot be verified by @gavrielc in #3339
  • feat(setup): forward optional client metadata on Slack service requests by @gavrielc in #3345
  • fix(approvals): record the delivering instance on pending_approvals by @gavrielc in #3340
  • fix: support current Node runtimes by @Koshkoshinsk in #3360
  • fix: expose decline notification overrides by @Koshkoshinsk in #3361
  • feat(cli): accept bounded JSON from stdin by @zvi-fried in #3218
  • fix(add-codex): bump @openai/codex pin 0.138.0 → 0.146.0 before GPT-5.4 retires from Codex (2026-08-31) by @chiptoe-svg in #3299
  • Log a warning for unrecognized engage_mode instead of silent drop by @wakqasahmed in #3317
  • feat: add agent mailbox seam and registry by @zvi-fried in #3349
  • fix(setup): manage template agents after install by @amit-shafnir in #3365
  • fix(setup): allow choosing a different Slack workspace by @Koshkoshinsk in #3383
  • fix(permissions): disclose shared agent-group scope on approval cards by @Koshkoshinsk in #3386
  • fix(setup): drop stale Slack experimental/public-URL copy, modal-agnostic app-creation walkthrough by @Koshkoshinsk in #3389
  • feat(setup): finish Slack app installs the workspace must approve by @gavrielc in #3399
  • setup: the managed Slack experience becomes the default by @gavrielc in #3404
  • feat: add /migrate-slack-agents upgrade path for classic Slack installs by @Koshkoshinsk in #3391
  • fix(permissions): assert the scope warning via its constant, not a copy of it by @gavrielc in #3407
  • docs+setup: announce one-click Slack agents by @gavrielc in #3421
  • feat(drivers): ratify the attach surface — a driver describes its exec argv by @gavrielc in #3429
  • fix: restore stable CI required check by @zvi-fried in #3430
  • [main] fix(providers): accept provider file events by @zvi-fried in #3402
  • [main] fix(matrix): use a refresh-safe ESM patch by @zvi-fried in #3403
  • [main] ci: test registry-backed skills by @zvi-fried in #3424
  • feat(setup): add Dial to the channel picker + wizard/skills (runChannelSkill model) by @OmriBenShoham in #3050
  • chore(container): bump claude-code to 2.1.238 and agent SDK to 0.3.238 by @gavrielc in #3439
  • fix(add-dial-number): use nc directives by @zvi-fried in #3433
  • feat(drivers): validate runtimeTier against driver isolation capabilities; select the tier from group config by @gavrielc in #3442
  • fix(upgrade-state): accept a version-matching marker when Git cannot identify the checkout by @gavrielc in #3444
  • build: drop better-sqlite3 from onlyBuiltDependencies — use its bundled prebuilds by @gavrielc in #3443
  • fix(setup): skip Slack auto-provisioning when a bot is already saved by @Koshkoshinsk in #3390
  • fix(telegram-setup): pairing card says 6 digits by @amit-shafnir in #3431
  • fix(chat-sdk): polling adapters do not open the webhook server by @amit-shafnir in #3434
  • feat(setup): carry the adapter instance through pairing, init-first-agent and the CLI welcome by @amit-shafnir in #3478
  • docs(add-telegram): add-another-bot path, instance-aware pairing and wiring by @amit-shafnir in #3479
  • feat(setup): the wizard offers "add another Telegram bot" when one is already configured by @amit-shafnir in #3480
  • chore(release): v2.3.0 by @gavrielc in #3495

Full Changelog: v2.2.0...v2.3.0

Don't miss a new nanoclaw release

NewReleases is sending notifications on new releases.