Overview
Zsh's completion system (compsys) is the most powerful tab completion engine in any shell. It provides context-aware suggestions for commands, flags, file paths, git branches, Docker containers, and more. Proper configuration transforms tab into a productivity multiplier.
Why This Matters
- -Context-aware — different completions for different arguments
- -Rich descriptions — shows what each flag/option does
- -Fuzzy matching — finds completions even with typos
- -Custom completions — add tab completion for your own functions
How It Works
Step 1: Initialize Completion
# ~/.zshrc — basic setup
autoload -Uz compinit
compinit
# Faster: only recompute once per day
autoload -Uz compinit
if [[ -n ~/.zcompdump(#qN.mh+24) ]]; then
compinit
else
compinit -C # Use cached dump
fi
Step 2: Configure Completion Behavior
# Case-insensitive matching
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}'
# Partial word completion
zstyle ':completion:*' matcher-list '' 'm:{a-z}={A-Z}' '+l:|=* r:|=*'
# Menu selection (navigate with arrows)
zstyle ':completion:*' menu select
# Colorize completions
zstyle ':completion:*' list-colors "${(s.:.)LS_COLORS}"
# Group completions by type
zstyle ':completion:*' group-name ''
zstyle ':completion:*:descriptions' format '%B%F{green}── %d ──%f%b'
# Cache completions (faster for slow commands like apt, pip)
zstyle ':completion:*' use-cache on
zstyle ':completion:*' cache-path ~/.zsh/cacheStep 3: Command-Specific Configuration
# Kill: show process list with colors
zstyle ':completion:*:*:kill:*:processes' list-colors '=(#b) #([0-9]#)*=0=01;31'
zstyle ':completion:*:kill:*' command 'ps -u $USER -o pid,%cpu,tty,cputime,cmd'
# SSH: complete hostnames from config
zstyle ':completion:*:ssh:*' hosts $(grep '^Host' ~/.ssh/config | awk '{print $2}')
# Docker: complete container names
zstyle ':completion:*:docker:*' option-stacking yes
# Git: show branch descriptions
zstyle ':completion:*:git-checkout:*' sort falseStep 4: Custom Function Completion
# Completion for the gbr function
_gbr() {
local -a types
types=(
'feat:New feature'
'fix:Bug fix'
'chore:Maintenance task'
'refactor:Code restructure'
'docs:Documentation'
'test:Test addition'
)
_arguments \
'1:branch type:((${types}))' \
'*:description:'
}
compdef _gbr gbr
# Completion for a deploy function
_deploy() {
_arguments \
'(-e --env)'{-e,--env}'[Target environment]:environment:(staging production)' \
'(-t --tag)'{-t,--tag}'[Deploy tag]:tag:_git_tags' \
'(-f --force)'{-f,--force}'[Force deployment]' \
'(-h --help)'{-h,--help}'[Show help]'
}
compdef _deploy deployBest Practices
- -Use compinit caching — check dump age, rebuild once per day
- -Enable menu select — arrow-key navigation through completions
- -Configure case-insensitive matching — saves keystrokes
- -Cache slow completions — pip, apt, and network-heavy commands
- -Add completions for custom functions — makes them feel like real commands
Common Mistakes
- -Calling
compinit multiple times (slow startup) - -Not caching compdump (recomputes every shell start)
- -Missing
autoload -Uz compinit before compinit - -Over-configuring zstyle (diminishing returns past basics)