Start with #!/usr/bin/env zsh and enable strict mode: setopt ERR_EXIT PIPE_FAIL NOUNSET
Declare an indexed array: local -a files=(); files+=("file1.txt" "file2.txt"); iterate with: for f in ${files[@]}; do echo $f; done
Declare an associative array (requires zsh 4+): local -A config; config[host]='localhost'; config[port]='5432'; access a value: echo ${config[host]}
Use zsh-specific parameter expansion: ${VAR:=default} to assign if unset, ${(U)VAR} to uppercase, ${#array} for array length.
Trap cleanup on exit: trap 'echo cleanup' EXIT — zsh EXIT trap fires on normal exit, error exit, and signal termination.
Known gotchas
zsh arrays are 1-indexed by default (unlike bash which is 0-indexed); ${array[1]} is the first element. This is a common source of off-by-one bugs when porting from bash.
setopt ERR_EXIT in zsh is equivalent to bash's set -e; it aborts on non-zero exit but similarly does not trigger inside [[ ]] conditions or after || and &&.
Associative arrays in zsh require explicit declaration with typeset -A or local -A; using a name without declaration may silently create a scalar instead.
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp