Fish is a friendly interactive shell with excellent autosuggestions, syntax highlighting, and tab completion out of the box. It is fast to set up and pleasant to use without a large configuration framework.
This guide covers a small, modern Fish setup on macOS.
Install Fish
Install Fish with Homebrew:
brew install fish
fishYou are now running Fish. Use exit to return to your previous shell.
Check the installed version with:
fish --versionHomebrew uses different prefixes on Apple Silicon and Intel Macs, so avoid
hard-coding /opt/homebrew/bin/fish or /usr/local/bin/fish. command -v fish
will find the correct path.
Make Fish your default shell
First, add Fish to the list of allowed login shells:
command -v fish | sudo tee -a /etc/shellsDo this once, then change your login shell:
chsh -s "$(command -v fish)"Restart your terminal. If iTerm2 still opens another shell, set Profiles → General → Command to Login Shell.
On Linux, setting Fish as the login shell can bypass setup normally performed by
/etc/profile. Follow your distribution's instructions or configure your
terminal to start fish directly.
Configure Fish
Fish stores user configuration in ~/.config/fish. The main startup file is
~/.config/fish/config.fish:
set --global --export EDITOR nvim
fish_add_path ~/.local/bin
if status is-interactive
# Interactive-only setup
endconfig.fish is not a direct replacement for .bash_profile: it runs for every
Fish shell. Use status is-interactive or status is-login when a command
should only run in one kind of session.
To customize colors and the prompt in your browser, run:
fish_configYou can also browse themes without leaving the terminal:
fish_config theme showAbbreviations and functions
For typing shortcuts, prefer an abbreviation. Fish expands it before the command runs, so you can see and edit the real command:
abbr --add gco git checkoutUse a function when you need behavior rather than text replacement:
function week --description 'Show the current ISO week number'
date +%V
end
funcsave weekfuncsave writes the function to ~/.config/fish/functions/week.fish, where
Fish can autoload it in future sessions.
Install plugins with Fisher
Fisher is a small plugin manager for Fish. Run its current installation command from Fish:
curl -sL https://raw.githubusercontent.com/jorgebucaran/fisher/main/functions/fisher.fish | source && fisher install jorgebucaran/fisherThe essential commands are:
fisher install owner/plugin
fisher list
fisher update
fisher remove owner/pluginFisher records installed plugins in ~/.config/fish/fish_plugins, more
precisely, $__fish_config_dir/fish_plugins. Put that file in your dotfiles,
then run fisher update on a new machine to install the same set.
Manage Node.js versions
The Bash-based nvm script is not native to Fish. The simplest alternative is
nvm.fish:
fisher install jorgebucaran/nvm.fish
nvm install ltsIt supports .nvmrc and .node-version files without a Bash compatibility
layer.
Run Bash scripts when needed
Fish is deliberately not POSIX-compatible, but executable Bash scripts still
work when they have a correct shebang such as #!/usr/bin/env bash.
For a one-off Bash command, run:
bash -c 'some_bash_command'Scripts that must be sourced to modify the current shell cannot change Fish's environment directly. Prefer a Fish-native integration for those tools.
Update Fish
If you installed Fish with Homebrew:
brew update
brew upgrade fishThat is the whole setup: keep config.fish, your saved functions, and
fish_plugins under version control, and let Fish handle the rest.
More useful references: