From NixOS Wiki
Revision as of 10:53, 6 April 2024 by Maintenance script (talk | contribs) (rollback unauthorized mass edits)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

fish, the Friendly Interactive Shell, is a command shell designed around user-friendliness.


A basic user-specific installation with Home Manager may look like this:

home-manager.users.myuser = { = true;

Change myuser to the username of the user you want to configure.

You can enable the fish shell and manage fish configuration and plugins with Home Manager, but to enable vendor fish completions provided by Nixpkgs you will also want to enable the fish shell in /etc/nixos/configuration.nix: = true;

Setting fish as your shell

Warning! As noted in the fish documentation, using fish as your *login* shell (referenced in /etc/passwd) may cause issues because fish is not POSIX compliant. In particular, this author found systemd's emergency mode to be completely broken when fish was set as the login shell.

This issue is discussed extensively on the Gentoo and Arch wikis. There they present an alternative, keeping bash as the system shell but having it exec fish when run interactively.

Here is one solution, which launches fish unless the parent process is already fish:

programs.bash = {
  interactiveShellInit = ''
    if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]]
      shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=""
      exec ${}/bin/fish $LOGIN_OPTION

If you still want to set fish as the login shell, see Command Shell#Changing default shell.


System wide

To enable fish plugins, add your preferred plugins to `environment.systemPackages`:

environment.systemPackages = with pkgs; [
]; = true;

Home Manager

An example configuration in Home Manager for adding plugins and changing options could look like this:

home-manager.users.myuser = { = {
    enable = true;
    interactiveShellInit = ''
      set fish_greeting # Disable greeting
    plugins = [
      # Enable a plugin (here grc for colorized command output) from nixpkgs
      { name = "grc"; src = pkgs.fishPlugins.grc.src; }
      # Manually packaging and enable a plugin
        name = "z";
        src = pkgs.fetchFromGitHub {
          owner = "jethrokuan";
          repo = "z";
          rev = "e0e1b9dfdba362f8ab1ae8c1afc7ccf62b89f7eb";
          sha256 = "0dbnir6jbwjpjalz14snzd3cgdysgcs3raznsijd6savad3qhijc";

Full list of home-manager options for fish can be found See also here.

See fishPlugins package set for available plugins in nixpkgs.

Useful scripts

Show that you are in a nix-shell

Add this to the fish_prompt function (usually placed in ~/.config/fish/functions/

set -l nix_shell_info (
  if test -n "$IN_NIX_SHELL"
    echo -n "<nix-shell> "

and $nix_shell_info to the echo in that function, e.g.:

echo -n -s "$nix_shell_info ~>"

Now your prompt looks like this:

  • outside: ~>
  • inside: <nix-shell> ~>

You can directly start nix-shell in fish with nix-shell --run fish.


Here are some examples of helper functions that put you in a nix-shell with the given packages installed.

You can either put these in with home-manager or in ~/.config/fish/functions/ without.


function haskellEnv
  nix-shell -p "haskellPackages.ghcWithPackages (pkgs: with pkgs; [ $argv ])"
# Invocation: haskellEnv package1 packages2 .. packageN


function pythonEnv --description 'start a nix-shell with the given python packages' --argument pythonVersion
  if set -q argv[2]
    set argv $argv[2..-1]
  for el in $argv
    set ppkgs $ppkgs "python"$pythonVersion"Packages.$el"
  nix-shell -p $ppkgs

# Invocation: pythonEnv 3 package1 package2 .. packageN
# or:         pythonEnv 2 ..

See also