Moving from Zsh to Fish 🐠

I recently began experimenting with Fish after a long time using zsh and oh my zsh. Thus far it’s been a good experience so thought I’d share why I did it, how I tweaked my setup and my thoughts on Fish so far. I also share some of the many mistakes I made in trying to configure fish to behave a bit like a faster zsh. If nothing else writing this is helpful so I remember next time I need to set this up.

Why

I’ve always liked zsh since being introduced to it while working at the mighty Mochi Media and have had maybe too much fun customizing my prompt over the years. But the persistent performance issues really began to bother me over the last year or two. Indeed there is a whole genre of blog posts spun up focused on addressing this issue. Specifically starting up a new shell is often painfully slow. I haven’t measured the latency but anecdotally it often seems to be >5 seconds just to get a new zsh prompt. So I experimented a bit with fish to compare and have yet to notice any such lag or latency.

My Arguably Unreasonable Requirements

Ok so now comes the hard part. Specifically I need fish to be fast as mentioned previously, but I also need it to be easy to use and behave more or less like zsh.

So my requirements are simple but arguably silly:

1. Speed

Zsh has always been laggy for me and at times I’ve hacked on my .zshrc to try to speed it up, but it just never felt snappy.

2. Fancy customizable prompt

I don’t care if this is silly fluff. I like it and I’m keeping it.

So far I would call this prompt sufficiently fancy and just the right amount of unnecessarily shiny.

By default fish has its own style of last command substitution using up arrow key but after having used it a bit my fingers prefer plain old ctrl-r.

4. bash/zsh-style Command Substitution

!!and !$ last command substitution. This one is tough, it’s very un-fish-like


What I did

1. Install fish

Do the easy thing on Mac:

$ brew install fish
$ fish --version
fish, version 3.1.2

I should say as well that I’m using iTerm2 (3.4.0 beta12) with patched Powerline fonts (MesloLGS NF).

2. Install oh-my-fish aka omf

oh-my-fish is apparently the most popular fish plugin manager and works as expected if you’re familiar with oh-my-zsh. I know curl piping to source thing is terrible and makes security people cringe but I used it anyway.

$ curl -L https://get.oh-my.fish | fish
$ omf version
Oh My Fish version 7

3. Install fisher

Fisher is a popular fish plugin manager. But why two plugin managers? Fisher is necessary to install fzf.fish

$ curl -sL https://git.io/fisher | source && fisher install jorgebucaran/fisher

4. Install fzf.fish

FZF really supercharges history search and comes with Ctrl-r as default so I installed fzf.fish

$ fisher install PatrickF1/fzf.fish

Example of using FZF via Ctrl-r in fish.

5. Emulate Bash Command Substitution

My fingers are used to !! and !$ (shorthand for last command and last argument of last command respectively) and emit them almost automatically at this point. So I’m skeptical that I could ever learn a new style. By following along with this StackOverflow thread and this page on the fish wiki I was able to get both bangbang and bangdollar to work.

I created the file ~/.config/fish/config.fish and pasted functions bind_bang, bind_dollar and fish_user_key_bindings in and it works great.


Mistakes I Made Along The Way

  1. Mucking around with too many plugins at once
  2. Misunderstanding fish’s “interactive first” mindset
  3. Having omf and tide collide and breaking my prompt
  4. Expecting fish to be equivalent to zsh out-of-the-box
  5. Making some changes in interactive mode and others in config files
  6. This goes for everything ever but: not fully reading the docs. I simply scan them and then copy/paste something

One Last Bit

The only snag remaining is an issue I encountered when trying to change my default shell to fish. Specifically after making the change in /etc/shells and with chsh the look of my bobthefish based prompt changes and lacks the colors and icons I like in the screenshot above.

Further Reading