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 realise just how easy it is to extend as nearly everything is a function.
First off, download and install Fish shell.
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.
Out of the box, you will get the excellent auto-suggest/completion.
While Fish shell is perfectly usable without customisations, there 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 would highly recommend you do is to install 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
Following is a brief list of the ones I installed.
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.)
Install using Fisher:
fisher install IlanCosman/tide
Making a plugin is so simple in Fish (it’s just a function) that I’ve already made my own (very simple one) even though I only just started using it yesterday.
The plugin, which I call Gills, 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 that handles Fish shell’s
(It also handles a couple of special cases like
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 using Fisher:
fisher install small-tech/gills
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 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
.nvmrc files so pop one of those bad boys into your project directory to automatically have the Node version specified within available when you switch to the directory in your shell.
One feature of Zsh that I use all the time is to navigate back multiple directories by simply 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 lets Fish shell do the same thing. Actually, it’s even better because you get in-place expansion.
Install using Fisher:
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
I like and use the Dracula theme pretty much everywhere and, of course, there is a version for Fish.
Install it using Fisher:
fisher install dracula/fish
If you’re coming from Bash or, like me, from Zsh, you might be wondering where to put your aliases, etc. The equivalent of
~/.zshrc in Fish is
You can also configure your shell visually in your web browser by running the following command in your terminal:
Also, while Fish does have aliases, it also has a much more powerful alternative called 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
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
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 and grep.
package.json validator (pjv) verifies that your package.json files are correct.
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 about it, view the documentation on the Fish shell website. You can also launch the documentation in a browser locally from Fish shell itself using the
For example, to learn about abbreviations, run the following command:
Have fun and remember: There might be plenty of other shells in the ocean, but only this one is a fish. (Again, I’m really sorry, I don’t know why I’m like this either.)
Small Technology Foundation is a tiny, independent not-for-profit.
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. ↩︎