UNPKG

@sebastienrousseau/dotfiles

Version:

The Trusted Shell Platform — Universal dotfiles managed by Chezmoi. Features Bash & Zsh for macOS, Linux & WSL. Rust modern tooling & enterprise-grade security.

124 lines (95 loc) 4.96 kB
--- render_with_liquid: false --- # Zsh Completion Cache Lifecycle This page documents how zsh completion compilation works in this repo and how to force a rebuild. Managed under [#864](https://github.com/sebastienrousseau/dotfiles/issues/864). ## The Pieces Three caches cooperate to keep `compinit` fast without compromising correctness: 1. **The compinit dump** — `$XDG_CACHE_HOME/zsh/zcompdump-$ZSH_VERSION`. Built by `compinit -d <path>` from the fpath corpus. Encodes which file provides each completion function. Per-zsh-version so an OS upgrade doesn't silently serve a stale binary index. 2. **The compinit dump bytecode** — `<dump>.zwc`. Built by `zcompile` in the background after the dump is rebuilt. Zsh prefers the `.zwc` form on subsequent shells, skipping re-parse. 3. **fpath bytecode siblings** — `_<tool>.zwc` next to each `_<tool>` source file under `~/.local/share/zsh/completions/`. Built once per chezmoi apply by `run_onchange_after_zcompile-completions.sh.tmpl` (so this happens *outside* the critical shell-start path). Zsh prefers the `.zwc` when autoloading the corresponding completion function. ## Flow on Shell Start ``` zsh starts → sources rc.d (no compinit yet) → registers a `preexec` (or `precmd`) hook → returns to prompt user presses Tab (or `precmd` fires) → `compinit -d $XDG_CACHE_HOME/zsh/zcompdump-$ZSH_VERSION` or `compinit -C -d <dump>` if the dump is < 24 hours old → background `zcompile` of the dump → first tab-completion uses the precompiled `.zwc` for each tool ``` ## Flow on Chezmoi Apply ``` chezmoi apply → if completion sources changed, run_onchange fires run_onchange_after_zcompile-completions.sh.tmpl → walks ~/.local/share/zsh/completions/ → for each _<tool> file whose .zwc is missing or stale: zsh -c "zcompile <file>" → reports compiled=N skipped=M ``` ## Configuration Surface | Variable | Default | Purpose | |---|---|---| | `DOTFILES_ENABLE_COMPINIT` | 1 on `laptop`/`desktop` profiles, 0 elsewhere | Whether to load the completion subsystem at all. Non-laptop profiles skip the runtime cost but still benefit from precompiled `.zwc` files if present. | | `DOTFILES_DEFER_COMPINIT` | 1 | When 1, compinit runs on first `preexec`. When 0, runs on `precmd`. | | `DOTFILES_FAST` | 0 | When 1, the entire completion path is skipped. | | `DOTFILES_ULTRA_FAST` | 0 | Same as `DOTFILES_FAST` but more aggressive. | | `DOTFILES_SKIP_ZCOMPILE` | 0 | When 1, the run_onchange hook does not precompile fpath files. Used in CI / minimal images where bytecode isn't needed. | | `XDG_CACHE_HOME` | `$HOME/.cache` | Standard XDG override; the dump path is `$XDG_CACHE_HOME/zsh/zcompdump-$ZSH_VERSION`. | ## Force Rebuild When completions go stale (e.g., after a tool upgrade): ```bash # Invalidate the compinit dump — next shell rebuilds it. rm -f "${XDG_CACHE_HOME:-$HOME/.cache}/zsh/zcompdump-${ZSH_VERSION}" rm -f "${XDG_CACHE_HOME:-$HOME/.cache}/zsh/zcompdump-${ZSH_VERSION}.zwc" # Force regeneration of fpath bytecode siblings: find ~/.local/share/zsh/completions -name '*.zwc' -delete chezmoi apply ~ # re-runs the run_onchange hook ``` Or, equivalently, `dot heal` (which calls both in sequence). ## Measured Cost The current dotfiles ship with `compinit` deferred to first-prompt, which means shell *startup* time is already nearly minimal — zsh doesn't parse the fpath corpus until tab-completion is invoked. The precompiled `.zwc` files cut down the *first tab-completion* latency per tool, not shell-start latency. On a 2026 M-series macOS host the P50 for `time zsh -i -c exit` measured at 39 ms before this change and 39 ms after — the change pays off when the user starts typing, not before. This makes the lifecycle policy still worth shipping: - Cleaner cache layout (XDG-cache, version-keyed). - Bytecode siblings auto-picked on non-laptop profiles (which skip compinit entirely) so completion is still fast even without the full subsystem. - A documented force-rebuild path. ## Skip Rules The run_onchange hook skips itself when: - `DOTFILES_SKIP_ZCOMPILE=1` (CI / minimal images). - `zsh` is not on PATH (servers without an interactive shell). - `~/.local/share/zsh/completions/` doesn't exist. System fpath directories (Homebrew, `/usr/local/share/zsh`) are intentionally NOT precompiled — the package manager already manages their lifecycle. ## References - [`dot_config/zsh/rc.d/30-options.zsh.tmpl`](../../defaults/dot_config/zsh/rc.d/30-options.zsh.tmpl) — the deferred-compinit logic. - [`run_onchange_after_zcompile-completions.sh.tmpl`](../../defaults/run_onchange_after_zcompile-completions.sh.tmpl) — the apply-time precompile hook. - [`zsh` completion docs](https://zsh.sourceforge.io/Doc/Release/Completion-System.html). - ADR-002 (Shell Performance Optimization). - Issue [#864](https://github.com/sebastienrousseau/dotfiles/issues/864).