Fish: the command line shell that’s got me hooked
August 31, 2018
Like many developers, I use a combination of Windows and Mac systems between my home and office. When using a console, I tend to stick to the default settings. But I reached a breaking point while navigating through directories using Mac’s stock Bash terminal. I starting looking into Zsh but still wasn’t sold. Then I discovered a shell called “Fish,” and my life has never been the same.
There may be plenty of fish in the sea, but there aren’t any quite like this one.
What is Fish?
As the “sh” at the end of its name implies, Fish is a shell. Fish itself stands for Friendly Interactive SHell. Courtesy of Github, this user-friendly command line shell was developed with a special emphasis on user experience.
So what sets Fish apart from its competition? For starters, it was developed more recently than its counterparts (with an initial release in 2005). It boasts powerful suggestion/auto-completion functionality, friendly syntax highlighting, and its GUI (browser)-based settings/help pages are usable straight out of the box, so to speak.
Installing this shell couldn’t be easier. If you’re using Homebrew on a Mac, input the following command:
|1||$ brew install fish|
And you’re done.
Installing with Linux is just a touch trickier — you’ll want to be sure to grab the official repository because using a distribution package manager to install it might saddle you with an older version instead. 。
Ubuntu users can install using the official Personal Package Archives (PPA).
|$ sudo apt–add–repository ppa:fish–shell/release–2
$ sudo apt–get update
$ sudo apt–get install fish
For instructions on how to install the shell on other OS’s (including Debian), visit Fish’s website here.
Suggestion and completion
Once installed, I recommend taking its suggestion and completion functionality for a spin.
From the home directory, try changing directories
(cd) by typing
/usr into the command line.
The above screenshot demonstrates how the shell behaves when you input the command
cd /u. In the grayed-out text, you can see that
sr/ is suggested to complete the line. The shell provides a suggestion without us even having to hit the tab key.
But what happens when another file/folder shares the same name up until a certain point? In this situation, the possibilities are sorted in alphabetical order and the entry that falls first in that order will be suggested first.
Unfortunately, the odds that the name you’re searching for will show up in the suggestions are slim. But rest assured: Fish has a user-friendly feature available for these kinds of situations.
This time, type in
/s and hit the tab key twice.
As shown above, this action displays an overview of all directories that begin with
/s. You can then use the tab key or arrow keys to move through each.
Until now, Fish’s suggestion functionality may have seemed more or less equal to Bash and other competitors, but here you can see that this shell is different: it allows you to directly choose your directory from a list. Never again will you have to go through the motions of looking at a list only to type out the rest of the characters anyways.
Fish also supports scanning through subdirectories using commands like
And these user-friendly suggestions are available in more than just path situations. Other Linux commands and functions are available. For example, entering ssh followed by a space and then the tab button yields a list of potential connections registered in known_hosts, and entering mount returns the devices currently mounted.
It’s no exaggeration to say that with these functions, practically anything you’re looking for can be autocompleted using the tab key.
It should be noted that since the completion of subcommands and options are generated through the man of each application, completion functionality will not be compatible with software installed at any point after Fish is installed. Instead, these updates must be pushed to Fish.
Thankfully, this can be accomplished fairly easily.
Just input the above command and you’re ready to go.
Syntax highlighting is another feature available ‘straight out of the box.’
As an example, let’s say you make a typo when typing in the word ‘clear.’ Obviously, there’s no corresponding command for ‘clare,’ so it will indicate the error using red letters as we see below.
This function works for directory paths as well.
In the above example, ‘/usr’ is mistyped as ‘/user.’ Since there is no ‘/user’ directory, Fish again returns an error in red letters.
Settings and help pages
Fish’s settings page and help page are both a little different. Type ‘help’ into the terminal and a browser window will pop open displaying a page that looks like this:
In addition to this page, Fish also hosts a help page that can be accessed via a browser. However, I don’t find this function necessary because the document is just a copy of the documentation already located on the official site.
What really impresses me is another function: return to your Fish terminal and type
fish_config. This will launch a web-based configuration interface where you can change the color settings (theme), prompt settings, access command histories, and a slew of other features.
They even provide examples of different settings, including colors and prompts, that you can preview before committing.
Rather than calling it out for its convenience, it bears mentioning here that if you choose to specify new color settings using the command line, other color changes—such as the color of typical letters in Fish’s environment variables, or the color of letters in quotes as returned by commands such as echo—must all be completed manually, one by one.
Likewise in the prompt area, functions must be created and defined individually by the user, an action which is, after all, best performed in a browser environment.
Similarly to what npm is for node.js, Fish has a package manager all its own. There are several different ones to choose from, but the most popular is Fisher.
To install, simply input the following and it’s ready to use:
|1||curl –Lo ~/.config/fish/functions/fisher.fish —create–dirs https://git.io/fisher|
There’s no real need to install any packages because Fish is a complete package in and of itself. But it can be useful for installing themes not available by default.
While Fish is incredibly easy to use, users comfortable with Bash may still hesitate to make the switch for various reasons. Here are a few.
The script structure is different
The Bash structure is difficult to master while Fish is uniquely simple; interestingly, that is a source of hesitation for would-be converts.
For example, Fish does not utilize the
&& AND operator.
apt update && apt upgrade commands are a regular fixture of Debian-style OS’s, but attempting to use this command in Fish will only return an error, as the && function is not recognized.
Instead, the equivalent Fish commands would be
apt update; and apt upgrade. Because the commands are recognized individually due to the
ANDoperator is no longer necessary.
Nor does Fish use the
|| operator, instead requiring the
or command after the end of a semicolon to combine commands. (Reminds you of Python, doesn’t it?)
Moreover, conditionals such as
if ~ fi also have their own constructions, which you can read more about here.
fishrc doesn’t exist
Fish has no equivalent for the ~rc file that we’ve all come to know and love. The settings that would normally be written to a ~rc file are instead located in the config.fish file at
This means the same Bash-style syntax can’t be used, so you will have to use the previously written descriptors unique to Fish. Environment variable settings can be recorded in the config, and they can also be set directly through the shell itself.
My personal preference is to alter the settings via the shell, since the environment variables changed—yes, even from the shell—will persist from there.
As for how to change those settings, Fish eschews the export function to instead use the set command to change settings.
From inside config.fish write the following:
|1||set PATH /usr/local/bin $PATH|
If using the shell, write the following:
|1||set –U fish_user_paths /usr/local/bin $fish_user_paths|
$fish_user_paths is one of Fish’s universal variables and is read before h$PATH.
As written at the beginning of this article, I personally prefer using default settings more often than not; the fact that the above functions can be used immediately with no configuration makes Fish an ideal choice for me.
However, due to the differences in the *rc file handling and script language, I can’t recommend it to people who like getting down and dirty with zsh and .zshrc, as these differences might cause more trouble than its worth.
For those who prefer using programs ‘straight out of the box’ with minimal attention to customization or people who wish zsh’s autocomplete function was just a little more robust, well… You could do far worse than Fish.