If you use Zsh, chances are you started with Oh-My-Zsh. It is a fantastic gateway into the Zsh ecosystem, but over time, terminal startup slows to a crawl.
Every time you open a new tab or split a pane in tmux, you wait 200 ms to 800 ms while shell scripts fork subshells, run uname, call git, and sequentially parse thousands of lines of uncompiled shell code.
I built zload to fix this once and for all: an ultra-fast, zero-friction Zsh plugin manager that replaces Oh-My-Zsh entirely while letting you keep your favorite OMZ plugins.
The Problem with Oh-My-Zsh
Oh-My-Zsh suffers from three architectural bottlenecks:
-
Subshell Fork Bomb on Startup: Running
$(git ...)or$(uname)during shell initialization spawns child operating system processes. Spawning processes in shells is expensive (especially on macOS and WSL). -
Sequential Uncompiled Parsing: Plain-text
.zshscripts are parsed into memory by the shell AST parser on every startup. -
Monolithic Coupling: To use a simple plugin like
gitorextract, you have to clone and maintain the entire Oh-My-Zsh framework.
Enter zload: 0.45 ms Warm Startup, 0 Subprocesses
zload was designed with strict performance invariants:
-
Warm Startup < 0.5 ms: Sourcing
zloadand 10 plugins takes less than half a millisecond. -
Zero Subprocess Forks: No
uname,which,find,sed,grep, or$(...)subshells on interactive startup. Pure Zsh builtins only. -
Memory-Mapped Bytecode (
.zwc): Automatically bundles and compiles your active plugins into native wordcode mapped directly into memory viammap. -
Automatic Canonical Ordering: You never have to worry about plugin load order.
zloadautomatically orders completions first, themes/prompts next, utilities in the middle, and syntax highlighting/autosuggestions last.
How zload Replaces Oh-My-Zsh (Without Losing Your Plugins)
You do not need Oh-My-Zsh installed to use Oh-My-Zsh plugins. zload natively understands the omz: prefix:
plugins=(
omz:git
omz:lib/completion.zsh
omz:plugins/extract
omz:plugins/docker
)
zload "${plugins[@]}"
When zload sees omz:, it automatically:
- Clones only the upstream Oh-My-Zsh repository once into
~/.local/share/zload/plugins/_omz. - Provides built-in lightweight shims for OMZ helper functions (
current_branch, git status decorators). - Automatically includes required dependencies (like
lib/git.zshforomz:git) without pulling in the rest of OMZ.
Before vs. After: .zshrc Migration
Before (Standard Oh-My-Zsh setup)
# Slow: 350ms - 700ms startup latency
export ZSH="$HOME/.oh-my-zsh"
ZSH_THEME="robbyrussell"
plugins=(
git
extract
zsh-autosuggestions
zsh-syntax-highlighting
)
source $ZSH/oh-my-zsh.sh
After (zload clean array setup)
# Fast: < 0.5ms startup latency
# 1. Bootstrap zload automatically on any machine
if [[ ! -d "${HOME}/.zload" ]]; then
git clone --depth 1 https://github.com/casonadams/zload.git "${HOME}/.zload"
fi
source "${HOME}/.zload/zload.zsh"
# 2. Fast paths with validation and deduplication
zload path ~/bin ~/.local/bin /opt/homebrew/bin
# 3. Declare plugins using standard native Zsh array syntax
plugins=(
casonadams/zline # Fast pure-Zsh prompt (< 0.7ms render)
omz:git # OMZ git plugin & aliases
omz:lib/completion.zsh # OMZ completion styling
omz:extract # OMZ archive extractor
lukechilds/zsh-nvm --on nvm,node,npm # Lazy-loaded on command invocation
zsh-users/zsh-syntax-highlighting --defer # Deferred until prompt displays
zsh-users/zsh-autosuggestions
)
zload "${plugins[@]}"
bindkey '^ ' autosuggest-accept
Benchmark Comparison
Benchmarking 10 active plugins on macOS (Apple Silicon):
| Framework / Plugin Manager | Warm Startup Overhead | Subprocess Forks | Compiled Bytecode (.zwc) |
|---|---|---|---|
| zload | 0.45 ms | 0 (Zero) | ✓ Native Bytecode |
| Antigen | 68.20 ms | 14 | ✗ Plain text |
| Zinit | 32.40 ms | 6 | Partials |
| Oh-My-Zsh (framework) | 185.00 ms | 18 | ✗ Plain text |
Lazy-Loading Primitives
For commands and utilities that you don't need on every keystroke, zload provides built-in zero-friction primitives:
-
Command Triggers (
--on): Create instant function stubs that clone and load the real plugin only when you first invoke the command (e.g.nvm,k8s,cargo). -
Post-Prompt Deferral (
--defer): Renders your prompt immediately at 0 ms and queues non-critical plugins (like syntax highlighting) to load during idle time viaprecmd. -
Directory Triggers (
--on-dir): Activate plugins only whencd-ing into specific project folders. -
Zero-Subprocess Eval Caching (
zload eval): Replaces sloweval "$(zoxide init zsh)"oreval "$(starship init zsh)"subshells by compiling tool initialization scripts into wordcode and loading them in 0.2 ms.
Pair with a Fast Pure-Zsh Prompt
A fast shell manager is only half the battle. If your prompt engine forks 10 subshells to check git status, your terminal will still feel sluggish.
I recommend pairing zload with zline, a pure-Zsh prompt engine designed with the same zero-fork philosophy that renders prompts in under 0.7 ms:
plugins=(
casonadams/zline
# ... other plugins
)
zload "${plugins[@]}"
Getting Started
Switching takes less than a minute:
# 1. Clone zload
git clone --depth 1 https://github.com/casonadams/zload.git ~/.zload
# 2. Add to the top of your ~/.zshrc
source ~/.zload/zload.zsh
# 3. Declare your plugins and start a new terminal!
Check out the full documentation and interactive website at casonadams.github.io/zload or star the repo on GitHub.
Give it a shot and let me know your terminal startup times before and after!
Top comments (0)