Why zsh isn’t just bash with sprinkles
Here’s the thing: bash is fine. It’s been fine for 30 years. But zsh is what bash would be if bash were designed by someone who actually used the shell every day instead of just once in 1989.
Let me walk you through the wins:
Smart tab completion — zsh context-aware tab completion will make you weep tears of joy the first time you use it. Bash gives you “complete the filename”. Zsh gives you “complete the filename, the flag, the flag argument, the command option, and also tell me what they all do while we’re at it”. Type git checkout [TAB] and watch zsh list branches with descriptions. Type apt install [TAB] and see available packages. It’s magic.
Shared history across tabs — Bash keeps each shell session’s history isolated. Close a tab, lose that history (unless you manually history -a). Zsh shares history across all open tabs in real-time. Every command you run anywhere is immediately available everywhere. This sounds small until you’ve used it for a week and can’t go back.
Better globbing — Zsh’s recursive globbing ** works intuitively. **/*.js actually does what you’d expect. Bash makes you jump through hoops with shopt -s globstar and even then it feels clunky.
Spelling correction — Type a command wrong and zsh will suggest a fix. Miss a typo in a file glob? Zsh catches it. It’s not annoying (you can disable it) but it’s useful.
Plugins and themes — This is optional, but the ecosystem is second to none. Syntax highlighting, auto-suggestions, directory jumping, git status in your prompt—all available with one line in your config.
Installing zsh and switching your default shell
On most modern Linux distros, zsh is already packaged:
sudo apt install zsh # Debian/Ubuntusudo dnf install zsh # Fedorasudo pacman -S zsh # ArchNow switch your default shell:
which zshchsh -s /bin/zsh(The first command tells you where zsh lives. Usually /bin/zsh or /usr/bin/zsh.)
Log out and back in. Your shell is now zsh. You’re already winning.
Oh My Zsh: the optional turbocharger
Oh My Zsh is a framework that makes configuring zsh less painful. It’s optional—you can configure zsh from scratch—but it’s convenient.
Install it:
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"It installs itself, creates a sensible ~/.zshrc, and you’re done. The script may ask to set zsh as your default shell—let it.
Pick a theme:
Edit ~/.zshrc and change the theme line:
ZSH_THEME="robbyrussell" # default, fineZSH_THEME="agnoster" # shows git branch, popularZSH_THEME="powerlevel10k" # fancy, requires nerd fontReload your shell: source ~/.zshrc
Essential plugins: the ones actually worth installing
Oh My Zsh ships with a huge plugin library. Most are noise. These are the winners:
zsh-autosuggestions — As you type, zsh suggests the previous command that matches. Hit → to accept it. Saves countless keystrokes.
zsh-syntax-highlighting — Your command turns red if it’s invalid, green if it’s good. Catches typos before you press Enter.
z — Jump to frequently-used directories by partial name. Type z blogs and you’re in /home/kingpin/steamz/code/sumguy_articles/sumguy-astro/src/data/blog/ without typing the full path. It learns as you navigate.
Enable them in ~/.zshrc:
plugins=(git z zsh-autosuggestions zsh-syntax-highlighting)Note: autosuggestions and syntax-highlighting need to be cloned into Oh My Zsh’s plugins directory first:
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestionsgit clone https://github.com/zsh-users/zsh-syntax-highlighting ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlightingThen reload: source ~/.zshrc
Essential .zshrc config
Your ~/.zshrc is where the magic lives. Here are the lines that matter:
# Make history bigger and smarterHISTSIZE=100000SAVEHIST=100000setopt SHARE_HISTORY # share across all shellssetopt HIST_IGNORE_DUPS # don't record duplicate commandssetopt HIST_IGNORE_SPACE # don't record commands starting with space
# Better completionsetopt MENU_COMPLETE # complete on first tab, cycle with more tabssetopt COMPLETE_IN_WORD # complete in the middle of words
# Friendly correctionssetopt CORRECT # suggest correctionssetopt CORRECT_ALL # correct all words, not just commands
# Case insensitive globbingsetopt NO_CASE_GLOBMigrating your aliases and functions
If you’ve got a bunch of bash aliases in ~/.bashrc, just copy them to ~/.zshrc. They work identically.
Bash functions? Same thing. Paste them into ~/.zshrc after the oh-my-zsh setup and they work fine.
# Copy this into ~/.zshrcalias gs='git status'alias ga='git add .'alias gc='git commit -m'alias ll='ls -lh'
# Functions work toomkcd() { mkdir -p "$1" && cd "$1"; }The gotcha that still trips everyone up
Here it is: Your shell scripts should still use #!/bin/bash as the shebang.
Your personal shell config is zsh. But the scripts you write and share? Those should target bash. Why? Because:
- Bash is more portable (still standard on macOS, all Linux distros, BSD)
- Some zsh syntax won’t work in bash and vice versa
- Your script might run in a container, on a CI server, or someone else’s machine where zsh isn’t installed
Write your personal config in zsh. Write your scripts in bash. Use zsh at the terminal, bash in your .sh files. That’s the deal.
You’re done
That’s it. Zsh installed, customized, and ready to make your terminal life objectively better. Go configure away. Your future self typing thousands of fewer characters will thank you.