Claude Code’s /doctor command told me ~/.local/bin wasn’t in my PATH. That’s where it installs its native binary. Simple fix, right?
The symptom was easy to reproduce: open a new shell, run echo $PATH, and ~/.local/bin is nowhere in there. Claude Code was installed fine; it just couldn’t find itself.
I’d just make sure that the path was configured in my .zshrc and all would be good. Since it’s NixOS, the obvious fix from home-manager was with home.sessionPath. One line in home/roles/base.nix, rebuild, done:
home.sessionPath = [ "$HOME/.local/bin" ];
Tried it. Rebuilt. Ran exec zsh. Opened Claude Code. Ran /doctor. Still broken.
In Which I Learn How NixOS Boots a Shell
Ok, so NixOS generates a script called set-environment at build time. You can find the one currently running your shell at something like /nix/store/<hash>-set-environment. It gets sourced via /etc/zshenv on every shell start, and it does this:
export PATH="$HOME/.nix-profile/bin:/run/current-system/sw/bin:/nix/var/nix/profiles/default/bin:/usr/local/bin:/usr/bin:/bin"
A hard export PATH=. Not PATH="something:$PATH". A fresh path every time. Usually a good thing to prevent cruft building up, but now important stuff was missing.
home-manager’s hm-session-vars.sh — which does correctly add ~/.local/bin — runs before /etc/zshenv. So it sets the path, and then NixOS immediately resets it. The entry is right there in hm-session-vars.sh if you go looking:
export PATH="$HOME/.local/bin${PATH:+:}$PATH"
Was this documented anywhere obvious? I mean, probably, but I didn’t do a lot of investigation.
The Actual Fix
Searching online got me to a better option pretty quickly: NixOS has environment.localBinInPath. Setting it to true injects ~/.local/bin directly into the set-environment script, so it survives the reset.
One line in nixos/profiles/base.nix:
environment.localBinInPath = true;
Rebuild. New shell. ~/.local/bin is in $PATH. Claude Code’s /doctor command goes quiet. Mission accomplished.
Onions and Parfaits
There are layers here I didn’t consider, and the lesson isn’t subtle: on NixOS, if something isn’t in the PATH that set-environment builds, it isn’t in your PATH. Full stop. home-manager’s sessionPath, sessionVariables, anything in hm-session-vars.sh — all of it happens before the hard reset. Anything you want to survive has to come from the NixOS level.
Was home.sessionPath the wrong tool? Yes. Would I have tried it first anyway? Also, yes.
$ echo $PATH | tr ':' '\n' | grep local
/home/grue/.local/bin
Good enough.