Flakes in nix shell do not override installed packages

I am new to nix, so sorry if this is a stupid question. :grimacing:

Basically, I am trying to manage nodejs versions in a sane way where I have one default version installed via home-manager:

   home.packages = [
     pkgs.nodejs_22
  ]

But then during some points when I am testing/debugging, I want to be able to switch to use a different nodejs version. I thought I could do this by running nix shell nixpkgs#nodejs_18 but it seems like the node version from the flake added in the nix shell actually gets appended to the end of the PATH and so does not override the base version of node installed by home-manager.

$ node --version
v22.8.0
$ whereis node
node: /nix/store/pzbymxal2vfak7f1fiwpn4n4s5345mg3-home-manager-path/bin/node
$ nix shell -v nixpkgs#nodejs_18
$ node --version
v22.8.0
$ whereis node
node: /nix/store/pzbymxal2vfak7f1fiwpn4n4s5345mg3-home-manager-path/bin/node /nix/store/lgw9z5sf9n6pm2dqmd92z4gq4irslnq1-nodejs-18.20.4/bin/node

If I run nix shell -i ... then I do see node 18 as expected, but it drops everything else from my PATH (which is not what I want).

Am I missing something obvious here? Is there a different way to achieve my desired functionality? Thanks!

:thinking: Interestingly it seems like when using nix-shell and an explicitly defined shell.nix file I do not have this issue:

$ node --version
v22.8.0
$ cat shell.nix
{ pkgs ? import <nixpkgs> {} }:
  pkgs.mkShell {
    # nativeBuildInputs is usually what you want -- tools you need to run
    nativeBuildInputs = with pkgs.buildPackages; [ nodejs_18 ];
}

$ nix-shell

$ node --version
v18.20.4

Okay, I think I basically figured this out. I am not using home-manager to manage my bash (I am running on Fedora, not NixOS). Because of this, I was sourcing ~/.nix-profile/etc/profile.d/hm-session-vars.sh in my .bashrc to get the home-manager session variables into my PATH.

When running nix shell... the .bashrc was getting sourced again after the new flakes were added to the path. So whatever was referenced in my .bashrc was taking preference over the new things added in the shell.

My fix was to move all the PATH manipulation our of my .bachrc to where it belongs in the .bash_profile file (so that it only gets executed for new login shells).

Hmm, actually turns out it was not ~/.nix-profile/etc/profile.d/hm-session-vars.sh. That only runs once (controlled by __HM_SESS_VARS_SOURCED).

It turns out it was this code in my default Fedora .bashrc:

# Source global definitions
if [ -f /etc/bashrc ]; then
    . /etc/bashrc
fi

Moving just that to my .bash_profile keeps my PATH from getting all screwy inside the shell.