Introduction
For most Linux users, the terminal is where they actually live. Package updates, git, servers, container logs, config files — it all funnels through the shell. Which makes your choice of shell the single most-repeated piece of software you interact with. Yet most people still run whatever shipped by default: Bash.
I used Bash for years. I never hated it — it was just there. Then I switched to Zsh with Oh My Zsh on my workstation. The first week felt like someone quietly upgraded my terminal. Commands I typed from memory started appearing before I finished typing. Typos highlighted themselves in red before I hit Enter. The prompt showed me which branch I was on, what the last command cost, and where I stood.
This is not a post about hating Bash. It is a post about why interactive, everyday Linux desktops and dev machines work better with Zsh — and why Oh My Zsh makes that switch painless. And it is honest about when you should not switch.
Why Your Interactive Shell Matters
Here is the math. Every command you type is a transaction: type, check, fix, rerun. Bash gives you raw tools for that transaction. Zsh gives you a user interface for it.
The difference shows up in small ways that compound:
- you don't scroll through history with arrow keys anymore — you search it
- you don't retype what you typed yesterday — autosuggestions finish it
- you don't misread a command — syntax highlighting flags it
- you don't guess at completions — they show up, filtered
None of these are "set up your dotfiles like a neckbeard" tricks. They are defaults once you install the right plugins. The terminal is the one place where a 10-minute setup improves every command you type afterwards.
What Zsh Gives You That Bash Doesn't
Zsh is a superset of Bash's interactive behavior with better ergonomics. The headline features:
| Feature | Bash | Zsh |
|---|---|---|
| Live autosuggestions | no (needs ble.sh) | yes, via plugin |
| Syntax highlighting while typing | no | yes, via plugin |
| Rich tab-completion (git, docker, kubectl) | basic | deep, extensible |
Recursive globbing (**/*.md) |
via globstar opt-in |
built-in, natural |
| Configurable prompt with git info | manual | themes do it for you |
| One-based arrays / scripts semantics | POSIX-ish | different, careful |
The pragmatic wins for daily use:
Autosuggestions. You start typing git pu and zsh quietly suggests the rest: git push origin main. Press right-arrow, done. The feature alone kills thousands of arrow-key taps a day.
Syntax highlighting. Commands colorize as you type. A valid command is green; a typo is red; a dangerous redirect stands out. Mistakes get caught before Enter, not after.
Completions. Zsh's completion system is genuinely different from Bash's. It groups, describes, and filters. git ch <Tab> doesn't dump raw options — it shows branches, sorted and searchable. Same for systemctl, docker, kubectl, and anything with a completion definition.
Recursive globbing. find . -name "*.py" becomes **/*.py. Small, but it changes how you think about paths.
The prompt. With a theme, one glance tells you the branch, dirty-file count, exit code of the last command, and how long it took. My Bash prompt was a username, a hostname, and a dollar sign. I did not notice how much context I was missing until it appeared.
Where Oh My Zsh Fits In
Zsh alone gives you the engine. Oh My Zsh, from ohmyz.sh, is the community framework that makes the engine usable — a plugin and theme ecosystem with batteries included.
Why it matters for a switcher:
- No dotfile archaeology. One install command and you have a sane
~/.zshrc, syntax highlighting, history config, and a decent prompt. - Plugins as one-liners. Want git shortcuts?
plugins=(git)and you get 100+ aliases. Want autosuggestions? Add the plugin, done. No hunting for snippets. - Themes that look like the demos.
agnoster,powerlevel10k,robbyrussell— oneZSH_THEME="..."line away. - Huge community. Anything you want to do — a plugin exists or the docs show the pattern.
It is not the only framework (Prezto, Zim, Zinit, Antigen all exist, and several are faster), but it is the one with the lowest barrier to entry and the largest ecosystem. For a first switch, that matters more than startup microbenchmarks.
Plugins That Pay For Themselves
Start minimal. Three plugins give 80% of the daily value:
plugins=(git zsh-autosuggestions zsh-syntax-highlighting)
If you installed Oh My Zsh the standard way, the last two come from the plugin repos:
git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
Then add them to the plugins=(...) line in ~/.zshrc and reload with source ~/.zshrc.
After the first week, worth adding:
zsh-completions— extra completion definitions for dozens of toolszoxide— a smartercdthat learns where you actually go (z blog, notcd ~/Documents/blog)docker/kubectl/terraform— alias + completion packs for your daily toolshistory-substring-search— type a fragment, arrow through matching history
The rule: every plugin adds startup cost, so only keep what you use weekly. Resisting the urge to install all 200 visible plugins is a feature, not a bug.
Installing On Fedora / AlmaLinux / Rocky
Good news for the RHEL family: zsh, git, and curl all live in the default BaseOS/AppStream repos on Fedora, AlmaLinux, and Rocky — no EPEL needed for this one. Same dnf command across all three:
sudo dnf install -y zsh git curl
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
That's it — the same command works whether you're on Fedora Workstation, an AlmaLinux server, or a Rocky Linux box. The installer detects your current shell, builds ~/.zshrc, and — same as everywhere else — offers to set Zsh as your default shell before it exits.
If you're running this on a minimal server install (common on AlmaLinux/Rocky VPS images) and curl isn't already there, the command above pulls it in as part of the same install line, so you don't need a separate step.
Installing On Debian / Ubuntu
The classic path, and the one that matches most of my earlier posts on this blog:
sudo apt update
sudo apt install zsh git curl
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
The installer detects your existing shell, creates ~/.zshrc, and — if you say yes — offers to set Zsh as your default shell right away.
Setting Zsh As Your Default
If you skip the installer prompt, do it manually:
chsh -s $(which zsh)
Log out and back in. Verify with:
echo $SHELL
It should print /bin/zsh or /usr/bin/zsh. (This is also your rollback path: chsh -s /bin/bash undoes everything.)
One migration tip worth following: keep your portable setup in the right files.
~/.zshenv— PATH and environment variables (runs for every zsh, interactive or not)~/.zshrc— interactive aliases, functions, plugins, theme~/.zprofile— login-time setup
Moving a Bash setup over is mostly copying export lines into ~/.zshenv and alias lines into ~/.zshrc. A full guide to the migration is at carlosroso.com, which covers the pitfalls I skipped over here.
The Honest Tradeoffs: When Bash Stays
Nuance time, because "everyone should switch" is only true for interactive machines.
Keep Bash — or /bin/sh — in these places:
- Servers and containers. Bash is there, always, and it starts fast. A login shell gaining 100–500 ms of plugin load matters on every SSH session. Raw zsh cold-start tends to run noticeably slower than Bash's even before any plugins are loaded, and an unoptimized Oh My Zsh setup can push interactive startup past half a second.
- CI pipelines and cron. Anything non-interactive, where output is consumed by machines, should stay POSIX-ish and boring. Scripts must survive on images you don't control.
- Anything where third-party code is policy-limited. Plugins are community code. There have been real CVEs in the Oh My Zsh plugin ecosystem, including a 2026 arbitrary-code-execution fix in the
dotenvplugin. Keep plugin lists short, update them, and never source untrusted directories. The hoop.dev securing-zsh guide is a good audit checklist.
Keep your scripts portable. Zsh is not a drop-in replacement for POSIX/Bash scripting. Arrays are one-based, floating-point arithmetic differs, and sh-oriented scripts can break. The rule that keeps everyone sane: interactive shell = zsh; scripts = /bin/sh or bash with set -euo pipefail. This is why my own posts and scripts on this blog still say #!/bin/bash — that's deliberate, and it's exactly the split I'm recommending.
If you genuinely love Bash but want the features, ble.sh brings autosuggestions and highlighting into Bash, and Bash-it offers a plugin/theme bundle. They're real options. They just aren't as mature or as widely documented as the Zsh ecosystem.
Making Zsh Fast Again
The one real objection to Zsh + Oh My Zsh is startup time. It is also solvable.
- Use a fast prompt. Swap the default theme for Powerlevel10k (instant, fully configurable, git info included) or an external prompt like Starship (one config across zsh, bash, fish).
- Lazy-load heavy tools. Don't initialize
nvmor language managers at startup. Defer them with a function:
load-nvm() {
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
}
nvm() { load-nvm; nvm "$@"; }
- Cache completions.
compinit -Cskips the slow recompilation pass on every start. - Cut plugins. Every plugin adds load. Ten rules-of-thumb plugins are faster than fifty.
Applied, these get an interactive Zsh close to Bash's startup — and for a tool you invoke hundreds of times a day, interactive responsiveness matters more than a few milliseconds either way.
Final Thought
My take, after running Zsh on desktops and dev machines: switch your interactive shell, respect your scripts.
Zsh with a minimal Oh My Zsh set changes the feel of the terminal in ways that compound daily — fewer typo round-trips, less history scrolling, more context in the prompt. The switching cost is one install command and an afternoon of tweaking a theme. The Bash skills you already have transfer; aliases and muscle memory carry over; nothing breaks overnight.
And keep Bash for servers, CI, and scripts. That split gives you the comfortable interactive shell today and the boring, dependable shell where it matters. Best of both worlds.
Start with the four plugins: git, zsh-autosuggestions, zsh-syntax-highlighting, and one good theme. A week later, the terminal feels like it belongs to you.