name: zsh-completions
description: Guide for creating effective skills. This skill should be used when users want to create, update, review, and debug native Zsh completion scripts built on the modern completion system (compsys). Use when Codex needs to create a new _command completion function, extend subcommand, option, or argument completion, fix completion parity against a CLI's current help output, migrate legacy compctl behavior to #compdef or compdef, or diagnose matcher, style, tag, or context issues in existing Zsh completion code.
metadata:
short-description: Create or update a Zsh completion script
Zsh Completions
Use this skill to work on native Zsh completion functions without falling back to Bash-completion assumptions or ad hoc shell parsing.
Workflow
- Establish the contract before editing.
- Identify the command name, aliases, install path, and existing completion file if one already exists.
- Treat current CLI help, command source, or generated command metadata as the primary contract for options, subcommands, and argument shapes.
- If a completion already exists, diff behavior before rewriting it.
- Prefer modern
compsysprimitives.- Use
#compdeforcompdeffor registration. - Start with
_arguments -Cfor option and position parsing. - Use
->statebranches pluscase $state in ...for nested subcommands or mode-specific arguments. - Drop to
compaddorcompsetonly when the higher-level helpers cannot express the behavior cleanly.
- Use
- Reuse the standard helpers.
- Use
_valuesfor enumerated values. - Use
_describefor labeled groups. - Use
_alternativewhen multiple completion sources are valid. - Use
_filesor_path_filesfor file and path completion. - Use
_guardand_messagefor validation and clear user feedback.
- Use
- Keep parsing state explicit.
- Track
words,CURRENT,PREFIX,SUFFIX,opt_args,line,state, andcurcontextdeliberately. - Use
compsetonly when you truly need to strip prefixes or suffixes, split quoted text, or narrow the effectivewordsrange. - Do not hard-code fragile position checks when the CLI already has nested subcommands, repeated options, or value-bearing flags.
- Track
- Separate semantics from user styling.
- Keep completion behavior in the function.
- Treat tags and
zstyleas the user-facing configuration layer for ordering, matching, grouping, and formatting. - Do not ship user-specific
zstyledefaults unless the owning project explicitly manages shell configuration too.
- Validate in layers.
- Run
zsh -non the completion file. - Load the function from the intended
fpathin a clean Zsh process withcompinit. - Run repository tests if the target project already has completion tests.
- For parity work, compare the completion surface against the current CLI help or authoritative command definitions before declaring success.
- Run
- Treat
compctlas legacy.- Prefer
compsysfor new work and for touched code unless compatibility requirements say otherwise. - If legacy
compctlbehavior must stay, isolate that decision and explain it in the summary.
- Prefer
Preferred Pattern
Use this as the default shape for a command with subcommands and state-dependent arguments:
#compdef mycmd
local curcontext="$curcontext" state line context
typeset -A opt_args
_arguments -C \
'(-h --help)'{-h,--help}'[show help]' \
'1:subcommand:->subcommand' \
'*::argument:->argument' || return
case $state in
subcommand)
_describe -t commands 'mycmd subcommand' \
'sync:synchronize state' \
'status:show current status'
;;
argument)
case $words[2] in
sync) _files ;;
status) _arguments '--json[emit JSON]' ;;
esac
;;
esac
Adapt the helpers to the command shape instead of forcing everything through
raw compadd.
Debugging Rules
- When completion acts on the wrong token, inspect
words,CURRENT,PREFIX,IPREFIX,SUFFIX, andISUFFIX. - When branches misfire, inspect
state,line,opt_args, andcompstate[context]. - When candidates are missing or misordered, inspect
curcontext, tags, and the activezstylerules before changing the function logic. - When matching is too strict or too loose, inspect
matcher-list,matcher, and any explicitcompadd -Musage. - When autoloading fails, confirm the file name matches
_command, the first line uses the correct#compdef, and the containing directory is infpathbeforecompinitruns.
Validation Commands
Use the narrowest command that proves the change:
zsh -n path/to/_mycmd
zsh -fc '
fpath=(path/to/completions $fpath)
autoload -U compinit
compinit -D
autoload -U _mycmd
whence -w _mycmd
'
If the completion is installed through a plugin manager or package layout, repeat the load test from that exact install path.
Reference
Read references/compsys-reference.md when you need exact reminders for:
#compdef,compdef,compinit,compaudit, andfpathwords,CURRENT,PREFIX,IPREFIX,SUFFIX,ISUFFIX, andcompstatecompset,compadd, matching control, tags, and styles- legacy
compctlbehavior that must be interpreted or migrated