How to avoid embedded nix-shell to re-use parent nix-shell's `shellHook`?

For example, there is a dev_shell.nix in my project that sets up a PostgreSQL server and loads of environment variables, then I’m planning to call tmux:

$ nix-shell dev_shell.nix

   ...dev_shell.nix's shellHook runs...

[nix-shell]$ nix-shell -p tmux --run "tmux"

   ...the same shellHook is starting to run...

Is there a way to avoid this? --pure is not an option because the whole point is to have access to the environment variables of my dev_shell.nix (e.g., the app is served in one tmux pane while another is used to dig around and experiment).


edit: Well, starting tmux won’t preserve my environment variables either, but curious about this anyway…:slight_smile:
edit-2: tmux -L <arbitrary_name> does preserve it.

This sounds a bit like an XY problem.

Why do you need to run nix-shell in the shell? Why isn’t tmux an input in dev_shell.nix so that it’s already in the environment?

1 Like

Yeah, I just realized that I haven’t thought this through… Nonetheless, I’m still curious if the shellHook is supposed to run again when inside a nix-shell. E.g., what if I need a simple tool and I just want run it with nix-shell -p. (… where “nix-shell” is the shell started with nix-shell shell.nix and nix-shell is the command line tool.)

I imagine the problem here is that shellHook is also just a shell variable added to the environment like any other attr in the derivation (but one that’s a little special in that the shell initialization stuff spit out by nix-shell will eval it).

I guess you could anticipate this and unset it at the end of your shellHook.

$ shellHook='echo NO NO' nix-shell -p jq
warning: Nix search path entry '/nix/var/nix/profiles/per-user/root/channels' does not exist, ignoring
NO NO

$ declare -p shellHook
declare -x shellHook="echo NO NO"

$ nix-shell -p pup
warning: Nix search path entry '/nix/var/nix/profiles/per-user/root/channels' does not exist, ignoring
this path will be fetched (1.76 MiB download, 3.61 MiB unpacked):
  /nix/store/ynzdvy1lrzbfw5jn4m43zjbmk8x9lxbw-pup-unstable-2019-09-19
copying path '/nix/store/ynzdvy1lrzbfw5jn4m43zjbmk8x9lxbw-pup-unstable-2019-09-19' from 'https://cache.nixos.org'...
NO NO

$ exit
exit

$ exit
exit

$ shellHook='echo NO NO; unset shellHook' nix-shell -p jq
warning: Nix search path entry '/nix/var/nix/profiles/per-user/root/channels' does not exist, ignoring
NO NO

$ declare -p shellHook
bash: declare: shellHook: not found

$ nix-shell -p pup
warning: Nix search path entry '/nix/var/nix/profiles/per-user/root/channels' does not exist, ignoring
1 Like

FWIW, it looks like nix develop intentionally skirts this issue (in basically the same way) since nix dev-shell: Unset shellHook · NixOS/nix@0135fd6 · GitHub

1 Like

Thank you so much for all the examples and for digging up the nix develop commit! I opened [nix-shell] unset shellHook? · Issue #8257 · NixOS/nix · GitHub just in case.