Using `nix develop` opens `bash` instead of `zsh`

So I’m using this flake specifically the command nix develop github:fuellabs/fuel.nix#sway-dev and when it opens up a new shell it chooses bash when I have zsh specified for my user in my configuration.nix. I see on the wiki that it does say a bash shell will open. Is there any way I can configure this?

3 Likes

I’ve found this very long thread that seems reasonable. And from reading the portion in the reference manual it seems this was developed only with the intention of supplying the user with a bash shell.

1 Like

Still if anyone has any shorter or more direct route I’m all ears!

When you run that nix develop command, nix downloads this file and builds the sway-dev output, which is defined using the pkgs.mkShell function.

In the mkShell docs, a parameter shellHook is mentioned. In that hook you should be able to start zsh if it’s installed into the environment.

So you have to create your own flake.nix file and basically override that argument.

You could just download the flake I linked above, modify sway-dev to launch into zsh and then run nix develop .#sway-dev. This should work with your locally installed zsh, but ideally you would use ${pkgs.zsh} in the hook and add that to the packages argument as well.

Maybe something to try first: can you manually start zsh inside the nix shell?

1 Like

You can also try nix develop github:fuellabs/fuel.nix#sway-dev -c $SHELL to launch your shell.

or more generically:

nix develop -c $SHELL

or you can use direnv which doesn’t change your shell after creating a cache.

9 Likes

I ended up going with this solution and just set it under the alias swaydev

nix-shell --help actually has a section which is helpful and exporting this in your configuration.nix or your shell config file will use whatever shell you specify.

Environment variables
       • NIX_BUILD_SHELL
         Shell used to start the interactive environment. Defaults to the bash found in <nixpkgs>, falling back to the
         bash found in PATH if not found.
2 Likes

Coming back here to say that Nix for some reason expects a bash derivative for NIX_BUILD_SHELL so zsh doesn’t actually work there. There is a package GitHub - chisui/zsh-nix-shell: zsh plugin that lets you use zsh in nix-shell shells. that helps to some degree. If an alias isn’t out of the question that also works in some instances but not with nix-shell directly. Adding -c <shell> to a nix develop command works, and also just zsh after nix-shell works. Unfortunately no clean way of just using the user’s default shell as of now.

Hey iFreilicht, before you had said I should be able to start zsh if it’s installed into the environment. Is there a way I could open any user’s shell in the shell hook?

Jup, seems like it. I just tested with this flake.nix:

{
  outputs = { self, nixpkgs }:
    let
      system = "aarch64-darwin";
      pkgs = nixpkgs.legacyPackages.${system};
    in {
      devShells.${system}.default = pkgs.mkShell {
        shellHook = ''
          $SHELL
        '';
      };
    };
}

and that works perfectly fine. There is the small issue that you have to Ctrl+D twice to go back out, and you could fix that by adding exit underneath $SHELL in the shellHook, but I think this caused some unexpected issues in the past for me, can’t remember what it was, though.

Interestingly, when replacing $SHELL with echo "$SHELL", I get /bin/zsh, even when running nix develop --ignore-environment.

1 Like

I needed to start a pipenv shell and also switch to zsh as a “developer env”

  • had issues with nested shells when I add zsh and pipenv shell to shellHook
  • depending on the order, either the pipenv shell will trigger and not enter zsh or vice versa

I have had decent success with:

  • not adding anything to shellHook
  • starting my dev shell using nix develop --command $SHELL -c "pipenv shell"

p.s. I use a Taskfile.yaml and just made it a standard command like task dev

hope it helps :slight_smile:

Other way to address “Ctrl+D twice” issue add exec built-in command before $SHELL. It seems preferable since exec replaces the current shell process with a new one and could be more reliable.

1 Like

This is indeed confusing, maybe even a bug. Related issue: `nix develop` does not set `SHELL` correctly · Issue #7971 · NixOS/nix · GitHub

Hello!
A good solution is to set the following alias for nix-shell and nix develop in your shell rc file.

alias nix-shell='nix-shell --run $SHELL'
nix() {
  if [[ $1 == "develop" ]]; then
    shift
    command nix develop -c $SHELL "$@"
  else
    command nix "$@"
  fi
}

For zsh, I added this to my zshrc file.

Now when I type nix-shell or nix develop, it opens zsh instead of bash.
Hope this helps!

Shouldn’t this be the default?