Skip to content

v2.1.0

Choose a tag to compare

@glifocat glifocat released this 17 Jun 14:51

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.json records 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 running pnpm 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-trace ships 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-traces dataset, browsable in the HF Agent Trace Viewer. Auth runs through the OneCLI gateway: the HF token is injected by HTTPS_PROXY and never touches agent code; a missing or unassigned token returns a clear setup message pointing at the gateway URL.
  • New /add-rtk skill. Installs rtk into agent containers via host binary mount + a Claude Code PreToolUse hook, 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-formatting container skill. Inlined into every group's CLAUDE.md on container spawn (via claude-md-compose.ts) so agents see WhatsApp's mention syntax — @<phone-digits> sourced from content.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 existing container/skills/slack-formatting/ layout; pairs with the channels-branch fix that wires mentions through to Baileys' contextInfo.
  • ncl groups delete now 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 .jsonl backing 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 to conversations/ and a fresh session starts. Caps are operator-overridable via CLAUDE_TRANSCRIPT_ROTATE_BYTES and CLAUDE_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 until tries=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.db corruption now exits the container so host-sweep can respawn with a fresh mount. On Docker Desktop macOS, the kernel page cache for the bind-mounted inbound.db can 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 emits database disk image is malformed at 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-code to 2.1.154 and @anthropic-ai/claude-agent-sdk to 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. to api. to match the new gateway DNS.
  • setup-register scope 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-cli 0.13+ identity field accepted; earlier versions kept working.
  • /add-teams CLI docs corrected — previous version referenced flags that had been renamed.
  • Photon integration URL corrected from photon.im to photon.codes to match the new authoritative domain.
  • CLAUDE.local.md writes now go through the SDK's settingSources plumbing 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:

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:

Full Changelog: v2.0.64...v2.1.0