Hello Fish Shell

#sysadmin

Three years ago I was becoming dissatisfied with my shell, and cast around for alternatives.

Why? What caused the dissatisfaction? I was using Bash, and had been for years. But, over time, I got tired of looking stuff up all the time. It seemed like no matter how long I used Bash, I was never going to master it. Not because I didn’t use it enough, but because it was full of arcana. Full of concepts and ideas that were glued together without any coherence. An encyclopedia of disparate facts to memorize.

Don’t get me wrong, Bash is a great shell. I still use it on my servers. It is a successor to the Bourne Shell, and must maintain backwards compatibility with it. That’s not a design flaw in Bash, but one of the keys to its success. But, it comes with trade-offs. These days I’m willing to make different trade-offs.

Why Fish?

Here are some of the reasons I chose to use Fish:

  • The shell language has a small syntax. There aren’t a lot of glyphs and tokens to memorize. If you know any Ruby or Python, you’ll feel at home.
  • The features of the shell fit together well. Fish shell’s author spent some time up front to think about the design of the shell and how its features would fit together.
  • Features like syntax highlighting, tab-completion, auto-suggestions, and auto-loading help my productivity in the shell.
  • Fish has sensible defaults. This results in a smaller configuration file for me. I always like having less code to maintain.

An Example - The Prompt

As an example of the difference between Bash and Fish, let me show you how to set the prompt in both shells. In these examples we’re going to set our prompt to look like this:

username@hostname $

In Bash, you set the environment variable, PS1, to a string which you want to be your prompt. Inside the string, you can put special characters which will expand into a variable value like hostname.

PS1="\u@\h \$ "

In the above sample, the special characters, \u, expands to your user name, and \h expands to your hostname. You have to escape the $ character, because it has a special meaning. It is used to expand variables like, $HOME.

After explanation this seems pretty trivial, and it is. However, you can only use those special characters like \u when setting your prompt. This is an example of cognitive load in Bash. To set the prompt you need to learn a mini-language. Let’s compare to how it’s done in Fish.

To set the prompt in the Fish shell, you declare a function named, fish_prompt. The output of this function should be a string, and that string will be used as your prompt.

function fish_prompt
  printf '%s@%s $' (whoami) (hostname | cut -d . -f 1)
end

We’re using the printf command which takes a format string, and subsequent arguments which fill in those placeholders. The argument (whoami) runs an external command and returns the result. This functionality is equivalent to backticks or the $(whoami) notation in Bash.

I prefer the way Fish sets the prompt. I find it easier to understand, and easier to maintain over time. I don’t have to learn any extra concepts or languages. It’s functions and subcommands all the way down. These two features are composable and reusable.

What’s even nicer, is Fish can autoload functions. If you put this function in the correct directory, Fish will find it, and load it for you. It’ll even reload it for you when you change it! To set the prompt, I’d put the sample code above in a file named, $HOME/.config/fish/functions/fish_prompt.fish.

I like this convention over configuration style. It’s one less thing for me to think about. One less decision to make.

In the end, it’s not that other shells can’t do what Fish does. It’s just that Fish does it by default. Without me thinking about it.

Further Reading

Here are some resources for learning more about the Fish shell.

  • Read the Fish Tutorial to start learning about Fish.
  • Fish has a Design Document. There are some good ideas there, and it’s worth a read.
  • If you want some examples of Fish configuration, I’ll offer you my dotfiles repo on GitHub.
  • The author of Fish, Axel Liljencrantz, wrote an article on LWN.net about what makes Fish unique. The article is old, but it’s still useful if you’re an experienced shell user and want an overview of Fish’s features, and why things are the way they are.