Set up fish, the user-friendly interactive shell
Fish (Friendly Interactive SHell) is a Unix shell designed to be user-friendly and interactive. It features syntax highlighting, autosuggestions, and a built-in help system, among other features. Fish aims to be more intuitive and easier to use than traditional Unix shells like Bash, while still providing powerful scripting capabilities. Modern macOS computers ship with zsh as the default shell, you can check out Why I Switched from zsh to fish but the main reasons are the speed, simplicity, autosuggestions and vim mode that the fish shell offers.
Fish does not come pre-installed on macOS, you have to install it with Homebrew by running the following command in the terminal.
If you’re not familiar with Homebrew, check out Managing macOS packages with Homebrew.
Making fish your default shell
Now that the fish shell is installed, you have to manually change the default shell by completing the following steps.
First, you will need to get the path to the fish shell executable. If you’re unfamiliar with how executables in the terminal work, I recommend checking out What is the terminal?. Run the following
The command will output something similar to
/opt/homebrew/bin/fish. Copy the value from your terminal and add it to the
/etc/shells file. You’ll want to edit the file using the
sudo command, since this is an system-level file that lists valid login shells for user accounts. Here is how to update it using
Enter your user password to open the file then add the fish shell’s path as an new line in the file and save it.
If you’re unfamiliar with
vi, I recommend running
vimtutor in your terminal which will guide you through the basics of how to edit text from inside the terminal.
Now that you’ve added fish as a valid login shell for macOS, you can run the
chsh (change shell) command to change the default login shell.
You may be prompted, again, to enter your user password and when the command is completed your login shell is now switched to fish, congrats! Now, close and reopen the terminal window for the changes to take effect.
Fish configuration is written in its own scripting language. The entry point for configuring the fish shell is the
config.fish file which can be created with the following command.
This command first creates the
~/.config/fish directory with the
-p option, which creates any parent directories that do not exist. Then it creates the
config.fish file inside the
~/.config/fish directory using the
touch command. Note: all of fish’s configuration files are stored in
~/.config/fish more of which will explore later.
I highly recommend you Manage macOS packages with Homebrew. Add the following eval code to your config file to configure homebrew with the fish shell.
Note: Evaluating a command in the shell is typically done with
$(cmd) but fish uses
(/cmd) instead, dropping in the
$. Some developers I’ve talked have chosen not to use fish because of the subtle syntax differences from more traditional shells, but I think it’s worth it.
Add directories to
In fish, the
fish_add_path function is used to add directories to the
PATH environment variable. Adding directories to your system’s
PATH environment variable allows you to run programs located in those directories from anywhere on your system without specifying the full path. By doing so, you extend the list of directories that the shell searches for executables, making it more convenient to run programs and execute commands.
To add support for Homebrew executables to the fish shell, add the following lines to your
I recommend creating a
~/.config/bin directory to store any custom scripts you make come up to improve your workflow or automate tasks.
Setting environment variables
In the Fish shell, the
set command is used to create and modify shell variables. Shell variables are used to store values that can be referenced and reused throughout a shell session or script. Here are some common variables that are helpful.
-U flag is used with the
set command to create or modify a universal variable. Universal variables are similar to regular variables, but they have a global scope and can be accessed from any shell session or script.
fish_greeting variable is used to customize the greeting message that is displayed when a new shell session is started. By default, the greeting message includes the Fish version number and a welcome message. Since I am constantly spinning up new shells in my development workflow, I prefer to disable the fish greeting by setting it with not value.
fish_vi_key_bindings variable allows you to hit escape while writing a command in fish to switch to a vi-mode to easily manipulate your command before running it. Just like vi, you can hit
i to get back to insert mode.
There are many other variables you can set to customize your shell, check out the fish documentation for more information.
The next most common variable to change is the default editor for your shell. This is set with the
-x flag is used with the
set command to export a variable as an environment variable. When a variable is exported, it becomes available to child processes and can be accessed by programs and utilities that use environment variables. This is helpful as you extend your development environment with other tools that can generate sub processes
One of my favorite features of fish is the ability to create abbreviations. This works similar to a shell aliasm but the main difference is the abbreviation will expand when ran.
You can create abbreviations with the
abbr command in your
config.fish file. Let’s add a few helpful ones for homebrew.
You’ll have to source your
config.fish file for the change to be reflected in your shell.
Now, you type
bs<space> and you’ll see the prompt quickly expand to
brew search to allow you to create commands quickly using a simple mnemonic-style abbreviations. Abbreviations speed up my dev workflow significantly and are one of my favorite features of the fish shell.
There is a large community of plugins for the fish shell. I recommend using fisher to manage them.
A great starter plugin for fish is sponge, which cleans your fish history from typos automatically. It can be installed with the fisher command.
You’ll notice two things.
~/.config/fish/fish_pluginsfile was created and added sponge as a plugin. This is how fisher manages plugins.
~/.config/fish/functionsdirectory was created and multiple
_sponge_*.fishfiles were added to it. This is the plugin code which fish will automatically read to extend the shell. This folder will contain more files as you add more plugins, you can even create your own!
The fish shell is a simple, fast, and intuitive shell alternative for macOS. In this post we installed fish, set it as your default user shell, configured homebrew, added a directory to your path, customized some of fish’s options, create abbreviations, and installed your first plugin.
Sign-Up for New Posts
Stay in the loop and get the latest blog posts about dotfiles sent to your inbox.