Interactive Bash with `nix develop` Flake

Consider the following bare Nix shell environment. shell.nix:

{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell { }

And this flake.nix:

{
  outputs = inputs@{ self, nixpkgs, ... }:
    let
      pkgs = import nixpkgs { system = "x86_64-linux"; };
    in
  {
    devShell."x86_64-linux" = import ./shell.nix { inherit pkgs; };
  };
}

The nix-shell will yield an interactive Bash:

$ nix-shell

[nix-shell:/tmp/x]$ echo $SHELL
/nix/store/lz9s7v9xxkr3jf4wlah9vw1knmic2nda-bash-interactive-5.1-p8/bin/bash

while nix develop does not:

$ nix develop
$ echo $SHELL
/nix/store/wadmyilr414n7bimxysbny876i2vlm5r-bash-5.1-p8/bin/bash

This leads to issues when launching applications like Vim and Visual Studio Code, which launch integrated terminals that will be ‘dumb’. This means the arrow keys and DEL will not behave like expected… This issue refers to when nix-shell also had this problem, it seems: Vim in nix-shell starts non-interactive bash on :shell and :terminal · Issue #2034 · NixOS/nix · GitHub


Is there a way to make nix develop behave like nix-shell?

(And as a side question: Is it possible for nix develop to show a prompt similar to nix-shell to be able to distinguish we’re in a sub shell?)


[Update: does not work.] A solution that I came up with is to add the following shellHook to mkShell for the Flake:

shellHook = ''
  SHELL=${pkgs.bashInteractive}/bin/bash
'';

But, I am not very experienced with Nix to know if this is the right direction. Or perhaps I am solving the wrong problem here.

My solution didn’t work as I kept debugging this with Visual Studio Code. The following does work, but I do not understand how and whether it’s a solid solution. I am not sure why nix-shell doesn’t require this, but nix develop then does:

buildInputs = [ pkgs.bashInteractive ];

To more reliably check the Bash binary used, we can use /proc/[pid]/exe. Combined with the previous solution, I end up with an interactive Bash:

$ nix develop
$ readlink /proc/$$/exe
/nix/store/yx24h6ywbkg7rm5x7lrm8mx8ypcf4ywi-bash-interactive-5.1-p8/bin/bash

nix-shell still works too:

$ nix-shell

[nix-shell:/tmp/x]$ readlink /proc/$$/exe
/nix/store/lz9s7v9xxkr3jf4wlah9vw1knmic2nda-bash-interactive-5.1-p8/bin/bash
1 Like

I think there is a related issue in the Nix repo for this now:

https://github.com/NixOS/nix/issues/6091

3 Likes

Thanks for linking to that issue. Not 100% sure it’s the same issue, but seems like it. The author of the issue doesn’t state what he means by ‘broken’.

My issue is about an non-interactive/dumb shell that inserts literal tabs. There is a similar issue where auto-completion doesn’t work for any software not specified in mkShell. So in that case git would not auto-complete anyway, because its share directory is not listed in $XDG_DATA_DIRS.

I am not sure what the underlying problem is, if there is any real problem here. Is nix develop pure (or nix-shell)? You can access tools from the ‘parent’ environment, like git, which begs the question why git is in $PATH, but its share directory not in $XDG_DATA_DIRS.

Also related: bash autocompletion in nix shell (nix command) · Issue #4453 · NixOS/nix · GitHub

@b-zee @cdepillabout The above line used to work for me (although I put it under nativeBuildInputs, but I don’t think it makes any difference for final.myHaskellPkgs.shellFor).

But it no longer works. I’m now on a later nixpkgs commit from June 2024.

Did you find a more recent working solution to the problem? The problem, to recap, is a dysfunctional bash shell within a “nix develop” shell (strange chars showing up, no tab completion, etc.).

1 Like

I have no alternative. I am on a commit from 2 weeks ago, and it seems to be working still.

What does $SHELL say in your shell?

1 Like

Also experiencing this issue on nixos-unstable. Weirdly, this used to just work, but this morning I launched a nix develop and my starship prompt blew up. Simply adding the bashInteractive package to the build deps doesn’t solve it. It seems to work ok if I just run nix develop and work directly in there, but I was running zellij and having it launch a sub-shell causes the problem.

1 Like