Building a Better Terminal: zsh, Oh My Zsh, and a Modern Toolbelt
Set up zsh with Oh My Zsh, a fast Starship prompt, and modern replacements for ls, cat, history search, and cd — step by step, on macOS or Ubuntu.
What you'll build
By the end of this tutorial you'll have a configured zsh shell running Oh My Zsh (with autosuggestions and syntax highlighting), a clean cross-shell prompt powered by Starship, and four modern command-line tools — eza, bat, fzf, and zoxide — that improve on ls, cat, history search, and directory navigation.
Prerequisites
- macOS (Apple Silicon or Intel) or a Debian/Ubuntu Linux machine.
- A terminal you can run commands in.
- Homebrew on macOS. Install it from brew.sh if you don't have it, then check:
brew --version. - On Linux,
sudoaccess forapt. gitandcurlinstalled (git --version,curl --version).- A Nerd Font for the prompt's icons. Install one with
brew install --cask font-fira-code-nerd-font(macOS) or download from nerdfonts.com, then set it as your terminal's font in its preferences.
Homebrew font note: Fonts were merged into the main Homebrew cask repo in 2024. Run
brew updatefirst so the cask resolves. On a very old Homebrew install you may still need to runbrew tap homebrew/cask-fontsbefore the--cask font-fira-code-nerd-fontcommand works.
macOS has shipped zsh as the default shell since Catalina (10.15). Most Linux distros default to bash, so we install zsh below.
Step 1: Install zsh and make it your default shell
macOS already has zsh, so skip the install. On Debian/Ubuntu:
sudo apt update
sudo apt install -y zsh
Confirm the version (you want 5.x or newer):
zsh --version
Set zsh as your login shell (works on both OSes):
chsh -s $(which zsh)
Log out and back in (or open a new terminal window) for the change to take effect.
Step 2: Install Oh My Zsh
Oh My Zsh is a framework that manages your zsh configuration, plugins, and themes. Install it with the official script:
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"
This creates ~/.zshrc and a ~/.oh-my-zsh directory. If it asks to change your default shell and you already did Step 1, you can decline.
Step 3: Add autosuggestions and syntax highlighting
These two plugins live outside Oh My Zsh, so clone them into the custom plugins folder:
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
Open ~/.zshrc in your editor and find the plugins=(...) line. Replace it with:
plugins=(git zsh-autosuggestions zsh-syntax-highlighting)
zsh-syntax-highlightingmust be the last plugin listed — it wraps the command line and needs to load after the others.
Step 4: Install the modern toolbelt
Here's what each tool does:
| Tool | Improves on | What it adds |
|---|---|---|
| eza | ls |
Colors, icons, git status, tree view |
| bat | cat |
Syntax highlighting, line numbers, paging |
| fzf | history/file search | Fuzzy interactive finder |
| zoxide | cd (adds z) |
Jump to frequently used dirs by name |
About zoxide: By default,
zoxide init zshdoes not replacecd. Your normalcdkeeps working, and zoxide adds a newzcommand plus a hook that learns which directories you visit. If you'd rather havezoverride thecdcommand itself, initialize it withzoxide init zsh --cmd cdin Step 5 instead.
macOS (Homebrew):
brew install eza bat fzf zoxide starship
Debian/Ubuntu:
sudo apt update
sudo apt install -y bat fzf
On Ubuntu, bat installs as the command batcat (a naming conflict), and eza / zoxide / starship aren't always in the default repos. Install the rest with the official scripts (review them first by opening the URL in a browser):
# zoxide (installs to ~/.local/bin by default)
curl -sSfL https://raw.githubusercontent.com/ajeetdsouza/zoxide/main/install.sh | sh
# starship (installs to /usr/local/bin by default; may prompt for sudo)
curl -sS https://starship.rs/install.sh | sh
For eza on Ubuntu, follow the apt-repo steps in the eza installation docs, or install Rust's cargo and run cargo install eza.
Step 5: Wire everything into ~/.zshrc
Ubuntu/apt users, read this first. The fzf --zsh command (used below) requires fzf 0.48 or newer. Ubuntu's apt repo ships much older versions (e.g. 0.29 on 22.04), so that line will error out when you reload. You have two options:
-
Easiest: in the block below, replace the
source <(fzf --zsh)line with the two fallback files that ship with the apt package:source /usr/share/doc/fzf/examples/key-bindings.zsh source /usr/share/doc/fzf/examples/completion.zshThe first file gives you the key bindings (Ctrl-R history search, Ctrl-T file search); the second enables fuzzy tab-completion. You need both for full functionality.
-
Or install a newer fzf (0.48+) so the
fzf --zshline works as written. fzf is written in Go (not Rust), so don't try tocargo installit. Use one of these instead:- Homebrew on Linux:
brew install fzf - Official git install:
git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf && ~/.fzf/install - Release binary: download the latest archive for your platform from the fzf releases page and put the
fzfbinary somewhere on yourPATH.
- Homebrew on Linux:
Now add the following block to the bottom of ~/.zshrc:
# --- Starship prompt ---
eval "$(starship init zsh)"
# --- zoxide (adds the `z` command; cd is unchanged) ---
eval "$(zoxide init zsh)"
# --- fzf key bindings and completion (fzf 0.48+) ---
# Ubuntu/apt users: replace the next line with the two source lines above.
source <(fzf --zsh)
# --- aliases for modern tools ---
alias ls='eza --icons --group-directories-first'
alias ll='eza -lah --icons --group-directories-first'
# A separate alias keeps the real `cat` intact:
alias cl='bat'
Notes:
- We use
clforbatrather than overridingcat. Globally aliasingcattobatcan surprise you (paging and decorations in interactive use) and confuse scripts that expect plaincat. (For the record,batautomatically strips decorations and disables paging when its output isn't a terminal — e.g. when piped — sobat file | grep ...behaves likecat. Using a separate alias just avoids the surprise.) If you're on Ubuntu where bat isbatcat, usealias cl='batcat'. - Because Starship now draws your prompt, you can leave Oh My Zsh's
ZSH_THEMEline as-is — Starship'sinitruns last and takes over.
Reload your shell:
source ~/.zshrc
Verify it works
Run these checks:
starship --version # prints a version, prompt shows a styled path
ls # icons + colors via eza
cl ~/.zshrc # syntax-highlighted via bat
- Start typing a command (e.g.
git st) — a gray suggestion appears; press the → (right arrow) to accept it. - Press Ctrl-R to fuzzy-search history with fzf; type part of an old command and hit Enter.
- Teach zoxide by
cd-ing into a few directories, then jump withz foldernamefrom anywhere. (Remember:cditself is unchanged — you navigate fast withz. If you used--cmd cd, then plaincd foldernamedoes the fuzzy jump.) - Valid commands turn green, unknown ones stay red (syntax highlighting).
Troubleshooting
Prompt shows boxes or question marks instead of icons. Your terminal isn't using a Nerd Font. Install one (see Prerequisites) and select it in your terminal app's font settings.
command not found: starship (or eza/zoxide) after install. The install directory isn't on your PATH. Note the defaults differ per tool:
-
zoxide's install script defaults to
~/.local/bin. If that's missing from yourPATH, add it near the top of~/.zshrc, thensource ~/.zshrc:export PATH="$HOME/.local/bin:$PATH" -
starship's install script defaults to
/usr/local/bin(and typically prompts for sudo). That directory is usually already onPATH, so the~/.local/binfix above won't help here. If you want starship in~/.local/bininstead, install it explicitly:curl -sS https://starship.rs/install.sh | sh -s -- --bin-dir "$HOME/.local/bin"(then make sure that directory is on yourPATH).
source ~/.zshrc errors on the fzf line (unknown option: --zsh). Your fzf is older than 0.48 (common on Ubuntu/apt). Replace source <(fzf --zsh) with the two source /usr/share/doc/fzf/examples/... lines shown in Step 5, or install a newer fzf via Homebrew, the official git installer, or a release binary.
Ubuntu: bat: command not found. It's installed as batcat. Either use that name or create a symlink: mkdir -p ~/.local/bin && ln -s $(which batcat) ~/.local/bin/bat.
Next steps
- Customize the prompt by creating
~/.config/starship.toml— see the Starship configuration docs. - Explore more Oh My Zsh plugins like
docker,kubectl, andzin the plugins directory. - Add
fdandripgrep(brew install fd ripgrep) and point fzf at them withFZF_DEFAULT_COMMANDfor faster file searches.
Discussion 1
Join the discussion
Sign in with GitHub to comment and vote.
i just set up starship on my zsh and it's been a game changer, the prompt is so much cleaner and more informative than what i had before, definitely going to check out eza and bat next