[BUG] : fresh native installation raise warning about npm

Open 💬 19 comments Opened Oct 16, 2025 by S1M0N38

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

I've removed Claude code and related files entirely from my computer (macOS 26).

Then I've installed Claude code using

curl -fsSL https://claude.ai/install.sh | bash

So I'm expecting a clean single installation, but when running claude doctor, I get

 claude doctor

 Diagnostics
 └ Currently running: native (2.0.19)
 └ Path: /Users/simo/.local/bin/claude
 └ Invoked: /Users/simo/.local/share/claude/versions/2.0.19
 └ Config install method: native
 └ Auto-updates enabled: default (true)
 └ Search: OK (bundled)
 Warning: Multiple installations found
 └ npm-global at /Users/simo/.local/bin/claude
 └ native at /Users/simo/.local/bin/claude
 Warning: Leftover npm global installation at /Users/simo/.local/bin/claude
 Fix: Run: npm -g uninstall @anthropic-ai/claude-code

 Press Enter to continue…

The file at /Users/simo/.local/bin/claude is a symlink to the /Users/simo/.local/share/claude/versions/2.0.19, however Claude doctor thinks that this is a NPM installation. I think this is a bug.

What Should Happen?

No warning

Error Messages/Logs

Steps to Reproduce

describe above

Claude Model

None

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.0.19

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Other

Additional Information

_No response_

View original on GitHub ↗

19 Comments

github-actions[bot] · 9 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/8523
  2. https://github.com/anthropics/claude-code/issues/7231
  3. https://github.com/anthropics/claude-code/issues/3199

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

FLGAI · 8 months ago

Claude Code's claude update command incorrectly identifies Homebrew cask
installations as npm global installations. When both native and Homebrew
cask are installed, it warns about a "leftover npm global installation" at
/opt/homebrew/bin/claude and suggests running npm -g uninstall
@anthropic-ai/claude-code, but no npm package exists. The detection logic
should check if the path is actually an npm installation versus a Homebrew
cask symlink.

Then when I run claude doctor:
Diagnostics
└ Currently running: native (2.0.36)
└ Path: /Users/***/.local/bin/claude
└ Invoked: /Users/
*/.local/share/claude/versions/2.0.36
└ Config install method: native
└ Auto-updates: false
└ Search: OK (bundled)
Warning: Multiple installations found
└ npm-global at /opt/homebrew/bin/claude
└ native at /Users/
***/.local/bin/claude
Warning: Leftover npm global installation at /opt/homebrew/bin/claude
Fix: Run: npm -g uninstall @anthropic-ai/claude-code

I've fixed this by removing homebrew install of claude. But still thought you all might want to know.

oskay · 7 months ago

Confirming FLGAI's Report: Homebrew Cask Misdetected as npm-global

I can confirm the same issue that FLGAI reported above. The Homebrew cask installation is incorrectly identified as an npm global installation.

My Environment

  • Claude Code Version: 2.0.46 (native auto-updated) + 2.0.31 (Homebrew cask)
  • Installation Method: Originally installed via brew install --cask claude-code
  • OS: macOS (Darwin 23.6.0)
  • Platform: Apple Silicon (Homebrew at /opt/homebrew)

The Issue

Running claude doctor shows:

Warning: Multiple installations found
└ npm-global at /opt/homebrew/bin/claude
└ native at /Users/oskay/.local/bin/claude
Warning: Leftover npm global installation at /opt/homebrew/bin/claude
Fix: Run: npm -g uninstall @anthropic-ai/claude-code

However:

  • npm list -g confirms no Claude Code package installed via npm
  • brew list shows claude-code is installed as a cask
  • /opt/homebrew/bin/claude is a symlink to /opt/homebrew/Caskroom/claude-code/2.0.31/claude

The suggested fix (npm -g uninstall @anthropic-ai/claude-code) has no effect because there's no npm installation.

Correct Fix

brew uninstall --cask claude-code

This properly removes the Homebrew cask installation and resolves the warning.

Root Cause

The detection logic appears to misidentify any installation in /opt/homebrew/bin as npm-global, without distinguishing Homebrew cask installations. This is a common scenario since the Homebrew cask's own documentation warns:

"Claude Code's auto-updater installs updates to ~/.local/bin/claude and not to Homebrew's location."

Anyone who originally installed via brew install --cask claude-code will eventually end up with this dual-installation state as the auto-updater creates the native installation.

Suggested Fix

The /doctor command should check the actual installation type (perhaps by running brew list or checking if the path is in Caskroom) before suggesting the fix command.

dave-shawley · 7 months ago

This is the closest to what I am seeing. Our installation process installs Claude Code by curling the install shell script through bash and installs some managed settings. After installation, claude doctor reports a Multiple installations found error:

% claude doctor

 Diagnostics
 └ Currently running: native (2.0.61)
 └ Path: /Users/.../.local/bin/claude
 └ Invoked: /Users/.../.local/share/claude/versions/2.0.61
 └ Config install method: native
 └ Auto-updates: false
 └ Search: OK (bundled)
 Warning: Multiple installations found
 └ npm-global at /Users/.../.local/bin/claude
 └ native at /Users/.../.local/bin/claude
 Warning: Leftover npm global installation at /Users/.../.local/bin/claude
 Fix: Run: npm -g uninstall @anthropic-ai/claude-code

As mentioned in this issue, there is not a NPM installation. In fact, /Users/.../.local/bin/claude is a symlink to the native version that the installer installed.

% ls -l ~/.local/bin/claude
lrwxr-xr-x  1 ...  staff  48 Dec  8 08:44 /Users/.../.local/bin/claude@ -> /Users/.../.local/share/claude/versions/2.0.61

The difference is that I do not have claude installed via homebrew or npm. The only copy is the one created (and symlinked) by install.sh. Another interesting note is that our NPM configuration would install claude into ~/.local/bin. I'm not sure if claude is looking at the npm config and noticing that the executable matches what npm would install and deciding that there is a duplicate or not.

Hopefully some additional breadcrumbs will help.

dave-shawley · 7 months ago

I verified that claude code is looking at the NPM configuration. If the NPM prefix option is set to ~/.local then claude code will always report multiple installations. This can be reproduced by:

  1. doing a fresh install of claude using the curl command
  2. running npm config set --location user prefix=$HOME/.local
  3. running claude doctor
$ npm config set --location user prefix=$HOME/.local/npm-bin
$ claude doctor

 Diagnostics
 └ Currently running: native (2.0.72)
 └ Path: /Users/.../.local/bin/claude
 └ Invoked: /Users/.../.local/share/claude/versions/2.0.72
 └ Config install method: native
 └ Auto-updates: enabled
 └ Search: OK (bundled)

 Press Enter to continue…
$ npm config set --location user prefix=$HOME/.local
$ claude doctor

 Diagnostics
 └ Currently running: native (2.0.72)
 └ Path: /Users/.../.local/bin/claude
 └ Invoked: /Users/.../.local/share/claude/versions/2.0.72
 └ Config install method: native
 └ Auto-updates: enabled
 └ Search: OK (bundled)
 Warning: Multiple installations found
 └ npm-global at /Users/.../.local/bin/claude
 └ native at /Users/.../.local/bin/claude
 Warning: Leftover npm global installation at /Users/.../.local/bin/claude
 Fix: Run: npm -g uninstall @anthropic-ai/claude-code

 Press Enter to continue…
colinbrophy-genius · 6 months ago

+1 Same issue on Fedora Linux with Claude Code 2.0.76. My npm prefix is set to ~/.local, which matches the native installation path. npm list -g @anthropic-ai/claude-code shows empty - the package isn't there.

S1M0N38 · 6 months ago

I had reviewed my config and I also had the npm configure to follow XDG spec:

export XDG_CONFIG_HOME="$HOME/.config"
export XDG_DATA_HOME="$HOME/.local/share"
export XDG_CACHE_HOME="$HOME/.cache"

export NPM_CONFIG_USERCONFIG="$XDG_CONFIG_HOME/npm/npmrc"
export NPM_CONFIG_CACHE="$XDG_CACHE_HOME/npm"
npm config set prefix "$HOME/.local"

Maybe Claude doctor is checking if claude is found in

ls -1 $(npm config get prefix)/bin

which in my case is also where the native version is installed.

---

The current workaround that I'm using is to change the npm config prefix location to be something different from $HOME/.local (for example to $HOME/.local/share/npm)

npm config set prefix "$HOME/.local/share/npm"
tree -L 1 "$(npm config get prefix)"
$HOME/.local/share/npm
├── bin
└── lib

Then manually delete claude from $HOME/.local/bin and reinstall claude with native installation.

⚠️ This could break the installation of other npm package that have been installed globally (i.e. using the -g flag). Delete those package from $HOME/.local/bin and reinstall them (they will be installed into the new location, i.e. $HOME/.local/share/npm/bin with libs in $HOME/.local/share/npm/libs ⚠️

---

I've implement this workaround a couple of weeks ago, so Idk if this issue persist in recent claude code versions. Since then I'm on native and updated claude with claude update.

breun · 6 months ago

My native claude binary is managed via MacPorts, and it's not in ~/.local/bin, but claude doctor still incorrectly thinks it's installed via NPM:

❯ claude doctor

 Diagnostics
 └ Currently running: native (2.1.4)
 └ Path: /opt/local/bin/claude
 └ Invoked: /opt/local/share/claude-code/claude
 └ Config install method: native
 └ Auto-updates: disabled (DISABLE_AUTOUPDATER set)
 └ Search: OK (bundled)
 Warning: Leftover npm global installation at /opt/local/bin/claude
 Fix: Run: npm -g uninstall @anthropic-ai/claude-code
itay-sadov · 5 months ago

Root Cause Found: Orphaned Daemon Process from Previous Installation

After extensive debugging, I found the actual root cause of the persistent installMethod reset.

The Problem

When switching from npm-local to native installation, background claude processes from the old installation continue running. These orphaned processes periodically reset ~/.claude.json back to installMethod: "local" and recreate ~/.claude/local.

In my case, I had an 8-day-old daemon process (adopted by systemd --user) that was originally started from ~/.claude/local/claude. This process kept resetting my config even after I:

  • Changed installMethod to "native"
  • Deleted ~/.claude/local
  • Cleared npm cache

Detection

Check if you have orphaned processes from the old installation:

for pid in $(pgrep -x "claude"); do
    echo "PID $pid: $(cat /proc/$pid/environ 2>/dev/null | tr '\0' '\n' | grep '^_=')"
done

Look for any process with _=.../.claude/local/claude — those are zombies from the old npm-local installation.

Fix

# 1. Kill ALL claude processes (including hidden daemons)
pkill -9 -x "claude"

# 2. Fix the config
sed -i 's/"installMethod": "local"/"installMethod": "native"/' ~/.claude.json

# 3. Remove the local installation directory
rm -rf ~/.claude/local

# 4. Restart claude fresh
claude
takver · 5 months ago

Worth noting that ~/.local is npm's own recommended prefix for avoiding sudo permission errors — which explains why this keeps getting reported. Anyone following official npm docs will hit this.
See also #7231 (same bug, Linux, closed as not planned).

danwan · 5 months ago

Same issue here. macOS, Claude Code v2.1.37, native installation via curl | bash.

~/.npmrc has prefix=/Users/dannywannagat/.local, which causes the false positive:

Warning: Multiple installations found
└ npm-global at /Users/dannywannagat/.local/bin/claude
└ native at /Users/dannywannagat/.local/bin/claude (currently running)

Warning: Leftover npm global installation at /Users/dannywannagat/.local/bin/claude
Fix: Run: npm -g uninstall @anthropic-ai/claude-code

Confirmed: npm list -g @anthropic-ai/claude-code returns nothing. The binary is a symlink to the native installation:

~/.local/bin/claude -> ~/.local/share/claude/versions/2.1.37

As @dave-shawley identified, the detection logic checks where npm would install, not whether an npm package actually exists. A simple npm list -g check before flagging would fix this.

pete-life · 5 months ago

Still hitting this on macOS (Darwin 25.1.0, Apple Silicon) with v2.1.38 native installation.

In my case it's not just a false warning — the config actively reverts. I've manually fixed this multiple times across sessions by:

  1. Editing ~/.claude.json to set installMethod: "native" and autoUpdates: true
  2. Running npm -g uninstall @anthropic-ai/claude-code

Each time, within some period of normal use, the config silently resets back to installMethod: "global" and autoUpdates: false, and the npm package reappears at /opt/homebrew/bin/claude. Auto-updates stay broken until I manually intervene again.

autoUpdatesProtectedForNative: true is present in my config but does not prevent the reset.

claude doctor output after it happens:

Diagnostics
└ Currently running: native (2.1.38)
└ Path: ~/.local/share/claude/versions/2.1.38
└ Invoked: ~/.local/share/claude/versions/2.1.38
└ Config install method: global
└ Search: OK (bundled)
Warning: Multiple installations found
└ npm-global at /opt/homebrew/bin/claude
└ native at ~/.local/bin/claude
Warning: Running native installation but config install method is 'global'
Warning: Leftover npm global installation at /opt/homebrew/bin/claude

Updates
└ Auto-updates: disabled (config)

This matches the root cause identified in #17612 — the auto-updater appears to unconditionally write installMethod: "global" and then the npm-global installation follows from that.

Workaround (PATH priority): In addition to the config fix, I found that on macOS, ~/.local/bin (where native claude lives) was ending up behind /opt/homebrew/bin in PATH due to macOS path_helper reordering. This means even after removing the npm package, the auto-updater could reinstall via npm and that binary would take priority. Fix: add export PATH="$HOME/.local/bin:$PATH" as the last line in ~/.zprofile (after brew shellenv), not just in .zshrc, since path_helper reorders PATH in login shells. This ensures the native binary always wins.

maximebrmd · 5 months ago

Still happening on v2.1.39 (native installation, macOS Darwin 25.2.0, Apple Silicon). Discovered this running claude update — the warning also appears there, not just in claude doctor.

As @oskay described, the detection logic misidentifies Homebrew cask installations at /opt/homebrew/bin/claude as npm-global and suggests npm -g uninstall @anthropic-ai/claude-code — which does nothing since there's no npm package installed.

The correct fix for Homebrew users is:

brew uninstall claude-code

---

Root cause analysis from decompiling v2.1.39 binary

The detection logic in findInstallations() (minified as XE8) works like this:

  1. Runs npm -g config get prefix to get npm's global prefix path
  2. Checks if {prefix}/bin/claude exists (e.g. /opt/homebrew/bin/claude)
  3. If it exists, calls realpathSync() and checks if the resolved path includes /Caskroom/
  4. If it does, calls isHomebrewInstallation() (minified as UVR) — but this function checks process.execPath, not the path being evaluated
// Simplified from minified source
function isHomebrewInstallation() {
  let platform = getPlatform();
  if (platform !== "macos" && platform !== "linux" && platform !== "wsl") return false;
  let execPath = process.execPath || process.argv[0] || "";
  if (execPath.includes("/Caskroom/")) return true; // only checks the RUNNING binary
  return false;
}

The bug: When running the native binary at ~/.local/bin/claude, process.execPath is ~/.local/share/claude/versions/X.Y.Z — it doesn't contain /Caskroom/. So isHomebrewInstallation() returns false, and the Homebrew binary at /opt/homebrew/bin/claude falls through to type: "npm-global".

The symlink resolution already proved it's Homebrew (realpathSync("/opt/homebrew/bin/claude").includes("/Caskroom/") was true), but the result is discarded.

Then in the doctor/update diagnostics, the fix message is hardcoded for npm-global:

if (installation.type === "npm-global") {
  let fix = "npm -g uninstall @anthropic-ai/claude-code";
  warnings.push({ issue: `Leftover npm global installation at ${path}`, fix: `Run: ${fix}` });
}

Suggested fix

  1. In findInstallations(): When realpathSync(path).includes("/Caskroom/") is already true, classify as { type: "homebrew", path } directly — don't delegate to isHomebrewInstallation() which checks the wrong binary.
  1. In the diagnostics: Handle type: "homebrew" separately:
if (installation.type === "homebrew") {
  warnings.push({
    issue: `Leftover Homebrew installation at ${path}`,
    fix: `Run: brew uninstall claude-code`
  });
}

Note: the CHANGELOG for v2.0.33 states "Fixed claude doctor incorrectly detecting Homebrew vs npm-global installations by properly resolving symlinks" — the symlink resolution was added but the result isn't used correctly because isHomebrewInstallation() checks process.execPath (the running binary) instead of the path that was just resolved.

breun · 5 months ago
The correct fix for Homebrew users is: `` brew uninstall claude-code ``

Some people actually want to manage the software on their system via a central package manager like Homebrew or MacPorts. (I happen to be the maintainer of the claude-code port for MacPorts.) In that case, telling the user to uninstall the software via their package manager is not appropriate advice.

I think that ideally there should be a generic way for package managers to let the claude binary know that it is being managed by a package manager, e.g. an environment variable or something.

Looking at the existing settings, I would expect that settings DISABLE_INSTALLATION_CHECKS=1 would suppress the installation checks, but that doesn't seem to be the case:

❯ DISABLE_INSTALLATION_CHECKS=1 /opt/local/share/claude-code/claude doctor

 Diagnostics
 └ Currently running: native (2.1.39)
 └ Path: /opt/local/share/claude-code/claude
 └ Invoked: /opt/local/share/claude-code/claude
 └ Config install method: native
 └ Search: OK (bundled)
 Warning: Native installation exists but ~/.local/bin is not in your PATH
 Fix: Run: echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc then open a new terminal or
 run: source ~/.zshrc
 Warning: Leftover npm global installation at /opt/local/bin/claude
 Fix: Run: npm -g uninstall @anthropic-ai/claude-code

 Updates
 └ Auto-updates: enabled
 └ Auto-update channel: latest
 └ Stable version: 2.1.29
 └ Latest version: 2.1.39

 Press Enter to continue…

There are two issues in this output:

  1. Claude tells me to add ~/.local/bin to their PATH, but that directory doesn't even exist on my system, so that's bad advice.
  2. Claude thinks /opt/local/bin/claude is a 'leftover npm global installation', but it is not. /opt/local/bin/claude is a wrapper script that calls /opt/local/share/claude-code/claude, which is the single-file claude binary, not an NPM installation, so this remark is also incorrect. (npm config get prefix returns /opt/local for MacPorts users, or whatever directory they specified if they use a custom prefix for their MacPorts setup.)
pogo19 · 4 months ago

Same issue here on Ubuntu Linux with Claude Code 2.1.70. Native installation via curl | bash, Linux x86_64. npm prefix is ~/.local (set in ~/.npmrc per npm's own recommendation).

The detection should verify that the npm package actually exists before flagging a path as npm-global — for example, check whether {prefix}/lib/node_modules/@anthropic-ai/claude-code exists. This is the standard location for globally-installed npm packages and would distinguish a real npm installation from a native binary that happens to share the same directory. Alternatively, deduplicating entries that resolve to the same file via symlink would also work.

Yzhav · 3 months ago

I’m seeing a very similar problem on Windows (native install), with timestamped evidence that npm global install is being triggered again.

What happens

Even after removing npm global installation and using native install, installMethod flips from native to global, and npm artifacts are recreated.

Timestamped evidence (JST)

  • 2026-04-02 12:52:47: installMethod changed native → global (autoUpdates=false)
  • At the same time, npm debug log recorded:
  • verbose title npm install @anthropic-ai/claude-code
  • verbose argv "install" "--global" "@anthropic-ai/claude-code"

Additional context

  • Platform: Windows
  • Installation: native
  • autoUpdates=false
  • Around reproduction time, I did not explicitly run claude install, claude update, or npm -g install (normal usage flow included /doctor).

<details>
<summary>Redacted analysis report</summary>

# Claude Install Monitor Report (Redacted)

- Session directory: `C:\Users\<REDACTED>\Documents\New project\claude-install-monitor\monitor-logs\20260402-124500`
- Generated at: 2026-04-02 12:56:30 +09:00

## Key Findings
- 2026-04-02 12:52:47 JST: `installMethod` changed from `native` to `global` (autoUpdates=False)
- 2026-04-02 12:52:47-12:52:48 JST: npm log recorded:
  - `verbose title npm install @anthropic-ai/claude-code`
  - `verbose argv "install" "--global" "@anthropic-ai/claude-code"`
- NPM artifacts were recreated under `%APPDATA%\npm` immediately after the above.

## Public-safe Path Style
- npm log file: `C:\Users\<REDACTED>\AppData\Local\npm-cache\_logs\2026-04-02T03_52_46_324Z-debug-0.log`
- recreated stubs: `C:\Users\<REDACTED>\AppData\Roaming\npm\claude(.cmd/.ps1)`

</details>

<details>
<summary>Redacted npm debug log snippet</summary>

0 verbose cli C:\Program Files\nodejs\node.exe C:\Users\<REDACTED>\AppData\Roaming\npm\node_modules\npm\bin\npm-cli.js
6 verbose title npm install @anthropic-ai/claude-code
7 verbose argv "install" "--global" "@anthropic-ai/claude-code"
104 verbose cwd C:\Users\<REDACTED>
108 verbose exit 0
109 info ok

</details>

If helpful, I can also share a longer redacted timeline from the monitor run.

Asseel-Naji · 3 months ago

The issue still exists as of v2.1.92

EnosXu · 2 months ago

Still reproducing on v2.1.119 (Linux x86_64, Ubuntu 24.04.4, native install via curl | bash).

Same scenario as @pogo19 and @danwan: npm prefix happens to be ~/.local, which is also where the native installer places the symlink. The path ~/.local/bin/claude is a symlink → ~/.local/share/claude/versions/2.1.119, and npm ls -g confirms no @anthropic-ai/claude-code package exists.

Warning appears in both claude doctor and claude update. The suggested fix npm -g uninstall @anthropic-ai/claude-code is a no-op (nothing to uninstall).

@danwan's suggestion — running npm list -g @anthropic-ai/claude-code (or equivalently checking {prefix}/lib/node_modules/@anthropic-ai/claude-code) before flagging the path as npm-global — would resolve this without requiring users to move their npm prefix away from the officially-recommended ~/.local.

aqrln · 1 month ago

I hate having to write a comment that brings nothing new to the conversation and spamming the inboxes of 15 people, but since this is apparently the expected etiquette in this repository, and the issues in which this doesn't happen get closed automatically "due to inactivity", here we go:

I'm also facing this bogus "multiple installations found" warning, for example, when running claude update:

aqrln@lima-dev ~/prisma> claude update
Current version: 2.1.168
Checking for updates to latest version...

Warning: Multiple installations found
- npm-global at /home/aqrln.guest/.local/bin/claude
- native at /home/aqrln.guest/.local/bin/claude (currently running)

Warning: Leftover npm global installation at /home/aqrln.guest/.local/bin/claude
Fix: Run: npm -g uninstall @anthropic-ai/claude-code
Claude Code is up to date (2.1.168)

Both installations point at the same path, Claude Code has never been installed using npm on this VM, and the suggested "fix" is of course a no-op.

My $NPM_CONFIG_PREFIX is set to ~/.local which is a normal and expected thing to do.