> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nanoclaw.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Releases

> NanoClaw release history, changelog, and version-by-version feature and fix notes.

<Update label="v2.1.54" description="2026-08-01" tags={["Breaking", "Feature", "Fix"]}>
  * **Breaking: iMessage unified — one `imessage` channel, local or hosted backends** — `/add-imessage` now installs a single channel with two pluggable backends: local (this Mac's `chat.db`) or hosted (a native Photon line via photon.codes, no Mac relay), chosen at install or via `IMESSAGE_BACKEND=local|hosted`. The legacy Chat-SDK remote mode (`IMESSAGE_SERVER_URL`/`IMESSAGE_API_KEY`) is removed (#3164)
  * **Breaking: agent memory is provider-agnostic** — every provider now shares one OKF-compatible `memory/` tree instead of provider-native memory stores, with persona moved to `instructions.prepend.md`; memory reloads automatically on startup, `/clear`, and compaction. Groups still on legacy memory need `/migrate-memory` before their next spawn (#3012)
  * **Hardened agent images are an opt-in setup path** — setup can fetch a digest-pinned, multi-architecture image built and patched by Echo instead of building locally, with architecture, lockfile-label, and provenance checks before it's retagged onto the same local name a build would use. Building locally stays fully supported and needs no account (#3150)
  * **Agent containers get more hardening by default** — every spawn now runs with `--cap-drop=ALL`, `no-new-privileges`, and Docker's `--init`; a new `CONTAINER_PIDS_LIMIT` (default 2048) backstops fork bombs (#2748)
  * **Per-agent-group timezone override** — `ncl groups config update --timezone <IANA>` overrides the install timezone for that group's scheduling, run-log stamps, and container `TZ`; passing `""` clears it back to the install default (#3125)
  * **New groups can inherit an instance-wide default provider** — `DEFAULT_AGENT_PROVIDER` sets the provider a freshly created agent group starts on; it's stamped once at creation, and a group's own `ncl groups config update --provider` still overrides it (#2906)
  * **Agent templates can seed scheduled tasks** — a template's `tasks/*.md` files define a cron schedule, an optional script gate, and a prompt; template-seeded tasks are created paused so you can review them before activating (#3022)
  * **MCP server approval cards show the full payload** — `add_mcp_server` cards now render every field being applied (name, command, args, env), not just name and command, so an approver can no longer authorize args or env they never saw; secret-shaped values are redacted with a fingerprint (#2998)
  * The Vercel CLI is no longer baked into every agent image — install it with `/add-vercel` when a group actually needs to deploy (#3159)
  * Duplicate replies after mid-turn context compaction fixed — the SDK's `compact_boundary` event no longer surfaces as a synthetic result the poll loop mistakes for unwrapped output (#3083)
  * Claude rate-limit telemetry only aborts a turn on an actual rejection — informational `rate_limit_event` updates no longer abort healthy turns, and a rejection is classified as transient rate-limit or billing exhaustion instead of always reading as quota (#3077)
  * Setup dispatches failure help to the picked provider — a failed step during a non-Claude install no longer pushes you to install and sign in to the Claude CLI just to see what went wrong; Claude remains a guarded fallback only when it's already installed and signed in (#3170)
  * Telegram deep links use `telegram.me` instead of `t.me` (#3043)
</Update>

<Update label="v2.1.53" description="2026-07-13" tags={["Feature", "Skill"]}>
  * **Setup wizard channel installs are SKILL.md-driven** — the bespoke per-channel setup modules (`setup/channels/<channel>.ts`) are deleted; `/setup` now drives the same `/add-<channel>` skills you run by hand, through a thin generic driver (render + ask + run, no phasing). The skills carry the whole flow in `nc:` directive fences: operator-facing prompts (`nc:operator`), command output captured into variables (`nc:run` capture), `when:` guards for either/or paths, precondition gates (`effect:check`), and a human barrier for manual UI steps. A lone `?` at any prompt hands off to Claude for help (#2958, #2972)
  * **Host-only mount verbs** — `ncl groups config add-mount` / `remove-mount` edit a group's additional mounts from the host socket; never runnable from inside a container. The gmail/gcal/rtk tool skills now use them instead of raw SQL (#3035)
  * Troubleshooting sections added to all 11 credentialed channel skills, and per-skill raw logs from every setup command (#2958)
</Update>

<Update label="v2.1.52" description="2026-07-13" tags={["Fix"]}>
  * Warn when a real directory entry blocks a shared skill symlink instead of silently skipping it (#3002)
</Update>

<Update label="v2.1.51" description="2026-07-13" tags={["Fix"]}>
  * Outbound messages whose channel adapter is missing route into the retry path instead of being dropped (#2996)
</Update>

<Update label="v2.1.50" description="2026-07-13" tags={["Fix"]}>
  * The agent runner logs when an errored batch is acked as completed, so silent failures leave a trace (#2966)
</Update>

<Update label="v2.1.49" description="2026-07-13" tags={["Feature"]}>
  * **One-door task delivery** — `send_message` is the only path out of a task session. A scheduled task's final text no longer implicitly routes anywhere; the agent explicitly sends what should reach a chat, and everything else stays in the task log (#2988)
</Update>

<Update label="v2.1.48" description="2026-07-13" tags={["Feature"]}>
  * Lean harness defaults for new agent groups — freshly created groups start with a smaller default toolset (#3031)
</Update>

<Update label="v2.1.47" description="2026-07-13" tags={["Fix"]}>
  * WhatsApp setup warns before configuring shared mode (the assistant on your own number), and the warning title renders cleanly (#3021)
</Update>

<Update label="v2.1.46" description="2026-07-10" tags={["Fix"]}>
  * Channel-defaults review fixes, and the WhatsApp service restarts after mode/name env writes so changes take effect (#3010)
</Update>

<Update label="v2.1.45" description="2026-07-10" tags={["Maintenance"]}>
  * **`slack-formatting` and `whatsapp-formatting` moved to the `channels` branch** — trunk `container/skills/` drops from 8 to 6 skills; installs that wire Slack or WhatsApp get the formatting skill through the channel install instead (#3009)
</Update>

<Update label="v2.1.44" description="2026-07-10" tags={["Fix"]}>
  * All timestamps stored as ISO and displayed in local time (#3003, #3006)
</Update>

<Update label="v2.1.43" description="2026-07-10" tags={["Fix"]}>
  * Task rows stamped with ISO timestamps (#3005)
</Update>

<Update label="v2.1.42" description="2026-07-10" tags={["Fix"]}>
  * `ncl wirings create` live-refreshes destinations, provisions companion rows (as does `ncl groups create`), and wraps INSERT + postCreate in one transaction (#2416)
</Update>

<Update label="v2.1.41" description="2026-07-09" tags={["Feature"]}>
  * **`ncl tasks` control plane** — scheduled tasks move from the agent's MCP tools to a full CLI resource: create, list, get, run, update, pause, resume, cancel, delete. Each task series runs in an isolated per-task session the host garbage-collects when the series is spent, with an optional pre-wake bash script gate. **Breaking:** the six scheduling MCP tools (`schedule_task` and friends) are no longer exposed to agents (#2981, #2978)
</Update>

<Update label="v2.1.40" description="2026-07-08" tags={["Feature"]}>
  * `ncl` CLI: verb-level args with per-verb deep help (`ncl <resource> help <verb>`), and a server-rendered human output format (#2980)
</Update>

<Update label="v2.1.39" description="2026-07-07" tags={["Fix"]}>
  * The agent runner matches `rate_limit_event` as a top-level SDK message type (#2965)
</Update>

<Update label="v2.1.38" description="2026-07-04" tags={["Fix"]}>
  * **Agent images build asynchronously** — `buildAgentGroupImage` swaps its blocking `execSync docker build` for an awaited promisified `exec`, so the single-threaded host stays responsive during the up-to-15-minute rebuild a package-install approval or `ncl groups restart --rebuild` can trigger. Timeout, buffered stdio, and non-zero-exit propagation are preserved (#2931)
</Update>

<Update label="v2.1.37" description="2026-07-04" tags={["Maintenance"]}>
  * Security docs rewritten to match the v2 perimeter — `docs/SECURITY.md` reworked, and the stale `docs/docker-sandboxes.md` and `docs/APPLE-CONTAINER-NETWORKING.md` removed (#2945)
  * Dead `data/env/env` secrets mirror removed from the setup and migrate paths — channel/setup scripts no longer write a second copy of credentials to disk (#2946)
  * Stale architecture, scheduling, provider-config, and overlay docs corrected (#2948)
</Update>

<Update label="v2.1.36" description="2026-07-04" tags={["Fix"]}>
  * **Mount allowlist honors the `readOnly` key** — the per-root `readOnly` flag (and the top-level `nonMainReadOnly` key) that `/manage-mounts` and setup actually write is now respected, so read-write grants are no longer silently forced read-only. The allowlist is also read and validated per call with an mtime-keyed cache instead of being parsed once for the whole process lifetime, so a parse error is no longer cached forever (#2943)
</Update>

<Update label="v2.1.35" description="2026-07-04" tags={["Fix"]}>
  * **Agent-to-agent reply stamping fixed** — the active batch's `in_reply_to` value lived in module-level state, but the nanoclaw MCP server runs as a separate subprocess from the poll loop, so the reply stamp was always read as `null` and a2a replies fell back to host peer-affinity routing. The stamp now publishes through `session_state` in `outbound.db` (both processes already open it), with an `updated_at` staleness guard so a stamp left by a killed container isn't reused (#2942)
  * Removed one-DB-era `@deprecated` shims and dead exports left over from the two-database session split (#2940)
</Update>

<Update label="v2.1.34" description="2026-07-04" tags={["Fix"]}>
  * Re-provision a missing session folder on resolve so the documented session-reset flow works instead of erroring on the recreated session (#2937)
</Update>

<Update label="v2.1.33" description="2026-07-04" tags={["Maintenance"]}>
  * Dead `ncl` CLI protocol vocabulary cleaned out of the command registry and framing (#2936)
  * Removed dead v1 config knobs and a broken pnpm auth script (#2935)
</Update>

<Update label="v2.1.32" description="2026-07-04" tags={["Fix"]}>
  * **Security-perimeter env vars are reachable under the packaged service** — egress lockdown and the per-container CPU/memory caps were read from `process.env` only, but the shipped launchd/systemd service sets just `PATH`+`HOME` and never loads `.env` into `process.env`, so these knobs couldn't be turned on the supported way. They now route through the same `readEnvFile` path as the other config keys, keeping `process.env` precedence so dev-mode/nohup installs are unaffected (#2934)
</Update>

<Update label="v2.1.31" description="2026-07-04" tags={["Feature", "Skill"]}>
  * **Colored approval buttons** — approval cards render Approve/Reject as styled buttons (Slack `primary`/`danger`) across the OneCLI, primitive, channel-approval, and sender-approval flows (#2933)
  * **`/add-clidash` skill** — a zero-dependency, read-only web dashboard that derives its tabs and tables at runtime from any CLI emitting JSON, pre-wired for `ncl` (agent groups, sessions, channels, users, roles) with message-activity charts, a log tail, and a read-only file viewer (#2795)
</Update>

<Update label="v2.1.30" description="2026-07-04" tags={["Fix"]}>
  * `ncl` positional-ID resolution fixed for generated (dashed) identifiers — the longest-registered-prefix lookup no longer mis-splits a dashed ID into command + args (#2932)
</Update>

<Update label="v2.1.29" description="2026-07-04" tags={["Fix"]}>
  * Command-gate hardening — `/start` is back in the host `FILTERED` set (a Telegram fix silently undone when host gating landed) so it's dropped instead of reaching the agent as a normal message, and the inline admin check now calls `hasAdminPrivilege` instead of a `hasTable('user_roles')` guard that only ever masked a missing check (fail-open removed) (#2930)
</Update>

<Update label="v2.1.28" description="2026-07-04" tags={["Feature"]}>
  * **OneCLI approval cards show what the agent is doing** — when the hosted OneCLI gateway sends a structured `summary` on an approval request, the card renders `Action:` plus labeled fields (e.g. the To / Subject / Body of an email send) instead of the raw `METHOD host/path` + body-preview HTTP trace. Rendering is defensive — values are coerced and length-capped, with a running budget that keeps the card under Slack's section-block limit and reports any omitted fields; without a summary the old body-preview fallback remains (#2929)
</Update>

<Update label="v2.1.27" description="2026-07-04" tags={["Maintenance"]}>
  * Removed the dead `/workspace/global` container mount and untracked leftover v1 group seed files (`groups/global`, `groups/main` CLAUDE.md) (#2928)
</Update>

<Update label="v2.1.26" description="2026-07-04" tags={["Maintenance"]}>
  * Unregistered the mock agent provider from the production container barrel so it can't be selected at runtime (#2927)
</Update>

<Update label="v2.1.25" description="2026-07-04" tags={["Security"]}>
  * **Approved CLI commands no longer run with escalated host privilege** — a `ncl` command held for approval was re-dispatched as `{ caller: 'host' }` when it executed, so an approved group-scoped command ran with unrestricted host scope. The approval now records the original caller context and replays the command under it, so it executes with exactly the requesting agent's scope (#2611)
</Update>

<Update label="v2.1.24" description="2026-07-02" tags={["Feature"]}>
  * **Agent templates** — folder-only templates under `templates/` (`context/instructions.md` plus optional context extras, `.mcp.json`, and a `skills/` overlay) stamp a new group with `ncl groups create --template <name>`: the provider-neutral instructions are inlined at the top of `CLAUDE.md`/`AGENTS.md` every spawn, context extras are copied preserving their layout, MCP servers are written to container config, and the per-group skills overlay is installed. See [`docs/templates.md`](https://github.com/nanocoai/nanoclaw/blob/main/docs/templates.md) (#2890)
  * Guided setup now offers Slack **Socket Mode** as a first-class option in the Slack setup flow (#2885)
</Update>

<Update label="v2.1.23" description="2026-06-30" tags={["Fix"]}>
  * Container tooling bumps: `@anthropic-ai/claude-code` 2.1.170 → 2.1.197 (via the `cli-tools.json` manifest), Claude agent SDK `^0.3.170` → `^0.3.197`, Anthropic SDK `^0.100.0` → `^0.108.0`
</Update>

<Update label="v2.1.22" description="2026-06-30" tags={["Fix"]}>
  * **Inbox symlink containment** — channel-inbound attachments and agent-to-agent forwarded files are written into a session's `inbox/` through a shared host-side guard (`src/inbox-safety.ts`): a symlinked inbox root or per-message directory is rejected, final paths are containment-checked against the session folder, and writes use exclusive-create flags so a pre-placed symlinked file can't be followed (security, #2828)
  * `ncl messaging-groups create` gained an `instance` column for running multiple adapters of one channel type; when `--instance` is omitted it defaults to the `channel_type` value
</Update>

<Update label="v2.1.21" description="2026-06-25" tags={["Feature"]}>
  * **Reject with reason** — declining a self-mod or agent-to-agent approval can now relay a one-line note back to the requesting agent (`Your <action> request was rejected by admin: "<reason>"`). A plain Reject is unchanged; an unanswered reason prompt finalizes as a plain reject after \~5 minutes
  * **`/learn` skill** — distill or refine a reusable skill from a directory, a URL, pasted notes, or the work just done, authored to the project's skill guidelines
  * Clearer agent-to-agent gate approval prompt
</Update>

<Update label="v2.1.20" description="2026-06-25" tags={["Breaking"]}>
  * **\[BREAKING] Chat SDK pinned to `4.29.0`** (was `^4.24.0`) — `chat` and the `@chat-adapter/*` channel adapters are version-locked, so a mismatched pair fails to typecheck. Core installs with no channel (only `cli`) are unaffected. **Migration:** re-run each installed channel's `/add-<channel>` skill to pull the matching `4.29.0` adapter
  * **Per-container resource caps** — `CONTAINER_CPU_LIMIT` and `CONTAINER_MEMORY_LIMIT` pass through to `docker run` as `--cpus` / `--memory`. Both empty by default (unbounded, byte-identical spawn args to before); `--memory` is a hard cap on a swapless host
  * `/update-skills` now rebuilds the agent image when a re-applied skill changed files under `container/`
  * Fixes: reap dead peer service registrations whose binary is gone; allow an env-selected agent provider in setup
</Update>

<Update label="v2.1.19" description="2026-06-18" tags={["Feature"]}>
  * **Per-message approval policies on agent-to-agent connections** — an operator can gate one agent→agent edge so every message waits for human approval, without un-wiring it: `ncl policies set --from <id> --to <id> --approver <user-id>`. Directed and per-pair; operator-only. Backed by the new `agent_message_policies` table (migration 017)
  * **Named approver** — a policy pins a single required approver; only that user (or an owner) can clear a held message, recorded as `approver_user_id` on `pending_approvals` (migration 018)
  * `.claude` is now mirrored into `.agents` via symlinks
</Update>

<Update label="v2.1.18" description="2026-06-18" tags={["Fix"]}>
  * Setup parses the Claude OAuth token correctly from a wrapped PTY capture
</Update>

<Update label="v2.1.17" description="2026-06-16" tags={["Feature"]}>
  * **Codex CLI installs via the `container/cli-tools.json` manifest** instead of a hard-coded Dockerfile layer
  * **`/update-nanoclaw` upgrades the OneCLI gateway when its pinned version moves** (`versions.json`), walking you through [`docs/onecli-upgrades.md`](https://github.com/nanocoai/nanoclaw/blob/main/docs/onecli-upgrades.md) before the restart
  * Budget/billing-exhausted LLM turns (e.g. an Anthropic `403 billing_error`) now reach the user instead of being silently dropped and retried
</Update>

<Update label="v2.1.16" description="2026-06-14" tags={["Feature"]}>
  * **Operator-driven provider selection in setup** — the installer can select, install, and authenticate a non-default agent provider, then set it on the first agent before its first spawn. A provider registry feeds the picker and a vault-only auth walkthrough; default (Claude) installs are unaffected
  * **Per-group provider choice** — the provider is a per-group database property, not an install-wide default: `ncl groups config update --id <group-id> --provider <name>` then restart. Group creation stays provider-agnostic
  * **Memory migrates via `/migrate-memory`, never at runtime** — each provider keeps its own store, so a fresh group on a different provider never inherits stale `CLAUDE.*` files
  * Container boot failures now log the last stderr lines at `warn` on a non-zero exit instead of looping silently
</Update>

<Update label="v2.1.15" description="2026-06-14" tags={["Feature"]}>
  * Container global CLIs (`@anthropic-ai/claude-code`, `agent-browser`, `vercel`) are now data-driven from `container/cli-tools.json`, each pinned to an exact version — a skill adds a CLI by appending to the manifest instead of editing the Dockerfile
</Update>

<Update label="v2.1.14" description="2026-06-13" tags={["Breaking"]}>
  * **\[BREAKING]** `@onecli-sh/sdk` 0.5.0 → 2.2.1 — now requires a OneCLI gateway with the `/v1` API; gateways that predate it answer `404` to every vault call. Sanctioned component versions are pinned in `versions.json` and the `onecli` setup step enforces them. Migration: [`docs/onecli-upgrades.md`](https://github.com/nanocoai/nanoclaw/blob/main/docs/onecli-upgrades.md)
  * Slash commands now interrupt an in-flight turn instead of waiting it out
  * New `onExchangeComplete` provider hook — providers whose harness keeps no on-disk transcript can archive each exchange themselves
</Update>

<Update label="v2.1.13" description="2026-06-13" tags={["Feature"]}>
  * Agent-surfaces capability seam (`providesAgentSurfaces`) — a provider can declare it owns the composed project doc, skill links, and state dir, and the host skips its default surfaces
</Update>

<Update label="v2.1.12" description="2026-06-13" tags={["Feature"]}>
  * Opt-in persistent memory scaffold (`usesMemoryScaffold`) — providers without native memory get an idempotent `memory/` tree in the agent's host-backed workspace at boot
</Update>

<Update label="v2.1.11" description="2026-06-11" tags={["Feature"]}>
  * Webhook raw-route registry — modules register non–Chat SDK webhooks (GitHub, payment providers, health checks) with `registerWebhookHandler()` on the shared server instead of opening a second port
</Update>

<Update label="v2.1.10" description="2026-06-11" tags={["Fix"]}>
  * Open `outbound.db` read-write in `writeOutboundDirect` so direct outbound writes aren't blocked
</Update>

<Update label="v2.1.9" description="2026-06-11" tags={["Feature"]}>
  * Approval-resolved callback registry — modules can observe when an approval is resolved (e.g. to clear an "awaiting approval" indicator)
</Update>

<Update label="v2.1.8" description="2026-06-11" tags={["Fix"]}>
  * Grace period for freshly-woken containers with stale processing claims — skips SLA enforcement on the tick that wakes a container, preventing a spawn-kill loop
</Update>

<Update label="v2.1.7" description="2026-06-11" tags={["Fix"]}>
  * Record the acting user on resolved approval cards
</Update>

<Update label="v2.1.6" description="2026-06-11" tags={["Fix"]}>
  * Add a read side (`getDeliveryAction`) to the delivery action registry so module registrations can be behavior-tested
</Update>

<Update label="v2.1.5" description="2026-06-11" tags={["Feature"]}>
  * **Multi-instance adapters** — run several adapters of one platform at once (e.g. three Slack apps in one workspace). A new `messaging_groups.instance` dimension (migration 016) keys the adapter registry, per-instance Chat SDK state namespaces and webhook routes, and threads the instance through the router, delivery, and typing indicators. Single-instance installs are unchanged (instance defaults to the channel type)
  * **Interactive uninstaller** — `bash nanoclaw.sh --uninstall` removes one NanoClaw copy (service, containers, data, OneCLI agents) with a scan → confirm → execute flow, `--dry-run` and `--yes` flags, and per-checkout install-slug scoping. See [Uninstall NanoClaw](/operate/uninstall)
</Update>

<Update label="v2.1.1 – v2.1.4" description="2026-06-09" tags={["Feature"]}>
  * **Egress lockdown (opt-in)** — an agent group's outbound network is forced through the OneCLI gateway, so a compromised agent can't reach arbitrary hosts (v2.1.1). See [Hardening](/operate/hardening#lock-down-network-egress)
  * v2.1.2–v2.1.4 were rapid patch follow-ups with no user-facing changes
</Update>

<Update label="v2.1.0" description="2026-06-07" tags={["Breaking"]}>
  * **\[BREAKING] Startup now requires an upgrade marker.** The host refuses to boot unless `data/upgrade-state.json` records that the install reached its version through a sanctioned path (`/setup`, `/update-nanoclaw`, `/migrate-nanoclaw`). Stamp it with `pnpm exec tsx scripts/upgrade-state.ts set` — the same command clears a tripped marker. See [Upgrading](/operate/upgrading)
  * Skills retrofit — channel, provider, and tool skills made v2-conformant (minimal integration surface, a test per integration point); four skills broken on v2 were dropped
</Update>

<Update label="v2.0.65 – v2.0.76" description="2026-06-05" tags={["Feature"]}>
  * **`/upload-trace`** — upload a session trace to Hugging Face for sharing or debugging
  * Session-transcript rotation before resume — oversized or aged transcripts are rotated so a cold resume can't wedge the container
  * **`/add-rtk`** token-efficient CLI-proxy skill, and a `whatsapp-formatting` container skill
  * Fixes: signal-cli 0.13+ `listAccounts`, the Photon remote-iMessage URL, channel-approval target scoping, and per-group `CLAUDE.local.md` loading
</Update>

<Update label="v2.0.64" description="2026-05-18" tags={["Fix"]}>
  * `ncl destinations add`/`remove` through the approval flow now reach the receiver immediately — an approved destination no longer fails `send_message` with `unknown destination` until the next container restart
</Update>

<Update label="v2.0.55 – v2.0.63" description="2026-05-15" tags={["Breaking"]}>
  Rollup release covering v2.0.55–v2.0.63; per-bump GitHub Releases begin here.

  * **\[BREAKING] Service names are now per-install** — the launchd label and systemd unit are slugged to your project root (`com.nanoclaw.<sha1(projectRoot)[:8]>`, `nanoclaw-<slug>.service`). The old `com.nanoclaw` / `nanoclaw.service` names no longer match; find yours with `source setup/lib/install-slug.sh && launchd_label` (macOS) or `systemd_unit` (Linux)
  * Stronger `<message>`-wrapping enforcement; MCP servers added via `add_mcp_server` inherit OneCLI gateway routing; CLI-scope hardening (`scopeField` fails closed, `sessions get` guarded against cross-group access); `/add-gmail-tool` and `/add-gcal-tool` aligned with the v2 container-config model; `qwibitai/nanoclaw` → `nanocoai/nanoclaw` swept across code and docs
</Update>

<Update label="v2.0.54" description="2026-05-10" tags={["Feature"]}>
  * **Per-group model and effort overrides** — `ncl groups config update --model <model> --effort <level>`, falling back to the host-configured model when unset
  * Container `claude-code` bumped to 2.1.128
</Update>

<Update label="v2.0.48 – v2.0.53" description="2026-05-09" tags={["Feature"]}>
  * **Container config moved to the database** — per-group runtime config (provider, model, packages, MCP servers, mounts, skills) lives in the `container_configs` table instead of `groups/<folder>/container.json`; filesystem configs are backfilled on startup
  * **`ncl groups restart`** with `--rebuild` / `--message` — config edits no longer auto-kill containers; on-wake messages are picked up only by a fresh container's first poll
  * **Per-group `cli_scope`** (`disabled` / `group` / `global`, default `group`) — controls what the agent can reach via `ncl` from inside its container, with cross-group result filtering
</Update>

<Update label="v2.0.45 – v2.0.47" description="2026-05-08" tags={["Feature"]}>
  * **The `ncl` admin CLI** — query and modify the central DB (agent groups, messaging groups, wirings, users, roles, members, destinations, sessions, approvals, dropped messages). Host transport over a Unix socket; container-side writes go through the approval flow
  * **v1 → v2 migration** — `bash migrate-v2.sh` finds your v1 install, merges `.env`, seeds the v2 DB, copies group folders (`CLAUDE.md` → `CLAUDE.local.md`) and session data, ports tasks and channels, then hands off to `/migrate-from-v1`. See [Migrate from v1](/migrate-from-v1)
</Update>

<Update label="v2.0.1 – v2.0.44" description="2026-05-07" tags={["Maintenance"]}>
  * Post-rewrite stabilization — roughly 44 rapid patch releases over two weeks, before the per-release changelog discipline began at v2.0.63. Not individually documented upstream; see the [GitHub releases](https://github.com/nanocoai/nanoclaw/releases) for raw notes
</Update>

<Update label="v2.0.0" description="2026-04-22" tags={["Breaking"]}>
  * Ground-up architectural rewrite with new entity model (users, roles, messaging groups, agent groups, wirings)
  * Two-database session model — `inbound.db` (host writes) and `outbound.db` (container writes) eliminate cross-mount SQLite contention
  * Agent-runner moved from Node.js to Bun — runs TypeScript directly without compilation
  * Shared-source agent-runner — `/app/src` is a read-only bind mount, source changes never require image rebuild
  * `tini` as PID 1 for proper signal forwarding
  * Three-level channel isolation model with `unknown_sender_policy` (strict, request\_approval, public)
  * Per-wiring engage modes: `pattern`, `mention`, `mention-sticky`
  * Sender scope enforcement per wiring (`all` or `known`)
  * Channel and sender approval flows with interactive cards
  * Tasks stored as `messages_in` rows with cron-based recurrence and series tracking
  * Delivery system with two-poll architecture (active 1s, sweep 60s)
  * Module system for permissions, scheduling, agent-to-agent, approvals, and self-modification
  * OneCLI Agent Vault is the sole credential path
  * Channels moved to separate branches (trunk ships no adapters)
  * Per-agent-group custom Docker images with additional packages
</Update>

<Update label="v1.2.53" description="2026-04-15" tags={["Maintenance"]}>
  * Updated token count to 43.8k tokens (22% of context window)
  * Added `.claude/settings.json` with default SDK configuration
  * Added `ONECLI_API_KEY` configuration option for OneCLI gateway authentication
</Update>

<Update label="v1.2.52" description="2026-04-05" tags={["Fix"]}>
  * Fixed Gmail OneCLI credential mode detection — properly detects when running under OneCLI Agent Vault
  * Reduced setup friction and improved diagnostics output
  * Added `.npmrc` with 7-day minimum release age for dependency safety
</Update>

<Update label="v1.2.51" description="2026-04-05" tags={["Fix"]}>
  * Fixed writable global memory mount for main agent — corrected the path in container `CLAUDE.md`
  * Fixed three issues in the Karpathy wiki skill
  * Updated `init-onecli` skill to use `ONECLI_URL` variable
</Update>

<Update label="v1.2.50" description="2026-04-05" tags={["Feature", "Skill"]}>
  * Lowered auto-compact threshold to 165k tokens for better context fidelity
  * Added `/add-karpathy-llm-wiki` skill — persistent wiki knowledge base per group, based on Karpathy's LLM Wiki pattern
  * Added `/migrate-nanoclaw` skill — intent-based upgrade that extracts customizations into a migration guide and reapplies them on a clean upstream base
  * Added `/migrate-from-openclaw` skill — guided migration from OpenClaw installations
  * NanoClaw now suggests `/migrate-nanoclaw` when the user's fork is far behind upstream
</Update>

<Update label="v1.2.49" description="2026-04-04" tags={["Feature"]}>
  * Added automatic session artifact pruning on startup and daily — cleans up stale session JSONLs (7 days), debug logs (3 days), todo files (3 days), and telemetry (7 days) while preserving active sessions
</Update>

<Update label="v1.2.48" description="2026-04-04" tags={["Feature"]}>
  * Upgraded agent SDK to 0.2.92 with auto-compact at 165k tokens
</Update>

<Update label="v1.2.47" description="2026-04-03" tags={["Feature"]}>
  * Main agent now has direct read-write access to the SQLite database — `store/` is mounted separately at `/workspace/project/store` so the main group can query and write data directly
  * Added `requiresTrigger` parameter to the `register_group` MCP tool (defaults to `false`) — controls whether messages must start with the trigger word for the group to respond
</Update>

<Update label="v1.2.46" description="2026-04-03" tags={["Feature", "Channel"]}>
  * Added reply/quoted message context support — channels can now pass `reply_to_message_id`, `reply_to_message_content`, and `reply_to_sender_name` fields with messages
  * Reply context is rendered as `<quoted_message>` XML in agent prompts, giving agents full awareness of which message a user is responding to
  * Database migration adds reply context columns to the messages table (nullable for backward compatibility)
</Update>

<Update label="v1.2.45" description="2026-04-02" tags={["Skill", "Maintenance"]}>
  * Added `/add-macos-statusbar` utility skill — macOS menu bar status indicator with start/stop/restart controls
  * Added Telegram channel contributors (contributed by @cschmidt, @leonalfredbot-ship-it, @moktamd, @gurixs-carson)
</Update>

<Update label="v1.2.43" description="2026-03-29" tags={["Fix"]}>
  * Auto-recover from stale Claude Code session IDs instead of retrying infinitely — detects missing session transcripts and clears the broken session for a fresh retry
  * Removed built-in Ollama MCP server from core — Ollama integration is now exclusively available via the `/add-ollama-tool` skill
  * Fixed npm audit dependency errors
</Update>

<Update label="v1.2.42" description="2026-03-28" tags={["Feature"]}>
  * Setup skill now routes credential system by container runtime: Docker uses OneCLI Agent Vault, Apple Container uses native credential proxy
  * Marked Apple Container as experimental
</Update>

<Update label="v1.2.41" description="2026-03-28" tags={["Fix", "Maintenance"]}>
  * Migrated `x-integration` host.ts from pino to built-in logger (follow-up to v1.2.36 cleanup)
  * Fixed `stopContainer()` test compatibility — mocked container-runtime so tests don't require Docker
  * Cleared stale Telegram token from `.env.example`
</Update>

<Update label="v1.2.40" description="2026-03-27" tags={["Fix"]}>
  * Fixed message history overflow: when `lastAgentTimestamp` was missing, all 200 messages were sent to the agent instead of respecting `MAX_MESSAGES_PER_PROMPT` (default 10). Added cursor recovery from last bot reply.
</Update>

<Update label="v1.2.39" description="2026-03-27" tags={["Fix", "Security"]}>
  * Security fixes: command injection prevention in `stopContainer` (name validation), mount path colon rejection, allowlist caching fix (contributed by @foxsky)
</Update>

<Update label="v1.2.38" description="2026-03-27" tags={["Fix"]}>
  * Fixed `isMain` flag preservation on `register_group` IPC updates — prevents accidental privilege stripping (contributed by @snw35)
</Update>

<Update label="v1.2.37" description="2026-03-27" tags={["Fix"]}>
  * Fixed `.env` parser crash on single-character values (contributed by @foxsky)
</Update>

<Update label="v1.2.36" description="2026-03-27" tags={["Maintenance", "Fix", "Breaking"]}>
  * **\[BREAKING]** Replaced `pino` logger with built-in logger module — removes 2 runtime dependencies. WhatsApp users must re-merge the WhatsApp fork to pick up the Baileys logger compatibility fix: `git fetch whatsapp main && git merge whatsapp/main`. If the `whatsapp` remote is not configured: `git remote add whatsapp https://github.com/nanocoai/nanoclaw-whatsapp.git`
  * Removed `yaml` and `zod` dependencies — core runtime now uses only 3 packages
  * Updated Ollama skill with admin model management tools
  * Channel-formatting text-style fixes for WhatsApp and Telegram (contributed by @kenbolton)
</Update>

<Update label="v1.2.35" description="2026-03-26" tags={["Breaking"]}>
  * **\[BREAKING]** OneCLI Agent Vault replaces the built-in credential proxy. Check your runtime: `grep CONTAINER_RUNTIME_BIN src/container-runtime.ts` — if it shows `'container'` you are on Apple Container, if `'docker'` you are on Docker. **Docker users**: run `/init-onecli` to install OneCLI and migrate `.env` credentials to the vault. **Apple Container users**: re-merge the skill branch (`git fetch upstream skill/apple-container && git merge upstream/skill/apple-container`) then run `/convert-to-apple-container` — do NOT run `/init-onecli` (it requires Docker). The legacy credential proxy is available as an opt-in skill via `/use-native-credential-proxy`.
  * Channel tokens (Telegram, Slack, Discord) remain in `.env` — only container-facing credentials (Anthropic, OpenAI, etc.) are migrated to the vault.
</Update>

<Update label="v1.2.34" description="2026-03-25" tags={["Fix", "Skill", "Channel"]}>
  * Added `/add-emacs` channel skill (contributed by @kenbolton)
  * Fixed mount-allowlist preservation — `/setup` no longer overwrites existing `mount-allowlist.json` (contributed by @akasha-scheuermann)
  * Fixed Telegram migration backfill to default chats as direct messages instead of groups (contributed by @RichardCao)
  * Fixed CI workflows to skip `bump-version` and `update-tokens` on forks (contributed by @shawnyeager)
</Update>

<Update label="v1.2.33" description="2026-03-25" tags={["Fix"]}>
  * Fixed container mounts to include group folder and sessions directory (contributed by @kenbolton)
</Update>

<Update label="v1.2.32" description="2026-03-25" tags={["Feature", "Skill", "Fix"]}>
  * Added `/channel-formatting` skill — channel-aware text formatting for WhatsApp, Telegram, Slack, and Signal
  * Fixed per-group trigger pattern matching — each group can now define its own trigger word (contributed by @mrbob-git)
  * Fixed `loginctl enable-linger` so systemd user service survives SSH logout (contributed by @IYENTeam)
  * Clarified WhatsApp phone number prompt to prevent auth failures (contributed by @ingyukoh)
  * Added Telegram forum topics contributor (contributed by @flobo3)
</Update>

<Update label="v1.2.31" description="2026-03-25" tags={["Fix"]}>
  * Fixed `isMain`-based CLAUDE.md template selection during runtime group registration
</Update>

<Update label="v1.2.30" description="2026-03-25" tags={["Fix"]}>
  * Fixed CLAUDE.md template copy when registering groups via IPC (contributed by @ingyukoh)
  * Fixed diagnostics to use explicit Read tool directive for pickup instructions (contributed by @Koshkoshinsk)
</Update>

<Update label="v1.2.29" description="2026-03-25" tags={["Feature"]}>
  * Added task scripts — scheduled tasks can now run a pre-execution bash script that conditionally wakes the agent via `wakeAgent` JSON contract (contributed by @gabi-simons)
</Update>

<Update label="v1.2.28" description="2026-03-25" tags={["Fix"]}>
  * Fixed agent-runner source cache to refresh based on file modification time instead of copying once at startup
</Update>

<Update label="v1.2.27" description="2026-03-25" tags={["Maintenance"]}>
  * Removed accidentally merged Telegram channel code from main
  * Removed Grammy dependency and pinned `better-sqlite3@11.10.0` and `cron-parser@5.5.0`
  * Removed auto-sync GitHub Actions
</Update>

<Update label="v1.2.26" description="2026-03-25" tags={["Fix"]}>
  * Enabled `loginctl linger` during setup so systemd user service survives SSH logout
  * Clarified WhatsApp phone number prompt format (digits only, no `+` prefix)
  * Added CLAUDE.md template copy during IPC group registration
</Update>

<Update label="v1.2.25" description="2026-03-24" tags={["Fix"]}>
  * Fixed timezone validation to prevent crash on POSIX-style TZ values — now validates IANA identifiers and falls back to UTC
  * Expanded fork sync auto-resolve patterns and added missing forks to dispatch list
</Update>

<Update label="v1.2.24" description="2026-03-24" tags={["Fix"]}>
  * Fixed diagnostics prompt not being shown to user (contributed by @Koshkoshinsk)
  * Added auto-resolve for `package-lock.json`, badge, and version conflicts during fork sync
</Update>

<Update label="v1.2.23" description="2026-03-24" tags={["Maintenance", "Skill"]}>
  * Added `/use-native-credential-proxy` skill — opt-in restoration of the built-in `.env`-based credential proxy for users who prefer it over OneCLI
  * Removed dead `src/credential-proxy.ts` code (unused since v1.2.22)
  * Updated token count to 39.8k tokens (20% of context window)
  * Upgraded Zod dependency from v3 to v4 (`^4.3.6`)
</Update>

<Update label="v1.2.22" description="2026-03-24" tags={["Maintenance"]}>
  * Replaced credential proxy with OneCLI Agent Vault for container credential injection
  * Updated token count to 40.7k tokens (20% of context window)
</Update>

<Update label="v1.2.21" description="2026-03-22" tags={["Feature"]}>
  * Added opt-in diagnostics via PostHog — collects anonymous system info (OS, architecture, version, selected channels) during `/setup` and `/update-nanoclaw` with explicit user consent
  * Three-option prompt: **Yes** (send once), **No** (skip), **Never ask again** (permanently opt out)
  * No runtime telemetry — diagnostics run only in skill workflows, not in the application itself
</Update>

<Update label="v1.2.20" description="2026-03-21" tags={["Maintenance"]}>
  * Added ESLint configuration with error-handling rules across the codebase
</Update>

<Update label="v1.2.19" description="2026-03-19" tags={["Fix"]}>
  * Reduced `docker stop` timeout for faster container restarts (`-t 1` flag — containers are stateless)
</Update>

<Update label="v1.2.18" description="2026-03-19" tags={["Security", "Channel"]}>
  ## Security

  * User prompt content is no longer logged on container errors — only input metadata (prompt length, session ID)

  ## Channel

  * Added Japanese README translation
</Update>

<Update label="v1.2.17" description="2026-03-18" tags={["Feature"]}>
  * Added read-only `/capabilities` and `/status` container-agent skills
</Update>

<Update label="v1.2.16" description="2026-03-18" tags={["Fix"]}>
  * Tasks snapshot now refreshes immediately after IPC task mutations (contributed by @mbravorus)
</Update>

<Update label="v1.2.15" description="2026-03-16" tags={["Fix"]}>
  * Fixed remote-control prompt auto-accept to prevent immediate exit
  * Added `KillMode=process` so remote-control survives service restarts (contributed by @gabi-simons)
</Update>

<Update label="v1.2.14" description="2026-03-14" tags={["Feature"]}>
  * Added `/remote-control` command for host-level Claude Code access from within containers
</Update>

<Update label="v1.2.13" description="2026-03-14" tags={["Feature", "Breaking"]}>
  Major architecture change: skills are now git branches, channels are separate fork repos.

  ## Features

  * Skills live as `skill/*` git branches merged via `git merge` — no more marketplace or plugin system
  * Added Docker Sandboxes announcement and manual setup guide
  * Added `nanoclaw-docker-sandboxes` to fork dispatch list

  ## Breaking

  * Skills are no longer installed via marketplace or plugin commands — use `git merge` workflow

  ## Fixes

  * Fixed setup registration to use `initDatabase`/`setRegisteredGroup` with correct CLI commands
  * Auto-resolve `package-lock` conflicts when merging forks
  * Bumped `claude-agent-sdk` to ^0.2.76
</Update>

<Update label="v1.2.12" description="2026-03-08" tags={["Feature", "Security"]}>
  ## Features

  * Added `/compact` skill for manual context compaction

  ## Security

  * Enhanced container environment isolation via credential proxy — API keys injected at runtime via local proxy instead of environment variables
</Update>

<Update label="v1.2.11" description="2026-03-08" tags={["Feature", "Channel", "Fix"]}>
  ## Features

  * **PDF reader skill**: Read and analyze PDF attachments
  * **Image vision skill**: Image analysis for WhatsApp
  * **WhatsApp reactions skill**: Emoji reactions and status tracker

  ## Fixes

  * Fixed task container to close promptly when agent uses IPC-only messaging
  * Fixed WhatsApp pairing code written to file for immediate access
  * Fixed WhatsApp DM-with-bot registration to use sender's JID
</Update>

<Update label="v1.2.10" description="2026-03-06" tags={["Fix", "Performance"]}>
  * Added `LIMIT` to unbounded message history queries for better performance
</Update>

<Update label="v1.2.9" description="2026-03-06" tags={["Feature", "Fix"]}>
  ## Features

  * Agent prompts now include timezone context for accurate time references

  ## Fixes

  * Fixed voice-transcription skill dropping WhatsApp `registerChannel` call
</Update>

<Update label="v1.2.8" description="2026-03-06" tags={["Fix"]}>
  * Fixed misleading `send_message` tool description for scheduled tasks
</Update>

<Update label="v1.2.7" description="2026-03-06" tags={["Feature"]}>
  * Added `/add-ollama` skill for local model inference
  * Added `update_task` tool and return task ID from `schedule_task`
</Update>

<Update label="v1.2.6" description="2026-03-04" tags={["Fix"]}>
  * Updated `claude-agent-sdk` to 0.2.68
</Update>

<Update label="v1.2.5" description="2026-03-04" tags={["Fix"]}>
  * CI formatting fix
</Update>

<Update label="v1.2.4" description="2026-03-04" tags={["Fix"]}>
  * Fixed `_chatJid` rename to `chatJid` in `onMessage` callback
</Update>

<Update label="v1.2.3" description="2026-03-04" tags={["Feature", "Security"]}>
  * Added sender allowlist for per-chat access control to restrict who can interact with the agent
</Update>

<Update label="v1.2.2" description="2026-03-04" tags={["Feature", "Fix"]}>
  ## Features

  * Added `/use-local-whisper` skill for local voice transcription
  * Atomic task claims prevent scheduled tasks from executing twice

  ## Fixes

  * Fixed WhatsApp `messages.upsert` error handling
</Update>

<Update label="v1.2.1" description="2026-03-02" tags={["Fix"]}>
  * Version bump (no functional changes)
</Update>

<Update label="v1.2.0" description="2026-03-02" tags={["Feature", "Breaking", "Channel"]}>
  Major release introducing multi-channel architecture. WhatsApp is no longer hardcoded — all channels self-register via a channel registry.

  ## Features

  * **Channel registry**: Channels self-register at module load time via `registerChannel()` factory pattern
  * **`isMain` flag**: Explicit boolean replaces folder-name-based main group detection
  * **Channel-prefixed group folders**: Groups use `whatsapp_main`, `telegram_family-chat` convention to prevent cross-channel collisions
  * Unconfigured channels now emit WARN logs naming the exact missing variable

  ## Breaking

  * **WhatsApp moved to skill**: No longer part of core — apply with `/add-whatsapp`
  * **`ENABLED_CHANNELS` removed**: Orchestrator uses `getRegisteredChannelNames()`; channels detected by credential presence
  * **All channel skills simplified**: No more `*_ONLY` flags — all use self-registration pattern

  ## Fixes

  * Prevent scheduled tasks from executing twice when container runtime exceeds poll interval

  ## Migration

  Existing WhatsApp users: run `/add-whatsapp` in Claude Code CLI after updating.
</Update>

<Update label="v1.1.6" description="2026-03-01" tags={["Fix"]}>
  * Added CJK font support (`fonts-noto-cjk`) for Chromium screenshots (contributed by @neocode24)
</Update>

<Update label="v1.1.5" description="2026-03-01" tags={["Fix"]}>
  * Fixed wrapped WhatsApp message normalization before reading content
</Update>

<Update label="v1.1.4" description="2026-03-01" tags={["Feature"]}>
  * Added third-party model support — use models beyond Claude
  * Added `/update-nanoclaw` skill for syncing customized installs with upstream (replaces old `/update`)
  * Added Husky and `format:fix` script for consistent formatting
</Update>

<Update label="v1.1.3" description="2026-02-25" tags={["Feature", "Channel"]}>
  Biggest pre-1.2 release — added Slack channel, refactored Gmail, and improved CI.

  ## Features

  * Added `/add-slack` skill
  * Restructured add-gmail skill for new architecture with graceful startup when credentials missing
  * Removed deterministic caching from skills engine
  * Added `.nvmrc` specifying Node 22
  * CI optimization, logging improvements, and codebase formatting
  * Added CONTRIBUTORS.md and CODEOWNERS

  ## Fixes

  * Fixed WhatsApp QR data handling
  * Rebased core skills (Telegram, Discord, voice) to latest main
</Update>

<Update label="v1.1.2" description="2026-02-24" tags={["Fix"]}>
  * Improved error handling for WhatsApp Web version fetch (follow-up to v1.1.1)
</Update>

<Update label="v1.1.1" description="2026-02-24" tags={["Feature", "Fix"]}>
  ## Features

  * Added official Qodo skills and codebase intelligence
  * Rewrote README for broader audience

  ## Fixes

  * Fixed WhatsApp 405 connection failures via `fetchLatestWaWebVersion`
</Update>

<Update label="v1.1.0" description="2026-02-23" tags={["Feature", "Security"]}>
  ## Features

  * Added `/update` skill to pull upstream changes from within Claude Code
  * Replaced 'ask the user' with `AskUserQuestion` tool in skills

  ## Security

  * Fixed critical skills path-remap root escape (including symlink traversal)

  ## Fixes

  * Fixed empty messages from polling queries
  * Fixed fallback name from 'AssistantNameMissing' to 'Assistant'
</Update>
