zsh and Oh My Zsh on Linux: Complete Setup Guide

zsh and Oh My Zsh on Linux: Complete Setup Guide

Tested on: Ubuntu 26.04 LTS · Debian 12 · Fedora 44 · Arch Linux · macOS Sequoia — Last updated: June 2026

Zsh (Z Shell) is a POSIX-compatible shell that improves on Bash with better tab completion, recursive globbing, spell correction, and a more powerful history system. Oh My Zsh wraps it in a plugin and theme framework that turns a competent shell into a genuinely productive environment. This guide covers installation, configuration, essential plugins, the Powerlevel10k prompt, and fzf integration — everything you need to go from a stock Bash prompt to a fully tuned zsh setup.

Contents
  1. Prerequisites
  2. Install zsh
  3. Set zsh as Your Default Shell
  4. What zsh Adds Over Bash
    1. Interactive Tab Completion
    2. Recursive Globbing
    3. Spell Correction and Helpful Options
    4. Shared History and Deduplication
  5. Install Oh My Zsh
  6. Essential Plugins
    1. Built-in Plugins
    2. Third-Party Plugins (Install Manually)
  7. Powerlevel10k — The Best Prompt
    1. Step 1: Install a Nerd Font
    2. Step 2: Install Powerlevel10k
  8. The ~/.zshrc Structure
  9. fzf — Fuzzy Finder Integration
    1. Further Reading

Prerequisites

  • A Linux system or macOS with terminal access (macOS ships with zsh already installed)
  • curl or wget and git installed
  • A terminal emulator that supports 256 colors — most modern ones do (GNOME Terminal, Kitty, Alacritty, iTerm2, WezTerm)
  • For Powerlevel10k: a Nerd Font installed and set in your terminal preferences

Install zsh

macOS Sequoia ships zsh as the default — skip ahead to setting it as default. On Linux, install from your package manager:

# Ubuntu / Debian:
sudo apt install zsh git curl

# Fedora:
sudo dnf install zsh git curl

# Arch Linux:
sudo pacman -S zsh git curl

# openSUSE:
sudo zypper install zsh git curl

# Verify the version:
zsh --version

Expected output:

zsh 5.9 (x86_64-ubuntu-linux-gnu)

Set zsh as Your Default Shell

# List shells available on your system:
cat /etc/shells

# Change default shell for your user:
chsh -s $(which zsh)

# Log out and back in, then verify:
echo $SHELL

Expected output after re-login:

/usr/bin/zsh

If chsh is unavailable or restricted (some corporate or containerized environments), add this to your ~/.bash_profile as a workaround:

echo 'exec zsh' >> ~/.bash_profile

The first time you launch zsh without an existing ~/.zshrc, it opens a configuration wizard. Press q to exit it — Oh My Zsh will generate a proper config file for you in the next step.

What zsh Adds Over Bash

Before reaching for Oh My Zsh, it's worth understanding what raw zsh gives you — these features work without any framework.

Interactive Tab Completion

Enable the completion system in ~/.zshrc (Oh My Zsh does this automatically, but here's what it looks like manually):

autoload -Uz compinit && compinit

With this active, pressing Tab after git shows a navigable menu of subcommands with descriptions. Pressing Tab after kill shows running processes. Arrow keys move through the menu; Enter selects.

Recursive Globbing

# Find all Python files in the current tree — no find or fd needed:
ls **/*.py

# Files modified within the last day:
ls -la *(m-1)

# Files larger than 1 MB:
ls -la *(Lm+1)

# Directories only:
ls -d **/

Spell Correction and Helpful Options

# Add to ~/.zshrc:
setopt CORRECT              # suggest corrections for mistyped commands
setopt AUTO_CD              # type a directory name to cd into it
setopt EXTENDED_GLOB        # enables extended globbing patterns

With CORRECT enabled, typing pyhon3 script.py produces:

zsh: correct 'pyhon3' to 'python3' [nyae]?

Shared History and Deduplication

# Add to ~/.zshrc:
setopt SHARE_HISTORY        # sync history across all open terminals
setopt HIST_IGNORE_DUPS     # skip duplicate consecutive commands
setopt HIST_IGNORE_SPACE    # skip commands prefixed with a space
setopt HIST_VERIFY          # show expanded history command before running

HISTSIZE=50000
SAVEHIST=50000
HISTFILE=~/.zsh_history

The space-prefix trick is particularly useful: prepend any command with a space and it won't appear in history — good for commands containing credentials.

Install Oh My Zsh

Oh My Zsh manages your zsh configuration, bundling 300+ plugins and 150+ themes. The installer backs up your existing ~/.zshrc, creates ~/.oh-my-zsh/, writes a fresh config, and sets zsh as your default shell if it isn't already.

sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

The installer output ends with something like:

         __                                     __
  ____  / /_     ____ ___  __  __   ____  _____/ /_
 / __ / __    / __ `__ / / / /  /_  / / ___/ __ 
/ /_/ / / / /  / / / / / / /_/ /    / /_(__  ) / / /
____/_/ /_/  /_/ /_/ /_/__, /    /___/____/_/ /_/
                         /____/

....is now installed!

Before you scream "Oh My Zsh!" please look over the ~/.zshrc file to select plugins, themes, and options.

To update Oh My Zsh at any time:

omz update

Essential Plugins

Plugins are enabled in the plugins=() array in ~/.zshrc. Order matters for the two syntax-related plugins — zsh-syntax-highlighting must be last.

Built-in Plugins

These ship with Oh My Zsh inside ~/.oh-my-zsh/plugins/. Enable them by name — no installation needed:

plugins=(
  git                 # git aliases (gst, gco, gcmsg, gp, gl, etc.) and branch in prompt
  docker              # docker and docker-compose completions and aliases
  kubectl             # kubernetes completion + kube-context in prompt
  python              # aliases: py=python3, pip=pip3, pyclean, etc.
  systemd             # aliases: sc-start, sc-stop, sc-status, sc-restart
  sudo                # press Esc twice to prepend sudo to the current/last command
  z                   # tracks directory visits; type 'z proj' to jump to ~/work/myproject
  history             # h = history, hsi = grep history, hsl = last 20
  colored-man-pages   # colorizes man page output — genuinely useful
  extract             # 'extract archive.tar.gz' works on any archive format
)

The sudo plugin deserves special mention: if you run a command and get a permission error, just double-tap Escape and zsh prepends sudo. No retyping.

Third-Party Plugins (Install Manually)

These two are non-negotiable — install them regardless of anything else:

# zsh-autosuggestions: shows command suggestions in grey as you type
# Accept with → (right arrow) or Ctrl+E
git clone https://github.com/zsh-users/zsh-autosuggestions 
  ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions

# zsh-syntax-highlighting: colors valid commands green, invalid ones red
# Catches typos before you hit Enter
git clone https://github.com/zsh-users/zsh-syntax-highlighting 
  ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting

Add them to your plugins list — syntax-highlighting goes last:

plugins=(
  git
  sudo
  z
  history
  colored-man-pages
  extract
  docker
  kubectl
  zsh-autosuggestions
  zsh-syntax-highlighting
)

Then reload:

source ~/.zshrc

Powerlevel10k — The Best Prompt

Powerlevel10k is the de facto standard zsh prompt. It renders asynchronously (the prompt never waits on slow operations like git status queries), is extremely configurable, and ships an interactive setup wizard.

Step 1: Install a Nerd Font

Powerlevel10k uses icons from Nerd Fonts for git symbols, directory separators, and status indicators. MesloLGS NF is the recommended choice:

mkdir -p ~/.local/share/fonts && cd ~/.local/share/fonts

# Download the four MesloLGS NF variants:
wget https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Regular.ttf
wget https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Bold.ttf
wget https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Italic.ttf
wget https://github.com/romkatv/powerlevel10k-media/raw/master/MesloLGS%20NF%20Bold%20Italic.ttf

# Rebuild font cache:
fc-cache -f

# Then go to your terminal's font settings and select "MesloLGS NF"

Step 2: Install Powerlevel10k

git clone --depth=1 https://github.com/romkatv/powerlevel10k.git 
  ${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/themes/powerlevel10k

Set the theme in ~/.zshrc:

ZSH_THEME="powerlevel10k/powerlevel10k"

Reload and the configuration wizard starts automatically:

source ~/.zshrc

The wizard asks a series of visual questions to detect font support and walks through style preferences: prompt shape (lean, classic, rainbow, pure), whether to show the current time, how to display git status, and what information segments to include. The output is written to ~/.p10k.zsh. Re-run the wizard anytime:

p10k configure

A configured p10k prompt shows: working directory (with intelligent path shortening), git branch, git status (staged/unstaged/untracked), Python virtualenv, kubectl context, last command exit code, and execution time for commands that took more than a threshold (default 3s). All of this updates without blocking your prompt.

The ~/.zshrc Structure

After Oh My Zsh and Powerlevel10k are set up, a clean ~/.zshrc looks like this:

# ~/.zshrc

# Powerlevel10k instant prompt — must be at the very top:
if [[ -r "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh" ]]; then
  source "${XDG_CACHE_HOME:-$HOME/.cache}/p10k-instant-prompt-${(%):-%n}.zsh"
fi

# Oh My Zsh installation path:
export ZSH="$HOME/.oh-my-zsh"

# Theme:
ZSH_THEME="powerlevel10k/powerlevel10k"

# Plugins:
plugins=(
  git sudo z history colored-man-pages extract
  docker kubectl
  zsh-autosuggestions
  zsh-syntax-highlighting
)

# Load Oh My Zsh:
source $ZSH/oh-my-zsh.sh

# ── Your customizations below this line ──────────────────────────

# History settings:
setopt SHARE_HISTORY
setopt HIST_IGNORE_DUPS
setopt HIST_IGNORE_SPACE
HISTSIZE=50000
SAVEHIST=50000

# Aliases:
alias ll='ls -alF'
alias ..='cd ..'
alias ...='cd ../..'
alias gs='git status'
alias gl='git log --oneline --graph --decorate'
alias ports='ss -tulpn'
alias myip='curl -s ifconfig.me'

# Functions:
mkcd() { mkdir -p "$1" && cd "$1"; }

# Load Powerlevel10k config:
[[ ! -f ~/.p10k.zsh ]] || source ~/.p10k.zsh

fzf — Fuzzy Finder Integration

fzf is a fast interactive filter for any list-based operation. Integrated with zsh, it replaces the default Ctrl+R history search with a full-screen fuzzy finder and adds fuzzy file and directory pickers.

# Install:
sudo apt install fzf # Ubuntu / Debian
sudo dnf install fzf # Fedora
sudo pacman -S fzf # Arch

# Enable zsh key bindings and completion:
# Ubuntu/Debian — source from the package's included files:
echo 'source /usr/share/doc/fzf/examples/key-bindings.zsh' >> ~/.zshrc
echo 'source /usr/share/doc/fzf/examples/


Go up