update-claude-code
Updating Claude Code on a machine touches THREE independent install surfaces. Updating one does not update the others. The trap that costs a session every time: a VS Code chat session runs the extension's OWN bundled binary, not the claude on your PATH. So claude update can report success while your VS Code session keeps running the old version — and a new model stays missing.
This skill is the verified playbook. Run the diagnostic first, update the surface that actually matters for where you're running, then do a FULL restart and verify.
The three install surfaces
| Surface | Path (Windows) | Updated by | What runs it |
|---|---|---|---|
| Native CLI | ~/.local/bin/claude.exe |
claude update |
A terminal claude session |
| VS Code extension bundled binary | ~/.vscode/extensions/anthropic.claude-code-<ver>-<platform>/resources/native-binary/claude.exe |
VS Code extension auto-update (Marketplace) | The VS Code Claude Code chat panel |
| Stale npm-global (cleanup target) | ~/AppData/Roaming/npm/claude |
npm |
Nothing it should — remove it; it only causes version confusion |
The <platform> suffix is the OS/arch triple: win32-x64 on Windows, darwin-arm64 on macOS, linux-x64 on Linux. The concept is identical on every platform.
Step 1 — Diagnose (always run this first)
echo "=== PATH CLI ==="; claude --version; where claude 2>/dev/null || which -a claude
echo "=== installed VS Code extension versions ==="; ls -1d "$HOME/.vscode/extensions/"anthropic.claude-code-*-win32-x64 2>/dev/null
echo "=== each extension's bundled binary version ==="
for d in "$HOME/.vscode/extensions/"anthropic.claude-code-*-win32-x64; do
printf "%s -> " "$(basename "$d")"; "$d/resources/native-binary/claude.exe" --version 2>/dev/null
done
echo "=== extensions pending removal on next restart ==="; cat "$HOME/.vscode/extensions/.obsolete" 2>/dev/null; echo
echo "=== stale npm-global copy? ==="; npm ls -g @anthropic-ai/claude-code --depth=0 2>/dev/null | grep claude-code || echo "(none)"
Read the output:
- If TWO extension versions are present and the newer one is NOT in
.obsolete, the newer is the intended-active version and the older is pending garbage-collection on restart. A running session may still be on the OLDER one. - The bundled-binary version of the highest installed extension is what a fresh VS Code session will run after a full restart.
Step 2 — Update the surface that matters
For the VS Code chat panel (the usual case): the extension auto-updates from the Marketplace. To force/confirm it:
- VS Code: Extensions panel → search "Claude Code" → if an Update button shows, click it. (Or Command Palette → "Extensions: Check for Extension Updates".)
- Re-run the Step 1 diagnostic and confirm the target version folder now exists with a matching bundled binary.
For terminal use: claude update (updates the ~/.local/bin native CLI in place). Confirm with claude --version.
Cleanup (recommended once): if Step 1 shows a stale npm-global copy:
npm -g uninstall @anthropic-ai/claude-code
This removes a redundant older copy so PATH never resolves to it.
Step 3 — FULL restart (this is the step people skip)
Reloading the VS Code window is NOT enough when a new extension version was just installed alongside the old one. VS Code activates the new version and removes the obsolete one (per .obsolete) only on a full restart.
- Quit VS Code entirely — close ALL windows (on Windows, ensure no
Code.exelingers). Reopen. - Open a brand-new Claude Code session (a fresh chat). The old session keeps the old binary in memory; only a new session picks up the new bundled binary.
Step 4 — Verify
- Re-run Step 1: only the new extension version remains (old one gone), bundled binary = target version.
- In the new session,
/modelshould list the new model; selecting it succeeds.
Troubleshooting: "model X isn't available in this environment" / model missing from /model
Diagnose in this order — the first is the cause ~90% of the time:
- Running binary predates the model. A model ships in a specific Claude Code version (a given model first appears in a particular release). If the active bundled binary is older than that release, the model won't appear regardless of plan. Fix = Steps 1-4 above (the PATH CLI version is a red herring for VS Code sessions). Confirm the bundled binary version, not
claude --version. - Plan / entitlement gating. Some models are API/consumption-only, or included in Pro/Max only during a limited free window. Verify current access from the source before concluding it's a version issue — search the web for the model's plan availability and any free-window dates (these move fast and post-date the training cutoff). Today's plan inclusion is not assumable.
- Stale entitlement cache. If the binary is new and the plan includes the model but it still won't show,
/login(re-auth) in a fresh session re-fetches the available-model list.
Why this skill exists (origin)
A newly launched model returned "isn't available in this environment" when selected via /model. claude update (an older release -> the release that introduced the model) succeeded on the PATH CLI, but the VS Code session kept failing — because the extension runs its own bundled binary, and a "Reload Window" did not swap the freshly-installed extension in for the still-active older one. A full VS Code restart activated the new version (the .obsolete file had the old version queued for removal) and the model appeared. The model id was correct the whole time; the missing piece was always the bundled-binary version. The authoritative source on every "can't" here is the artifact on disk: read the bundled binary's --version and the .obsolete file, not memory.