edmundmiller/dotfiles/zbench
Claude Code and agent skill by edmundmiller/dotfiles
- community
Checking that the SKILL.md file is still in the repository.
Measures interactive zsh latency with zsh-bench. Use for slow-shell diagnosis, performance comparisons, or regression bisection.
Install
npx vskill@latest install edmundmiller/dotfiles/zbenchSKILL.md
zsh-bench Integration
Proper benchmarking of interactive zsh using romkatv/zsh-bench. Measures real user-visible latency, NOT time zsh -lic exit (which is meaningless).
Commands
All commands accept extra zsh-bench args: hey zbench --iters 4 for quick runs. Run from the intended checkout: both installed hey and ./bin/hey execute that project's mise tasks. No host rebuild is needed for task edits. The Nushell entrypoints in bin/hey.d/zbench/ use def --wrapped ... [...args] so flags such as --iters pass through to zsh-bench.
Metrics & Thresholds
From romkatv's blind perception study — values at or below threshold are indistinguishable from zero:
| Metric | Threshold | What it means | |
|---|---|---|---|
first_prompt_lag_ms | 50ms | Time to see prompt after opening terminal | |
first_command_lag_ms | 150ms | Time until first command can execute | |
command_lag_ms | 10ms | Delay between Enter and next prompt | |
input_lag_ms | 20ms | Keystroke-to-screen latency |
Indicators: 🟢 ≤50% (headroom) · 🟡 ≤100% (imperceptible) · 🟠 ≤200% (noticeable) · 🔴 >200% (sluggish)
exit_time_ms is shown but not used for thresholds — it doesn't measure interactive performance.
Git Bisect Workflow
Find which commit made the shell slow:
zbench-check exits non-zero when any metric exceeds its threshold.
File Layout
Baselines are per-host (MacTraitor-Pro.json, Seqeratop.json) because hardware varies.
Typical Workflow
Autoresearch Optimization Prompt
For a multi-iteration optimization loop, use pi-autoresearch to drive small zsh config experiments and zsh-bench to measure whether each experiment helped. Do not use autoresearch instead of zsh-bench; use it as the edit → benchmark → keep/revert loop around zsh-bench.
Run the local prompt template with pi-autoresearch:
If you prefer to install the extension persistently first:
Canonical prompt file: .pi/prompts/zbench-autoresearch.md.
Debugging Slow Startup
Phase Timing Script
Don't guess — measure. Paste this into zsh -c '...' to time each phase of startup:
Adapt phases to match the actual .zshrc. The gap between this total and zsh-bench is overhead from /etc/zshrc (nix-darwin generated) and deferred plugin loading.
To drill into extra.zshrc, time each source line individually — one slow alias file can dominate.
Known Culprits (ranked by typical impact)
| Culprit | Typical cost | Fix | |
|---|---|---|---|
| Redundant compinit | 2000-3000ms | Ensure compinit runs exactly once. Check EOF of .zshrc, /etc/zshrc, and completion.zsh — easy to end up with 2+ calls. Use compinit -C -d "$cache" with 24h staleness check. | |
| Nix store globs | 200-400ms | for f in /nix/store/*foo*/*.zsh is slow — thousands of dirs. Cache the resolved path to a file. | |
| Shell startup file scanning | 100-500ms | Functions that grep/sed across many files at startup (e.g., fixing session files). Move to on-demand or a cron job. | |
| Uncached `eval "$(tool init)"` | 40-100ms each | brew shellenv, direnv hook zsh, fnm env, zoxide init zsh, entire completion zsh. Use _cache pattern to write output to file, re-eval only when binary changes. | |
| Double `brew shellenv` | 40-80ms | nix-homebrew adds eval "$(brew shellenv)" to /etc/zshrc. If you handle it in .zshenv, set enableZshIntegration = false in nix-homebrew config. | |
| Plugin manager overhead | 10-40ms | Antidote's antidote load does staleness checks. If static file exists, source it directly and skip antidote init entirely. | |
| Deferred plugins | 0ms startup | antidote kind:defer is free at startup but zsh-bench won't detect has_syntax_highlighting/has_autosuggestions. This is fine. |
The _cache Pattern
Central to fast startup. Already defined in .zshrc:
Invalidates when the binary changes ($commands[$1] mtime check). Delete ~/.cache/zsh/*.zsh to force regeneration.
Replay Mode
Use zsh-bench --iters 1 --scratch-dir /tmp/zbench-debug then dbg/replay --scratch-dir /tmp/zbench-debug to watch what zsh-bench actually sees. For worktree experiments that should read the repo copy of config/zsh, run with ZDOTDIR=$PWD/config/zsh ZSH_CACHE=$HOME/.cache/zsh; otherwise zsh-bench may exercise the currently installed Home Manager generation.
Key Design Decisions
- Uses zsh-bench's non-raw output (median of 16 iterations) for stable numbers.
- `--raw` gives per-iteration arrays — useful for variance analysis but not default.
- Baselines stored as JSON for easy programmatic comparison.
- History stored as TSV for easy
column -t,awk, or import into spreadsheets. - Regression detection: flags changes > 20% or > 5ms (whichever is larger).
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewPassed
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryChecking.pi/skills/zbench/SKILL.md
Popularity
- Repository stars
- 48
- Repository forks
- 4
- 7-day trend score
- 19
Stars and forks are for the whole GitHub repository, not this skill alone. Refreshed 18 Mar 2026, 7 months ago.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/edmundmiller/dotfiles/zbench)