TechLead
Lesson 8 of 20
5 min read
DevTools & Productivity

Zsh and Oh My Zsh

Configure Zsh with Oh My Zsh, Powerlevel10k, plugins, and custom themes for a beautiful and productive shell

Why Zsh?

Zsh (Z shell) is the default shell on macOS and is available on all major Linux distributions. It is fully compatible with Bash but adds powerful features like better tab completion, spelling correction, programmable command-line editing, shared command history, and a rich plugin ecosystem. Combined with Oh My Zsh, it becomes the most productive shell environment available.

Zsh Advantages Over Bash

  • Better Tab Completion: Case-insensitive, substring matching, and menu-style completion
  • Shared History: All terminal sessions share the same history file in real time
  • Globbing: Extended glob patterns like **/*.ts work natively without shopt
  • Spelling Correction: Automatically suggests corrections for mistyped commands
  • Plugin System: Rich ecosystem of plugins via Oh My Zsh, zinit, or antigen

Installing Oh My Zsh

# Install Oh My Zsh (one-liner)
sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"

# This creates ~/.oh-my-zsh/ and updates ~/.zshrc
# The framework manages plugins, themes, and configuration

Installing Powerlevel10k Theme

Powerlevel10k is the most popular Zsh theme. It provides a beautiful, informative prompt that shows git status, node version, execution time, error codes, and more. It is extremely fast - the prompt renders instantly even in large repositories.

# Install Powerlevel10k
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git \
  $ZSH_CUSTOM/themes/powerlevel10k

# Set the theme in ~/.zshrc
ZSH_THEME="powerlevel10k/powerlevel10k"

# Reload and run configuration wizard
source ~/.zshrc
# Or manually run: p10k configure

# Install recommended font (MesloLGS NF)
# Download from: https://github.com/romkatv/powerlevel10k#fonts
# Then set it as your terminal font

Essential Oh My Zsh Plugins

Edit the plugins array in ~/.zshrc to enable plugins:

# ~/.zshrc - Plugin configuration
plugins=(
  git                    # Git aliases (gst, ga, gc, gp, etc.)
  z                      # Jump to frequently used directories
  zsh-autosuggestions    # Fish-like auto-suggestions from history
  zsh-syntax-highlighting # Syntax highlighting for commands
  docker                 # Docker command completion
  npm                    # npm command completion and aliases
  node                   # Node.js version display
  extract                # Extract any archive with 'extract' command
  web-search             # Search Google/DuckDuckGo from terminal
  copypath               # Copy current directory path to clipboard
  copyfile               # Copy file contents to clipboard
  jsontools              # JSON pretty-printing and validation
  sudo                   # Double-press Escape to prepend sudo
  history                # History command aliases
  colored-man-pages      # Colorized man pages
)

Installing Third-Party Plugins

# zsh-autosuggestions (Fish-like suggestions)
git clone https://github.com/zsh-users/zsh-autosuggestions \
  $ZSH_CUSTOM/plugins/zsh-autosuggestions

# zsh-syntax-highlighting (colors for valid/invalid commands)
git clone https://github.com/zsh-users/zsh-syntax-highlighting \
  $ZSH_CUSTOM/plugins/zsh-syntax-highlighting

# zsh-completions (additional completion definitions)
git clone https://github.com/zsh-users/zsh-completions \
  $ZSH_CUSTOM/plugins/zsh-completions

# After installing, add to plugins array in ~/.zshrc and reload
source ~/.zshrc

Git Plugin Aliases

The git Oh My Zsh plugin provides over 100 aliases. Here are the most useful ones:

# Most useful git plugin aliases
gst     # git status
ga      # git add
gaa     # git add --all
gc      # git commit
gcmsg   # git commit -m
gp      # git push
gpsup   # git push --set-upstream origin $(current_branch)
gl      # git pull
glog    # git log --oneline --decorate --graph
gd      # git diff
gds     # git diff --staged
gco     # git checkout
gcb     # git checkout -b
gb      # git branch
gba     # git branch -a
gbd     # git branch -d
gf      # git fetch
grb     # git rebase
grbc    # git rebase --continue
grba    # git rebase --abort
gsta    # git stash push
gstp    # git stash pop
gstl    # git stash list
gcp     # git cherry-pick

Zsh Configuration Deep Dive

# ~/.zshrc - Advanced configuration

# History configuration
HISTSIZE=50000
SAVEHIST=50000
HISTFILE=~/.zsh_history
setopt HIST_IGNORE_ALL_DUPS    # Remove older duplicate entries
setopt HIST_FIND_NO_DUPS       # Do not display duplicates in search
setopt HIST_SAVE_NO_DUPS       # Do not save duplicates
setopt SHARE_HISTORY           # Share history between sessions
setopt HIST_REDUCE_BLANKS      # Remove unnecessary blanks
setopt INC_APPEND_HISTORY      # Append to history immediately

# Directory navigation
setopt AUTO_CD                 # Type directory name to cd into it
setopt AUTO_PUSHD              # Push directories onto stack
setopt PUSHD_IGNORE_DUPS       # No duplicates in dir stack
setopt PUSHD_SILENT            # Silent pushd

# Completion settings
setopt COMPLETE_ALIASES        # Complete aliases
setopt ALWAYS_TO_END           # Move cursor to end after completion
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' # Case insensitive
zstyle ':completion:*' menu select  # Menu-style completion
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"  # Colored completions

# Key bindings
bindkey '^[[A' history-substring-search-up    # Up arrow searches history
bindkey '^[[B' history-substring-search-down  # Down arrow searches history

# Custom PATH
export PATH="$HOME/.local/bin:$HOME/.npm-global/bin:$PATH"

# Node Version Manager
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && source "$NVM_DIR/nvm.sh"

# Load completions
autoload -Uz compinit && compinit

Alternative: zinit (Faster Plugin Manager)

If Oh My Zsh feels slow (especially with many plugins), consider zinit. It supports lazy loading, parallel installation, and turbo mode for near-instant shell startup.

# Install zinit
bash -c "$(curl --fail --show-error --silent --location \
  https://raw.githubusercontent.com/zdharma-continuum/zinit/HEAD/scripts/install.sh)"

# ~/.zshrc with zinit
source "$HOME/.local/share/zinit/zinit.git/zinit.zsh"

# Load plugins with turbo mode (deferred loading)
zinit light-mode for \
  zdharma-continuum/fast-syntax-highlighting \
  zsh-users/zsh-autosuggestions \
  zsh-users/zsh-completions

# Load Oh My Zsh plugins via zinit
zinit snippet OMZP::git
zinit snippet OMZP::docker
zinit snippet OMZP::npm

Shell Configuration Tips

  • Benchmark startup time: Run time zsh -i -c exit to measure shell startup. Target under 200ms.
  • Lazy load nvm: nvm adds 300-500ms to startup. Use --no-use flag and lazy-load it when first needed.
  • Version control your dotfiles: Keep ~/.zshrc and related configs in a Git repo with symlinks.
  • Use direnv: Automatically load/unload environment variables when entering project directories.

Continue Learning