Choosing Between Legacy and Modern Zsh Completion: A Decision Guide
A decision guide for choosing between Zsh's basic completion and the programmable compinit framework, with a concrete cached configuration and validation steps.
02 Jan 2026, 14:19 UTC

The Decision: Basic vs. Programmable Completion
Every Zsh user faces a choice: rely on the shell’s built-in basic completion or enable the programmable compinit framework. Basic completion completes filenames and simple command options. compinit loads completion functions from fpath, enabling context-aware suggestions for tools like git, docker, and custom scripts. The decision hinges on startup latency tolerance, security posture, and how much custom completion logic you need.
Constraints That Shape the Choice
- Startup latency:
compinitscansfpathand builds a cache (.zcompdump). Without caching, each shell start pays a noticeable penalty. - Directory permissions: World-writable directories in
fpathtrigger security warnings unless you invokecompinit -u. - Extensibility: Third-party plugins (e.g.,
zsh-completions) only work withcompinit. Basic completion cannot use them.
Supported Options Compared
| Aspect | Basic Completion (no compinit) | Modern compinit Framework |
|---|---|---|
| Completion scope | Filenames, built-in command flags | Any command with a completion function in fpath |
| Configuration | None | zstyle patterns for menus, case-insensitivity, grouping |
| Startup cost | Negligible | Low with .zcompdump; high without cache |
| Security warnings | None | Triggered by insecure fpath directories |
| Custom completions | Not supported | Drop a _command file in fpath |
Trade-offs
If you only need file and flag completion, basic mode avoids cache management and permission audits. For developers using git, kubectl, or language-specific tools, compinit pays off: you get subcommand, branch, and option completion out of the box. The main cost is the initial compinit run and ensuring fpath directories are not world-writable. Overloading fpath with many third-party completions can introduce conflicts—prefer curated collections like zsh-completions over ad-hoc scripts.
Concrete Implementation: Minimal, Cached, Styled
Add the following to ~/.zshrc (run as your user, no root required). This snippet enables compinit with caching, silences insecure-directory warnings for user-owned paths, and sets a menu-driven, case-insensitive style.
# Ensure completion functions are discoverable
fpath=($HOME/.zsh/completions $fpath)
# Load and initialize compinit with caching
autoload -Uz compinit
if [[ -n ${ZDOTDIR:-$HOME}/.zcompdump(#qN.mh+24) ]]; then
compinit -u # -u skips insecure-directory check for user dirs
else
compinit -C -u # -C uses existing dump without checking
fi
# Completion styling: menu selection, case-insensitive, grouped descriptions
zstyle ':completion:*' menu select
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z}'
zstyle ':completion:*' group-name ''
zstyle ':completion:*:descriptions' format '%F{yellow}-- %d --%f'
Place custom completion files (e.g., _mytool) in $HOME/.zsh/completions. The autoload -Uz call prevents alias expansion and marks the function for ksh-style autoloading.
Validation Steps
- Open a new terminal or run
exec zsh. - Type
git che<Tab>— you should seecheckout,cherry-pick, etc., in a selectable menu. - Run
zstyle -L ':completion:*'and confirm the four styles above appear. - Check
ls -l ~/.zcompdump*— a dump file (and optionally.zcompdump-) indicates caching is active.
If git completions don’t appear, verify /usr/share/zsh/functions/Completion (or your distro’s equivalent) is in fpath by running echo $fpath.
Limitations
- The
-uflag disables security checks; only use it for directories you control. - Case-insensitive matching via
matcher-listapplies globally; per-command overrides require more specificzstylecontexts. - This guide assumes Zsh 5.8+. Older versions may lack
menu selectormatcher-listbehavior.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.