Oh My Zsh Plugins: Enabling, Ordering, and Keeping Startup Fast
How Oh My Zsh's plugins=() array actually works, why load order causes alias conflicts, and how to measure and fix slow shell startup.
19 May 2026, 20:42 UTC

Oh My Zsh ships with more than 300 plugins, and the useful answer up front is this: enable only the plugins you actually use, list them in the plugins=() array in ~/.zshrc, and put zsh-syntax-highlighting last if you use it. Everything else — startup speed, weird alias conflicts, broken prompts — follows from how that array is processed.
What a plugin actually does
A plugin is just a .plugin.zsh file that gets sourced when your shell starts. Sourcing means the file's contents run in your current shell, so any aliases, functions, and completion definitions it contains become part of your session. When Oh My Zsh initializes, it loops over your plugins array and sources each matching file from ~/.oh-my-zsh/plugins/<name>/ (or from the custom plugin directory for third-party plugins).
Because everything lands in one shared shell namespace, two plugins that define a function or alias with the same name will collide — and the one loaded later wins. This is the single most common source of "my alias suddenly does something different" reports.
A worked configuration
Edit ~/.zshrc in any text editor (no special permissions needed; the file belongs to your user). A realistic setup for someone working with Git, Docker, and Kubernetes looks like this:
# In ~/.zshrc, before the "source $ZSH/oh-my-zsh.sh" line
plugins=(
git
docker
kubectl
zsh-autosuggestions
zsh-syntax-highlighting
)
source $ZSH/oh-my-zsh.sh
What each entry gives you:
git— aliases likegst(git status) andgco(git checkout), plus helper functions. Runalias | grep gitafter reloading to see what it defines.dockerandkubectl— mostly tab-completion definitions and a few aliases. Completions are the real value here; trykubectl get p<TAB>.zsh-autosuggestions— suggests commands from your history as you type; accept with the right arrow key. This is a third-party plugin, not bundled, so it must be installed separately (see below).zsh-syntax-highlighting— colors commands green/red as you type to flag typos before you hit enter. Also third-party, and it must be loaded last because it wraps the line editor; loading it earlier lets later plugins clobber its hooks.
Apply changes with source ~/.zshrc or by opening a new terminal. If something breaks, commenting out entries in the array and reloading is the entire rollback — nothing else is modified.
Installing third-party plugins
Bundled plugins (git, docker, kubectl) need no installation. Community plugins like autosuggestions and syntax highlighting must be cloned into the custom plugins directory. Run these in any terminal as your normal user:
git clone https://github.com/zsh-users/zsh-autosuggestions \
${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
git clone https://github.com/zsh-users/zsh-syntax-highlighting \
${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
The ${ZSH_CUSTOM:-...} placeholder resolves to your custom directory if you've overridden it, otherwise the default. Cloning code into your shell's startup path means that code runs every time you open a terminal — only install plugins from repositories you trust, and check the commit activity before relying on one. Unmaintained plugins can break when Oh My Zsh updates.
Startup cost and how to measure it
Every plugin adds sourcing time. A handful of well-maintained plugins is usually fine, but enabling 30 plugins "just in case" can add a noticeable delay to every new terminal. Measure it:
time zsh -i -c exit
This starts an interactive shell, exits immediately, and reports total time. Run it before and after trimming your plugin list to see the real difference on your machine — don't trust generic millisecond figures from blog posts, since results vary with hardware and plugin mix. If startup feels slow, remove plugins you don't use rather than reaching for lazy-loading hacks first.
Diagnosing problems
When a plugin misbehaves, work through these checks in order:
omz plugin list(older versions:omz list plugins) shows available plugins and which are enabled.- Check whether an alias was overridden:
which gcooralias gcoshows what a name currently resolves to. If it's not what you expected, a later plugin in your array redefined it — reorder the array. - Source a plugin manually in a fresh shell to isolate errors:
source ~/.oh-my-zsh/plugins/git/git.plugin.zsh. Any error messages point at the offending file. - Read the plugin's own README:
~/.oh-my-zsh/plugins/<name>/README.mddocuments its aliases and dependencies.
Note that omz doctor appears in some community advice but is not a standard Oh My Zsh command in current versions — verify with omz --help on your installation rather than assuming it exists.
Limits and common mistakes
- Order matters. Later plugins override earlier ones. Syntax highlighting goes last; if two plugins fight over an alias, the one you want should come after.
- Plugins are not packages. The
dockerplugin provides completions but does not install Docker. Several plugins assume the underlying tool is already on your$PATH. - Theme features are separate. Prompt elements like git branch or exit status come from your theme (e.g., Powerlevel10k), not from plugins. Enabling the git plugin won't change your prompt.
- Updates can break third-party plugins.
omz updateonly updates Oh My Zsh itself; plugins you cloned into the custom directory need their owngit pull.
The practical check after any change: open a new terminal, confirm startup time is acceptable with the time command above, and exercise one feature per enabled plugin (a git alias, a kubectl completion, an autosuggestion). If all three work, the configuration is doing what you asked.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.