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.