How to Install Fish Shell on Ubuntu 26.04, 24.04 and 22.04

Install Fish Shell on Ubuntu 26.04, 24.04, and 22.04 with the Ubuntu package, release-4 PPA, or GitHub binary, plus default-shell setup and updates.

PublishedAuthorJoshua JamesRead time7 minGuide typeUbuntu

A faster interactive shell matters most once command history, completions, and prompt context start doing real work. To install Fish Shell on Ubuntu, choose the Ubuntu repository package for low maintenance, the Fish Shell release-4 PPA for the current 4.x branch, or an official standalone GitHub binary managed by a repeatable update helper.

Ubuntu keeps Bash as the default login shell until you change it with chsh. Fish can handle your interactive terminal while Bash scripts keep using their own shebangs, so the workflow separates installation, default-shell changes, first-use configuration, updates, and removal.

Install Fish Shell on Ubuntu

Choose a Fish Shell Installation Method on Ubuntu

Choose the method that matches how you want Fish updated. The Ubuntu package is the lowest-maintenance option, the release-4 PPA keeps Fish package-managed while tracking the newer major branch, and the standalone binary avoids APT package changes but needs the update helper.

MethodSourceUpdate behaviorBest for
Ubuntu repositoryUbuntu universe packageapt upgradeRepository package with minimal maintenance
Fish release-4 PPAFish Shell release-4 PPAapt upgradeNewer Fish 4.x package while staying inside APT
Standalone GitHub binaryFish Shell GitHub releasesupdate-fish-standaloneManual install under /opt with a stable /usr/local/bin/fish launcher

The Ubuntu repository package comes from universe. If a minimal system cannot find the package, enable the component with the Ubuntu Universe repository workflow before retrying the install.

Update Ubuntu Before Installing Fish Shell

Refresh the package index first so Ubuntu uses current repository metadata for packages, dependencies, and PPA setup tools.

sudo apt update

Most commands require sudo privileges. If your account cannot run sudo, configure an administrative user first with the Ubuntu sudoers workflow.

Install Fish Shell from Ubuntu Repositories

Use the Ubuntu repository package when you want Fish maintained entirely through the standard Ubuntu archive. This method installs fish and fish-common from the enabled Ubuntu release.

sudo apt install fish

Check the installed version after APT finishes.

fish --version
fish, version 4.2.1

The exact version depends on your Ubuntu release. Current repository candidates are Fish 4.2.1 on Ubuntu 26.04, Fish 3.7.0 on Ubuntu 24.04, and Fish 3.3.1 on Ubuntu 22.04. Use the PPA method when you want the current Fish 4.x branch through APT.

Install Fish Shell from the Release-4 PPA

Use the release-4 PPA when you want a newer Fish 4.x package and still want APT to handle upgrades and removal. The PPA currently publishes Fish 4.x packages for Ubuntu 26.04, 24.04, and 22.04, while the Ubuntu archive package remains visible as a fallback candidate.

Install the repository helper package if your system does not already have it.

sudo apt install software-properties-common

Add the Fish Shell release-4 PPA, then refresh APT metadata.

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

Confirm that the Fish candidate comes from the PPA before installing.

apt-cache policy fish
fish:
  Installed: (none)
  Candidate: 4.7.1-1~resolute
  Version table:
     4.7.1-1~resolute 500
        500 https://ppa.launchpadcontent.net/fish-shell/release-4/ubuntu resolute/main amd64 Packages
     4.2.1-3.2 500
        500 http://archive.ubuntu.com/ubuntu resolute/universe amd64 Packages

Install Fish from the newly added PPA.

sudo apt install fish

Verify the installed shell version.

fish --version
fish, version 4.7.1

Install Standalone Fish Binary from GitHub Releases

Use the standalone method when you want Fish installed outside APT under /opt/fish-shell. The helper resolves the latest stable release from the Fish Shell GitHub repository, installs the official Linux binary for x86_64 or aarch64, updates a stable launcher at /usr/local/bin/fish, registers that launcher in /etc/shells, and creates a reusable update-fish-standalone command.

Use one Fish method at a time. On most Ubuntu PATH layouts, /usr/local/bin/fish from the standalone method is found before /usr/bin/fish from APT. The standalone binary release assets do not include separate checksum or signature files; use the signed source tarball from the Fish release page if your environment requires source-level cryptographic verification.

Install the download and archive tools used by the helper. For more detail on the download flags used here, review the curl command examples.

sudo apt install curl tar xz-utils

Write the updater into /usr/local/bin so the repeat command is available from any terminal directory.

sudo tee /usr/local/bin/update-fish-standalone > /dev/null <<'SCRIPT_EOF'
#!/usr/bin/env bash
set -euo pipefail

REPO="fish-shell/fish-shell"
INSTALL_ROOT="/opt/fish-shell"
CURRENT_LINK="${INSTALL_ROOT}/current"
BIN_LINK="/usr/local/bin/fish"
TMP_DIR="$(mktemp -d)"
trap 'rm -rf "$TMP_DIR"' EXIT

need_cmds=(curl grep install ln mktemp readlink sed sudo tar uname xz)
for cmd in "${need_cmds[@]}"; do
  if ! command -v "$cmd" >/dev/null 2>&1; then
    echo "Error: $cmd is required but not installed." >&2
    echo "Run: sudo apt install curl tar xz-utils" >&2
    exit 1
  fi
done

case "$(uname -m)" in
  x86_64|amd64)
    asset_arch="x86_64"
    ;;
  aarch64|arm64)
    asset_arch="aarch64"
    ;;
  *)
    echo "Unsupported CPU architecture: $(uname -m)" >&2
    exit 1
    ;;
esac

latest_url="$(curl -fsSLI -o /dev/null -w '%{url_effective}' "https://github.com/${REPO}/releases/latest")"
latest_version="${latest_url##*/}"
latest_version="${latest_version#v}"

case "$latest_version" in
  [0-9]*.[0-9]*.[0-9]*)
    ;;
  *)
    echo "Could not resolve a stable Fish release from ${latest_url}" >&2
    exit 1
    ;;
esac

current_version="none"
if [ -x "$CURRENT_LINK/bin/fish" ]; then
  current_version="$("$CURRENT_LINK/bin/fish" --version | sed -n 's/^fish, version //p')"
fi

echo "Current version: $current_version"
echo "Latest version:  $latest_version"

if [ "$current_version" = "$latest_version" ] && [ -L "$BIN_LINK" ]; then
  echo "Already up to date."
  exit 0
fi

archive="fish-${latest_version}-linux-${asset_arch}.tar.xz"
download_url="https://github.com/${REPO}/releases/download/${latest_version}/${archive}"
staging="${TMP_DIR}/fish"

echo "Downloading: $archive"
curl -fsSL -o "${TMP_DIR}/${archive}" "$download_url"
mkdir -p "$staging"
tar -xJf "${TMP_DIR}/${archive}" -C "$staging"

if [ ! -x "${staging}/fish" ]; then
  echo "Downloaded archive did not contain an executable fish binary." >&2
  exit 1
fi

target="${INSTALL_ROOT}/fish-${latest_version}"
echo "Installing Fish $latest_version."
sudo install -d -m 0755 "$target/bin"
sudo install -m 0755 "${staging}/fish" "$target/bin/fish"

if [ -e "$BIN_LINK" ] && [ ! -L "$BIN_LINK" ]; then
  echo "Error: $BIN_LINK exists and is not a symlink. Move it before continuing." >&2
  exit 1
fi

if [ -L "$BIN_LINK" ]; then
  link_target="$(readlink -f "$BIN_LINK")"
  case "$link_target" in
    "$INSTALL_ROOT"/*)
      ;;
    *)
      echo "Error: $BIN_LINK points outside $INSTALL_ROOT: $link_target" >&2
      exit 1
      ;;
  esac
fi

sudo ln -sfn "$target" "$CURRENT_LINK"
sudo ln -sfn "$CURRENT_LINK/bin/fish" "$BIN_LINK"

if ! grep -qxF "$BIN_LINK" /etc/shells; then
  printf '%s\n' "$BIN_LINK" | sudo tee -a /etc/shells >/dev/null
fi

"$BIN_LINK" --version
"$BIN_LINK" -c 'echo "Fish standalone install is ready."'
echo "Standalone Fish is installed at $BIN_LINK."
SCRIPT_EOF

Make the helper executable, then confirm your shell can find it.

sudo chmod 0755 /usr/local/bin/update-fish-standalone
command -v update-fish-standalone
/usr/local/bin/update-fish-standalone

Since the helper lives in /usr/local/bin, run it by name when you install Fish or check for standalone updates later.

update-fish-standalone

The first run downloads the latest stable Fish binary, installs it under /opt/fish-shell, and connects the stable /usr/local/bin/fish launcher.

Current version: none
Latest version:  4.7.1
Downloading: fish-4.7.1-linux-x86_64.tar.xz
Installing Fish 4.7.1.
fish, version 4.7.1
Fish standalone install is ready.
Standalone Fish is installed at /usr/local/bin/fish.

A later run exits cleanly when the installed standalone release already matches the latest GitHub release.

update-fish-standalone
Current version: 4.7.1
Latest version:  4.7.1
Already up to date.

Confirm the active launcher path and version.

command -v fish
fish --version
/usr/local/bin/fish
fish, version 4.7.1

Start Fish Shell and Set It as Default on Ubuntu

A shell is the program that reads your interactive terminal commands. Ubuntu opens Bash by default for most users, but you can start Fish manually at any time before changing your login shell.

fish

Leave the Fish session with exit when you want to return to the parent shell.

exit

Check which Fish executable your terminal finds. APT and PPA installs normally resolve to /usr/bin/fish, while the standalone method resolves to /usr/local/bin/fish.

command -v fish
/usr/bin/fish

Before Fish can become a login shell, its path must be listed in /etc/shells. Register the path only if it is missing.

FISH_PATH="$(command -v fish)"
grep -qxF "$FISH_PATH" /etc/shells || printf '%s\n' "$FISH_PATH" | sudo tee -a /etc/shells >/dev/null

Set Fish as your login shell.

chsh -s "$(command -v fish)"

Log out and back in, then verify the shell field for your account.

getent passwd "$USER" | cut -d: -f7
/usr/bin/fish

Fish is excellent for interactive use, but it is not a POSIX sh replacement. Do not point /bin/sh at Fish, and do not rewrite system scripts just because your login shell changed. Scripts that start with #!/bin/bash keep running with Bash.

Get Started with Fish Shell on Ubuntu

Use Suggestions, Completions, and History Search

Fish highlights commands as you type, suggests commands from history, and expands many completions without extra plugin setup. Type part of a previous command, accept a visible suggestion with the right arrow key, or press Tab to browse completions for commands, options, files, Git branches, package names, and many common tools.

These features are interactive, so the fastest check is to start Fish and type a command fragment that already exists in your history, such as sudo apt or git. Fish shows suggestions in muted text and colors invalid command names differently from valid commands.

Open Fish Help and Web Configuration

Fish includes local help and a web-based configuration tool. From a Fish prompt, use the official Fish tutorial and Fish documentation when you want deeper details on syntax, functions, completions, and prompt customization.

help
fish_config

The fish_config command can help browse prompts, themes, functions, and variables from a local web interface. On a desktop session it opens in your browser; on a server, use the terminal output and documentation link it prints.

Create a Fish Configuration File

Fish reads user startup configuration from ~/.config/fish/config.fish. Create the directory and open the file when you want commands to run each time an interactive Fish session starts.

mkdir -p "$HOME/.config/fish"
nano "$HOME/.config/fish/config.fish"

A small starting file can keep simple aliases behind Fish’s interactive-session check.

if status is-interactive
    alias ll='ls -lah'
end

Reload the file in the current Fish session after saving changes.

source "$HOME/.config/fish/config.fish"

Set Persistent Fish Preferences

Fish also supports universal variables and abbreviations that persist without editing config.fish. Run these examples from a Fish prompt, then adjust them for your own editor, PATH entries, and common commands.

set -Ux EDITOR nano
fish_add_path "$HOME/.local/bin"
abbr -a gs git status
abbr -a ga git add
abbr -a gc git commit
set -U fish_greeting

Abbreviations expand before execution, so gs becomes git status on the command line. If you use Git heavily, install Git first with the Git on Ubuntu guide so completions and examples match your workflow.

Move Bash Customizations Carefully

Fish does not read ~/.bashrc, and complex Bash functions usually need Fish syntax before they work. Move simple aliases gradually, convert frequently typed commands into abbreviations, and keep project scripts with their original #!/bin/bash or #!/usr/bin/env bash shebangs when they rely on Bash behavior.

Update Fish Shell on Ubuntu

Update APT or PPA Fish Packages

If you installed Fish from Ubuntu repositories or the release-4 PPA, normal APT upgrades include Fish updates. To check Fish directly, refresh APT metadata and upgrade only the Fish packages.

sudo apt update
sudo apt install --only-upgrade fish fish-common

Update Standalone Fish Binary

If you installed the standalone GitHub binary, rerun the helper. It resolves the latest stable release, replaces the current symlink only after a successful download and install, and exits without changes when the installed version already matches GitHub.

update-fish-standalone

Troubleshoot Fish Shell on Ubuntu

APT Cannot Locate the fish Package

If APT cannot find fish, the universe component may be disabled on a minimal or custom image.

E: Unable to locate package fish

Enable universe, refresh package metadata, and retry the install.

sudo apt install software-properties-common
sudo add-apt-repository -y universe
sudo apt update
sudo apt install fish

chsh Reports an Invalid Shell

The chsh command rejects shell paths that are missing from /etc/shells. This is most common after manual installs.

chsh: /usr/local/bin/fish is an invalid shell

Register the active Fish path, then rerun chsh.

FISH_PATH="$(command -v fish)"
grep -qxF "$FISH_PATH" /etc/shells || printf '%s\n' "$FISH_PATH" | sudo tee -a /etc/shells >/dev/null
chsh -s "$FISH_PATH"

Bash Commands from .bashrc Do Not Work in Fish

Fish uses its own scripting language. Simple aliases may be easy to recreate, but Bash-specific functions, arrays, parameter expansion, and prompt logic often need a Fish rewrite. Keep a terminal open with Bash while migrating important aliases so you can compare behavior before making Fish your default shell.

Standalone Installer Cannot Find curl

The helper checks its required commands before downloading Fish. Install the missing tools if it reports a dependency error.

Error: curl is required but not installed.
Run: sudo apt install curl tar xz-utils
sudo apt install curl tar xz-utils

Remove Fish Shell from Ubuntu

Restore Bash Before Removing Fish

If Fish is your login shell, switch back to Bash before removing the Fish binary. Log out and back in after changing the shell.

chsh -s /bin/bash

Confirm that your account now points to Bash.

getent passwd "$USER" | cut -d: -f7
/bin/bash

Remove APT or PPA Fish Packages

Remove Fish packages installed from Ubuntu repositories or the release-4 PPA.

sudo apt remove fish fish-common

Preview dependencies that APT no longer needs, then run the cleanup only after the package list looks safe for your system.

sudo apt autoremove --dry-run
sudo apt autoremove

If you added the release-4 PPA, remove it and refresh package metadata. The Ubuntu PPA removal guide covers additional cleanup options for systems with many third-party repositories.

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

Verify that the APT packages are no longer installed.

dpkg -l fish fish-common 2>/dev/null | grep '^ii' || echo "fish packages are not installed"
fish packages are not installed

Remove Standalone Fish Binary

Removing standalone Fish deletes /opt/fish-shell, removes the /usr/local/bin/fish launcher, removes the helper script, and deletes the standalone shell entry from /etc/shells. It does not delete your user Fish configuration.

Preview the standalone paths before deleting them.

ls -ld /opt/fish-shell 2>/dev/null || true
ls -l /usr/local/bin/fish 2>/dev/null || true
ls -l /usr/local/bin/update-fish-standalone 2>/dev/null || true

Remove the standalone install and clear the shell command cache for the current terminal.

sudo rm -rf /opt/fish-shell
sudo rm -f /usr/local/bin/fish /usr/local/bin/update-fish-standalone
sudo sed -i '\#^/usr/local/bin/fish$#d' /etc/shells
hash -r
test ! -e /usr/local/bin/fish && echo "standalone Fish launcher removed"
command -v update-fish-standalone || echo "update-fish-standalone command not found"

Remove Fish User Configuration

Only remove user configuration when you want a full Fish reset. This deletes your Fish startup file, functions, completions, history, and universal variable data.

Review the user-level Fish directories first.

find "$HOME/.config" "$HOME/.local/share" "$HOME/.cache" -maxdepth 1 -type d -name fish -print 2>/dev/null

Delete the user-level Fish directories only after confirming that you no longer need them.

rm -rf "$HOME/.config/fish" "$HOME/.local/share/fish" "$HOME/.cache/fish"

Conclusion

Fish Shell is ready as an interactive shell through Ubuntu’s package manager, the Fish release-4 PPA, or a standalone GitHub binary with a repeatable updater. Start Fish manually before changing your login shell, then migrate aliases, abbreviations, and prompt changes gradually so existing Bash scripts keep their expected behavior.

Share this guide

Help another Linux user troubleshoot faster

Share this guide with someone troubleshooting Linux systems or saving it for later.

Follow LinuxCapable

Want more LinuxCapable guides in Google?

Add LinuxCapable as a preferred source so Google can show more of our fresh Linux tutorials in Top Stories and From your sources when relevant.

Add LinuxCapable as a preferred source on Google
Search LinuxCapable

Need another guide?

Search LinuxCapable for package installs, commands, troubleshooting, and follow-up guides related to what you just read.

Found this guide useful?

Support LinuxCapable to keep tutorials free and up to date.

Buy me a coffeeBuy me a coffee
Before commenting, please review our Comments Policy.
Formatting tips for your comment

You can use basic HTML to format your comment. Useful tags currently allowed in published comments:

You type Result
<code>command</code> command
<strong>bold</strong> bold
<em>italic</em> italic
<blockquote>quote</blockquote> quote block

Got a Question or Feedback?

We read and reply to every comment - let us know how we can help or improve this guide.

Verify before posting: