Oh My Zsh is the answer to “how do I make my terminal nicer?” that everyone gives, and it’s the answer I gave for years. Install it, run a few git clone commands for some plugins, pick a theme, you’re done. It works. Most developers I know use it.
About two years ago I uninstalled it and built a simpler setup from scratch. I haven’t looked back, and my shell starts faster, is easier to understand, and I actually know what it does.
This is not a “Oh My Zsh is bad” post. It’s a post about why the complexity stopped being worth it for me, and what the alternative looks like in practice.
The Oh My Zsh Problem
Oh My Zsh has three hundred and eighty plugins in the default install. Even if you only enable ten of them, you’re loading a framework that was built to support three hundred and eighty. The startup time reflects this.
Run this and see what you get:
time zsh -i -c exit
On a decent machine with a modest Oh My Zsh setup, that number is often 500ms to 1.5 seconds. On a machine with heavy plugins — syntax highlighting, autosuggestions, a theme with git status — it can be 2-3 seconds. Every time you open a terminal tab.
For most people, this is background noise — you don’t notice 800ms when you’re already doing something else. But on a slow machine, in a Docker container, over SSH, or when you open 10 terminal tabs in quick succession, it adds up and becomes annoying. More importantly, a slow start usually means something is doing work you’re not aware of.
The second problem is harder to fix: I didn’t understand what my shell was doing. Oh My Zsh put a lot of stuff in .zshrc that I copy-pasted from the internet and forgot about. I had aliases that shadowed commands. I had completions loaded in an order I didn’t understand. One of my plugins was making every git status call slower because of something in the prompt. I found this out only when I profiled my shell.
The complexity becomes a liability. You don’t own the thing; you’re a passenger in it.
What I Use Instead
The stack is three tools, each of which does one job:
1. zinit for plugin management
2. Starship for the prompt
**3. A small .zshrc I can actually read in five minutes
That’s it.
zinit for Plugin Management
zinit is a fast Zsh plugin manager. It supports lazy loading — plugins load only when you actually need them, not all at startup. The syntax is terse but learnable.
The plugins I actually need:
zinit light zsh-users/zsh-autosuggestions
zinit light zsh-users/zsh-syntax-highlighting
zinit light zsh-users/zsh-completions
That’s the full list. Autosuggestions (the grey text that completes commands based on history), syntax highlighting (commands turn red if they’re invalid, green if they’re good), and enhanced completions.
With zinit and lazy loading, my shell starts in under 150ms. Same plugins, same behavior, five times faster.
The thing I like about zinit: it’s just plugin loading. It doesn’t have opinions about my aliases, my key bindings, my theme, or my directory structure. I added those myself, I know where they are, and I can change any of them without understanding a framework.
Starship for the Prompt
Starship is a prompt written in Rust. It’s fast — the prompt rendering happens in a subprocess and doesn’t block your shell — and it shows exactly the context information I want without a theme framework.
My ~/.config/starship.toml is about 40 lines:
[character]
success_symbol = "[❯](bold green)"
error_symbol = "[❯](bold red)"
[git_branch]
symbol = " "
[git_status]
format = '([$all_status$ahead_behind]($style) )'
conflicted = "⚡"
ahead = "↑${count}"
behind = "↓${count}"
modified = "!"
untracked = "?"
[nodejs]
symbol = " "
[ruby]
symbol = " "
[python]
symbol = " "
[directory]
truncation_length = 3
fish_style_pwd_dir_length = 1
Result: a prompt that shows current directory, git branch and status, and the active language runtime when relevant. Renders in ~15ms. No fonts required unless you want the icons (Nerd Fonts work with it, but you can use plain ASCII fallbacks).
The alternative many people use is Powerlevel10k, which is excellent and faster than most Oh My Zsh themes. If you want to stay in the Zsh theme ecosystem, p10k is the right choice — it does async prompt rendering and won’t slow your shell down. I switched to Starship because it works identically across Zsh, Bash, and Fish, which means my prompt looks the same when I drop into a bash session or a container.
The .zshrc
The full .zshrc I actually run:
# Plugin manager
source ~/.zinit/bin/zinit.zsh
# Plugins
zinit light zsh-users/zsh-autosuggestions
zinit light zsh-users/zsh-syntax-highlighting
zinit light zsh-users/zsh-completions
# Completion setup
autoload -Uz compinit && compinit
# History
HISTFILE=~/.zsh_history
HISTSIZE=50000
SAVEHIST=50000
setopt HIST_IGNORE_DUPS
setopt SHARE_HISTORY
# Options
setopt AUTO_CD
setopt CORRECT_ALL
# Key bindings
bindkey -e # Emacs key bindings
bindkey '^[[A' history-beginning-search-backward
bindkey '^[[B' history-beginning-search-forward
# Aliases
alias ls='ls --color=auto'
alias ll='ls -alh'
alias g='git'
alias gc='git commit'
alias gco='git checkout'
alias gs='git status'
alias ..='cd ..'
alias ...='cd ../..'
# PATH additions (project-specific)
export PATH="$HOME/.local/bin:$PATH"
export PATH="$HOME/.cargo/bin:$PATH" # Rust
# Tool initialization
eval "$(mise activate zsh)" # Runtime version manager
eval "$(starship init zsh)" # Prompt
That’s the whole file. Every line in it is something I put there deliberately. I know what each one does. When something breaks, I can read the file and understand it.
The Transition
Moving off Oh My Zsh is not hard, but it’s annoying if you’ve accumulated years of configuration inside the OMZ framework. My approach:
cat ~/.zshrcand write down every alias and setting you actually use- Check which OMZ plugins you have enabled — honestly, how many do you use? Really use?
- Uninstall OMZ:
uninstall_oh_my_zsh(it’s a built-in command) - Install zinit and get autosuggestions and syntax-highlighting running
- Add your aliases and settings
- Install Starship
- Add anything else you find yourself missing over the next week
In practice, most people discover they were using five or six things from OMZ. Those five or six things are easy to replicate directly.
What I’d Miss If I Were Wrong
Let me be honest about what Oh My Zsh does well:
- Lower barrier to entry. The installer is one command and the default experience is good. If you’re setting up your shell for the first time, OMZ gets you to “functional and pretty” in ten minutes. That’s valuable.
- Community and docs. The plugin ecosystem is huge and well-documented. If you want to do something weird with your shell, someone in the OMZ community has already done it.
- Works everywhere. Because it’s so popular, almost every “how to do X with your shell” tutorial assumes OMZ.
If you’re happy with OMZ and your shell is fast, you don’t need to do this. The setup I’ve described takes more up-front investment. The payoff is a shell I understand completely and a startup time that doesn’t annoy me.
Who This Is For
If any of these are true, it might be time to look at what’s actually in your .zshrc:
- You’ve noticed your terminal starts slowly
- You’re using someone else’s dotfiles and don’t understand what they do
- You’ve been in the same OMZ config for years and have never audited it
- You copy-paste stuff into your shell config without really understanding it
The goal isn’t to have the fastest possible shell. The goal is to have a shell you own — where you know what’s running and why. Whether you get there with Oh My Zsh, zinit, or something else is secondary.
But if you’ve never looked at the shell startup time on your machine: open a terminal and run time zsh -i -c exit. You might be surprised.