Jump to content

Fish: Difference between revisions

From Official NixOS Wiki
Pigs (talk | contribs)
Reorganized and polished content, added information about installing fish for those not using home manager
Tags: Mobile edit Mobile web edit Advanced mobile edit
DHCP (talk | contribs)
Setting fish as default shell: remove {{expansion}} as i've implemented the changes. If this change has broken something for you, please discuss at Talk:Fish#Suggested_bashrc_in_Fish#Setting_fish_as_default_shell_needs_revision
 
(16 intermediate revisions by 10 users not shown)
Line 1: Line 1:
{{DISPLAYTITLE:fish}}
{{DISPLAYTITLE:fish}}
fish, the [http://fishshell.com/ Friendly Interactive Shell], is a [[Command Shell|command shell]] designed around user-friendliness.
fish, the [https://fishshell.com/ Friendly Interactive Shell], is a [[Command Shell|command shell]] designed around user-friendliness.


== Installation ==
== Installation ==
Line 20: Line 20:
Replace <code>myuser</code> with the appropriate username.
Replace <code>myuser</code> with the appropriate username.


{{warning| [https://fishshell.com/docs/current/index.html#default-shell As noted in the fish documentation], using fish as your *login* shell (via <code>/etc/passwd</code>) may cause issues, particularly for the <code>root</code> user, because fish is not POSIX compliant. While using fish as the default shell for regular users is generaly safe, caution is still advised. See the [[#section Setting fish as default shell|Setting fish as default shell]] section for recommendations and mitigations.}}
{{warning| [https://fishshell.com/docs/current/index.html#default-shell As noted in the fish documentation], using fish as your *login* shell (via <code>/etc/passwd</code>) may cause issues, particularly for the <code>root</code> user, because fish is not POSIX compliant. While using fish as the default shell for regular users is generaly safe, caution is still advised. See [[#Setting fish as default shell]] for recommendations and mitigations.}}


=== Home Manager ===
=== Home Manager ===
Line 54: Line 54:
{{file|/etc/nixos/configuration.nix|nix|
{{file|/etc/nixos/configuration.nix|nix|
<nowiki>
<nowiki>
environment.systemPackages = with pkgs; [
  programs.fish = {
  ...
    enable = true;
  fishPlugins.done
    interactiveShellInit = ''
  fishPlugins.fzf-fish
      set fish_greeting # Disable greeting
  fishPlugins.forgit
    '';
  fishPlugins.hydro
  };
  fzf
 
  fishPlugins.grc
  environment.systemPackages = with pkgs; [
  grc
    ...
];
    fishPlugins.done
    fishPlugins.fzf-fish
    fishPlugins.forgit
    fishPlugins.hydro
    fzf
    fishPlugins.grc
    grc
    # Use 3rd-party fish plugins manually packaged.
    (pkgs.callPackage ../fish-colored-man.nix {buildFishPlugin = pkgs.fishPlugins.buildFishPlugin; } )
  ];
</nowiki>
|name=/etc/nixos/configuration.nix|lang=nix}}
Example of a file containing the definition of a fish plugin.
{{file|/etc/nixos/fish-colored-man.nix|nix|
<nowiki>
{
  lib,
  buildFishPlugin,
  fetchFromGitHub,
}:
buildFishPlugin {
  pname = "fish-colored-man";
  version = "0-unstable-20240416";
  src = fetchFromGitHub {
    owner = "decors";
    repo = "fish-colored-man";
    rev = "1ad8fff696d48c8bf173aa98f9dff39d7916de0e";
    hash = "sha256-uoZ4eSFbZlsRfISIkJQp24qPUNqxeD0JbRb/gVdRYlA=";
  };
}
</nowiki>
</nowiki>
}}
}}
Line 106: Line 135:
=== Setting fish as default shell ===
=== Setting fish as default shell ===


Using fish as the the login shell can cause compatibility issues. For example, certain recovery environments such as systemd's emergency mode to be completely broken when fish was set as the login shell. This  limitation is noted on the [https://wiki.gentoo.org/wiki/Fish#Caveats Gentoo] wiki. There they present an alternative, keeping bash as the system shell but having it exec fish when run interactively.
Using fish as the the login shell can cause compatibility issues. For example, certain recovery environments such as systemd's emergency mode to be completely broken when fish was set as the login shell. ArchWiki presents an [https://wiki.archlinux.org/title/Fish#Modify_.bashrc_to_drop_into_fish alternative solution], 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:
Here is one solution, which launches fish unless the parent process is already fish:
Line 114: Line 143:
programs.bash = {
programs.bash = {
   interactiveShellInit = ''
   interactiveShellInit = ''
     if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]]
    # "check if parent process is not fish" && "make nested shells work properly"
    then
     if grep -qv fish /proc/$PPID/comm && [[ $SHLVL == [12] ]]; then
      shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=""
        # set $SHELL for better integration with programs like nix shell, tmux, etc.
      exec ${pkgs.fish}/bin/fish $LOGIN_OPTION
        SHELL=${pkgs.fish}/bin/fish exec fish
     fi
     fi
   '';
   '';
Line 123: Line 152:
</nowiki>
</nowiki>
}}
}}
For a more detailed explanation, please see the [https://wiki.archlinux.org/title/Fish#Modify_.bashrc_to_drop_into_fish aforementioned ArchWiki page].
'''Setting fish as default for Gnome Console'''
It is possible to set fish as the interactive non-login shell for Gnome Console without setting fish as the login shell (the login shell in /etc/passwd for your user will not be fish).
{{File|3=home-manager.users.myuser = {
    dconf = {
        enable = true;
        settings."org/gnome/Console" = {
            shell = [ "fish" ];
        };
    };
};|name=home.nix|lang=nix}}


If you still want to set fish as the login shell, see [[Command Shell#Changing the default shell]].
If you still want to set fish as the login shell, see [[Command Shell#Changing the default shell]].
==== Disable man page generation ====
Some users suffer from slow build due to fish enabling `documentation.man.generateCaches`. You may force false.
documentation.man.generateCaches = false'';''
For home-manager users, man cache need to be disabled in programs
programs.man.generateCaches = false'';''


==== Running fish interactively with zsh as system shell on darwin ====
==== Running fish interactively with zsh as system shell on darwin ====
{{outdated|date=May 14, 2026|reason=I've updated the interactiveShellInit snippet that this section refers to. Either the following paragraph should be reworded or the provided zsh config be modified. For more context, please see my corresponding [https://wiki.nixos.org/w/index.php?title=Fish&oldid=31760 edit] and the linked talk page.|talk=Talk:Fish#Suggested_bashrc_in_Fish#Setting_fish_as_default_shell_needs_revision}}


Zsh users on darwin will need to use a modified version of the above snippet. As written, it presents two incompatibilities. First, being BSD-derived, MacOS's <code>ps</code> command accepts different options. Second, this is a script intended for bash, not zsh. MacOS uses zsh as its default shell.
Zsh users on darwin will need to use a modified version of the above snippet. As written, it presents two incompatibilities. First, being BSD-derived, MacOS's <code>ps</code> command accepts different options. Second, this is a script intended for bash, not zsh. MacOS uses zsh as its default shell.
Line 151: Line 206:
)
)
</syntaxhighlight>
</syntaxhighlight>
{{Note|This won't work with the new {{ic|nix shell}} command, as it doesn't set {{ic|IN_NIX_SHELL}} variable. You can instead check if {{ic|$SHLVL}} is {{ic|> 1}}, or check if {{ic|$PATH}} contains paths from {{ic|/nix/store}} (which get added at the beginning of the {{ic|$PATH}} when you enter nix shell). See https://github.com/NixOS/nix/issues/6677 for more context and workarounds.}}


and <code>$nix_shell_info</code> to the echo in that function, e.g.:
and <code>$nix_shell_info</code> to the echo in that function, e.g.:

Latest revision as of 21:16, 13 May 2026

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

Installation

NixOS System Installation

To install fish for a user on a regular nixos system:

❄︎ /etc/nixos/configuration.nix
  programs.fish.enable = true;
  users.extraUsers.myuser = {
    ...
    shell = pkgs.fish;
  };

Replace myuser with the appropriate username.

⚠︎
Warning: As noted in the fish documentation, using fish as your *login* shell (via /etc/passwd) may cause issues, particularly for the root user, because fish is not POSIX compliant. While using fish as the default shell for regular users is generaly safe, caution is still advised. See #Setting fish as default shell for recommendations and mitigations.

Home Manager

For a user-specific installation managed by Home Manager, use the following configuration:

❄︎ home.nix
home-manager.users.myuser = {
  programs.fish.enable = true;
};

Replace myuser with the appropriate username.

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:

❄︎ /etc/nixos/configuration.nix
  programs.fish.enable = true;

Configuration

Available fish plugins packaged in Nixpkgs can be found via the fishPlugins package set.

NixOS System Configuration

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

❄︎ /etc/nixos/configuration.nix
  programs.fish = {
    enable = true;
    interactiveShellInit = ''
      set fish_greeting # Disable greeting
    '';
  };

  environment.systemPackages = with pkgs; [
    ...
    fishPlugins.done
    fishPlugins.fzf-fish
    fishPlugins.forgit
    fishPlugins.hydro
    fzf
    fishPlugins.grc
    grc
    # Use 3rd-party fish plugins manually packaged.
    (pkgs.callPackage ../fish-colored-man.nix {buildFishPlugin = pkgs.fishPlugins.buildFishPlugin; } )
  ];

Example of a file containing the definition of a fish plugin.

❄︎ /etc/nixos/fish-colored-man.nix
{
  lib,
  buildFishPlugin,
  fetchFromGitHub,
}:
buildFishPlugin {
  pname = "fish-colored-man";
  version = "0-unstable-20240416";
  src = fetchFromGitHub {
    owner = "decors";
    repo = "fish-colored-man";
    rev = "1ad8fff696d48c8bf173aa98f9dff39d7916de0e";
    hash = "sha256-uoZ4eSFbZlsRfISIkJQp24qPUNqxeD0JbRb/gVdRYlA=";
  };
}

For a full list of fish module options, refer to programs.fish.

Home Manager

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

❄︎ home.nix
home-manager.users.myuser = {
  programs.fish = {
    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";
        };
      }
    ];
  };
};

For the full list of available home-manager options for fish, refer to the module source.

Tips and tricks

Setting fish as default shell

Using fish as the the login shell can cause compatibility issues. For example, certain recovery environments such as systemd's emergency mode to be completely broken when fish was set as the login shell. ArchWiki presents an alternative solution, 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:

❄︎ /etc/nixos/configuration.nix
programs.bash = {
  interactiveShellInit = ''
    # "check if parent process is not fish" && "make nested shells work properly"
    if grep -qv fish /proc/$PPID/comm && [[ $SHLVL == [12] ]]; then
        # set $SHELL for better integration with programs like nix shell, tmux, etc.
        SHELL=${pkgs.fish}/bin/fish exec fish
    fi
  '';
};

For a more detailed explanation, please see the aforementioned ArchWiki page.

Setting fish as default for Gnome Console

It is possible to set fish as the interactive non-login shell for Gnome Console without setting fish as the login shell (the login shell in /etc/passwd for your user will not be fish).

❄︎ home.nix
home-manager.users.myuser = {
    dconf = {
        enable = true;
        settings."org/gnome/Console" = {
            shell = [ "fish" ];
        };
    };
};


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

Disable man page generation

Some users suffer from slow build due to fish enabling `documentation.man.generateCaches`. You may force false.

documentation.man.generateCaches = false;

For home-manager users, man cache need to be disabled in programs

programs.man.generateCaches = false;

Running fish interactively with zsh as system shell on darwin

⏲︎︎
This article or section is outdated as of May 14, 2026. I've updated the interactiveShellInit snippet that this section refers to. Either the following paragraph should be reworded or the provided zsh config be modified. For more context, please see my corresponding edit and the linked talk page. Further information might be found in the corresponding discussion. Please remove this notice once the information has been updated.

Zsh users on darwin will need to use a modified version of the above snippet. As written, it presents two incompatibilities. First, being BSD-derived, MacOS's ps command accepts different options. Second, this is a script intended for bash, not zsh. MacOS uses zsh as its default shell.

programs.zsh = {
  initExtra = ''
    if [[ $(ps -o command= -p "$PPID" | awk '{print $1}') != 'fish' ]]
    then
        exec fish -l
    fi
  ''
};

Show that you are in a nix-shell

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

set -l nix_shell_info (
  if test -n "$IN_NIX_SHELL"
    echo -n "<nix-shell> "
  end
)
Note: This won't work with the new nix shell command, as it doesn't set IN_NIX_SHELL variable. You can instead check if $SHLVL is > 1, or check if $PATH contains paths from /nix/store (which get added at the beginning of the $PATH when you enter nix shell). See https://github.com/NixOS/nix/issues/6677 for more context and workarounds.

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.

Environments

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 programs.fish.functions with home-manager or in ~/.config/fish/functions/fish_prompt.fish without.

haskellEnv

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

pythonEnv

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

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

See also