Anvil v2.2.17 is live across seven platforms today. This release rewrites the first-run experience as a single in-TUI alt-screen wizard, adds an autonomous reflection loop that re-strategizes when a turn gets stuck, ships an isolated sandbox-runner companion binary for hub-install safety, and surfaces a viewable source archive for every one of the 558 packages on AnvilHub. A long tail of TUI correctness fixes — including a photosensitivity-grade flash on Gnome Terminal — also lands.
The new setup wizard
A single alt-screen owns the entire first-run experience. The welcome card explains what the wizard will do before it asks for anything. Nine modal steps follow — vault password, provider login, defaults — each with a tight per-step description so you always know why a question is being asked.
OAuth callbacks now poll a 100 ms timeout (previously they blocked on keypress), so the elapsed counter ticks live and the callback completes the moment your browser redirects. No extra keystroke required.
Step 9 is the CC migration handoff, also in-modal: import memory, instructions, settings, skills, plugins, and sessions from ~/.claude if present. When the wizard finishes it hands directly to the password modal for vault unlock, then drops into the main TUI — one alt-screen, one teardown, zero seam.
Autonomous reflection loop
Long-running turns now get a stuck-detector. When a turn loops without progress, the reflection layer switches strategy and writes a multi-attempt scratchpad so the next iteration sees what didn’t work. No more silent dead-ends in deep agent runs.
Sandbox-runner companion binary
Hub-install detonation now runs in a separate anvil-sandbox-runner binary. When you run anvil install <hub-id>, the package code is unpacked and executed inside an isolated child process rather than inside the main anvil process. A malicious or buggy hub package cannot escape into your live session, tamper with your vault, or read sessions in flight.
The companion binary ships alongside anvil on all seven platforms (macOS ARM64/Intel, Linux x86_64/ARM64, Windows x86_64, FreeBSD x86_64, NetBSD x86_64).
AnvilHub source viewer
Every one of the 558 packages on anvilhub.culpur.net now has a viewable source archive. A backfill seeded archives for all packages that were missing them, and Documentation tabs are now populated for the 547 packages that had a NULL README. You can see exactly what a skill, agent, theme, or plugin does before you install it.
TUI accessibility — the photosensitivity fix
v2.2.16 introduced a region-gated repaint optimization that, on Gnome Terminal and alacritty, produced an unconditional full-screen Clear() on every token streamed. That’s a photosensitivity hazard. v2.2.17 gates the Clear() widget on DirtyRegions::ALL and routes TextDelta events away from the terminal-clear path entirely. Streaming output is now smooth on every supported terminal.
The vertical-split rail also no longer goes blank/garbage on the first prompt after a fresh wizard exit — a ratatui swap_buffers contract violation in the v2.2.16 repaint optimization that surfaced as missing cells. All three layouts now paint every region every frame.
Wizard accessibility — mouse capture off by default
The wizard now defaults mouse capture OFF across all platforms, so native text selection works on Mac, Linux, and Windows Terminal out of the box. The previous “recommended” default was Mac-only and broke selection on Linux + Windows.
The long tail
/agent composeand/agent traitsrewired to push through the TUI — no moreprintln!corrupting the alt-screen. A cross-binary clippy lint (#![deny(clippy::print_stdout, clippy::print_stderr)]) prevents the regression.- In-TUI
ConfirmModalandPasswordModal: vault unlock for returning users is now a modal in the existing alt-screen, not a CLI prompt. - Vertical-split Shift+drag selects deck text only, not the rail.
- Vertical-split rail keybinds (g / d / s / a / Ctrl+R) now work, with a drift gate to keep them wired.
- Reactive compaction now seeds its summary-size budget from the actual overflow delta, not a fixed token guess.
ANVIL_STOP_HOOK_BLOCK_CAPcaps Stop-hook blocking to prevent infinite loops.- Session auto-titling actually fires now:
derive_title_from_first_message()is wired to the trigger. - Hook paths refresh after
EnterWorktree, so PWD-relative hooks don’t go stale. - Welcome banner names the active provider for third-party users (no more hardcoded Anthropic for Groq/Bedrock/etc.).
Infrastructure under the hood
The release pipeline got a new release-surfaces.yaml manifest with a scripts/verify-release-surfaces.sh enforcement gate that kills the Swiss-cheese-checklist class of bug we’ve been chasing for the last three releases. Every publicly advertised surface is now declared in one YAML file, and the gate fails the build if anything drifts.
The Anvil Passage backend cluster also finished its production migration: HAProxy patroni_rw routing wired, ownership reconciled across 63 prod tables, F1 prisma migrations green, sequential deploys clean. A P0 incident where Patroni replication had been silently dead since May 8 was discovered, diagnosed, and resolved during this release cycle.
Compatibility & upgrade
v2.2.17 is a drop-in upgrade from v2.2.16. Config, vault, and session formats are forward-compatible — no migration steps required.
To upgrade:
brew upgrade anvil # macOS / Linux
anvil upgrade # any platform with anvil already installed
To install fresh:
curl -fsSL https://anvilhub.culpur.net/install.sh | bash
The --version output will report anvil 2.2.17.
Links
- GitHub Release: github.com/culpur/anvil/releases/tag/v2.2.17
- Install page: anvilhub.culpur.net/install
- Source archives + SHA256s: anvilhub.culpur.net/sha256/2.2.17.txt
- Public README + changelog: github.com/culpur/anvil#changelog
