Speed
Light enough to forget it's there
Hooks run on every tool call, so each has a time budget and the bench holds them to it. Only the guard and the write validators run in the call's path.
Show the numbers
| value | budget | |
|---|---|---|
| PreToolUse:Bash:script | 274 | 300 |
| UserPromptSubmit | 92.6 | 150 |
| PreToolUse:Bash | 67.1 | 150 |
| SessionStart | 63.4 | 150 |
| PreToolUse:Edit | 56.5 | 150 |
| PreToolUse:Bash:block | 48.7 | 150 |
| Stop | 47.6 | 150 |
| PreCompact | 45.3 | 150 |
| Notification | 42.4 | 150 |
| PostToolUse | 41.5 | 150 |
| SubagentStop | 41.4 | 150 |
| PostToolUseFailure | 39 | 150 |
| SessionEnd | 38.8 | 150 |
| TaskCompleted | 35.8 | 150 |
| MessageDisplay | 35.6 | 100 |
| SubagentStart | 35.4 | 150 |
How it stays fast
- Budgets per hook, checked by
bench_hooks.pyon every release. - Reused gate passes.
fm checkskips a gate that passed on an identical tree. - Cached verdicts. Scripts the guard read are cached by content.
- Notes once. Context is injected only when it changes what Claude should do next.
Gate runs558
Median full gate run, s75.6