No, you don't need Oh My Zsh

Don’t get me wrong – Oh My Zsh is an excellent product. It’s well-maintained, feature-rich, and has helped millions of developers enhance their shell experience. But here’s the thing: you don’t need it to have a great zsh experience.

When I recently set up a new workstation, I decided to skip Oh My Zsh entirely and configure zsh manually. The result? A lightweight, fast, and fully customized shell that does exactly what I need – nothing more, nothing less.

The Oh My Zsh Bloat Problem

Oh My Zsh comes with a lot of features out of the box. Themes, plugins, aliases, functions – it’s a complete ecosystem. But here’s the catch: most of us only use a tiny fraction of what it provides.

When you install Oh My Zsh, you get:

  • Hundreds of themes (when you’ll only use one)
  • Dozens of plugins (when you need maybe 3-4)
  • Tons of aliases (many of which you’ll never remember)
  • Complex initialization scripts that slow down shell startup
  • A configuration system that abstracts away the underlying zsh mechanics

This bloat has real consequences:

  • Slower shell startup: Every plugin and theme adds initialization time
  • Complexity: It becomes harder to understand what’s actually happening in your shell
  • Dependencies: You become reliant on Oh My Zsh’s structure and conventions

My Lightweight Alternative

Instead of Oh My Zsh, I built a minimal zsh configuration that focuses on the essentials. Here’s what I actually need:

1. Smart Autosuggestions

The zsh-autosuggestions plugin suggests commands as you type based on your history:

# Installation
git clone https://github.com/zsh-users/zsh-autosuggestions ~/.zsh/zsh-autosuggestions

2. Syntax Highlighting

The zsh-syntax-highlighting plugin highlights commands as you type, showing invalid commands in red:

# Installation
git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ~/.zsh/zsh-syntax-highlighting

Instead of Oh My Zsh’s history plugin, I use simple key bindings that let me search through history using arrow keys:

bindkey '\e[A' history-beginning-search-backward
bindkey '\e[B' history-beginning-search-forward

Now when I type git and press the up arrow, it only shows commands that start with git from my history. This is incredibly useful for finding that complex command you ran last week.

4. Tool-Specific Autocompletion

Instead of generic Oh My Zsh plugins, I load completions only for tools I actually use:

# Docker completion
source <(docker completion zsh)

# kubectl (with kubecolor if available)
if command -v kubecolor >/dev/null 2>&1; then
  alias kubectl=kubecolor
  compdef kubecolor=kubectl
fi

# Google Cloud SDK
if [ -f '/opt/homebrew/share/google-cloud-sdk/completion.zsh.inc' ]; then
  source '/opt/homebrew/share/google-cloud-sdk/completion.zsh.inc'
fi

Smart Word Navigation

One thing that frustrated me about default zsh was word jumping. When you press Alt+→ to jump forward by word, it doesn’t behave intuitively with paths or complex strings.

I fixed this with:

autoload -Uz select-word-style
select-word-style normal
zstyle ':zle:*' word-style unspecified

Now when I have a path like /usr/local/bin/my-script and I’m at the beginning:

  • Before: Alt+→ jumps to the end of the entire path
  • After: Alt+→ jumps to each segment: /usr/local/bin/my-script

This makes editing long paths or URLs much more efficient.

Intelligent Completion System

Instead of Oh My Zsh’s completion system, I configured zsh’s built-in completion with smart behaviors:

# Initialize completion system
autoload -Uz compinit
compinit

# Smart case matching - lowercase matches both cases
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'

# Menu selection for multiple matches
zstyle ':completion:*' menu select

# Error tolerance in completion
zstyle ':completion:*' completer _complete _approximate

When I type cd Pro and hit tab, instead of just completing to the first match, I get a visual menu:

cd Pro
> Projects/     Programming/     Profile.txt

I can use arrow keys to select the right one. If I make a typo like cd Porjects and hit tab, zsh’s approximate completion suggests:

cd Porjects
correct to: Projects/ _

Starship: Prompt Done Right

For my prompt, I chose Starship instead of Oh My Zsh themes. Starship is a single-purpose tool that does one thing exceptionally well: creating beautiful, informative prompts.

eval "$(starship init zsh)"

Why Starship over Oh My Zsh themes?

  • Fast: Written in Rust, it’s significantly faster than shell-based themes
  • Cross-shell: Works with zsh, bash, fish, and more
  • Single responsibility: Only handles prompts, doesn’t mess with other shell functionality
  • Highly configurable: Easy-to-understand TOML configuration
  • No dependencies: Doesn’t require Oh My Zsh or any other framework

Essential Aliases (But Not Too Many)

Oh My Zsh comes with hundreds of aliases. I keep mine minimal and memorable:

alias ls='ls --color=auto'
alias ll='ls -alF'

That’s it. I could add more, but I’ve found that too many aliases make you forget the actual commands, which hurts you when working on systems that don’t have your config.

Understanding What’s Happening

Let me explain the key components of my setup:

The compinit Function

autoload -Uz compinit
compinit

This initializes zsh’s completion system. The autoload -Uz tells zsh to load the function when needed (lazy loading), and the U flag ensures it’s loaded even if there are aliases for the same name.

Script Sourcing with Error Handling

Instead of blindly sourcing files that might not exist, I check first:

local scripts_to_source=(
    ~/.zsh/zsh-autosuggestions/zsh-autosuggestions.zsh
    ~/.zsh/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
    # ... more scripts
)

for script_file in "${scripts_to_source[@]}"; do
  if [ -r "$script_file" ]; then
    source "$script_file"
  else
    print -P "%F{yellow}Warning:%f Script not found: $script_file"
  fi
done

This approach:

  • Prevents errors when scripts don’t exist
  • Gives clear feedback about missing dependencies
  • Makes the config portable across different systems

Making the Switch

If you’re currently using Oh My Zsh and want to try this approach:

  1. Backup your current config: cp ~/.zshrc ~/.zshrc.backup
  2. Start minimal: Begin with just the essentials (autosuggestions, syntax highlighting)
  3. Add incrementally: Only add features as you realize you need them
  4. Understand each piece: Don’t copy-paste without understanding what each line does

The goal isn’t to recreate Oh My Zsh – it’s to build exactly what you need and understand every piece of it.

Conclusion

Oh My Zsh is a great project that has introduced countless developers to the power of zsh. But once you understand what you actually need from your shell, you might find that a custom configuration serves you better.

My lightweight setup gives me everything I need: smart completions, helpful suggestions, a beautiful prompt, and fast performance. Most importantly, I understand every line of my configuration and can modify it without fear of breaking some complex framework.

Sometimes the best tool is the one you build yourself – even if it’s simpler than the popular alternative.


Here you can find my complete zsh configuration: zshrc