Fish shell
Beautiful defaults
Good design isn’t about removing the seams altogether1; it’s about having beautiful defaults and layering the seams. And this is something that Fish shell absolutely nails.
To be fair, I have no idea why I didn’t give it a proper shot until yesterday. I guess because Zsh, or more precisely Oh My Zsh, has been perfectly adequate.
It’s not until you experience the intelligent auto-suggestions and completions in Fish, however, that you truly realise what you’ve been missing. And that’s before you learn just how easy it is to extend as nearly everything is a function.
Getting started
First off, download and install Fish shell.
I’m running elementary OS on my Star Labs notebook so I followed the Ubuntu instructions:
sudo apt-add-repository ppa:fish-shell/release-3
sudo apt update
sudo apt install fish
At this point, you can simply type fish
in your current shell to open a Fish shell instance.
I recommend you take a moment to at least skim through the comprehensive tutorial, documentation, and frequently-asked questions.
Sprucing it up
While Fish shell is perfectly usable without customisations, there are a few things I’ve gotten used to having in my shells that I wouldn’t want to do without. These range from the practical to the merely cosmetic.
The first thing I’d highly recommend you do is install Fisher.
Fisher
Fisher is a plugin manager for Fish. It does one thing and does it well.
You can install it by running the following one-liner (this is the script that it will run on your machine):
curl -sL https://git.io/fisher | source && fisher install jorgebucaran/fisher
From there, you can browse the list of Fisher plugins on awsm.fish.
Following is a brief list of the ones I installed.
Tide
Tide is a modern prompt manager for Fish.
After playing with it a little, I forked it to customise the Git prompt (I like to have my Git prompt tell me what the status is in words instead of cryptic symbols.)
Also, note that in the screenshot you can see a count of the files that fall into different git statuses. Normally, this would slow a prompt down but Tide is about as snappy as can be because it is asynchronous so you are never blocked from entering a command while waiting for your prompt to render.
Install it using Fisher:
fisher install IlanCosman/tide
Gills
Creating a plugin is so simple in Fish that I’ve already made a very simple one even though I only just started using the shell yesterday.
The plugin, which I call Gills, is about as simple as it gets: it just adds an empty line after your prompt and before the output of your command to balance the whitespace around them so you can more easily separate your prompts from your command output while skimming your terminal’s scrollback buffer.
It’s called Gills because it gives your output room to breathe. Get it? (Did I mention I was sorry?)
Technically, like basically everything else in Fish shell, it’s just a function. In this case, one that handles Fish shell’s fish_postexec
event.
(It also handles a couple of special cases like cd
, pushd
, and popd
that do not produce any output. In those cases, it doesn’t add the additional empty line. If you find any other edge cases, please feel free to open an issue or a pull request.)
Install it using Fisher:
fisher install small-tech/gills
Node Vesion Manager (nvm)
I work with Node.js everyday so, prior to Fish shell, I was using nvm-sh/nvm to manage my node versions.
While you can still use that script in Fish, there is a better option that’s called nvm.fish.
Designed for Fish, this tool helps you manage multiple active versions of Node on a single local environment. Quickly install and switch between runtimes without cluttering your home directory or breaking system-wide scripts.
Install it using Fisher:
fisher install jorgebucaran/nvm.fish
From there on, you can use commands like nvm install lts
to quickly install and use different versions of Node.
nvm.fish also supports .node-version
and .nvmrc
files so pop one of those bad boys into your project directory to automatically have the Node version specified within them available when you switch to your project’s directory in your shell.
Puffer Fish
One feature of Zsh that I use all the time is to navigate back multiple directories simply by adding more dots to my command. So, for example, if I’m in the /a/b/c/d/e/
directory and I want to change to the b
folder, I can simply write cd ....
and Zsh will interpret that as cd ../../../
and save me some typing.
(Hey, I’m a developer, being lazy is part of the job description.)
So, anyway Puffer Fish enables Fish shell do the same thing. Actually, it’s even better because you get in-place expansion.
Install it using Fisher:
https://github.com/nickeb96/puffer-fish
z
While Puffer Fish makes it easy traverse backwards through a directory stack, z makes it easy to jump to any (previously visited) directory at any time.
z tracks the directories you visit. With a combination of frequency and recency, it enables you to jump to the directory in mind.
So, for example, if I visit ~/small-tech/small-web/domain
and then, later, I want to get back there, I can simply type the following from anywhere:
z domain
And it’ll pop me back into my project folder.
I wasn’t sure if I’d end up using it when I first installed it but I find myself using it quite often to quickly switch to the directories of projects I work on often.
Install it using Fisher:
fisher install jethrokuan/z
Autopair
Autopair automatically matches opening/closing pairs of common punctuation like quotation marks and parentheses.
It might seem like a small thing, but it’s one of those things that gives you a little jolt of dopamine every time it Just Works™.
Install it using Fisher:
fisher install jorgebucaran/autopair.fish
Dracula theme
I like and use the Dracula theme pretty much everywhere and, of course, there’s a version for Fish.
Install it using Fisher:
fisher install dracula/fish
Configuration
If you’re coming from Bash or, like me, from Zsh, you might be wondering where to put your aliases, etc. The equivalent of ~/.bashrc
or ~/.zshrc
in Fish is ~/.config/fish/config.fish
.
You can also configure your shell visually in your web browser by running the following command in your terminal:
fish_config
Also, while Fish does have aliases, it also has a much more powerful alternative called abbreviations.
Abbreviations
Abbreviations are just regular Fish functions but you get a handy shortcut (abbr) for defining them. Unlike aliases, you get auto-suggestions for abbreviations and they are expanded in place so you can see the full command.
While I’ve converted most of my Zsh aliases to abbreviations, I’ve kept some (like code
for codium
) as aliases.
My advice is to convert all your aliases to abbreviations and then you will know right away whether you need to convert any back to aliases when you use them. (e.g., I didn’t want to keep seeing /usr/local/codium
on my history so I decided to keep code
as an alias.)
Here is my current config.fish
file, in case it gives you some ideas. I’ve also listed links to the custom commands used to make it easier for you to find and install them.
if status is-interactive
#
# Aliases
#
# VSCodium
alias code '/usr/bin/codium'
#
# Abbreviations
#
# Copy and paste to the clipboard by piping to these commands.
# (Inspired by the default behaviour in macOS.)
abbr --add --global pbcopy 'xsel --clipboard --input'
abbr --add --global pbpaste 'xsel --clipboard --output'
# Open files in their associated apps from Terminal.
abbr --add --global open 'xdg-open &>/dev/null '
# Git aliases to make git a bit more humane for everyday use.
abbr --add --global git-log 'git log --graph --decorate --pretty=oneline --abbrev-commit'
abbr --add --global git-log-dates 'git log --graph --decorate --pretty=format:"%h [%cr] %s'
abbr --add --global git-tag 'git tag -n'
abbr --add --global git-undo-last-commit 'git reset HEAD~'
# Aliases for getting system and app information.
abbr --add --global system-information 'neofetch'
abbr --add --global disk-usage 'dust'
abbr --add --global which-kernel 'apt-cache policy linux-generic'
abbr --add --global node-v8-version 'node -p process.versions.v8'
# Make rm a little safer (have it prompt once when deleting
# more than three files or when deleting recursively).
abbr --add --global rm 'rm -I'
# A nicer ls that also shows the git status of files
abbr --add --global l 'exa -lh --git --all'
# A nicer ls that also shows the git status of files
# (but not hidden files)
abbr --add --global ll 'exa -lh --git'
# Same nicer ls but in tree view.
abbr --add --global lt 'exa -lh --git --all --tree'
# lc = line count
abbr --add --global lc 'wc -l'
# Find out what’s running on port X
abbr --add --global port 'lsof -i'
# Better find
abbr --add --global find 'fd'
# Better ps
abbr --add --global ps 'procs'
# Package.json validator
abbr --add --global validate-package.json 'pjv package.json'
# Use ripgrep instead of grep
abbr --add --global grep 'rg'
end
Tools mentioned in the configuration
-
XSel is a command-line program for getting and setting the contents of the X selection. Normally this is only accessible by manually highlighting information and pasting it with the middle mouse button.
-
xdg-open opens a file or URL in the person’s preferred application.
-
neofetch displays information about your operating system, software and hardware in an aesthetic and visually pleasing way.
-
dust is a more intuitive
du
for visualising disk usage. -
exa is a modern replacement for
ls
that uses colours to distinguish file types and metadata and knows about symlinks, extended attributes, and Git. -
fd is a simple, fast and user-friendly alternative to the
find
command for finding entries in your filesystem. -
procs is a replacement for
ps
in a human-readable format and with some other additional features. -
ripgrep (rg) is a line-oriented search tool that recursively searches the current directory for a regex pattern. It is similar to other popular search tools like The Silver Searcher,
ack
andgrep
. -
package.json validator (pjv) verifies that your package.json files are correct.
Next steps
This introductory post doesn’t even begin to scratch the surface of what you can do with Fish but I hope that it sparks your interest and whets your appetite.
To learn more, view the documentation on the Fish shell website. You can also launch the documentation in a browser locally from Fish shell itself using the help
command.
For example, to learn about abbreviations, run the following command:
help abbreviations
So, what are you waiting for?
Go Fish!
Like this? Fund us!
Small Technology Foundation is a tiny, independent not-for-profit.
We exist in part thanks to patronage by people like you. If you share our vision and want to support our work, please become a patron or donate to us today and help us continue to exist.
-
If you remove the seams altogether, you end up with the shiny locked boxes that Apple ships. Sure, they’re lovely to look at and use but you do so on the ever-evolving unilateral terms imposed by the corporation that makes them. This has considerable ramifications when it comes to protecting your freedom to own, control, and use your tools as you want to and impacts on your human rights (e.g., privacy), right to tinker, right to repair, etc. ↩︎