Is it Idiomatic to develop from within a nix shell?

I have been trying to develop a project using a nix flake.

I have been specifying what I need within the shell in my flake.nix, then entering the environment with `nix develop .`, then launching my editor (nvim).

However, when launching a shell from within my editor, I get prompt breakage and no autocomplete, because the $SHELL variable inside the environment is set to noninteractive bash.

I have simplified this down to simply attempting to launch a nested shell within the environment, which causes the same breakage.

I have attempted to set the $SHELL in the flake in many ways, from specifying `shell = pkgs.bashInteractive` to using a shell hook to manually set the SHELL, all to no avail.

Am I doing something wrong here?

Should I be trying to set the SHELL at all?

Developing inside the shell at all?

If there is an idiomatic way to do it, what is it?

Using devshells is idiomatic.

As far as I remember, adding bashInteractive to the shell is sufficient enough to get SHELL correctly.

Though the most common approach is to use direnv for it automatically applying the environment on cd in your actual login shell.

It also knows about some special environment variables and how to ā€œmergeā€ them, or it ignores SHELL to keep your login shell set.

3 Likes

You’d think adding bashInteractive to the shell would be enough, but no. The SHELL env var seems to be set to noninteractive bash, even in that case.

I think I have found the culprit here

So I tried it out again, and it seems to still work like before :+1:

One thing I did notice is that this can create an opposite problem for everyone using nix develop -c zsh:

$ nix develop -c zsh
$ echo $SHELL
/nix/store/q0l990ga8fly926kc4sw5svjf12zfscf-bash-5.2-p15/bin/bash

Hmm, I think this is still correct behavior. zsh is only executed as a command, it isn’t the shell that is required to build the derivation. SHELL should point to the shell that the package derivation uses as its shell (which usually is bash).

The main case I ran into is where make uses SHELL to execute its sub-commands. The Makefile expects the shell to be the one defined in the derivation. Not nushell/fish that are likely incompatible with the commands in Makefile.

My case is essentially identical, just replacing zshwith bash-interactive

The thread then resolves saying that this isn’t such a big issue, since allowing SHELL to point to another shell than what the derivation expects could cause builds to fail.

There’s also the experience of someone else being told to use direnv for this, and failing.

So basically setting the SHELL to something custom is straight up not supported without changing the derivation itself.

Direnv works fine. If you’re using an embedded shell in your text editor, you may need a direnv plugin for said editor.

2 Likes

Would like to add that it also can be nice to use a direnv plugin to get LSP versions that are in the nix shell if you put them in (i personally do).

1 Like