[BUG] Silent npm→native auto-migration writes autoUpdatesChannel: "stable" and downgrades the CLI (2.1.220 → 2.1.212), removing new models from /model
Summary
The background auto-updater performed a silent npm → native migration during a running session and, as a side effect, (1) wrote "autoUpdatesChannel": "stable" into ~/.claude/settings.json without any notice, (2) removed the npm-installed CLI (which was on 2.1.220), and (3) installed the older stable release 2.1.212 — an effective downgrade that removed access to newly released models (Claude Opus 5 disappeared from /model).
Because settings.json is a file many users sync between machines (dotfile syncs, our own settings sync), the silently injected "stable" flag then propagated to a second machine, whose auto-updater obediently downgraded it too (2.1.220 → 2.1.212). Net effect: a fleet-wide, unattended downgrade with no log line, no notice, and a confusing user experience ("the model I used yesterday is gone").
Environment
- macOS 26.5 (Darwin 25.5.0), two Macs (Mac Studio + MacBook)
- Claude Code native install in
~/.local/share/claude/versions/, plus a leftover npm-global install (nvm) on the MacBook - Timezone MDT (UTC−6); timestamps below are local unless marked UTC
Evidence timeline (from disk artifacts)
- Jul 25, 21:35 — MacBook auto-update via npm path,
~/.claude/.last-update-result.json:
``json`
{"timestamp":"2026-07-26T03:35:37.137Z","path":"npm-global","outcome":"success","status":"success","version_from":"2.1.208","version_to":"2.1.220","error_code":null}
/model` from here on.
Opus 5 available in
- Jul 27, 19:49 — during an ordinary running session (session transcript contains no install/update commands; shell history clean; no LaunchAgent involved), the auto-updater migrated npm → native:
- npm package removed:
~/.nvm/versions/node/v24.14.1/lib/node_modules/@anthropic-ai/is now empty, dir mtime Jul 27 19:49 - native stable installed:
~/.local/share/claude/versions/2.1.212created Jul 27 19:49 "autoUpdatesChannel": "stable"appeared in~/.claude/settings.json(captured by our settings-sync git history at 2026-07-28T02:18Z, absent in the previous snapshot 30 min earlier)
- Jul 28, 13:12 — second machine (Mac Studio, native install, previously auto-updating on latest: 2.1.214 → 2.1.217 → 2.1.219 → 2.1.220 per
versions/dir timestamps) received the synced"stable"flag and its auto-updater downgraded:
``json`
{"timestamp":"2026-07-28T19:12:52.767Z","path":"native","outcome":"success","status":"success","version_from":"2.1.220","version_to":"2.1.212","error_code":null}
/model` on both machines.
Result: Opus 5 gone from
Why this matters beyond a version number
- The downgrade silently removed access to a just-released model tier. Users can't tell whether the model was pulled server-side, their account changed, or their client regressed — it looks like data/feature loss.
- A background process mutating user settings (
autoUpdatesChannel) without notice interacts badly with any settings-sync setup, turning a single-machine side effect into a multi-machine downgrade. - If a future stable→latest gap contains security or data-integrity fixes, the same silent channel switch would roll those back too.
Expected behavior
- npm → native migration should preserve the currently installed version and effective channel (npm installs track
latest; migrating to nativestable+ older binary is a downgrade, not a migration). - Any write to
settings.jsonby the updater should be surfaced to the user (message in-session, log line, changelog entry) — ideally not happen at all without consent. - The updater should never move to a lower version than currently active without an explicit user action, or at minimum should print/notify that a downgrade occurred and why.
Repro sketch
- Have both an npm-global (
@anthropic-ai/claude-codeat a recentlatest) and conditions for native migration on macOS. - Run an ordinary interactive session and let the background updater trigger the npm → native migration.
- Observe: npm package removed, native
stable(older) installed and activated,"autoUpdatesChannel": "stable"written into~/.claude/settings.jsonwith no user-visible notice; newer-model entries disappear from/model.
Related (adjacent, not duplicate): #69319 — claude update checks "stable" despite autoUpdatesChannel: "latest". Together they suggest channel handling in the native updater needs a review.
Recovery that worked for us, for anyone else hitting this: claude install latest, then delete the autoUpdatesChannel key from ~/.claude/settings.json (absent key = latest), on every affected machine.