Introduction
fish (Friendly Interactive Shell) reimagines what a shell should feel like: the moment you start typing, it suggests the next command from your history (like Chrome URL bar). Syntax highlighting colors invalid commands red and quoted strings cyan. Tab completion reads the actual man pages to offer relevant options.
With over 33,000 GitHub stars, fish is the go-to "interactive shell" for developers who spend their day in the terminal. It's not POSIX-compatible by default (a deliberate tradeoff for cleaner syntax), but that's rarely a problem — you can always bash -c a legacy script.
What fish Does
fish evaluates commands interactively with rich feedback. The built-in prompt customization, universal variables, function definitions, and abbreviations replace the .bashrc + plugin managers of bash/zsh. Everything works out of the box — no Oh My Zsh required.
Architecture Overview
fish shell
|
[Interactive front-end]
- autosuggestions (history + completions)
- syntax highlighting
- tab completions from man pages
- multi-line editing
|
[Scripting language]
functions, abbreviations, universal vars
saner if/for/while/switch blocks
|
[Web-based config]
fish_config -> localhost:8080 color/prompt editor
|
[Integrations]
fisher (plugin manager), starship (prompt),
zoxide/atuin/fzf hooksSelf-Hosting & Configuration
# ~/.config/fish/config.fish
# Path
fish_add_path ~/.local/bin ~/.cargo/bin
# Abbreviations (expand as you type)
abbr -a gst git status
abbr -a gc git commit -m
abbr -a gp git push
# Function definition
function mcd
mkdir -p $argv[1]; and cd $argv[1]
end
# Launch starship prompt
starship init fish | source
# zoxide (smarter cd)
zoxide init fish | source# Switch to fish explicitly without changing default shell
exec fish
# Try before you commit
fish --no-config # vanilla sessionKey Features
- Autosuggestions — grayed-out completion from history, accept with →
- Syntax highlighting — valid commands green, invalid red
- Man-page tab completion — options parsed from installed man pages
- Universal variables — set once, persist across sessions + machines
- Abbreviations — better than aliases; expand inline so you see the real command
- Web-based config —
fish_configopens a browser UI for colors/prompt - Functions > aliases — first-class function definitions with autoloading
- No .bashrc bloat — sensible defaults, very little config needed
Comparison with Similar Tools
| Feature | fish | zsh | bash | Nushell | xonsh |
|---|---|---|---|---|---|
| POSIX compatible | No (by design) | Yes | Yes | No | Partly |
| Autosuggestions | Built-in | Via plugin (zsh-autosuggestions) | No | Yes | Yes |
| Syntax highlighting | Built-in | Via plugin | No | Yes | Partial |
| Tab completion | From man pages | Via framework | Basic | Structured | Python |
| Scripting similarity | Unique | bash-compatible | Standard | Structured | Python inside |
| Best For | Interactive DX | Power users with plugins | Universal compatibility | Typed data shell | Python users |
FAQ
Q: fish isn't POSIX — will my scripts break?
A: Interactive scripts yes, CI scripts no. Keep shell scripts in #!/usr/bin/env bash files; use fish only as your interactive shell. The two coexist without issues.
Q: fish vs zsh + Oh My Zsh? A: fish gives you the "OMZ experience" by default, no plugin manager needed. zsh has a much bigger ecosystem and POSIX compatibility. Pick fish if you value sensible defaults; zsh if you already have a curated OMZ setup.
Q: Can I use Oh My Fish / fisher?
A: Yes. Fisher is the modern plugin manager (curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source). Oh My Fish is older and less maintained.
Q: How do I migrate from zsh?
A: Copy over your PATH settings (convert export to fish_add_path), translate aliases to abbr, and leave bash scripts untouched. Most CLI tools (fzf, zoxide, atuin, starship, mise) have fish hooks out of the box.
Sources
- GitHub: https://github.com/fish-shell/fish-shell
- Website: https://fishshell.com
- License: GPL-2.0