Fish: Difference between revisions

Claes (talk | contribs)
Add category shell
Sapi (talk | contribs)
m Replaced attr def with a inherit, does the same thing.
 
(25 intermediate revisions by 14 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 ==


A basic user-specific installation with [[Home Manager]] may look like this:
=== NixOS System Installation ===


<syntaxhighlight lang="nix">
To install fish for a user on a regular nixos system:
home-manager.users.myuser = {
 
{{file|/etc/nixos/configuration.nix|nix|
<nowiki>
   programs.fish.enable = true;
   programs.fish.enable = true;
};
  users.extraUsers.myuser = {
</syntaxhighlight>
    ...
    shell = pkgs.fish;
  };
</nowiki>
}}
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 [[#Setting fish as default shell]] for recommendations and mitigations.}}


Change <code>myuser</code> to the username of the user you want to configure.
=== Home Manager ===


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 <code>/etc/nixos/configuration.nix</code>:
For a user-specific installation managed by [[Home Manager]], use the following configuration:


<syntaxhighlight lang="nix">
{{file|home.nix|nix|
<nowiki>
home-manager.users.myuser = {
   programs.fish.enable = true;
   programs.fish.enable = true;
</syntaxhighlight>
};
</nowiki>
}}


== Setting fish as your shell ==
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 (referenced in <code>/etc/passwd</code>) 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.
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:


This issue is discussed extensively on the [https://wiki.gentoo.org/wiki/Fish#Caveats Gentoo] and [https://wiki.archlinux.org/title/Fish#System_integration Arch] wikis. There they present an alternative, keeping bash as the system shell but having it exec fish when run interactively.
{{file|/etc/nixos/configuration.nix|nix|
<nowiki>
  programs.fish.enable = true;
</nowiki>
}}


Here is one solution, which launches fish unless the parent process is already fish:
== Configuration ==
 
<syntaxhighlight lang="nix">
programs.bash = {
  interactiveShellInit = ''
    if [[ $(${pkgs.procps}/bin/ps --no-header --pid=$PPID --format=comm) != "fish" && -z ''${BASH_EXECUTION_STRING} ]]
    then
      shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=""
      exec ${pkgs.fish}/bin/fish $LOGIN_OPTION
    fi
  '';
};
</syntaxhighlight>


If you still want to set fish as the login shell, see [[Command Shell#Changing default shell]].
Available fish plugins packaged in Nixpkgs can be found via the [https://search.nixos.org/packages?query=fishPlugins fishPlugins package set].


== Configuration ==
=== NixOS System Configuration ===


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


To enable fish plugins, add your preferred plugins to `environment.systemPackages`:
{{file|/etc/nixos/configuration.nix|nix|
<nowiki>
  programs.fish = {
    enable = true;
    interactiveShellInit = ''
      set fish_greeting # Disable greeting
    '';
  };


<syntaxhighlight lang="nix">
  environment.systemPackages = with pkgs; [
environment.systemPackages = with pkgs; [
    ...
  fishPlugins.done
    fishPlugins.done
  fishPlugins.fzf-fish
    fishPlugins.fzf-fish
  fishPlugins.forgit
    fishPlugins.forgit
  fishPlugins.hydro
    fishPlugins.hydro
  fzf
    fzf
  fishPlugins.grc
    fishPlugins.grc
  grc
    grc
];
    # Use 3rd-party fish plugins manually packaged.
    (pkgs.callPackage ../fish-colored-man.nix { inherit (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>
}}


programs.fish.enable = true;
For a full list of fish module options, refer to [https://search.nixos.org/options?query=programs.fish programs.fish].
</syntaxhighlight>


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


<syntaxhighlight lang="nix">
{{file|home.nix|nix|
<nowiki>
home-manager.users.myuser = {
home-manager.users.myuser = {
   programs.fish = {
   programs.fish = {
Line 88: Line 125:
     ];
     ];
   };
   };
};
</nowiki>
}}
For the full list of available home-manager options for fish, refer to the [https://github.com/nix-community/home-manager/blob/master/modules/programs/fish.nix module source].
== Tips and tricks ==
=== Setting fish as the default shell ===
It is possible to set fish as the interactive non-login shell for your terminal emulator without setting it as the login shell (the one in <code>/etc/passwd</code>).
As this is usually a user-wise setting, to configure the terminal emulator you will need to either modify its config file, or use [[Home Manager]].
==== Setting fish as default for Kitty ====
Using [[Home Manager]]:
{{File|3=programs.kitty = {
    enable = true;
    shellIntegration.enableFishIntegration = true;
    settings = {
      shell = "fish";
    };
  };|name=home.nix|lang=nix}}
Note: the <code>shellIntegration.enableFishIntegration = true;</code> is not required for setting fish as default, but provides other useful quality-of-life features, see https://sw.kovidgoyal.net/kitty/shell-integration/.
For use without home-manager, refer to https://sw.kovidgoyal.net/kitty/conf/#opt-kitty.shell and https://sw.kovidgoyal.net/kitty/conf/#opt-kitty.shell_integration.
'''Setting fish as default for Gnome Console'''
Using [[Home-manager|Home Manager]]:
{{File|3=home-manager.users.myuser = {
    dconf = {
        enable = true;
        settings."org/gnome/Console" = {
            shell = [ "fish" ];
        };
    };
};|name=home.nix|lang=nix}}
=== Setting fish as the login 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 [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.
Do note that even the following code is not full-proof, and should only be used with a thorough understanding. Prefer [[Fish#Setting fish as default shell|Setting fish as the default shell]].
Here is one solution, which launches fish unless the parent process is already fish:
{{file|/etc/nixos/configuration.nix|nix|
<nowiki>
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
  '';
};
</nowiki>
}}
For a more detailed explanation, please see the [https://wiki.archlinux.org/title/Fish#Modify_.bashrc_to_drop_into_fish aforementioned ArchWiki page].
If you are using Lix, you can change the grep condition to <code>"fish\|nix-shell"</code> so the <code>nix-shell</code> command still works, this is necessary since Lix forks before spawning the shell process so the parent process ends up being nix-shell and not fish.<ref>https://git.lix.systems/lix-project/lix/issues/1131#issuecomment-18341</ref>
↵If you still want to set fish as the login shell, see [[Command Shell#Changing the default shell]].
==== 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.
<syntaxhighlight lang="nix">
programs.zsh = {
  initExtra = ''
    if [[ $(ps -o command= -p "$PPID" | awk '{print $1}') != 'fish' ]]
    then
        exec fish -l
    fi
  ''
};
};
</syntaxhighlight>
</syntaxhighlight>
Full list of home-manager options for fish can be found  See also [https://github.com/nix-community/home-manager/blob/master/modules/programs/fish.nix here].


See [https://search.nixos.org/packages?channel=unstable&from=0&size=50&buckets=%7B%22package_attr_set%22%3A%5B%22fishPlugins%22%5D%2C%22package_license_set%22%3A%5B%5D%2C%22package_maintainers_set%22%3A%5B%5D%2C%22package_platforms%22%3A%5B%5D%7D&sort=relevance&query=fishPlugins fishPlugins package set] for available plugins in nixpkgs.
=== 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'';''


== Useful scripts ==
For home-manager users, man cache needs to be disabled in programs
 
programs.man.generateCaches = false'';''


=== Show that you are in a nix-shell ===
=== Show that you are in a nix-shell ===
Line 106: Line 226:
)
)
</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.:
Line 121: Line 243:


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


Line 158: Line 281:
* [[Command Shell]]
* [[Command Shell]]


[[Category:Applications]]
 
[[Category:Shell]]
[[Category:Shell]]