How to Install fish on Ubuntu: The Friendly Interactive Shell

fish is the friendly interactive shell, and its pitch is refreshingly direct: everything good should already be on. A brand new fish install gives you autosuggestions drawn from your history, syntax highlighting while you type, tab completions generated from your installed man pages, and a scripting language free of the quoting traps that make POSIX shells so easy to get subtly wrong.

That last part is not a small thing. set files (ls) produces an actual list, $var never word-splits on you, and command substitution needs no defensive quotes. fish is not POSIX compatible, and that is intentional: it optimises for the shell you sit in all day rather than the shell your scripts run under.

From version 4.0 fish is written in Rust, with the functions and completions that used to ship as separate data files compiled into the executable. Ubuntu carries fish in its archive, but each release pins a version for its lifetime while upstream keeps moving.

The unofficial deb.griffo.io repository packages the upstream statically linked musl build as a proper Ubuntu .deb. There is no fish-common package to install, nothing to link against at runtime, and the package registers fish as a valid login shell for you.

Install the Latest fish on Ubuntu: The Short Version

If you only came for the commands, this adds the repository and installs the latest fish .deb package on Ubuntu:

sudo install -d -m 0755 /etc/apt/keyrings
curl -fsSL https://deb.griffo.io/EA0F721D231FDD3A0A17B9AC7808B4DD62C41256.asc | sudo gpg --dearmor --yes -o /etc/apt/keyrings/deb.griffo.io.gpg
echo "deb [signed-by=/etc/apt/keyrings/deb.griffo.io.gpg] https://deb.griffo.io/apt $(lsb_release -sc 2>/dev/null) main" | sudo tee /etc/apt/sources.list.d/deb.griffo.io.list > /dev/null
sudo apt update
sudo apt install fish

The rest of this guide explains what each command does, how to verify the install, how to keep fish up to date, and what to check when something goes wrong.

What Makes fish Special?

  • ๐Ÿ’ก Autosuggestions out of the box - fish proposes the rest of your command from history and completions as you type; โ†’ accepts it.
  • ๐ŸŽจ Syntax highlighting as you type - Typos and unmatched quotes go red before you press enter.
  • ๐Ÿ“– Completions from man pages - fish reads your installed manuals, so even niche tools get flag completion.
  • ๐Ÿง  Sane scripting - Genuine lists, no word splitting, no IFS landmines, one consistent set model for variables.
  • ๐ŸŒˆ Web-based configuration - fish_config opens a browser UI for colours, prompts, functions and bindings.
  • โŒจ๏ธ Rich interactive editing - Multi-line editing, in-place abbreviations, and Alt-โ†/Alt-โ†’ directory history.
  • ๐Ÿฆ€ Rust rewrite - fish 4.0 and later are Rust, with runtime data embedded in the binary.
  • ๐Ÿ“ฆ Single static binary - Nothing extra to install alongside it.

Why Use the deb.griffo.io Repository?

  • A current fish rather than the version pinned by your Ubuntu release.
  • Easy installation and updates through APT, with no source build and no PPA.
  • No fish-common required because the runtime files live inside the executable.
  • Registered as a login shell automatically with add-shell, so chsh accepts it.
  • Works across supported Ubuntu releases, with the codename detected for you.

Prerequisites

Before starting, confirm you have:

  • An Ubuntu system (Jammy 22.04 LTS, Noble 24.04 LTS, or newer)
  • sudo privileges
  • curl installed (sudo apt install curl if needed)

The suggested extras are worth having too: xsel for clipboard integration, man-db so fish can generate completions from manuals, and python3 for a few helper functions.

Step 1: Add the deb.griffo.io Repository

Register the key and repository source:

# Create the keyrings directory
sudo install -d -m 0755 /etc/apt/keyrings

# Download and install the repository GPG key
curl -fsSL https://deb.griffo.io/EA0F721D231FDD3A0A17B9AC7808B4DD62C41256.asc | sudo gpg --dearmor --yes -o /etc/apt/keyrings/deb.griffo.io.gpg

# Add the repository (auto-detects your distro codename)
echo "deb [signed-by=/etc/apt/keyrings/deb.griffo.io.gpg] https://deb.griffo.io/apt $(lsb_release -sc 2>/dev/null) main" | sudo tee /etc/apt/sources.list.d/deb.griffo.io.list > /dev/null

# Update the package list
sudo apt update

Breaking it down:

  1. Create the keyrings directory - makes sure /etc/apt/keyrings exists with the right permissions.
  2. Install the GPG key - downloads and de-armours the repository key into its own keyring so APT can verify signatures.
  3. Add the repository - writes a signed-by source line, letting lsb_release -sc fill in your Ubuntu codename.
  4. Update the package list - refreshes APTโ€™s view of available packages.

Step 2: Update the Package List

If you did not run the final command above, do it now:

sudo apt update

Step 3: Install fish

Install with APT:

sudo apt install fish

The packaged version outranks the one in the Ubuntu archive, so APT prefers it, and an existing archive install is upgraded in place. On configure, the package runs add-shell /usr/bin/fish, adding it to /etc/shells so it can serve as a login shell.

Step 4: Verify the Installation

Check the version:

fish --version

You should see something like:

fish, version 4.8.1

And confirm it is a registered login shell:

grep fish /etc/shells

Getting Started with fish

Try It Without Switching Shells

There is no need to change your login shell to give fish a fair trial. Just run it:

fish

Start typing a command you have used before and the grey autosuggestion appears. โ†’ or Ctrl-F accepts all of it, Alt-โ†’ accepts a single word. exit drops you back into bash.

Making fish Your Login Shell

Once you are sold:

chsh -s /usr/bin/fish

Log out and back in to pick up the change; chsh -s /bin/bash reverses it. Scripts with their own shebang are unaffected, but tooling that appends bash snippets to ~/.bashrc (some language version managers do this) will need a fish equivalent instead.

Configuration

fish reads ~/.config/fish/config.fish at startup and auto-loads functions from ~/.config/fish/functions/:

# ~/.config/fish/config.fish

# Interactive sessions only
if status is-interactive
    set -gx EDITOR nvim
    alias ll 'eza -l --icons'
end

Variables use set, with -x to export and -U to persist universally across every fish session:

# Exported for this session and its children
set -gx EDITOR nvim

# Universal: stored permanently, no config file edit needed
set -Ux RIPGREP_CONFIG_PATH ~/.config/ripgrep/ripgreprc

# PATH is a real list; fish_add_path is idempotent
fish_add_path ~/.local/bin

Abbreviations Instead of Aliases

Abbreviations expand on the command line as you type, so you always see the real command and your history stays greppable:

abbr -a gco git checkout
abbr -a gst git status
abbr -a k kubectl

Type gst, press space, and the line becomes git status.

The Web Config UI

fish_config

That opens a local browser interface for colour schemes, prompts, functions, variables, abbreviations and key bindings, writing your selections back to disk. fish_config prompt stays in the terminal if you only want to pick a prompt.

Useful Interactive Bindings

โ†’  or Ctrl-F     accept the full autosuggestion
Alt-โ†’            accept one word of the suggestion
Alt-โ†  /  Alt-โ†’  (on an empty line) walk directory history
Alt-Up / Alt-Down  search history for the token under the cursor
Ctrl-R           interactive history search
Alt-E            edit the current command line in $EDITOR
Alt-S            prepend sudo to the previous command

Completions and Prompts

fish builds completions from your man pages, and you can regenerate them on demand:

fish_update_completions

If you would rather use a dedicated prompt engine, both of these are in the same repository and support fish:

# ~/.config/fish/config.fish
starship init fish | source
# or
oh-my-posh init fish | source

Keeping fish Updated

fish now upgrades with the rest of Ubuntu:

sudo apt update && sudo apt upgrade

When deb.griffo.io publishes a newer fish, apt upgrade picks it up along with your other packages.

Other Tools from deb.griffo.io

The repository has plenty that fits naturally into a fish setup:

  • Starship - a fast, customisable prompt with native fish support.
  • zoxide - a smarter cd, with first-class fish integration.
  • Atuin - searchable, synced shell history.
  • Nushell - a different take on the modern shell, if you like comparing.

Troubleshooting

GPG or Key Errors

If APT flags the repository as unsigned or the key as invalid, re-import it:

curl -fsSL https://deb.griffo.io/EA0F721D231FDD3A0A17B9AC7808B4DD62C41256.asc | sudo gpg --dearmor --yes -o /etc/apt/keyrings/deb.griffo.io.gpg
sudo apt update

Package Not Found

If APT cannot locate fish:

  1. Re-run sudo apt update after adding the repository.
  2. Verify your Ubuntu release is supported (Jammy, Noble, or newer).
  3. Check the source list: cat /etc/apt/sources.list.d/deb.griffo.io.list.

APT Chose the Ubuntu Archive Version

Inspect the candidates:

apt policy fish

If the archive version is preferred, request the repository build by version:

sudo apt install fish=4.8.1-1~noble

Substitute whatever version string apt policy reports for deb.griffo.io on your release.

A Leftover fish-common Package

Ubuntuโ€™s fish pulls in a separate fish-common data package. This build embeds those files, so after switching, the old data package may be left behind:

sudo apt autoremove

An Old PPA Still Wins

If you previously added the fish-shell PPA, it may outrank this repository. List your sources and disable the PPA if you no longer want it:

apt policy fish
sudo add-apt-repository --remove ppa:fish-shell/release-4
sudo apt update

chsh Rejects /usr/bin/fish

chsh only accepts shells listed in /etc/shells. The package adds the entry at install time, so if it has gone missing:

grep -q '^/usr/bin/fish$' /etc/shells || echo /usr/bin/fish | sudo tee -a /etc/shells

Uninstalling

Remove fish with:

sudo apt remove fish

If fish is your login shell, switch away first:

chsh -s /bin/bash

Removal runs remove-shell so /usr/bin/fish is taken out of /etc/shells automatically. To also remove the repository and key:

sudo rm /etc/apt/sources.list.d/deb.griffo.io.list
sudo rm /etc/apt/keyrings/deb.griffo.io.gpg
sudo apt update

Conclusion

The best argument for fish is how little you have to do to enjoy it. No plugin manager, no framework, no borrowed config: autosuggestions, highlighting and completions are on from the first prompt, and the scripting language stops fighting you the moment you need to write more than one line.

Installing it from deb.griffo.io on Ubuntu gives you a current, self-contained build that is already registered as a login shell and stays current with apt upgrade. Run it as a subshell for a week and see how often you go back.

Frequently Asked Questions

How do I install the latest fish on Ubuntu?

Add the deb.griffo.io APT repository and its signing key, then run sudo apt install fish. The repository tracks upstream fish releases, so you get the latest packaged version rather than a build frozen when your distribution was released.

Is there a .deb package for fish?

Yes. deb.griffo.io publishes fish as a signed .deb for Ubuntu. You could download that .deb and install it by hand, but adding the repository is the better option: APT then resolves dependencies and picks up new versions on its own.

How do I update fish to the latest version?

Run sudo apt update && sudo apt upgrade. Once fish is installed from APT there is no separate updater to remember, since new releases arrive with the rest of your system updates.

How do I install fish on Debian?

Exactly the same way; lsb_release -sc simply resolves to a different codename. There is a companion guide with the Debian specifics: How to install fish on Debian.

Which Ubuntu releases are supported?

Jammy 22.04 LTS, Noble 24.04 LTS and newer. Because the repository line is built from lsb_release -sc, the matching suite is selected for you.

Resources


Disclaimer: The deb.griffo.io repository is an unofficial community project and is not affiliated with the official Debian or Ubuntu projects, or with the upstream fish project.