Signup to the waiting list!
I’ve been using the Fish Shell for months, and I think it’s the best shell I ever used. For many reasons.
Bash, while great, is a very basic shell, with a limited set of configurable options. I tend to use it mostly to run Bash scripts (which are another topic) rather than as an interactive shell. Zsh offers a lot of features but requires a little bit of configuration to set up, which might frighten beginners. Also, too many options and freedom means you can get in a configuration paralysis pretty easily, and you end up changing the options 20 times in a week to make sure you’re not missing out.
I don’t want to “bash” on those projects, which are amazing and I used for a lot of time and sometimes still use. This description is my attempt at highlighting the benefits of Fish
Fish Shell to the rescue! This shell provides an amazing environment, and fully featured configuration out of the box.
My favorite features of Fish are:
- it has a better autocomplete features for commands you already executed and this alone is really making my day to day faster and less stressful.
- you begin typing a command and press the
upkey to see all the times in the shell history where you used that command before.
- you can install Fish on any system and it works in the same way everywhere, without having to customize too much to get the fancy things.
When it comes to scripting, it is fairly different from Bash scripting (in a better way IMHO), but you can run any Bash script provided it is prefixed with
Right after the installation you get those nice things:
- syntax highlighting
- a nice prompt
- parameter suggestion with man page hints
- web-based configuration
and in my opinion is the most beginner friendly shell.
One of the funny things I remember I noticed was the homepage. At first I could not understand if that was some sort of relic from the past:
For those lucky few with a graphical computer, you can set your colors and view functions, variables, and history all from a web page.
Then I realized it was programmer’s humor and it made me chuckle. Tech should always be fun, right?
First things first: what is a shell?
A shell is an interface to the underlying operating system. It allows you to execute operations using text and commands, and it provides users advanced features like being able to create scripts.
Install Fish by running
brew install fish on macOS.
Check out my macOS terminal guide
fish is installed in
Since that is likely already in your path, run
fish to start the Fish shell (type
exit to return back to your default shell)
Once nice thing about Fish is a web-based configuration. Run
fish_config to start the web client.
From here you can
- choose a color scheme from a list of predefined ones
- choose a prompt from a list of predefined ones
- inspect the Fish functions and variables configured
- see the commands history
The configuration is stored in the
~/.config/fish folder, and that’s where you can edit it without having to use the (optional) web based configuration.
Fish features: syntax highlighting, autocompletion and parameter suggestion with man page hints
Fish lets you execute the usual Unix commands available on your system. Filesystem operations, for example:
lsto list files
cdto change folder
rmto remove a file or folder
mvto move a file to another folder, or change a file name
cpto copy a file
If you run one of those commands (or
any command, really) you will start seeing the words you type get different colors. It makes it really easy to read and understand commands.
Fish also adds autocompletion. If you ran
cd ~/.config/fish/ previously, and now you type
cd, Fish will suggest commands you might want to type, and you just press the right arrow to accept the suggestion (or you can continue to type to change the command). This suggestion is based on command history and file paths.
Suggestions based on autocomplete also work for commands. Here I typed
c and pressed tab:
Fish also suggests parameters and how to use them. Type
ls - and press
tab. A list of the parameters you can use, and their meaning, is shown right below:
This inline help is generated from man pages, the helpful shell help (try running
man ls for the complete help).
Set Fish as the default shell
If you like Fish once you try it out and want to make it your default shell, open the file
/etc/shells. I use
pico to do those small file edits, with
pico /etc/shells, but you can use any editor you prefer, even VS Code with
It should contain something similar to:
# List of acceptable shells for chpass(1). # Ftpd will not allow users to connect who are not using # one of these shells. /bin/bash /bin/csh /bin/ksh /bin/sh /bin/tcsh /bin/zsh
Add this line at the end to add the Fish shell:
chsh -s /usr/local/bin/fish
enter your password, and the shell will change for your user.
You can install Fish plugins.
Fisher is a popular Fish package manager.
Install it using
curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish
and it’s available with the
Now a package can be installed using
fisher add <github-repository-path> and removed using
fisher rm <github-repository-path>.
List all plugins installed using
fisher to update all the packages you installed.
Popular plugins are
Here is a list of packages you can install.
Various shells comply with the POSIX shell command standard.
- X (for Unix)
and it’s a standard meant to unify the various Unix environment that were built over time. There is a shell command standard subset, which is meant as a way to unify how Unix shells work.
Unix is a specification/standard for a family of operating systems. Linux and macOS are based on Unix (Windows is not).
ksh and others are POSIX compliant. Being POSIX compliant makes scripts written with POSIX compatibility work across POSIX compliant shells.
csh for example) is not compliant, so it’s not a POSIX shell, and this means that writing commands and scripts for Fish is different. Scripts written for Fish won’t work outside of Fish. Just like
csh scripts only work on csh (and derivatives)
Why is it different? Various reasons, but I imagine having to support POSIX means the shell must adhere to a common language that might interfere with the shell philosophy and way of working. Not everyone want to have that baggage of tech to support forever.
This will very rarely be a problem with executing commands, but you need to keep it in mind when it comes to scripting and programming.
Download my free Linux Commands Handbook
More cli tutorials:
- The Bash shell
- Introduction to Bash Shell Scripting
- The Fish Shell
- Shell, watch file content as it populates
- How to exit Vim
- UNIX Editors
- The UNIX Filesystem Commands
- Unix Shells Tutorial
- How to set an alias in a macOS or Linux shell
- A practical guide to Homebrew
- How to fix the xcrun invalid active developer path error in macOS
- The Command Line for Complete Beginners
- Introduction to Linux
- How to find the process that is using a port
- Linux commands: mkdir
- Linux commands: cd
- Linux commands: pwd
- Linux commands: rmdir
- Linux commands: ls
- Linux commands: mv
- Linux commands: cp
- Linux commands: less
- Linux commands: tail
- Linux commands: touch
- Linux commands: cat
- Linux commands: find
- Linux commands: ln
- Linux commands: ps
- Linux commands: echo
- Linux commands: top
- Linux commands: kill
- Linux commands: killall
- Linux commands: alias
- Linux commands: jobs
- Linux commands: bg
- Linux commands: fg
- Linux commands: type
- Linux commands: which
- Linux commands: whoami
- Linux commands: who
- Linux commands: clear
- Linux commands: su
- Linux commands: sudo
- Linux commands: chown
- Linux commands: chmod
- Linux commands: passwd
- Linux commands: open
- Linux commands: wc
- Linux commands: history
- Linux commands: du
- Linux commands: umask
- Linux commands: grep
- Linux commands: man
- Linux commands: uname
- Linux commands: sort
- Linux commands: uniq
- Linux commands: diff
- Linux commands: nohup
- Linux commands: df
- Linux commands: xargs
- Linux commands: gzip
- Linux commands: gunzip
- Linux commands: ping
- Linux commands: traceroute
- Linux commands: tar
- Linux commands: export
- Linux commands: crontab
- Linux commands: dirname
- Linux commands: basename
- Linux commands: printenv
- Linux commands: env
- A short guide to the ed editor
- A short guide to vim
- A short guide to emacs
- A short guide to nano
- Linux, no space left on device
- How to use Netcat
- How to use pm2 to serve a Node.js app