PATH check false-positive on macOS/fish: "~/.local/bin is not in your PATH" despite being present
Summary
The native installation PATH check (OF1 in the bundle) fires a persistent warning even when ~/.local/bin is unambiguously present in $PATH. The warning appears on every claude upgrade and recurs during normal sessions. The suggested fix is also wrong syntax for fish shell.
Environment
- Claude Code version: 2.1.114
- OS: macOS Darwin 24.6.0 (Apple Silicon)
- Shell: fish
Reproduction
- Install Claude Code natively on macOS with fish as the login shell
- Run
claude upgrade(or start a session) - Warning appears despite correct PATH
Evidence that PATH is correct
$ echo $PATH | tr ' ' '\n'
/opt/homebrew/bin
/opt/homebrew/sbin
/Users/ian/go/bin
/usr/local/go/bin
/Users/ian/.local/bin ← present and clean
/Users/ian/bin
...
Simulating the exact check from OF1 inside a fish subprocess passes:
$ node -e "console.log(process.env.PATH.split(':').includes('/Users/ian/.local/bin'))"
true
Root cause analysis
The installer creates ~/.local/bin/env.fish and injects a source line into ~/.config/fish/conf.d/uv.env.fish (a file it shouldn't touch). That env file adds the path using the unresolved form $HOME/.local/share/../bin rather than $HOME/.local/bin.
OF1's PATH check does a plain string comparison (no path.resolve):
D === w // w = path.join(os.homedir(), ".local", "bin") = "/Users/ian/.local/bin"
So "/Users/ian/.local/share/../bin" !== "/Users/ian/.local/bin" — the check misses the installer's own path entry. The PDH function uses path.resolve() and handles this correctly; OF1 does not.
After cleaning up the installer's residue, the clean path /Users/ian/.local/bin remains in PATH and the simulation confirms the check should pass — yet the live warning persists. The check appears to run in a context where process.env.PATH differs from what fish exports to normal subprocesses. This was not fully resolved during diagnosis.
Secondary bugs
DISABLE_INSTALLATION_CHECKSdoes not suppress this warning. The env var guard in OF1 only wraps checks after the native PATH check, not the PATH check itself.
- Wrong fix suggested for fish. The fix message emits:
```
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.config/fish/config.fish
export
is bash syntax. The correct fish idiom is fish_add_path ~/.local/bin`.
- Installer writes into
uv.env.fish, which is semantically owned by theuvPython package manager. This silently corrupts uv's own env setup for any user with both tools installed.
---
Diagnosed by Claude Sonnet 4.6 running at max effort via claude CLI on behalf of the affected user.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗