It appeared to me recently that I’ve inadvertently switched to fish shell full time and am loving it! Hopefully after this little intro you will too. For a more complete introduction, I recommend the official tutorial, my aim here is to highlight some of my favorite fish features to entice you…
First, what is fish? Out of the box you get autosuggestions, 24-bit color, man page completions, tab completions, syntax highlighting, and optional web-based configuration. That’s just the tip of the iceberg.
Installation is super easy, for Mac run
brew install fish (or grab the pkg!) and Debian-based a
sudo aptitude install fish should do the trick.
To start fish, simply type
fish in your terminal and you will be greeted with “Welcome to fish, the friendly interactive shell.” If you want to commit right away, we can change our login shell by running
chsh -s /usr/local/bin/fish so we always use fish.
“Unlike other shells, there is no prompt variable like PS1. To display your prompt, fish executes a function with the name fish_prompt, and its output is used as the prompt.”
Building a prompt took a little trial and error, but I love that I can script one out in shell vs the PS1 syntax. Running
fish_config will launch a browser-based editor, you can set prompts and check the code under
~/.config/fish/functions/fish_prompt.fish to get ideas, or perhaps one of the defaults suites you just fine, in which case set it and move on.
Here is my current prompt config:
function fish_prompt --description 'Write out the prompt' # Save our status set -l last_status $status set -l last_status_string "" if [ $last_status -ne 0 ] printf "%s(%d)%s " (set_color red --bold) $last_status (set_color normal) end set -l color_cwd set -l suffix switch "$USER" case root toor if set -q fish_color_cwd_root set color_cwd $fish_color_cwd_root else set color_cwd $fish_color_cwd end set suffix '#' case '*' set color_cwd $fish_color_cwd set suffix '>' end echo -n -s (date "+%H:%M:%S") ' ' (set_color normal) (pwd) ' ' (set_color $color_cwd) (prompt_pwd) (set_color normal) "$suffix " end
I built upon one of the presets and am only defining the color red for exit status alerts and adjusting the prompt from ‘>’ to ‘#’ when moving between root. Otherwise, I use Solarized Light in iTerm2 so
set_color normal retains the Solarized palette, if I wanted to override a color all the time, I could specify a hex value or ANSI name instead of ‘normal.’
“A fish function is a list of commands, which may optionally take arguments. Unlike other shells, arguments are not passed in “numbered variables” like $1, but instead in a single list $argv.”
Say I want to display a notification using osascript, I can test out a function in the terminal like so:
~> function notify osascript -e "display notification \"$argv\" with title \"Terminal\"" end
Now I can call
~> notify Here is an alert! and receive a notification like the following:
I don’t believe you can set a custom icon, at least according to Apple’s documentation unless you were to export a .app version with a custom ICNS file built using
This function will disappear after we close out the session, if we want to save it, we can call
funcsave notify. Now a folder called ‘functions’ will be created under
~/.config/fish/functions containing a file with the name of our function (in this case ‘notify’) along with a .fish extension. When we
cat the file to peak, we see exactly what we constructed in the terminal.
I love the modular approach to how fish stores functions, instead of running
funcsave we can manually create these files in
.config/fish/functions. Just remember to name the file the same as the function name with a .fish extension.
Here is another example (a bit arbitrary but maybe this is useful) on manually creating a function, we will call it
rf and it will invoke
rm -rf against
$argv (which would be a path to a folder).
> vim ~/.config/fish/functions/rf.fish function rf rm -rf $argv end # I can immediately use this > rf ~/path/to/some/folder/to/delete
Keep in mind, there are some minor nuances when working in fish, for instance a variable assignment:
# in bash > var=$(pwd) > name="Drew Diver" # in fish > set var (pwd) > set name Drew Diver
One final and cool fish command is
fish_update_completions which parses manual pages installed on the system, and attempts to create completion files in the fish configuration directory. This does not overwrite custom completions.