Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 31 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,37 @@ All notable changes to NanoClaw will be documented in this file.

## [Unreleased]

- **Budget/billing-exhausted LLM turns now reach the user instead of being silently dropped.** When a turn ends in a non-retryable provider error (e.g. an Anthropic `403 billing_error`) with no `<message>` wrapping, the agent-runner delivers the provider's notice to the originating channel and stops re-nudging the failing gateway. `providers/claude.ts` now surfaces the SDK's `is_error` flag (and the error subtype's `errors[]` text); `poll-loop.ts` delivers 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.
- [BREAKING] **`@onecli-sh/sdk` 0.5.0 -> 2.2.1 — requires a OneCLI server with the `/v1` API** (older servers 404 every SDK call). The sanctioned gateway and CLI versions are pinned in `versions.json`. **The gateway is a separate component — updating NanoClaw does not upgrade it for you:** `/update-nanoclaw` upgrades it when the pin moves, otherwise upgrade manually. **Migration:** [docs/onecli-upgrades.md](docs/onecli-upgrades.md).
- **New agent provider: Codex (OpenAI) — run `/add-codex`.** Full runtime via `codex app-server` (planning, MCP tools, server-side history, resume). Trunk ships the seams and the skill; the payload installs from the `providers` branch (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 --provider` + restart; creation is provider-agnostic.
- **Memory migrates via `/migrate-memory`, never at runtime.** Each provider keeps its own store; fresh groups on a surfaces-owning provider see no stale `CLAUDE.*` files. See [docs/provider-migration.md](docs/provider-migration.md).
- **Per-exchange archiving is provider-owned** — the `onExchangeComplete` hook; the markdown writer ships with the codex payload.
- **Container boot failures now say why** — the last stderr lines are logged at `warn` on a non-zero exit instead of a silent crash loop.
- **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 out the turn.
## [2.1.17] - 2026-06-17

- [BREAKING] **`@onecli-sh/sdk` 0.5.0 → 2.2.1 — requires a OneCLI server with the `/v1` API.** Older servers 404 every SDK call. The sanctioned gateway and CLI versions are now pinned in `versions.json`, and the `onecli` setup step enforces them. **The gateway is a separate component — updating NanoClaw does not upgrade it for you:** `/update-nanoclaw` upgrades the gateway when its pin moves, otherwise upgrade manually. See [docs/onecli-upgrades.md](docs/onecli-upgrades.md).
- **New agent provider: Codex (OpenAI) — run `/add-codex`.** Full runtime via `codex app-server` (planning, MCP tools, server-side history, resume). Trunk ships the seams and the skill; the payload installs from the `providers` branch — 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 --provider` plus a restart; group creation is provider-agnostic.
- **`/migrate-memory` runs 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 stale `CLAUDE.*` files left over from another provider's writes. See [docs/provider-migration.md](docs/provider-migration.md).
- **`/update-nanoclaw` now 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-nanoclaw` flow when the pin in `versions.json` shifts. 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.ts` surfaces the SDK's `is_error` flag and the error subtype's `errors[]` text; `poll-loop.ts` delivers 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.** `writeOutboundDirect` was opening the session's outbound DB through the readonly opener, so the INSERT it ran threw `SQLITE_READONLY` on every call — the router's `Permission denied` response 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 `warn` level on a non-zero exit (`code !== null && code !== 0`). Previously, a container that died at boot — unknown provider, missing binary, bad config — logged only at `debug`, 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](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 `channelType` when no `instance` is set.
- **Native uninstaller.** `bash uninstall.sh` from a checkout, or `nanoclaw.sh --uninstall` from the installed launcher, removes the service, the data directory, and the host registration in one step — no more manual `launchctl bootout` / `systemctl --user disable`. Includes `--dry-run` and 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-prompt` with 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-id` on the first spawn, `--resume` on 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 `getDeliveryAction` so 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 `onExchangeComplete` hook 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_agent` host-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-sweep` now 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-browser` is now pinned to 0.27.1 (what `latest` last 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 in `README.md`, `docs/SPEC.md`, `CONTRIBUTING.md`, and `CLAUDE.md`.
- Skills install model documented; see [docs/skills-as-branches.md](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`, `opencode` provider, `codex` provider, `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](docs/ollama.md).
- `chat-sdk-bridge` records 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-code` 2.1.170 and `@anthropic-ai/claude-agent-sdk` 0.3.170.

## [2.1.0] - 2026-06-07

Expand Down
Loading