Zsh Style Guide
Apply the zsh conventions from ./references/ZSH.md when creating or editing zsh scripts, configurations, and plugins.
Key Conventions
Read ./references/ZSH.md for the complete guide. Summary:
Script Structure
- Shebang:
#!/usr/bin/env zsh - Strict mode:
setopt ERR_EXIT NO_UNSET PIPE_FAIL - Main function called at end:
main "${@}"
Naming
- Functions:
snake_case - Local variables:
lower_case - Constants:
ALL_CAPSwithreadonly - Private/internal:
_underscore_prefix
Syntax
- Variable expansion:
${var}not$var - Command substitution:
$(...)not backticks - Tests:
[[ ]]not[ ] - Function syntax:
function name() { }with both keyword and parentheses - Arithmetic:
(( ))for statements,$(( ))for expressions
Quoting
- Always quote variable expansions:
"${var}" - Always quote command substitutions:
"$(cmd)" - Use arrays for lists, not word splitting
- Use
"${(@)array}"to preserve elements in quoted context
Variables and Scope
- Use
typesetoverdeclare - Use
localfor all function variables - Arrays are 1-based (not 0-based like Bash)
- Use
typeset -Afor associative arrays - Separate
localdeclaration from command substitution
Zsh-Specific Features
- Expansion flags:
${(L)var},${(s:/:)path},${(u)array} - Glob qualifiers:
*(.)for files,*(/)for dirs,*(N)for null glob - Extended glob:
setopt EXTENDED_GLOBfor^,~,#patterns alwaysblocks:{ ... } always { ... }for try/finally- Named traps:
TRAPINT(),TRAPZERR(),TRAPEXIT() - Process substitution:
=(...)creates a temp file (zsh-only)
Completions
For zsh completion function conventions, read ./references/completions.md. Key points:
- Use
_descriptionfor all group descriptions; never pass text directly tocompadd - Every
compaddcall must include"${expl[@]}" - Make
curcontextlocal in functions using_arguments -C - Register tags before offering matches
- Return zero if matches were added, non-zero otherwise
Validation
Whenever possible, validate the script before finishing. Prefer using a project-specific validation script, if available. Common locations include declarations in package.json, Makefile targets, and scripts stored in bin/.
If those aren't present:
zsh -n path/to/scriptfor syntax checkingshellcheck --shell=bashfor general linting (limited zsh support, may produce false positives on zsh-specific syntax)