pub struct HookDef {
pub action: HookAction,
pub timeout_secs: u64,
pub fail_closed: bool,
pub if: Option<String>,
}Expand description
A single hook definition.
Hooks are fired at specific lifecycle points. The action field determines
whether the hook runs a shell command or dispatches to an MCP server tool.
§Examples
[[hooks.cwd_changed]]
type = "command"
command = "echo changed to $ZEPH_NEW_CWD"
timeout_secs = 10
fail_closed = false
# Conditional hook — only fires when the triggering tool name contains "shell":
[[hooks.post_tool_use]]
matcher = "Shell"
[[hooks.post_tool_use.hooks]]
type = "command"
command = "echo shell ran"
if = "tool:shell"Fields§
§action: HookActionThe action to execute: shell command or MCP tool call.
timeout_secs: u64Maximum seconds to wait for the hook before timing out. Default: 30.
fail_closed: boolWhen true, a non-zero exit code or timeout aborts the remaining hooks in the same
sequence (no further hooks in the list run). When false (default), errors are logged
and the next hook in the sequence continues.
Note: in pre_tool_use and post_tool_use contexts this field controls hook-chain
execution only — it does not block the tool call itself. Hook dispatch is always
fail-open at the agent level; the tool executes regardless of hook outcomes.
if: Option<String>Optional condition that must match for this hook to fire.
When None (the default), the hook fires unconditionally at every matching lifecycle
event. When Some, the value is a key:value filter string. Supported keys:
tool:<token>— the hook fires only whenZEPH_TOOL_NAMEcontains<token>(case-sensitive substring, same rule asHookMatcher). An empty token (tool:) always evaluates tofalse(fail-closed).
Unknown keys and malformed values (no :) also evaluate to false so that a
misconfigured condition silently skips the hook rather than firing unconditionally.
Note: tool: conditions on file_changed, cwd_changed, and turn_complete
events will never match because those events carry no triggering-tool context.
The hook will be permanently skipped in those positions (a warn! is emitted once
when the hook config is first evaluated).