- Book: AI That Acts
- The series: AI in TypeScript — 5 books, from your first LLM call to agents in production — all five here
- My project: Hermes IDE | GitHub — an IDE for developers who ship with Claude Code and other AI coding tools
- Me: xgabriel.com | GitHub
You approve a tool call once. You expect it to run once.
For five days in October, one Claude Code release could break that in some sessions. Version 2.1.296 shipped on October 9. The entry for 2.1.299, released October 14, in the official changelog reads: "Fixed a regression in 2.1.296 where cloud and headless sessions could run an approved tool call twice if a new message arrived as the session resumed after a restart."
Read the conditions before you panic. Cloud and headless sessions only, and only when a new message arrives while the session resumes after a restart. That is a narrow window. Still, think about what sits behind an approval in a headless run. A git status run twice costs nothing. A migration, a deploy, a gh pr create or a call to a payment API run twice is something you clean up by hand.
Nobody chose 2.1.296. Native installs of Claude Code update themselves in the background, and the default channel is latest, which gets "new features as soon as they're released" (setup docs). A CI job that installs Claude Code fresh on every run gets whatever is newest that minute.
A coding agent that auto-updates is new code running with your permissions on your repo every few days, and nobody on your team read it first. Treat it like a dependency bump: pin it, and let one machine try each new version before the rest of the team moves.
Nine days of changelog, read like a dependency bump
The double run is not the only line worth reading from that week. From 2.1.294, released October 8: "Fixed prompt and agent hooks written as instructions (such as "Block commands that...") allowing what they should block."
A prompt hook sends the decision to a Claude model for a single-turn evaluation, and an agent hook spawns a subagent that can read files before it decides (hooks docs). Say you wrote one that says "Block commands that touch the production database." The changelog lists the fix for hooks phrased as instructions like that in 2.1.294, without saying which earlier versions were affected. On an affected build, the guard sits in your settings file and can still wave the command through.
Then look at what else changed between October 8 and October 16, all from the same changelog:
- 2.1.295 added
onFailure: "block"for command and HTTP hooks, so a hook that can't start or times out blocks the action instead of letting it through. - 2.1.299 changed plugin hooks to refuse an action when the hook can't be handed it or can't hand back its answer.
- 2.1.302 changed
claude -pand Agent SDK sessions with no permission mode to start indefaultmode "on third-party providers, with telemetry off or on a fresh install," adding that "--permission-mode autokeeps auto." A headless job that never set a mode can behave differently after an update it never chose.
Most of those make you safer. 2.1.296, released in the middle of that stretch, made headless sessions less predictable. They all arrived the same way: "Updates download and install in the background, then take effect the next time you start Claude Code" (setup docs).
An auto-update is a deploy nobody reviewed
You would not let a production service pull whatever version of a library was published this morning. That is why lockfiles exist. Your coding agent has a shell, your git credentials and often a cloud token or two. Yet on most machines it is the one binary allowed to float.
The fair argument for floating is speed. The double-run fix reached latest five days after the regression did. Pin hard and you wait for fixes too. So don't freeze. Add a short, deliberate lag: one machine runs the new version on real work, everyone else moves when that machine has had a few quiet days and someone has read the entries in between.
The knobs Claude Code already has
All of these are in the setup docs. Pick the one that matches how much lag you want.
Follow the stable channel. In /config, change Auto-update channel to stable, or put it in ~/.claude/settings.json. Stable is "typically about one week old, skipping releases with major regressions." A minimumVersion sets a floor that auto-updates won't go below:
{
"autoUpdatesChannel": "stable",
"minimumVersion": "2.1.299"
}
Turn the updater off. Add DISABLE_AUTOUPDATER to the env block of the same file. Then run claude doctor. The docs say the Auto-updates line should read disabled (set by env: DISABLE_AUTOUPDATER).
{
"env": {
"DISABLE_AUTOUPDATER": "1"
}
}
That only stops the background check. claude update still works. To block every update path, including manual ones, the docs point you to DISABLE_UPDATES.
Install an exact version. The native installer takes a version number, and so does npm:
curl -fsSL https://claude.ai/install.sh | bash -s 2.1.299
# or, with npm
npm install -g @anthropic-ai/claude-code@2.1.299
Pinning the install is not the same as pinning the version you run. The docs describe npm global installs as auto-updating too, and they don't say a version-numbered native install turns the updater off. Set DISABLE_AUTOUPDATER either way and confirm with claude doctor. If you install with Homebrew, the docs say the claude-code cask tracks stable and does not auto-update by default.
Enforce a range for a team. In managed settings, requiredMinimumVersion and requiredMaximumVersion make Claude Code refuse to start outside the versions your organization allows.
Then make drift loud. A few lines at the top of a CI job, or in a shell profile:
want="2.1.299"
have="$(claude --version | cut -d' ' -f1)"
if [ "$have" != "$want" ]; then
echo "claude is $have, pinned to $want" >&2
exit 1
fi
The docs show claude --version printing a line like 2.1.89 (Claude Code), so the first field is the version.
What npm's stable tag is serving today
"Just use stable" sounds like the end of the discussion. It isn't. On October 19, the npm registry lists the stable tag at 2.1.292 and latest at 2.1.303. That's npm's tag. I haven't checked what the native installer's stable channel serves today.
Version 2.1.292 is older than the 2.1.296 regression, so stable skipped the double run. It is also older than the 2.1.294 fix, so if you count on prompt or agent hooks written as instructions to block things, npm's stable build doesn't have that fix. The changelog doesn't say which versions had the bug, so test such a hook on that build before you trust it.
A channel picks a delay for you. It doesn't read the entries for you. That's still your job, and it's a short one:
- Keep one machine on
latest. Yours, or one CI runner that does real but low-stakes work. - Pin everyone else to a version you chose.
- Before you move the pin, open the changelog and read every entry between the two versions. Search the page for "hook", "permission", "approved", "headless" and "default".
- Move the pin when the canary has had a few quiet days and nothing in step 3 touches a guard you depend on.
Where Hermes fits, and where it doesn't
I build Hermes IDE, so weigh this with that in mind. Hermes runs each vendor's own CLI in a real terminal, "exactly as it would anywhere else," as its README puts it. A vendor's new commands work the day they ship, and a vendor's regression does too. Hermes runs the Claude Code you installed, unchanged, so pinning stays your job.
What it does give you is a quick look at which version you're on. The agent picker in the ⌘N task sheet shows the version of each agent CLI you have installed, and marks the rest Not installed.

The ⌘N New task sheet with its agent picker open: Claude Code installed (2.1.299), Codex installed (0.145.0), the other supported agents marked Not installed, plus Custom agent.
On the canary machine, start the new version's first tasks with ⌘N (Ctrl+Shift+N on Windows and Linux). Each one gets its own hermes/ branch and worktree, and the Review Desk (⌘G, or Ctrl+Shift+G) shows what each turn changed before you land anything.
The same advice applies to Hermes itself. Its recent release notes each end with "Published to the beta channel, then promoted to stable straight away." Hermes is free, source-available under BSL 1.1, runs on macOS, Windows and Linux, and isn't affiliated with Nous Research, Anthropic or any other agent vendor. Download it here.
Do you let your agent float?
The 2.1.296 regression was narrow, and Anthropic fixed it in five days. That's the good version of this story. The next one might be wider, and auto-updates will deliver it to every machine you didn't pin.
So, honestly: which version of your coding agent is running in CI right now? Do you know without checking? And if you pin, how do you decide when to move? Tell me in the comments.
If this was useful
The double run is a lesson for the agents you build, too. A resumed run can repeat a tool call, so any tool that changes something needs to be safe to call twice. AI That Acts is where I cover tool calling, functions and a first working agent in TypeScript.
It's book 3 of AI in TypeScript, a five-book series that runs from your first LLM call to agents in production. If you run several coding agents a day, Hermes IDE puts them in one window, each on its own branch.


Top comments (0)