$linuxjunkies
>

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.

BeginnerUbuntuDebianFedoraArch8 min readUpdated June 7, 2026

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 --list and 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.

tested on:Ubuntu 24.04Fedora 40Arch rollingDebian 12

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