Why I use Fish Shell

Develop transferable shell skills quickly with fish

6 min readNov 17, 2023

--

tldr: With Bash I often did not start automating because the time investment of learning is not worth the effort. With fish you have one environment that is configured and pretty complete out of the box. It allows you to automate way more than you could possibly do with Bash or ZSH in the same amount of time.

What I love about fish

I have been using the Fish shell for a couple of years. Let me take you through some of the features that make me love this shell.

Here are three reasons why I do not want to change to another shell:

  1. Fish provides good defaults out of the box. Unlike ZSH and other shells, it takes no time to set up and configure fish. After installation you have a functional shell that including features like vi and emacs key-binds, private mode, auto completion, highlighting and theming.
  2. The scripting language is more sane than bash. It provides proper scoping, better argument parsing and better string manipulations.
  3. Further it has great documentation, error message, examples, tab completion, and other features that add to its discoverability.

Every configuration option in a program is a place where the program is too stupid to figure out for itself what the user really wants, and should be considered a failure of both the program and the programmer who implemented it.

Quoting the design documentation. Read it here. It’s an interesting read.

Extendability

The fish language makes extensive use of callables. Even for assigning variables, fish uses a callable. Callables can be build-ins, functions or shell executables. They are treated mostly equal.

This makes the language highly configurable..

Here is an example of the ‘set’ builtin that assigns variables:

> set x 5
> echo $x
5

Fish provides a couple of callables that are build-in’s like type and set:

> type type
type is a builtin
> type set
set is a builtin

The majority of callables that fish provides are functions. This includes aliases, prompt, and coloring functions.
For example, this is a prompt function:

function fish_prompt
# A simple prompt. Displays the current directory
# (which fish stores in the $PWD variable)
# and then a user symbol - a '►' for a normal user and a '#' for root.
set -l user_char '►'
if fish_is_root_user
set user_char '#'
end

echo (set_color yellow)$PWD (set_color purple)$user_char
end
``'
The prompt can be configured by re-defining the prompt function.


The executable `ls' is an alias function:
```fish
> type ls
ls is a function with definition
# Defined in /usr/share/fish/functions/ls.fish @ line 20
function ls --description 'List contents of directory'
# Make ls use colors and show indicators if we are on a system that supports that feature and writing to stdout.
....

Functions

Fish makes it easy to modify functions. The following command let you modify the function la:

> funced la

This opens $EDITOR with the content of the la functions

#
# These are very common and useful
#
function la --wraps ls --description "List contents of directory, including hidden files in directory using long format"
ls -lAh $argv
end

As you can see, la is an alias for ls.

After modifying a function, it is redefined for the current session. You can save it to the user’s autoload directory with one simple command:

funcsave la

To view all functions, use functions

> functions
N_, abbr, alias, bg, cd, cdh, contains_seq, diff, dirh, dirs, disown, down-or-search, edit_command_buffer, export, fg, fish_add_path, fish_breakpoint_prompt, fish_clipboard_copy, fish_clipboard_paste, fish_command_not_found, fish_commandline_append,
fish_commandline_prepend, fish_config, fish_default_key_bindings, fish_default_mode_prompt, fish_delta, fish_git_prompt, fish_greeting, fish_hg_prompt, fish_hybrid_key_bindings, fish_is_root_user, fish_job_summary, fish_mode_prompt, fish_opt, fish_print_git_action,
fish_print_hg_root, fish_prompt, fish_right_prompt, fish_sigtrap_handler, fish_status_to_signal, fish_svn_prompt, fish_title, fish_update_completions, fish_vcs_prompt, fish_vi_cursor, fish_vi_cursor_handle, fish_vi_cursor_handle_preexec, fish_vi_key_bindings, fisher,
funced, funcsave, fzf_configure_bindings, fzf_key_bindings, grep, help, history, isatty, kill, la, ll, ls, man, micromamba, nextd, open, popd, prevd, prompt_hostname, prompt_login, prompt_pwd, psub, pushd, realpath, return_last_status, seq, setenv, suspend, trap, umask,
up-or-search, vared, wait

functions can also be used to inspect the source of a function:

> functions fg
# Defined in /usr/share/fish/config.fish @ line 229
function fg
builtin fg (__fish_expand_pid_args $argv)[-1]
end

Variables are lists

Fish has good native support for lists. It has to because all variables in fish are lists.

Concatenation for example:

> set characters a b c d
> set characters $characters e f
> echo $characters
a b c d e f

It also has convenient functions like count

> count $EDITOR
1
> count $PATH
6
```fish

And it implements indexing like this:
```fish
> echo $PATH[1]
/usr/local/sbin
> echo $EDITOR[1]
vim
```fish

And slicing:
```fish
> echo $characters [1..1]
a
> echo $characters [1..2]
a b
> echo $characters [-1..2]
a b
/usr/bin/core_perl

Command substitutions

Unlike most shells, there is not need to back-tick command substitutions:

> echo "last file eddited: " (ls -1t | head -n 1)
last file eddited: public

There is no $ character needed, unless the command substitution takes is surrounded by double quotes:

> echo "last file eddited:  $(ls -1t | head -n 1)"
last file eddited: public
> touch "week-$(date +%W).txt"
week-46.txt

Theming

Fish provides functions that let you preview and set themes with ease.

# List all themes
fish_config theme list
# Show a single theme
fish_config theme show Tomorrow
# Show all themes
fish_config theme show
# Choose a theeme
fish_config theme choose Tomorrow

This is the default prompt on my machine:

Default prompt
Default prompt

Choosing a fish prompt is easy too

# List all prompts
fish_config prompt list
# Show a single prompt example
fish_config prompt show informative
# Choose a theeme
fish_config prompt choose informative

Fish even provides a web based configuration tool with

fish_config

Getting help

By default fish opens up a browser to show help pages

These are some useful help pages:

> help tutorial
> help interactive # more about
> help expand-brace
> help language

And some specific sections:
Shared key bindings
Vi key bindings command mode
Vi key bindings insert mode
Vi key bindings visual mode
Emacs key bindings

--

--

Improving life science research with machine learning. Physicist (PhD) and machine learning engineer.