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
IFSlandmines, one consistentsetmodel for variables. - ๐ Web-based configuration -
fish_configopens 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-commonrequired because the runtime files live inside the executable. - Registered as a login shell automatically with
add-shell, sochshaccepts 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)
sudoprivilegescurlinstalled (sudo apt install curlif 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:
- Create the keyrings directory - makes sure
/etc/apt/keyringsexists with the right permissions. - Install the GPG key - downloads and de-armours the repository key into its own keyring so APT can verify signatures.
- Add the repository - writes a
signed-bysource line, lettinglsb_release -scfill in your Ubuntu codename. - 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:
- Re-run
sudo apt updateafter adding the repository. - Verify your Ubuntu release is supported (Jammy, Noble, or newer).
- 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
- fish Website
- fish Documentation
- fish GitHub Repository
- deb.griffo.io Repository
- Install guide on deb.griffo.io
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.