How to Install and Use the Fish Shell
Install Fish shell on Linux, set it as your default, and learn abbreviations, autosuggestions, and how to migrate your bash habits in one practical guide.
Before you start
- ▸A working Linux installation with a terminal emulator
- ▸sudo or root access to install packages and edit /etc/shells
- ▸Basic familiarity with the command line (cd, ls, echo)
Fish (the Friendly Interactive SHell) is a modern shell that ships with syntax highlighting, autosuggestions, and tab completions out of the box — no plugins or configuration files required. If you spend time at a terminal, Fish will immediately make you faster. This guide covers installation, making Fish your default shell, its key features, and a practical path for bash users switching over.
Installing Fish
Debian and Ubuntu
Fish is in the official repos, but the version is often behind. Use the Fish project's own PPA on Ubuntu for the latest stable release.
sudo apt-add-repository ppa:fish-shell/release-3
sudo apt update
sudo apt install fish
On Debian, the official repo is usually fine:
sudo apt install fish
Fedora and RHEL / Rocky Linux
sudo dnf install fish
Arch Linux
sudo pacman -S fish
Verify the installed version:
fish --version
You should see something like fish, version 3.7.1. Fish 3.x is the current stable series; earlier versions are missing features covered here.
Making Fish Your Default Shell
Fish must be listed in /etc/shells before chsh will accept it. Most package managers add it automatically — confirm first:
grep fish /etc/shells
If the path is missing, add it:
which fish | sudo tee -a /etc/shells
Now change your login shell:
chsh -s $(which fish)
Log out and back in (or start a new login session). Your terminal emulator should now open Fish directly. Confirm with:
echo $SHELL
The output should be the full path to Fish, e.g. /usr/bin/fish.
Fish Defaults You Get Immediately
Unlike bash, Fish works well the moment you launch it. These features require zero configuration.
Syntax highlighting
As you type, valid commands appear in blue and invalid ones in red. File paths that exist are underlined. This eliminates a whole category of typo-driven errors before you press Enter.
Autosuggestions
Fish reads your command history and suggests completions in grey text as you type. Press → (right arrow) or End to accept a full suggestion. Press Alt+→ to accept a single word at a time. The suggestions are context-aware: Fish cycles through history entries that match your exact prefix.
Tab completions
Fish ships with completions for hundreds of common tools, generated in part from man pages. Press Tab once to complete, twice to see a menu. The menu is navigable with arrow keys — far more usable than bash's plain list.
The web-based configurator
Fish includes a browser UI for setting colours and viewing keybindings:
fish_config
This opens http://localhost:8000 in your default browser. Changes apply immediately and persist without editing any file manually. Close the server with Ctrl+C when done.
Fish Configuration Files
Fish does not use ~/.bashrc or ~/.profile. Its user config lives at:
~/.config/fish/config.fish
This file is sourced on every interactive shell start, equivalent to ~/.bashrc. Functions go in their own files under ~/.config/fish/functions/ — each file should be named after the function it defines (e.g. mkcd.fish for a function called mkcd). Fish lazy-loads these automatically.
Setting environment variables
Fish uses set, not export. To set a variable for the current session:
set -x MY_VAR "hello"
To make it permanent (universal, persists across sessions and survives reboots):
set -Ux MY_VAR "hello"
Universal variables are stored in ~/.config/fish/fish_variables, not in config.fish. Avoid setting universal variables inside config.fish — that re-sets them on every shell start, which is both redundant and occasionally causes bugs.
Abbreviations: Smarter Than Aliases
Fish abbreviations are the recommended replacement for bash aliases. When you type an abbreviation and press Space or Enter, Fish expands it inline so the real command appears in your history. This means you can audit history, share commands with others, and avoid the "what does that alias do?" mystery.
Creating an abbreviation
abbr --add gst 'git status'
Now typing gst and pressing Space expands to git status right in the command line before execution.
Making abbreviations permanent
The abbr --add command above persists automatically — Fish saves abbreviations as universal variables. You do not need to add them to config.fish. List all current abbreviations with:
abbr --list
Remove one with:
abbr --erase gst
Migrating from Bash
Fish is intentionally not POSIX-compatible, which is the source of nearly all confusion for bash migrants. Here are the most common adjustments.
Variable syntax
Bash uses $VAR and sets with VAR=value. Fish still reads $VAR but sets with set VAR value (no equals sign, no quotes required unless the value has spaces). Inline assignment like PORT=8080 ./server does not work in Fish; use:
env PORT=8080 ./server
Conditionals and loops
Bash uses [ ] and [[ ]]. Fish uses test or its built-in if/string/math commands. A simple example:
if test -f ~/.config/fish/config.fish
echo "config exists"
end
Running bash scripts
Your existing bash scripts do not need to change. Any script with a proper shebang (#!/usr/bin/env bash) runs fine from Fish. Fish only replaces your interactive shell — it has no effect on scripts invoked by their interpreter.
Sourcing bash environment variables
Some tools (nvm, rbenv, certain CI scripts) dump bash-syntax exports. The bass plugin from the Fisher plugin manager bridges this gap, but for most users the cleaner path is to re-export necessary variables using Fish's set -Ux after checking the tool's Fish-specific install notes.
PATH manipulation
In bash you append to PATH with string concatenation. Fish treats PATH as a list:
fish_add_path ~/.local/bin
This is idempotent — calling it twice will not duplicate the entry. It also persists automatically via universal variables.
Verification
Run through this short checklist after setup:
- Open a new terminal — you should see Fish's prompt (
~>by default). - Type a partial command from your history and confirm the grey autosuggestion appears.
- Type a non-existent command (e.g.
foobar) and confirm it renders in red. - Run
abbr --listand confirm your abbreviations are present. - Run
echo $SHELL— it should return the Fish binary path.
Troubleshooting
chsh: PAM authentication failure
This usually means your system's PAM stack is enforcing something (common on RHEL/Rocky with restricted configs). Try running chsh as root targeting your username: sudo chsh -s $(which fish) yourusername. Alternatively, configure your terminal emulator to launch Fish directly without changing the login shell.
Environment variables from /etc/environment or .profile are missing
Fish does not source bash login files. Variables set system-wide in /etc/environment are still read by PAM and will be available. Variables set only in ~/.bash_profile will not. Re-export them via set -Ux in Fish or add them to ~/.config/fish/config.fish.
Autosuggestions not appearing
Autosuggestions draw from history. If your history file is empty (fresh install), they will not appear yet. Also confirm your terminal emulator supports the correct escape sequences for colour — most modern terminals do, but some minimal ones do not render Fish's highlighting correctly.
Frequently asked questions
- Is Fish POSIX-compatible?
- No, and intentionally so. Fish's syntax is cleaner but differs from POSIX sh. Your existing bash scripts are unaffected as long as they have a proper shebang line — Fish only changes your interactive shell.
- Can I use Fish without making it my default shell?
- Yes. Simply type fish from any bash session to start it interactively, or configure your terminal emulator to run fish directly as the startup command without touching your login shell.
- What is the difference between Fish aliases and abbreviations?
- Aliases execute silently under a short name, so your history records the alias not the real command. Abbreviations expand in-place before execution, keeping your history clean and commands portable.
- How do I install Fish plugins?
- The most popular plugin manager is Fisher (github.com/jorgebucaran/fisher). Install it with a single curl command from its README, then use fisher install to add plugins. Many tools like Tide (a prompt) and z (directory jumping) have native Fish support.
- Will tools like nvm or pyenv work in Fish?
- Most have Fish-specific install instructions — check the tool's documentation for a fish block. If a tool only provides bash eval-style setup, the bass plugin can source it, but native Fish integrations are cleaner and more reliable.
Related guides
Linux Clipboards Explained (+ Clipboard Managers)
Learn the difference between Linux's PRIMARY and CLIPBOARD selections, use xclip, xsel, and wl-clipboard from the terminal, and manage history with GPaste or Klipper.
Configure LibreOffice for Daily Use
Configure LibreOffice for daily use: set default save formats for MS Office interop, tune autosave, install fonts, and add productivity extensions.
Configure the Touchpad and Multitouch Gestures
Configure Linux touchpad behavior and multitouch gestures using libinput, libinput-gestures, and native GNOME and KDE Plasma settings on both Wayland and X11.
Wayland vs X11: How to Choose and Configure Each
Know when to run Wayland or X11, how to check your current session, switch at login with GDM/SDDM/LightDM, and handle NVIDIA and XWayland edge cases.