Skip to content

perf: fixed slow zsh startup in new tabs - #62

Merged
CaddyDz merged 1 commit into
masterfrom
fix/zsh-startup-time
Sep 10, 2026
Merged

CaddyDz merged 1 commit into
masterfrom
fix/zsh-startup-time

Conversation

@CaddyDz

@CaddyDz CaddyDz commented Sep 10, 2026

Copy link
Copy Markdown
Owner

New iTerm tabs took ~0.6s to show a prompt. Profiling showed .zshrc ran compinit three times per shell (oh-my-zsh, then the Homebrew and Docker Desktop blocks). Each extra call re-audited ~970 completion files, and because fpath differed between calls the completion dump was rewritten twice on every start (~0.45s). A second, intermittent cause: ZSH_COMPDUMP was keyed on $HOST, so macOS flipping the hostname (VPN / DHCP reverse-DNS) rebuilt the whole dump again.

  • Put Homebrew's site-functions and ~/.docker/completions on fpath before sourcing oh-my-zsh so its single compinit covers them, and dropped the two trailing compinit blocks
  • Replaced the $(brew --prefix) subprocess with ${commands[brew]:h:h}
  • Kept Docker Desktop's marker comments so it does not re-append its own compinit block on a future update
  • Disabled the oh-my-zsh auto-update check via zstyle ':omz:update' mode disabled: its two git calls through Apple's xcrun shim cost ~45ms per tab; update manually with omz update
  • Gave ZSH_COMPDUMP a fixed filename

Startup on a tty (what iTerm spawns) went from 0.61s to 0.11s. Verified that aliases, functions, options, keybindings, prompt, and tab-completion candidates are unchanged, with one exception: docker <TAB> now uses Docker Desktop's generated completer instead of the legacy static script Homebrew links from the app bundle, which was mis-parsing docker --help output into bogus candidates.

[skip ci]

New iTerm tabs took ~0.6s to show a prompt. Profiling showed `.zshrc`
ran `compinit` three times per shell (oh-my-zsh, then the Homebrew and
Docker Desktop blocks). Each extra call re-audited ~970 completion
files, and because `fpath` differed between calls the completion dump
was rewritten twice on every start (~0.45s). A second, intermittent
cause: `ZSH_COMPDUMP` was keyed on `$HOST`, so macOS flipping the
hostname (VPN / DHCP reverse-DNS) rebuilt the whole dump again.

- Put Homebrew's `site-functions` and `~/.docker/completions` on
  `fpath` before sourcing oh-my-zsh so its single `compinit` covers
  them, and dropped the two trailing `compinit` blocks
- Replaced the `$(brew --prefix)` subprocess with
  `${commands[brew]:h:h}`
- Kept Docker Desktop's marker comments so it does not re-append its
  own `compinit` block on a future update
- Disabled the oh-my-zsh auto-update check via
  `zstyle ':omz:update' mode disabled`: its two `git` calls through
  Apple's xcrun shim cost ~45ms per tab; update manually with
  `omz update`
- Gave `ZSH_COMPDUMP` a fixed filename

Startup on a tty (what iTerm spawns) went from 0.61s to 0.11s.
Verified that aliases, functions, options, keybindings, prompt, and
tab-completion candidates are unchanged, with one exception:
`docker <TAB>` now uses Docker Desktop's generated completer instead
of the legacy static script Homebrew links from the app bundle, which
was mis-parsing `docker --help` output into bogus candidates.

[skip ci]

Signed-off-by: Salim Djerbouh <[email protected]>
@CaddyDz CaddyDz self-assigned this Sep 10, 2026
@CaddyDz CaddyDz added enhancement New feature or request config Configuration files or variables perf Performance improvements labels Sep 10, 2026
@CaddyDz
CaddyDz merged commit 40ff7c9 into master Sep 10, 2026
1 check passed
@CaddyDz
CaddyDz deleted the fix/zsh-startup-time branch September 10, 2026 06:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

config Configuration files or variables enhancement New feature or request perf Performance improvements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant