Hooks
Hooks run shell commands at fixed points in the tool lifecycle. They are how you wire up auto-formatting after an edit, a lint pass when a session ends, or an audit log of every command the engine runs. You declare them in the config file.
The three events
Section titled “The three events”| Event | Fires | Behavior |
|---|---|---|
pre_tool_use | Before a tool runs. | A non-zero exit blocks the tool. |
post_tool_use | After a tool runs. | Non-blocking; errors are logged. |
stop | When the session ends. | Non-blocking. |
Use pre_tool_use to gate a tool (for example, refuse a write to a protected path), post_tool_use for follow-up work like formatting, and stop for a final pass.
Configuration
Section titled “Configuration”Each hook is a [[hooks.<event>]] table. Match on tool name, on file path, or on neither to match everything:
# Format Rust files after they change[[hooks.post_tool_use]]name = "rustfmt"tool_match = ["Write", "Edit"]file_match = ["*.rs"]command = "rustfmt ${TOOL_INPUT_FILE_PATH}"
# Format TypeScript files[[hooks.post_tool_use]]name = "prettier"tool_match = ["Write", "Edit"]file_match = ["*.ts", "*.tsx"]command = "npx prettier --write ${TOOL_INPUT_FILE_PATH}"
# Audit every Bash command[[hooks.post_tool_use]]name = "audit-log"tool_match = ["Bash"]command = "echo \"$(date): ${TOOL_INPUT_COMMAND}\" >> .wayland-core/audit.log"
# Lint once at session end[[hooks.stop]]name = "final-lint"command = "cargo clippy --quiet 2>&1 | tail -5"Variables in hook commands
Section titled “Variables in hook commands”Hook commands reference these with ${VAR} syntax:
| Variable | Description |
|---|---|
TOOL_NAME | The tool name. |
TOOL_INPUT | Full tool input as JSON. |
TOOL_INPUT_FILE_PATH | File path, when the tool has one. |
TOOL_INPUT_COMMAND | Command, when the tool has one. |
TOOL_INPUT_PATTERN | Search pattern, when the tool has one. |
TOOL_OUTPUT | Tool output (post_tool_use only). |
Matching and timeout
Section titled “Matching and timeout”tool_match takes glob patterns against tool names; an empty list matches all tools. file_match works the same against file paths. Each hook has a 30-second default timeout, set per hook with timeout_ms.