In this post, I describe how to switch to the fish shell and some of the interesting features it offers.
Installing fish is a piece of cake. On Ubuntu, a fish package is readily available. An additional PPA supplies newer versions of fish than those that ship with the distribution. The following steps install fish through the PPA.
Once installed, switching is just a matter of updating the login shell.
/usr/bin/fishas a login shell by adding its path to
Debian provides a convenient
add-shellcommand to accomplish this.
➜ sudo add-shell /usr/bin/fish
Set the current user’s login shell to fish with
➜ chsh -s /usr/bin/fish Password:
Now, open up a fresh terminal session to start using fish.
You should see a fresh, vanilla shell prompt like the following.
Welcome to fish, the friendly interactive shell Type help for instructions on how to use fish jordan@jwillkers ~>
Adjusting basic configuration options is quick ang easy with fish.
Configuring the fish shell is as easy as selecting options the provided by the web interface.
Style the prompt.
If you like that oh-my-zsh feel as I do, you might want to use robbyrussell’s theme for your shell prompt. If you like doing things the old fashion way - or want to set the prompt remotely, here’s a quick rundown.
Make sure the
➜ mkdir -p ~/.config/fish/functions
Then copy over the desired prompt configuration,
robbyrussell.fishin this case, from
➜ cp /usr/share/fish/tools/web_config/sample_prompts/robbyrussell.fish ~/.config/fish/functions/fish_prompt.fish
Adjust the color theme.
The color theme can be important when your terminal’s color theme obscures autosuggestions. Solarized is my color scheme of choice. The
fish_configweb tool outputs the commands that set the various variables for a color theme when one is selected. This is easy to translate to a command-line which can be quite helpful when configuring remotely. As an example, the following command sets the color scheme to solarized dark.
➜ set -U fish_color_normal normal; \ set -U fish_color_command 93a1a1; \ set -U fish_color_quote 657b83; \ set -U fish_color_redirection 6c71c4; \ set -U fish_color_error dc322f; \ set -U fish_color_end 268bd2; \ set -U fish_color_selection white --bold --background=brblack; \ set -U fish_color_search_match bryellow --background=black; \ set -U fish_color_history_current --bold; \ set -U fish_color_operator 00a6b2; \ set -U fish_color_param 839496; \ set -U fish_color_cwd green; \ set -U fish_color_cwd_root red; \ set -U fish_color_valid_path --underline; \ set -U fish_color_autosuggestion 586e75; \ set -U fish_color_user brgreen; \ set -U fish_color_escape 00a6b2; \ set -U fish_color_cancel -r; \ set -U fish_pager_color_completion B3A06D; \ set -U fish_pager_color_description B3A06D; \ set -U fish_pager_color_prefix cyan --underline; \ set -U fish_pager_color_progress brwhite --background=cyan; \ set -U fish_color_host normal; \ set -U fish_color_match --background=brblue; \ set -U fish_color_comment 586e75
Customize the greeting message with the variable
➜ set -U fish_greeting ""
Enable backwards-incompatible features.
➜ set -U fish_features stderr-nocaret qmark-noglob
Enable Vi mode.
For user’s who prefer Vi and Vim, there is a nifty method of enabling Vim keyboard shortcuts in addition to the default Emacs shortcuts. Creating the file below will enable this and default to insert mode.~/.config/fish/functions/fish_user_key_bindings.fish
function fish_user_key_bindings fish_default_key_bindings -M insert fish_vi_key_bindings insert end
fish_mode_promptfunction with an empty function to disable the Vi mode indicator.~/.config/fish/functions/fish_mode_prompt.fish
function fish_mode_prompt end
Now, if you’re thinking about
.fishrc, forget about it. The equivalent of
~/.config/fish/config.fishbut a lot of configuration is better achieved - and organized - through universal variables and autoloading functions.
PATHenvironment variable in fish to suit your needs.
When messing with
PATH, use fish’s dedicated internal variable
fish_user_paths. This variable is special and populates
PATH. Some Linux distributions don’t include
PATHby default. With the
➜ set -p fish_user_paths /usr/local/bin
-poption prepends a value to the given variable. The
-Uoption signifies a universal variable, which persists the variable in the future and across any currently running fish sessions. This reduces the overhead of having to mess about with shell startup files. These variables can be managed in the file
A lot of fish functionality has been covered already, but "there’s always more to learn" as they say. A few additional fish topics are covered here.
Export shell variables with the
This makes the variables accessible to other programs.
PATHis automatically exported from the contents of the un-exported
fish_user_pathsvariable, making this an exception. For everything else, export the variable by calling
-xflag. To add a value to the beginning of the
LD_LIBRARY_PATHenvironment variable and export it, use
➜ set -px LD_LIBRARY_PATH /usr/local/lib
Understand how fish handles PATH variables.
The fish shell stores lists internally as arrays of strings. This is fundamentally different from how shells typically represent many fundamental variables which contain lists of paths, such as
LD_LIBRARY_PATH. Classic shells store these "lists" as a single string of colon-separated paths. Many applications and programs expect the incumbent formatting, so fish treats these as special variables called PATH variables. When printing or joining PATH variables, colons are used to delimit values when the variables are quoted. Otherwise, spaces separate each path in the list. Any variable ending in
PATHis automatically treated as a PATH variable. So, when using
setto deal a PATH variable, you can still treat it as you would any other list in fish. As an example, the following command adds
/usr/local/libto the beginning of the classic
LD_LIBRARY_PATHvariable and appends
~/libto the end.
➜ set -x LD_LIBRARY_PATH /usr/local/lib $LD_LIBRARY_PATH ~/lib
When quoting the variable, it must be modified like so to achieve the same result.
➜ set -x LD_LIBRARY_PATH /usr/local/lib:"$LD_LIBRARY_PATH":~/lib
Take advantage of autosuggestions.
Just start typing a command and fish will provide suggestions on your prompt. As autosuggestion appear from your history, choose the suggested line with →. To select only the next word of the suggestion, use Alt+→.
This one has required a bit of learning curve since I’m so used to finding previous commands by searching with Ctrl+R. With fish, this is even simpler. Start typing the letters, word, or phrase you want to match. Then, just press Alt+↑ to scroll backwards through history for matches.
Another nifty feature is the recursive wildcard which automatically descends into subdirectories for matching a particular pattern.
The following example recursively searches and lists all files ending in
➜ ls ~/.config/**.fish /home/jordan/.config/fish/functions/fish_prompt.fish
Common issues involve various environment variables and initialization functionality which assumes the default login shell is Bash.
Some people place
fish in their
~/.bashrc file to start fish from within Bash so that all environment variables are correctly configured.
I prefer to use
fish as my login shell and file bugs as necessary for projects to properly support it, but this is definitely a bit a of a pain but thus is progress, eh?
There’s a lot to learn about the fish shell. It provides an extremely convenient feature set and is attempting to solve issues inherited from shells of generations past. I love it, and its a great improvement to my workflow.