Completions
Guide for writing and managing custom ZSH completion files in this dotfiles repository.
When to Use
- Implementing custom completions for CLI tools
- Fixing or updating existing completion files
- Understanding how completions are loaded in this repo
Do NOT use when installing homebrew packages - they handle completions automatically.
Repository Conventions
File Naming
Completion files in this repo use: <topic>/completion.zsh
Example: claude/completion.zsh
Loading Process
From zsh/zshrc.symlink:
compinitis called to initialize the completion system- All
*/completion.zshfiles are sourced - Files are sourced directly, NOT added to
fpath
File Structure
#!/usr/bin/env zsh
# Define completion function
_toolname() {
local line state
# Define options
local -a options=(
'-h[Display help]'
'--help[Display help]'
)
# Define subcommands
local -a subcommands=(
'command:Description'
)
_arguments -C \
"${options[@]}" \
'1: :->command' \
'*::arg:->args'
case $state in
command)
_describe -t commands 'tool command' subcommands
;;
args)
# Handle subcommand args
;;
esac
}
# Register completion
compdef _toolname toolname
Key Patterns
Registration
Use compdef at the end of the file:
compdef _toolname toolname
NOT the #compdef directive (that's for files in fpath).
Options Format
local -a options=(
'-h[Display help]'
'--help[Display help]'
'--flag[Description]'
'--option[Description]:value:'
'--file[Description]:file:_files'
'--dir[Description]:directory:_directories'
)
Subcommands
local -a subcommands=(
'command:Description'
'subcommand:What it does'
)
_describe -t commands 'tool command' subcommands
Argument Handling
_arguments -C \
"${options[@]}" \
'1: :->command' \
'*::arg:->args'
case $state in
command)
_describe -t commands 'tool command' subcommands
;;
args)
case ${line[1]} in
subcommand)
_arguments \
'--subcommand-option[Description]' \
'1:arg:'
;;
esac
;;
esac
Nested Subcommands
For tools like git or docker with deep command hierarchies:
_tool_subcommand() {
local line state
local -a sub_subcommands=(
'action:Description'
)
_arguments -C \
'1: :->command' \
'*::arg:->args'
case $state in
command)
_describe -t commands 'tool subcommand command' sub_subcommands
;;
esac
}
Common Completers
Built-in zsh completion functions:
_files- File paths_directories- Directory paths_values- Predefined values_describe- Command descriptions_arguments- Argument parsing
File Completion
'--config[Config file]:file:_files'
Choice Completion
'--format[Output format]:format:(json yaml text)'
Multiple Values
'--env[Environment variables]:env:' # Free form
'--scope[Scope]:scope:(local user project)' # Fixed choices
Testing
After creating/modifying a completion file:
- Reload shell:
source ~/.zshrc - Test completion:
tool <TAB> - Test subcommands:
tool subcommand <TAB> - Test options:
tool --<TAB>
Generating Completions
Steps to create completions for a new tool:
- Run
tool --helpto see main options - Run
tool subcommand --helpfor each subcommand - Create
<topic>/completion.zsh - Define
_toolname()function with all discovered options - Register with
compdef _toolname toolname - Test thoroughly
Common Issues
"command not found: _arguments"
The completion function is being executed instead of sourced. Ensure:
- File is named
completion.zsh(notcompletions.zsh) - Using
compdef(not#compdef) - File is in a topic directory that gets sourced
"can only be called from completion function"
Using #compdef directive when file is sourced directly. Use compdef registration instead.
Completions Not Loading
- Check file naming:
*/completion.zsh - Verify file is being sourced:
echo $ZSH/**/*.zsh | grep completion - Check for syntax errors:
zsh -n path/to/completion.zsh
Examples
See existing completion files:
claude/completion.zsh- Complex multi-level subcommandsgcloud/completions.zsh- Third-party completion sourcing
Scan to join WeChat group