another man's ramblings on code and tech

Shell Wars: Fish VS Zsh

I think I'm a bit unique in the dev world in that I use two different shells as daily drivers. The two very powerful shells that I would recommend are Fish and Zsh. There are easy-install wrappers for them called OhMyFish and OhMyZsh; if you wanted to try one, I'd recommend using those resources. The two shells have similar goals; to supercharge your productivity and make working in a CLI more efficient and less tedious. They have similar features as well, however they both have unique differences in the ways they handle things. Here I'll go over the pros and cons of each that I've run into, and why I still use them both on a daily basis.

Autocompletion of Commands and Paths

The powerful standout feature with Zsh and Fish is their ability to allow for quick autocompletion of commands and paths. They allow you quickly sort through your command history and build paths on the fly. There are some idiosyncrasies unique to each shell, however:

  • Fish shows a preview of the full command it wants to autocomplete and allows stepping through one word at a time, know as Autosuggestions
    • Zsh by default shows no preview and cannot step through words in a command; I'm sure there's a plugin to do this though
  • Fish seems to have smoother integrations with various tools, including fzf, kubectx, and other bleeding edge stuff

Fish shell's autosuggestion feature allows you to build commands composed of earlier ones word by word

Beautiful Themes and Rich Plugin Ecosystems

This is a point that I give to both shells. They both provide for many beautiful, vibrant, and helpful themes. Fish does this on its OhMyFish Themes page and Zsh on its OhMyZsh page respectively. In addition, both have a rich ecosystem of plugins. I highly recommend the kubectl plugins for both Zsh and Fish, which reduce common long kubectl commands like kubctl get pods to kgp, and a series of other helpful shorthands.

My favourite theme is Batman, by the way. I don't personally like him as a hero, but I do like his beautiful theme.

The beautiful Batman theme

POSIX Compliance

The thing that drives most people away from Fish is that it's not POSIX compliant. The majority of the time, you're not going to be able to copy and paste code from Stack Overflow and watch it just work in Fish. You can always get around this by running your commands like sh -c 'YOUR COMMAND HERE', using the right shebang path in a script, or simple dropping into the shell you need for a moment to run the affected commands. Alas, this tends to be the detail that drives people away. However, on the plus side, the Fish language is a lot easier to use than arcane Bash syntax. For example, here's a Fish loop:

for var in a b c
    if break_from_loop

Looks much cleaner than the comparable Bash with it's intermix of do, done, then, and fi muddling it all up:

for var in a b c
    if [ break_from_loop ]

There are countless other examples of Fish being easier to handle than it's comparably arcane Bash equivalents.

Who's the winner in the end?

Well, as I said, I regularly use both Fish and Zsh at the moment. Fish is my default shell I use for getting around and running my everyday commands. I drop into Zsh when I need to run long Bash-like commands. The POSIX compatibility is usually a deal breaker for Fish, but I highly recommend trying it. Zsh is beautifully themed, but lacks some of the nicer integrations that Fish has with existing and emerging tools. Overall, they're both great CLI's to run with.

Date: Aug 16 2022