>_EXECUTIVE SUMMARY
zsh-xcode-completions is the largest plugin in this batch by completion-file count: 11 separate #compdef files covering the Xcode command-line tools, totaling 435 lines under src/ plus a 1-line plugin entrypoint. Coverage spans the entire mac developer CLI surface — xcodebuild (the largest at 139 lines), swift (54 lines for the compiler driver), xcrun (the developer-tool dispatcher with SDK/toolchain switches), nm (symbol table dump), plutil (plist conversion), strings, dyldinfo, genstrings (localization), instruments (profiling templates), swift-demangle, and xcode-select. Many completers shell out to xcodebuild itself for live data: schemes / targets / configurations / valid-archs are queried at completion time via xcodebuild -list + xcodebuild -showBuildSettings piped through sed / cut for parsing. SDK lists go through _retrieve_cache SDKS / _store_cache SDKS because they rarely change. An xcrun-shim binary at bin/swift-demangle works around xcrun's inability to dispatch zsh completion through its xcrun <tool> ... indirection — the shim is a one-line xcrun swift-demangle "$@" wrapper that surfaces the nested tool as a direct PATH binary so its _swift-demangle completer can fire.
~ARCHITECTURE · FILE STRUCTURE
Eleven #compdef files under src/, one xcrun-shim binary under bin/, one 1-line plugin entrypoint.
| Path | Lines | Role |
|---|---|---|
| src/_xcodebuild | 139 | Largest completer — 30+ flags (-scheme, -target, -configuration, -sdk, -arch, -workspace, -project, -archivePath, -derivedDataPath, sanitizer toggles, code coverage, export format/signing) + 5 build actions (analyze, archive, build, clean, install, installsrc, test); shells out to xcodebuild -list / -showsdks / -showBuildSettings at completion time |
| src/_swift | 54 | Swift compiler driver — -emit-assembly/-library/-object, -F framework path, -I import path, -L library path, -l library link, -module-cache-path, -O/-Onone/-Ounchecked, -sdk with SDK cache, -target-cpu, -Xcc/-Xlinker passthrough |
| src/_xcrun | 49 | The tool dispatcher — -f/--find, -l/--log, -r/--run, -k/--kill-cache, --sdk (cached SDK list), --toolchain (glob /Applications/Xcode*.app/Contents/Developer/Toolchains/*.xctoolchain), --show-sdk-{path,platform-path,platform-version,version}; executable completion via ls $(dirname $(xcrun -f swift)) |
| src/_nm | 38 | -a/-A/-f/-g/-j/-l/-m/-n/-o/-p/-r/-s/-u/-U/-x; -arch with arch enum |
| src/_instruments | 33 | -s templates/devices; -t template selection backed by _instruments_templates cache (parses quoted output of instruments -s templates); -p attach-pid via zsh's _pids; mutex group between pid-attach and command-launch modes |
| src/_plutil | 29 | -help, -lint, -convert (with format enum: xml1/binary1/json), -p print, -extract, -replace, -insert, -remove |
| src/_strings | 26 | Symbol-table strings dump — flag set + file completion |
| src/_xcode-select | 19 | -p/--print-path, -r/--reset, -s/--switch backed by glob of /Applications/Xcode*.app, --install |
| src/_genstrings | 18 | Localization-string generator flag set + source-file completion |
| src/_swift-demangle | 15 | Swift name-mangling decoder — flag set + stdin/file input |
| src/_dyldinfo | 15 | dyld load-commands inspector |
| bin/swift-demangle | 3 | #!/bin/sh shim — xcrun swift-demangle "$@" — gives zsh a direct PATH binary it can run _swift-demangle against (xcrun's nested dispatch hides it from zsh's completion-system #compdef lookup) |
| zsh-xcode-completions.plugin.zsh | 1 | fpath=("${0:h}/src" $fpath) — only line, no setup chrome needed because every file is autoloaded by zsh's compsys when compinit runs after fpath patch |
| Total source | ~439 | 11 completion files + 1 shim + 1 entrypoint |
@COMPLETION COVERAGE
11 distinct tools. Common pattern: _arguments flag table + state machine for context-sensitive args + project-aware queries that shell out to the tool itself.
Project-aware xcodebuild completion
Instead of static enum lists, _xcodebuild queries the current directory:
-scheme <TAB>→xcodebuild -listoutput, sed-extracted between "Schemes:" and end-target <TAB>→xcodebuild -list, sed-extracted between "Targets:" and "Build Configurations:"-configuration <TAB>→ same, between "Build Configurations:" and "If no build"-arch <TAB>→xcodebuild -showBuildSettings | grep VALID_ARCHS | cut -f 2 -d '='-project <TAB>→ glob*.xcodeprojvia_multi_parts /-workspace <TAB>→ glob*.xcworkspace-xcconfig <TAB>→ glob*.xcconfig
Cached SDK list (cross-tool)
Both _xcodebuild and _swift share the same SDK-cache idiom: _retrieve_cache SDKS → populate _installed_sdks via xcodebuild -showsdks → _store_cache SDKS. The cache key (SDKS) is shared across completers so a single SDK install/uninstall invalidates everywhere.
xcrun toolchain glob
xcrun --toolchain <TAB> → toolchains=(/Applications/Xcode*.app/Contents/Developer/Toolchains/*.xctoolchain) — glob over every installed Xcode's toolchains directory. Works with side-by-side Xcode installations (beta + release).
Instruments template cache
instruments -t <TAB> → _instruments_templates → _call_program templates 'instruments -s templates'. Output format is one quoted template per line with a "Known Templates" header. The completer uses ${(Q)${(f)...}} to split-by-line + strip-quotes, then shift template_list to drop the header. _retrieve_cache _instruments_templates persists the result so repeated TABs don't re-spawn instruments.
xcode-select Xcode picker
xcode-select --switch <TAB> → xcodes=(/Applications/Xcode*.app) → _values "Available Xcodes" $xcodes. Side-by-side Xcode versions are visible by glob, no enumeration of /Applications needed.
xcrun shim for nested tools
xcrun's design (xcrun <tool> <args>) hides nested tools from zsh's completion-system #compdef lookup — swift-demangle isn't directly on PATH, so _swift-demangle never fires. The shim at bin/swift-demangle (3-line POSIX sh wrapper running xcrun swift-demangle "$@") gives users a direct PATH binary that surfaces the completer. Homebrew offers --without-shims for users who don't want the wrapper.
#TEST COVERAGE
40 zunit @test cases across 6 files, plus 21 structural shell gates from the umbrella. The t-completions.zsh file pins every one of the 11 _* files individually.
| Test file | @test count | What it pins |
|---|---|---|
| tests/t-completions.zsh | 20 | Per-completer pins — each of the 11 src/_* files exists, starts with the right #compdef line, parses cleanly under zsh -n |
| tests/t-contract.zsh | 3 | Entrypoint stem matches plugin-dir basename (Zinit / OMZ source-line copy-paste pin); plugin file is exactly the 1-line fpath patch |
| tests/t-contract2.zsh | 5 | src/ contains exactly 11 completion files with names matching the documented tool list |
| tests/t-contract3.zsh | 5 | bin/swift-demangle shim exists, is executable, has the xcrun swift-demangle "$@" body |
| tests/t-contract4.zsh | 5 | SDK cache key consistency — _xcodebuild + _swift + _xcrun all use SDKS as the cache key (so SDK install invalidates everywhere) |
| tests/t-syntax.zsh | 2 | zsh -n parse-cleanness on entrypoint + every src/_* file |
| Total | 40 | 6 zunit files |
// STRUCTURAL GATES (21 shell scripts)
Same 21-script umbrella gate-set: 9 docs/*.html gates + 4 README + 3 man-page + 2 tests/ + 2 workflows + 1 cargo (vacuous).
?KEY DESIGN DECISIONS
Five tradeoffs unique to completing Xcode CLI tools.
11 separate #compdef files, not one mega-file
Each Xcode CLI tool is its own binary with its own flag surface; folding them into a single _xcode dispatcher would slow autoload and couple their lifecycles. Keeping 11 small #compdef files means zsh only loads the completer for the tool the user actually invokes — compinit-time cost is paid once and lazily-resolved per tool.
Live project queries, not static enums
Xcode schemes / targets / configurations / valid-archs differ per project. Hardcoding enums would be wrong the moment the user cds into a different repo. Instead, _xcodebuild shells out to xcodebuild -list / -showBuildSettings at completion time — cost is one xcodebuild spawn per TAB, but the result is project-correct.
Shim binary for xcrun nesting
xcrun's dispatch model breaks zsh's completion-system #compdef <binary> contract — nested tools aren't directly on PATH. The shim path (bin/swift-demangle = xcrun swift-demangle "$@") is the cleanest workaround: surface the tool as a PATH binary so the completer fires. Cost is one extra fork; benefit is autocomplete that Just Works.
Shared SDK cache key
Three completers (_xcodebuild, _swift, _xcrun) all need the SDK list. They share the cache key SDKS, so installing or uninstalling an SDK invalidates the cache for all three at once — no per-tool cache divergence. The cache key is plain SDKS (not prefix-keyed) because SDK lists are tiny and global.
1-line plugin entrypoint
The plugin file is literally fpath=("${0:h}/src" $fpath). No ZSH_ARGZERO self-locate because the plugin file lives at the repo root, and ${0:h} works correctly for direct sourcing. Zinit / OMZ / antibody all set $0 to the plugin file's path before sourcing — the 2-line idiom is unnecessary here. Less code, fewer pins, same outcome.