Drop Bash for fish shell to get beautiful defaults

The fish-themed "friendly interactive shell" creates a more enjoyable experience on the command line.
148 readers like this
148 readers like this
Jump-start your career with open source skills

Opensource.com

I am one of those people who immediately opens a terminal window after my computer boots up. It's not out of necessity at this point, but the habit is there. I spent most of my career learning its magical incantations, and I find navigating through my daily tasks on the terminal makes for a more enjoyable day at work. That all said, it's nice to try something new once in a while.

I recently let go of the default command line interpreter, Bash, in favor of fish, which proudly markets itself as "a command line shell for the '90s." Here's why I switched.

fish shell website

I found that .bashrc is not enough

A little over a year ago I decided to stop abstracting away my operating systems and start to learn it from the ground up. I recently switched from Mac to Linux, which gave me a reason to look into porting my dotfiles to the new environment. It was refreshing; I found a ton of confusing shortcuts and duplication and paired it down to something that ports between operating systems well. Here are a few favorites:

## Nicer shell experience
export GREP_OPTIONS="--color=auto"; # make grep colorful
export LSCOLORS=gxfxbEaEBxxEhEhBaDaCaD; # make ls more colorful as well
export HISTSIZE=32768; # Larger bash history (allow 32³ entries; default is 500)
export HISTFILESIZE=$HISTSIZE;
export HISTCONTROL=ignoredups; # Remove duplicates from history. I use `git status` a lot.
export HISTIGNORE="ls:cd:cd -:pwd:exit:date:* --help"; # Make some commands not show up in history
export LANG="en_US.UTF-8"; # Language formatting is still important
export LC_ALL="en_US.UTF-8"; # byte-wise sorting and force language for those pesky apps
export MANPAGER="less -X"; # Less is more
export GPG_TTY=$(tty); # for gpg key management

I've been on a journey to demystify the magic of my environment, and it is starting to make more sense.

Customization breaks my .bashrc

It's at this point of clarity that I got stuck again. I want some modern conventions in my terminal, especially auto-suggestions, syntax highlighting, and colorization of command outputs without too many dependencies, and I'd like that configuration to be independent of whatever command line interpreter I'm running. (iTerm2 is great on a Mac, but I don't want to track its cryptic configuration file in my dotfiles.) So what am I to do?

The first time I went after an answer, I solved it one step at a time:

  • First, I customized my ~/.inputrc file to allow for forward and backward search.
  • Then, I replaced cat with the prettified output of ccat and aliased cat to ccat in my .bashrc. This later eventually broke writing to stdout in some cases, so I stopped using it.
  • Ultimately, I used Bash-it, which is a powerful plugin system for customizing Bash.

After peeling back the pieces one-by-one, I felt I understood a bit more about how my system ran. The hoops I felt like I had to jump through to get the modern experience I sought led me back to the standards that brought me to this point. I felt like I was a prisoner of history until I decided to throw it all away and try something totally different.

Easy defaults and customization with fish shell

Fish shell is a modern command-line interface with auto-suggestions, tab completion, and syntax highlighting (among other features). I especially like how from the first time you give it a try by typing fish, you get a beautiful experience:

An example of the fish shell with Solarized Light theme

In the first line, the command is blue because pwd is a valid command. On the second line, it is red because pdw is not a valid command. I hit Enter to show that it's true, but I could have quickly corrected the error and moved on with my day. In the third command, I want to change directory (cd) into my Development folder, and fish automatically asks whether I want to hop into my dotfiles, as I did the last time. When I hit Tab twice, it shows other options in the same directory, just like I'd expect.

If I want to customize my fish shell experience, I don't need to install any additional library or framework to do so. Fish ships with the fish_config command, which launches a graphical user interface (GUI) where you can choose different colors and prompt configurations.

fish shell's colors

What's more impressive is you can review all available functions, variables, bindings, and more from the GUI as well:

fish functions

If you tune your configuration, all customizations are stored in the same place: ~/.config/fish. The screenshot above shows that I made a custom function that allows me to easily activate a Python environment using pyenv. Check out the tutorial on fish functions for more.

Be warned: fish is not like Bash

When trying out other shells, I found there were always a few differences I needed to tune, but they felt familiar overall. That is not the case with fish. Function definition, aliasing, and variables all work a little differently. There are helpful strategies for converting .bashrc and .bash_profile files into fish configuration, but it's more than I will cover in this article. So, while I've grown to love fish, I recommend taking the interactive tutorial for a spin to see if you like it.

Give fish a try for a beautiful default shell

I enjoy starting my day by opening up the terminal, and I enjoy it even more since switching to the fish shell. It's allowed me to shift away from worrying about what's in Bash to focusing on what code I plan to write. If you're looking to move away from tinkering with your terminal and focus more on code, give it a try. Use chsh to set it as your default shell, and let me know how it goes in the comments.

What to read next
I'm happiest at a microphone
Matt is an advocate for open source software and currently the Managing Editor of Enable Architect. He specializes in designing technology communities that develop products and content in a way that tells a powerful story.

8 Comments

"I recently let go of the default terminal emulator, Bash"

Bash and Fish aren't terminal emulators, they are command language interpreters (as written in the man page). Otherwise, nice article. I wasn't aware of fish_config command, it looks very useful.

To follow up on this, the terminal emulator is usually an application, ex: iTerm3, rxvt, Gnome Terminal, etc. These provide your graphical UI and rendering and some UX enhancements (check out Terminology).

The phrasing comes from the fact that this functionality used to come from physical terminals like the DEC VT500. You may notice "VT100 compatibility" still listed in a few places as it is a logical fallback to ensure basic functions are available even now.

In reply to by Matthew Broberg

keep real ,keep simple,safe is priority.
I love bash.

I also use bash however changing your shell to fish may have unintended side-effects. For instance /etc/profile{,.d} isn't automatically sourced and can't be sourced with fish.

A hack that I and others use from the archlinux wiki is having bash be the main shell and initialise fish when the session is interactive:

if [[ $(ps --no-header --pid=$PPID --format=cmd) != "fish" ]]
then
exec fish
fi

Try zsh. 100% bash compatible, has all the features of fish, only faster. Combine it with Powerlevel10k and you have a lightning fast, functional, beautiful prompt. And MacOS use zsh as their default shell now. Not that I use Mac's, eurgh

Fish is interesting. Too much a change for me, though. I'll stick with Bash , thanks!

I'm always happy to explore and learn new things. In fact, I spend most of my time sidetracking into new terrain when I see something like this.
That being said, just like coming home, I always gravitate back to good old bash.

Creative Commons LicenseThis work is licensed under a Creative Commons Attribution-Share Alike 4.0 International License.