Schniz / fnm

🚀 Fast and simple Node.js version manager, built in Rust
https://fnm.vercel.app
GNU General Public License v3.0
16.53k stars 421 forks source link

How to correctly set PATHS for fish shell when both homebrew and fnm install node? #1096

Open kris-anderson opened 5 months ago

kris-anderson commented 5 months ago

I'm using fish shell, and I like to have all my configuration in code, that gets kept in sync with my various macs through my dotfiles. This means I use set -gx PATH /some/path $PATH instead of set -g fish_user_paths /some/path $fish_user_paths.

Since I also have node installed via some dependencies I have with homebrew, I run into a situation where the homebrew path to node comes before the fnm path to node. This means that even when I fnm use 18, I still end up using the latest node binary installed at /opt/homebrew/bin/node.

In my config.fish file, I have the following:

set -gx PATH "$HOME/.local/bin" "$PYENV_ROOT/bin" "$HOME/go/bin" "$FNM_MULTISHELL_PATH/bin" /opt/homebrew/opt/ruby/bin /opt/homebrew/sbin /opt/homebrew/bin $PATH

This allows me to put the fnm path before the homebrew paths.

I then have this in my $HOME/.config/fish/conf.d/fnm.fish file:

set PATH "$HOME/Library/Application Support/fnm" $PATH
/opt/homebrew/bin/fnm env --use-on-cd | source

The problem with this, is that when I echo $SHELL, I end up with /Users/kris/Library/Caches/fnm_multishells/2300_1707350728310/bin listed twice:

/Users/kris/.pyenv/shims /Users/kris/.local/bin /Users/kris/.pyenv/bin /Users/kris/go/bin /Users/kris/Library/Caches/fnm_multishells/2300_1707350728310/bin /opt/homebrew/opt/ruby/bin /opt/homebrew/sbin /opt/homebrew/bin /Users/kris/Library/Caches/fnm_multishells/2300_1707350728310/bin /usr/local/bin /System/Cryptexes/App/usr/bin /usr/bin /bin /usr/sbin /sbin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin /Applications/VMware Fusion.app/Contents/Public /usr/local/MacGPG2/bin /Applications/Wireshark.app/Contents/MacOS /Applications/kitty.app/Contents/MacOS

The first path is coming from the set -gx PATH command in my config.fish file, but the second path is loading dynamically when /opt/homebrew/bin/fnm env --use-on-cd | source is called in my fnm.fish file. If I remove the /opt/homebrew/bin/fnm env --use-on-cd | source line from fnm.fish, then both /opt/homebrew/bin /Users/kris/Library/Caches/fnm_multishells/2300_1707350728310/bin paths get removed from my PATH.

Hopefully this is making sense? What do I need to do in order to ensure /Users/kris/Library/Caches/fnm_multishells/2300_1707350728310/bin is always in the path before /opt/homebrew/bin, but at the same time /Users/kris/Library/Caches/fnm_multishells/2300_1707350728310/bin only shows up once in my PATH?

kris-anderson commented 5 months ago

I think I may have figured this out.

I updated my path setting towards the top of my config.fish file to the following:

set -gx PATH "$HOME/.local/bin" "$PYENV_ROOT/bin" "$HOME/Library/Application\ Support/fnm" /opt/homebrew/opt/ruby/bin /opt/homebrew/sbin /opt/homebrew/bin $PATH

In the above path command, I removed the path of "$FNM_MULTISHELL_PATH/bin" that I was setting previously

I then deleted my $HOME/.config/fish/conf.d/fnm.fish file.

The fnm automatic install script creates the above file, but if I do that, it puts the path to fnm after my homebrew paths. So to get around that, I deleted the above file, and I put the source call for fnm towards the bottom of my config.fish file:

# fnm
/opt/homebrew/bin/fnm env --use-on-cd | source

# Pyenv
pyenv init - | source

# Starship prompt
starship init fish | source

With the above setup, I now have the path for fnm set to be before the path for Homebrew, and it's only showing up once in my echo $PATH:

/Users/kris/.pyenv/shims /Users/kris/Library/Caches/fnm_multishells/23714_1707382543780/bin /Users/kris/.local/bin /Users/kris/.pyenv/bin /Users/kris/Library/Application\ Support/fnm /opt/homebrew/opt/ruby/bin /opt/homebrew/sbin /opt/homebrew/bin /usr/local/bin /System/Cryptexes/App/usr/bin /usr/bin /bin /usr/sbin /sbin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin /Applications/VMware Fusion.app/Contents/Public /usr/local/MacGPG2/bin /Applications/Wireshark.app/Contents/MacOS /Applications/kitty.app/Contents/MacOS

I'm open to feedback on if there's a better way to do this. But if not, we can close this issue and hopefully the above is helpful for anyone else with both fnm and homebrew installing node, and using fish as their shell.