Fish is a shell, more specific, it’s the “friendly interactive shell”.

It is a non-POSIX compliant shell that focuses on user-friendliness, usability, ease of use, easy scriptability of the shell (not necessarily as extensive as Nushell). It is particularly known for its superb autocompletion, command suggestions and tab completion.

Not only that, but it also features a unique concept, where you can, for example, set environment variables globally, which means they persist longer than the shell session. In reality, fish simply populates a file with all these settings, which is, however, separate to the fish config. This is particularly useful for me, as I manage my dotfiles using Chezmoi, so any change to the config file is considered a conflict or change by chezmoi. I, however, don’t necessarily need these specific variables to be present on other machines.

In other words, it Just Works™, at least when it comes to the features specified above, without the need for an elaborate setup like with ZSH, for example. And although I ship my custom config with my Dotfiles, requiring Additional Tools, fish is highly usable out of the box, with sane defaults and easy configuration.

Install

Fedora

sudo dnf install fish

Homebrew

If the latest fish shell isn’t available for your distribution or version, you can try installing it using Homebrew:

brew install fish

Update Completions

You might also want to update completions (automagically), especially after installing new software.

fish_update_completions

Additional Tools

My specific Dotfiles, use various tools, so it’s best to make sure they’re available and set up.

Install

Plugins

There’s also a plugin manager for fish, called Fisher.

Setup

Note

After deploying my Dotfiles, as well as installing Fisher, I usually install the following plugins.

Catppuccin

Catppuccin is my theme of choice. Everywhere.

Install

fisher install catppuccin/fish

Save it

fish_config theme save "Catppuccin Macchiato"

Sponge

To keep my typos out of the shell history, I use Sponge.

fisher install meaningful-ooo/sponge

Pufferfish

Some neat text expansion. See the project’s GitHub for more information.

fisher install nickeb96/puffer-fish

Replay

Replay enables you to execute bash snippets and proceed with an up-to-date environment.

fisher install jorgebucaran/replay.fish

Eza

fish-eza is a neat little eza integration. Make sure the dependencies are set up

Install

fisher install plttn/fish-eza

fzf

fzf.fish is a nice fzf integration. Make sure the dependencies are set up beforehand

Install

fisher install PatrickF1/fzf.fish

jj

plugin-jj for some Jujutsu integration.

fisher install kapsmudit/plugin-jj

Abbreviation Tips

fish-abbreviation-tips is a really useful tool to get into the habit of using your and your plugin’s abbreviations. Because, if you don’t use them, you might as well get rid of them.

fisher install gazorby/fish-abbreviation-tips

Login Shell

If you follow a System Administration Guide, I normally set the login shell to bash when creating the custom user, so you might wonder why I don’t directly set it to fish.

Well, fish isn’t POSIX-compliant, and neither does it want to be. Therefore, running fish as a login shell might not be the absolute best experience you’ll ever have.

Instead, I include a code snippet at the bottom of my ~/.bashrc, below the interactive check [[ $- == *i* ]], which will let fish take over any interactive shell, while scripts, etc. that expect a POSIX compliant shell can have their way.

~/.bashrc
[[ $- == *i* ]] || return
 
if [[ $(ps --no-header --pid=$PPID --format=comm) != "fish" && -z ${BASH_EXECUTION_STRING} && ${SHLVL} == 1 ]]
then
        shopt -q login_shell && LOGIN_OPTION='--login' || LOGIN_OPTION=''
        FISH_BIN=$(command -v fish)
        [ -x "$FISH_BIN" ] && SHELL=${FISH_BIN} exec $FISH_BIN "$LOGIN_OPTION"
fi