How to Install fish on Debian: The Friendly Interactive Shell
fish, the friendly interactive shell, is built on a simple premise: the good stuff should work without configuration. Open a fresh fish and you already have autosuggestions from your history, syntax highlighting as you type, tab completions generated from your system’s man pages, and a scripting language without the arcane quoting rules that make POSIX shells a minefield.
That last point matters more than it sounds. In fish, set files (ls) gives you a real list, $var never word-splits behind your back, and command substitution does not require defensive quoting. It is not POSIX compatible, and that is a deliberate design decision: fish is an interactive shell first, and it is willing to break with tradition to be a better one.
Since fish 4.0 the shell is written in Rust, and the functions and completions that used to be shipped as data files are embedded in the executable. Debian carries fish in the archive, but a stable release freezes the version for years while upstream keeps shipping improvements.
The unofficial deb.griffo.io repository packages the upstream statically linked musl build as a proper Debian .deb. It needs no fish-common data package and no shared libraries at runtime, and it registers itself as a valid login shell on install.
Install the Latest fish on Debian: The Short Version
If you only came for the commands, this adds the repository and installs the latest fish .deb package on Debian:
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 - As you type, fish proposes the rest of the command from your history and completions; press
→to accept. - 🎨 Syntax highlighting as you type - Invalid commands and unmatched quotes turn red before you ever hit enter.
- 📖 Completions from man pages - fish parses your installed manuals, so third-party tools get option completion for free.
- 🧠 Sane scripting - Real lists, no word splitting, no
IFSsurprises, and a consistentset-based variable model. - 🌈 Web-based configuration -
fish_configopens a browser UI for prompts, colours, functions and bindings. - ⌨️ Rich interactive editing - Multi-line editing, abbreviations that expand in place, and
Alt-←/Alt-→directory history. - 🦀 Rust rewrite - fish 4.0 and later are Rust, with the runtime data baked into the binary.
- 📦 Single static binary - This build depends on nothing at runtime.
Why Use the deb.griffo.io Repository?
- A current fish rather than the version frozen into your Debian release.
- Easy installation and updates through APT, no building from source.
- No
fish-commonneeded because the runtime files are embedded in the executable. - Registered as a login shell automatically via
add-shell, sochshaccepts it. - Works across supported Debian releases, with the codename detected automatically.
Prerequisites
Before you start, make sure you have:
- A Debian-based system (Bookworm 12, Trixie 13, Forky, or Sid)
sudoprivilegescurlinstalled (sudo apt install curlif needed)
Optionally, install the suggested extras: xsel for clipboard integration, man-db so fish can build completions from man pages, and python3 for a handful of helper functions.
Step 1: Add the deb.griffo.io Repository
Add the signing 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
What each command does:
- Create the keyrings directory - ensures
/etc/apt/keyringsexists with proper permissions. - Install the GPG key - downloads the repository key and de-armours it into a dedicated keyring for verification.
- Add the repository - writes a
signed-bysource line, withlsb_release -scsupplying your Debian codename. - Update the package list - refreshes APT so it knows about the new packages.
Step 2: Update the Package List
If you skipped the last line, run the update now:
sudo apt update
Step 3: Install fish
Install fish with APT:
sudo apt install fish
The package version is higher than the one in the Debian archive, so APT prefers it. If the archive’s fish is already installed, this upgrades it in place. The post-install script calls add-shell /usr/bin/fish, which registers fish in /etc/shells so it can be used as a login shell.
Step 4: Verify the Installation
Check the version:
fish --version
You should see output similar to:
fish, version 4.8.1
Confirm it is registered as a login shell:
grep fish /etc/shells
Getting Started with fish
Try It Without Committing
You do not need to change your login shell to use fish. Just start it:
fish
Type a command you have run before and watch the grey autosuggestion appear. Press → or Ctrl-F to accept the whole thing, or Alt-→ to accept a word at a time. exit returns you to your previous shell.
Making fish Your Login Shell
When you are convinced:
chsh -s /usr/bin/fish
Log out and back in for the change to take effect. To go back to bash later, chsh -s /bin/bash.
A word of caution: scripts with a #!/bin/sh or #!/bin/bash shebang are unaffected, but anything that assumes your interactive shell is POSIX (some installers append export PATH=... to ~/.bashrc, for example) will need a fish equivalent.
Configuration
fish reads ~/.config/fish/config.fish on startup, and auto-loads functions from ~/.config/fish/functions/:
# ~/.config/fish/config.fish
# Only for interactive sessions
if status is-interactive
set -gx EDITOR nvim
alias ll 'eza -l --icons'
end
Environment variables use set, with -x to export and -U to make them universal (persisted across sessions, no config file needed):
# Exported for this session and children
set -gx EDITOR nvim
# Universal: saved permanently, available in every fish
set -Ux RIPGREP_CONFIG_PATH ~/.config/ripgrep/ripgreprc
# PATH is a real list; prepend with fish_add_path
fish_add_path ~/.local/bin
fish_add_path is the idiomatic way to extend PATH: it is idempotent, so re-running it never duplicates entries.
Abbreviations Instead of Aliases
Abbreviations expand in place as you type, so you see the real command before running it, and your history stays readable:
abbr -a gco git checkout
abbr -a gst git status
abbr -a k kubectl
Type gst then space, and it becomes git status right there on the command line.
The Web Config UI
fish_config
This opens a local web interface for browsing colour schemes, prompts, functions, variables, abbreviations and key bindings, and it writes your choices back to disk. To only pick a prompt, fish_config prompt works from the terminal.
Useful Interactive Bindings
→ or Ctrl-F accept the full autosuggestion
Alt-→ accept one word of the suggestion
Alt-← / Alt-→ (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 last command
Completions and Prompts
fish generates completions from your man pages the first time it needs them, and you can refresh them explicitly:
fish_update_completions
If you prefer an external prompt engine, both of these are packaged in the same repository and work with fish:
# ~/.config/fish/config.fish
starship init fish | source
# or
oh-my-posh init fish | source
Keeping fish Updated
Because fish arrived via APT, updates come with the rest of the system:
sudo apt update && sudo apt upgrade
Whenever deb.griffo.io ships a newer fish, apt upgrade installs it automatically.
Other Tools from deb.griffo.io
The repository packages plenty of tools that feel at home in a fish session:
- Starship - a fast, customisable prompt that supports fish natively.
- zoxide - a smarter
cdwith first-class fish integration. - Atuin - searchable, synced shell history.
- Nushell - another modern shell, if you want to compare approaches.
Troubleshooting
GPG or Key Errors
If APT reports an unsigned repository or an invalid key, import it again:
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 see the fish package:
- Re-run
sudo apt updateafter adding the repository. - Confirm your release is supported (Bookworm, Trixie, Forky, or Sid).
- Inspect the source list:
cat /etc/apt/sources.list.d/deb.griffo.io.list.
APT Installed the Archive Version Instead
Compare the candidates:
apt policy fish
If the Debian archive version wins, ask for the repository one by version:
sudo apt install fish=4.8.1-1~trixie
Use whichever version string apt policy lists for deb.griffo.io on your release.
A Leftover fish-common Package
The archive’s fish depends on a separate fish-common data package; this build does not, because those files are inside the binary. After switching, fish-common may sit around unused:
sudo apt autoremove
chsh Rejects /usr/bin/fish
chsh only accepts shells listed in /etc/shells. The package adds the entry on install, so if it is missing, add it back:
grep -q '^/usr/bin/fish$' /etc/shells || echo /usr/bin/fish | sudo tee -a /etc/shells
Something Expects bash Syntax
If a tool’s installer writes bash into your shell config and fails, run it under bash explicitly (bash -lc '...') and translate the resulting export lines into set -gx or fish_add_path in config.fish.
Uninstalling
Remove fish with:
sudo apt remove fish
If fish is your login shell, switch back before removing it:
chsh -s /bin/bash
The package’s removal script calls remove-shell to take /usr/bin/fish out of /etc/shells for you. To also drop 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
fish is the rare tool where the defaults are the selling point. There is no plugin framework to install and no 300-line dotfile to copy from a stranger: autosuggestions, highlighting and completions are simply there the first time you open it, and the scripting language stays out of your way when you do want to write something.
Installing it from deb.griffo.io on Debian gets you a current, self-contained build that is registered as a login shell and updated with a plain apt upgrade. Start it as a subshell for a week, and see whether you ever go back.
Frequently Asked Questions
How do I install the latest fish on Debian?
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 Debian. 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 Ubuntu?
Exactly the same way; lsb_release -sc simply resolves to a different codename. There is a companion guide with the Ubuntu specifics: How to install fish on Ubuntu.
Which Debian releases are supported?
Bookworm 12, Trixie 13, Forky and Sid. 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.