Fish: Difference between revisions
imported>Legendofmiracles adds a bit of examples of how to configure fish with home-manager |
Clay pidgin (talk | contribs) →Setting fish as default shell: Added a method for Gnome Console |
||
(29 intermediate revisions by 16 users not shown) | |||
Line 1: | Line 1: | ||
{{DISPLAYTITLE:fish}} | {{DISPLAYTITLE:fish}} | ||
fish | fish, the [http://fishshell.com/ Friendly Interactive Shell], is a [[Command Shell|command shell]] designed around user-friendliness. | ||
== | == Installation == | ||
< | === NixOS System Installation === | ||
{ | |||
... | To install fish for a user on a regular nixos system: | ||
{{file|/etc/nixos/configuration.nix|nix| | |||
<nowiki> | |||
programs.fish.enable = true; | |||
users.extraUsers.myuser = { | |||
... | |||
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.}} | |||
=== Home Manager === | |||
For a user-specific installation managed by [[Home Manager]], use the following configuration: | |||
{{file|home.nix|nix| | |||
<nowiki> | |||
home-manager.users.myuser = { | |||
programs.fish.enable = true; | |||
}; | |||
</nowiki> | |||
}} | |||
Replace <code>myuser</code> 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: | |||
{{file|/etc/nixos/configuration.nix|nix| | |||
<nowiki> | |||
programs.fish.enable = true; | programs.fish.enable = true; | ||
</nowiki> | |||
}} | |||
== Configuration == | |||
Available fish plugins packaged in Nixpkgs can be found via the [https://search.nixos.org/packages?query=fishPlugins fishPlugins package set]. | |||
=== NixOS System Configuration === | |||
To enable fish plugins system-wide, add your preferred plugins to `environment.systemPackages`: | |||
{{file|/etc/nixos/configuration.nix|nix| | |||
<nowiki> | |||
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; } ) | |||
]; | |||
</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> | ||
}} | |||
For a full list of fish module options, refer to [https://search.nixos.org/options?query=programs.fish programs.fish]. | |||
=== Home Manager === | |||
An example configuration in Home Manager for adding plugins and changing options could look like this: | |||
{{file|home.nix|nix| | |||
<nowiki> | |||
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"; | |||
}; | |||
} | |||
]; | |||
}; | |||
}; | |||
</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 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. | |||
Here is one solution, which launches fish unless the parent process is already fish: | |||
== | {{file|/etc/nixos/configuration.nix|nix| | ||
<nowiki> | |||
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 | |||
''; | |||
}; | |||
</nowiki> | |||
}} | |||
'''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}} | |||
</code> | |||
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'';'' | |||
==== Running fish interactively with zsh as system shell on darwin ==== | |||
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> | |||
=== Show that you are in a nix-shell === | === Show that you are in a nix-shell === | ||
Add this to the <code>fish_prompt</code> function (usually placed in <code>~/.config/fish/functions/fish_prompt.fish</code>): | Add this to the <code>fish_prompt</code> function (usually placed in <code>~/.config/fish/functions/fish_prompt.fish</code>): | ||
Line 55: | Line 205: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Now your prompt looks like this | Now your prompt looks like this: | ||
* outside: <code>~></code> | * outside: <code>~></code> | ||
* inside: <code><nix-shell> ~></code> | * inside: <code><nix-shell> ~></code> | ||
You can directly start nix-shell in fish with <code>nix-shell --run fish</code>. | |||
=== Environments === | === 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 <code>programs.fish.functions</code> with home-manager or in <code>~/.config/fish/functions/fish_prompt.fish</code> without. | |||
==== haskellEnv ==== | ==== haskellEnv ==== | ||
Line 76: | Line 229: | ||
==== pythonEnv ==== | ==== pythonEnv ==== | ||
<syntaxhighlight lang="fish"> | <syntaxhighlight lang="fish"> | ||
function pythonEnv --description 'start a nix-shell with the given python packages' --argument pythonVersion | function pythonEnv --description 'start a nix-shell with the given python packages' --argument pythonVersion | ||
Line 92: | Line 246: | ||
# or: pythonEnv 2 .. | # or: pythonEnv 2 .. | ||
</syntaxhighlight> | </syntaxhighlight> | ||
== See also == | |||
* [[Command Shell]] | |||
[[Category:Shell]] |
Latest revision as of 05:48, 30 September 2025
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:
programs.fish.enable = true;
users.extraUsers.myuser = {
...
shell = pkgs.fish;
};
Replace myuser
with the appropriate username.
/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-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:
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`:
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.
{
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-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. This limitation is noted on the Gentoo wiki. 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} ]]
then
shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=""
exec ${pkgs.fish}/bin/fish $LOGIN_OPTION
fi
'';
};
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-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;
Running fish interactively with zsh as system shell on darwin
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
)
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 ..