Fish Shell vs Zsh - Which Should You Choose?

A practical comparison of Fish Shell and Zsh for daily terminal use, covering autocompletion, plugins, scripting, configuration, and which shell fits your workflow.

Fish Shell vs Zsh - Which Should You Choose?

I used Zsh with Oh My Zsh for about three years before switching to Fish. Both are big upgrades over Bash, but they take different approaches to getting there. Zsh gives you a POSIX-compatible shell that you build up with plugins. Fish gives you a polished experience from the first launch but breaks with POSIX conventions.

If you want to see how all three shells compare, check my Fish vs Bash vs Zsh comparison. This article goes deeper on just Fish and Zsh.

Out-of-the-box experience

This is where Fish and Zsh differ most.

Fish gives you autosuggestions, syntax highlighting, rich tab completions, and man page parsing from a fresh install. You open a terminal and everything works. No configuration, no plugins, no framework.

Zsh out of the box is… plain. It’s a step above Bash, with better globbing and some built-in features, but the experience most people associate with Zsh comes from Oh My Zsh and plugins. You need to install zsh-autosuggestions for history-based suggestions and zsh-syntax-highlighting for command coloring.

If you care about time-to-productive, Fish wins by a wide margin. You trade configuration flexibility for a shell that just works.

Autosuggestions

Both shells can show inline suggestions from your command history as you type. The difference is that Fish does it by default and Zsh needs a plugin.

In Fish, press the right arrow to accept the full suggestion or Alt+Right to accept one word at a time. Fish also blends history suggestions with file path and command completions. I go into more detail in my Fish Shell autocomplete and suggestions guide.

In Zsh with zsh-autosuggestions, the behavior is similar but can feel slightly less polished. The plugin sometimes conflicts with other completions or themes, and you may need to tweak your configuration to get it working smoothly.

Tab completions

Fish’s tab completion system is more sophisticated out of the box. It reads man pages and generates completions automatically, so commands you’ve never configured still get useful tab results. Type rsync -- and press tab, and you’ll see all available flags with descriptions.

Fish also displays completions in a pager-style list with descriptions next to each option. You navigate with arrow keys and press enter to select.

Zsh has a powerful completion system too (compinit plus zstyle configuration), and it can match Fish once properly configured. But “properly configured” is the key phrase. Most Zsh users rely on Oh My Zsh or frameworks to handle this, and even then it’s rarely as complete as what Fish generates from man pages.

Syntax

This is the real decision point for many people.

Zsh is largely POSIX-compatible. Bash scripts run in Zsh with minimal changes, and Zsh scripts look almost identical to Bash:

# Zsh
export MY_VAR="hello"
if [[ -f "$HOME/.zshrc" ]]; then
    source "$HOME/.zshrc"
fi
my_list=("one" "two" "three")
for item in "${my_list[@]}"; do
    echo "$item"
done

Fish has its own syntax. It’s arguably cleaner, but it’s different:

# Fish
set -gx MY_VAR "hello"
if test -f ~/.config/fish/config.fish
    source ~/.config/fish/config.fish
end
set my_list one two three
for item in $my_list
    echo $item
end

The Fish version has less punctuation. No [[ ]], no do/done, no semicolons, no ${}-style variable expansion. Variables are just $name, lists don’t need quotes around each element, and blocks end with end instead of fi/done/esac.

The trade-off: you can’t paste Bash commands directly. Things like export VAR=value (use set -gx VAR value), $(command) for command substitution (use (command)), and && between commands (use ; and or && since Fish 3.0 added support) need adjustment.

Fish does support && now

Fish 3.0 added && and || support. So command1 && command2 works. Older guides that say otherwise are outdated.

Plugin ecosystem

Zsh has the larger ecosystem thanks to Oh My Zsh, which has been around since 2009. There are 300+ bundled plugins, 150+ themes, and a massive community. Alternative managers like zinit, antigen, and zplug offer faster loading. I have a list of the best Oh My Zsh plugins if you’re interested.

Fish has a smaller but focused ecosystem. Fisher is the recommended plugin manager, it’s fast and stays out of your way. Popular plugins include Tide (a prompt), fzf.fish (fuzzy search integration), and nvm.fish (Node version management). I cover these in best Fish Shell plugins and tools.

Oh My Fish exists as an alternative framework, but it’s been unmaintained for a while. Fisher is the way to go. If you’re still curious about OMF, see my Oh My Fish guide.

One thing worth noting: Fish needs fewer plugins to begin with. Features that require a Zsh plugin (autosuggestions, syntax highlighting, good completions) are built into Fish. So while Zsh has more plugins available, Fish users need fewer of them.

Configuration complexity

Zsh configuration can get involved. A typical .zshrc with Oh My Zsh includes theme selection, plugin lists, custom aliases, path configuration, and framework settings. It’s not uncommon to end up with a 100-line .zshrc. Oh My Zsh also adds measurable startup time, especially with many plugins enabled.

Fish configuration tends to be shorter. Your ~/.config/fish/config.fish might just have path additions and some abbreviations. Fish also supports conf.d/ for splitting config into separate files, and the fish_config web interface lets you change colors and prompts without editing files.

Fish’s abbreviation system also reduces what you put in config files. Instead of defining shell functions for common commands, you add abbreviations that expand inline.

Prompt customization

Zsh themes through Oh My Zsh give you quick prompt changes. Powerlevel10k is the most popular option, it’s fast and has a configuration wizard. You can also use Starship, which I covered in my Starship and Ghostty guide.

Fish has Tide as its native prompt option, with a similar configuration wizard to Powerlevel10k. Starship also works with Fish. I wrote a guide on setting up Starship with Fish Shell, and a broader Fish Shell themes and prompts comparison covering Tide, Starship, Pure, and Hydro.

Both shells work well with Starship if you want a consistent prompt across shells.

Scripting

If you write automation scripts that need to run on different systems, Zsh (or Bash) is the safer choice. Zsh scripts run on macOS (where Zsh is the default shell) and most Linux systems with Zsh installed. Bash scripts run everywhere.

Fish scripts only run in Fish. For automation, I keep my scripts as Bash files with #!/bin/bash shebangs and run them from Fish. This is the standard recommendation in the Fish community. Fish is meant to be your interactive shell, not necessarily your scripting language for portable automation.

That said, Fish’s scripting syntax is pleasant for Fish-specific things like custom completions, prompt functions, and abbreviation handlers. See my Fish Shell functions guide for examples.

Performance comparison

MetricFish 4.5Zsh (with Oh My Zsh)Zsh (bare)
Startup time~30ms200-800ms~40ms
Interactive responseInstantDepends on pluginsFast
Memory usage~15MB~20-40MB~10MB
Written inRustCC

Fish 4.0 was rewritten in Rust (February 2025), and the latest release is 4.5.0. Startup is fast and interactive response is immediate. Zsh with Oh My Zsh and several plugins can have noticeable startup delay, though this varies a lot depending on which plugins you enable.

So which one should you pick?

Go with Fish if:

  • You want things to work immediately without configuring them
  • You spend most of your time running commands interactively, not writing shell scripts
  • The POSIX syntax differences don’t bother you
  • You prefer a smaller, focused plugin ecosystem over a huge one

Go with Zsh if:

  • You want Bash compatibility so you can paste commands from tutorials without changes
  • You like having a massive plugin ecosystem with lots of themes
  • You write shell scripts that need to be portable
  • You’re already comfortable with your Zsh setup and don’t feel limited by it

If you’re currently on Bash and looking to upgrade, I’d suggest trying Fish first. The barrier to trying it is low. Just install it on Ubuntu (or on macOS), run fish, and use it for a day. You don’t have to set it as your default shell to test it out. If the syntax differences bother you too much, switch to Zsh instead.