claude update bails out on false-positive npm-global detection when npm prefix == native install bin dir
Summary
claude update aborts with a "Multiple installations found" warning that fires as a false positive when the user's npm prefix happens to equal the parent of the native-install launcher (~/.local). The suggested remediation (npm -g uninstall @anthropic-ai/claude-code) is a no-op because the npm package is not actually installed. The updater never proceeds to check the remote channel, so the user is silently pinned to whatever native version is currently symlinked.
Environment
- OS: Linux (Ubuntu, kernel 6.8)
- Shell: zsh
- Claude Code:
2.1.119(native build) - Install layout: native binaries under
~/.local/share/claude/versions/, launcher symlink at~/.local/bin/claude - npm prefix:
/home/qdu/.local(set in~/.npmrc) — i.e.npm-prefix/bin == native-launcher dir ~/.local/lib/node_modules/does not contain@anthropic-ai/claude-code— npm package is genuinely absent. Other npm-global packages (codex-activator,neovim,@openai,tree-sitter-cli) live there.
Reproduction
$ which claude
~/.local/bin/claude
$ ls -la /home/qdu/.local/bin/claude
lrwxrwxrwx ... ~/.local/bin/claude -> ~/.local/share/claude/versions/2.1.119
$ npm config get prefix
~/.local
$ ls ~/.local/lib/node_modules/ | grep claude
(empty)
$ claude update
Current version: 2.1.119
Checking for updates to latest version...
Warning: Multiple installations found
- npm-global at ~/.local/bin/claude
- native at ~/.local/bin/claude (currently running)
Warning: Leftover npm global installation at ~/.local/bin/claude
Fix: Run: npm -g uninstall @anthropic-ai/claude-code
$ echo $?
0
The output ends there — the updater never reports the remote latest version or whether an update is available.
What was tried (none of which work)
npm -g uninstall @anthropic-ai/claude-code— returnsup to date in 22ms, exit 0. No-op. Subsequentclaude updateproduces the identical warning.claude install latest— succeeds, but "latest" resolves to the version already installed (2.1.119 in this case). Symlink mtime updates, target unchanged.claude install 2.1.120— a binary at~/.local/share/claude/versions/2.1.120exists locally (apparently pre-downloaded). Command reports✔ Claude Code successfully installed! Version: 2.1.120but the~/.local/bin/claudesymlink still points to 2.1.119. So the install command silently fails to swap the launcher when this detector trips.NPM_CONFIG_PREFIX=/tmp/npm-temp-claude claude update— gets past the warning (no "Multiple installations" output), but then hangs indefinitely atChecking for updates to latest version.... Killed after ~5 minutes; no further output, no network or filesystem activity visible in/proc/<pid>/fd.
Likely root cause
The npm-global detector appears to flag any claude binary located at $(npm config get prefix)/bin/claude, regardless of whether the npm package metadata (node_modules/@anthropic-ai/claude-code) exists. When the user's npm prefix is ~/.local (a common choice for non-root npm setups), the path collision is unavoidable because the native launcher also lives at ~/.local/bin/claude.
Suggested fixes
- The npm-global check should require the actual npm package to be present (e.g.
node_modules/@anthropic-ai/claude-code/package.json), not just a binary at the prefix's bin path. claude install <version>should bypass the npm-global guard (since the user has explicitly named a version) and update the launcher symlink unconditionally.- The hang under
NPM_CONFIG_PREFIXoverride is a separate issue worth investigating — the updater appears to depend on more than justnpm config get prefixto make forward progress.
Workaround for affected users
None that is non-disruptive. Moving npm prefix off ~/.local requires reinstalling all other npm-global packages. Manually re-pointing the launcher works for a known new version (ln -sfn ~/.local/share/claude/versions/<new> ~/.local/bin/claude) but is not discoverable.
This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗