Documentation
¶
Overview ¶
Package hook holds the shape of a hooks configuration block and the naming its events and transports use.
It is the contract half of the pair whose implementation is internal/infra/hook, the same split as internal/core/llm and internal/infra/llm. It sits in core because two callers that cannot share anything higher both need it: loading a file for a run, and inspecting an uploaded plugin package before publishing it, which internal/server does and which may not import internal/config.
Index ¶
Constants ¶
const ( EventSessionStart = "SessionStart" EventSessionEnd = "SessionEnd" EventUserPromptSubmit = "UserPromptSubmit" EventPreToolUse = "PreToolUse" EventPostToolUse = "PostToolUse" EventPostToolUseFailure = "PostToolUseFailure" EventNotification = "Notification" EventPreCompact = "PreCompact" EventPostCompact = "PostCompact" EventSubagentStart = "SubagentStart" EventSubagentStop = "SubagentStop" EventStop = "Stop" EventStopFailure = "StopFailure" EventWorktreeCreate = "WorktreeCreate" EventWorktreeRemove = "WorktreeRemove" EventCwdChanged = "CwdChanged" )
Event keys recognised in settings.yaml under "hooks". The values match agent.HookEvent so callers can pass them through directly.
const ( TypeCommand = "command" // shell command on stdin/stdout TypeHTTP = "http" // HTTP POST with JSON body TypeMCP = "mcp_tool" // MCP tool invocation TypePrompt = "prompt" // single-turn LLM prompt )
Hook transport types. Match the canonical names used by Claude Code so scripts and operator docs port directly.
const DefaultTimeoutSecs = 30
DefaultTimeoutSecs is the per-hook execution timeout when a hook entry does not set its own timeout. Long enough for formatters/linters; short enough that a hung script does not block the agent for a full LLM turn.
const DefaultType = TypeCommand
DefaultType is the transport assumed when a Entry omits Type. "command" preserves back-compat with pre-v2 settings.yaml files.
Variables ¶
This section is empty.
Functions ¶
func EventNames ¶
func EventNames() []string
EventNames lists every event in dispatch order, for a surface that has to enumerate them.
Types ¶
type Config ¶
type Config struct {
SessionStart []Entry `mapstructure:"session_start" json:"session_start,omitempty" yaml:"session_start,omitempty"`
SessionEnd []Entry `mapstructure:"session_end" json:"session_end,omitempty" yaml:"session_end,omitempty"`
UserPromptSubmit []Entry `mapstructure:"user_prompt_submit" json:"user_prompt_submit,omitempty" yaml:"user_prompt_submit,omitempty"`
PreToolUse []Entry `mapstructure:"pre_tool_use" json:"pre_tool_use,omitempty" yaml:"pre_tool_use,omitempty"`
PostToolUse []Entry `mapstructure:"post_tool_use" json:"post_tool_use,omitempty" yaml:"post_tool_use,omitempty"`
PostToolUseFailure []Entry `mapstructure:"post_tool_use_failure" json:"post_tool_use_failure,omitempty" yaml:"post_tool_use_failure,omitempty"`
Notification []Entry `mapstructure:"notification" json:"notification,omitempty" yaml:"notification,omitempty"`
PreCompact []Entry `mapstructure:"pre_compact" json:"pre_compact,omitempty" yaml:"pre_compact,omitempty"`
PostCompact []Entry `mapstructure:"post_compact" json:"post_compact,omitempty" yaml:"post_compact,omitempty"`
SubagentStart []Entry `mapstructure:"subagent_start" json:"subagent_start,omitempty" yaml:"subagent_start,omitempty"`
SubagentStop []Entry `mapstructure:"subagent_stop" json:"subagent_stop,omitempty" yaml:"subagent_stop,omitempty"`
Stop []Entry `mapstructure:"stop" json:"stop,omitempty" yaml:"stop,omitempty"`
StopFailure []Entry `mapstructure:"stop_failure" json:"stop_failure,omitempty" yaml:"stop_failure,omitempty"`
WorktreeCreate []Entry `mapstructure:"worktree_create" json:"worktree_create,omitempty" yaml:"worktree_create,omitempty"`
WorktreeRemove []Entry `mapstructure:"worktree_remove" json:"worktree_remove,omitempty" yaml:"worktree_remove,omitempty"`
CwdChanged []Entry `mapstructure:"cwd_changed" json:"cwd_changed,omitempty" yaml:"cwd_changed,omitempty"`
}
Config is the "hooks" block of settings.yaml. Per CLAUDE.md §6.1 the keys are snake_case; the values still resolve to the canonical HookEvent names listed above.
func ParseConfig ¶
ParseConfig decodes a hooks.yaml document.
This is for a caller holding bytes rather than a path — inspecting an uploaded package, for one. A run loads through internal/config, which reads the same block out of settings.yaml as well.
func (*Config) EachEntry ¶
EachEntry applies fn to every entry, in dispatch order.
The pointer is the point: expansion rewrites entries in place, and inspection walks the same set. Both would otherwise repeat this thirteen-way list and drift the first time an event was added.
type Entry ¶
type Entry struct {
// Type selects the transport: "command", "http", "mcp_tool", "prompt".
// Empty defaults to TypeCommand.
Type string `mapstructure:"type" json:"type,omitempty" yaml:"type,omitempty"`
Matcher string `mapstructure:"matcher" json:"matcher,omitempty" yaml:"matcher,omitempty"`
Timeout int `mapstructure:"timeout" json:"timeout,omitempty" yaml:"timeout,omitempty"`
// Command transport: shell command to execute via "sh -c" (Unix) or
// "cmd /C" (Windows). Stdin receives the HookInput JSON.
Command string `mapstructure:"command" json:"command,omitempty" yaml:"command,omitempty"`
// HTTP transport: POSTs the HookInput JSON to URL. Headers values may
// contain "$VAR" / "${VAR}" references; only env vars whitelisted in
// AllowedEnv may be interpolated.
URL string `mapstructure:"url" json:"url,omitempty" yaml:"url,omitempty"`
Headers map[string]string `mapstructure:"headers" json:"headers,omitempty" yaml:"headers,omitempty"`
AllowedEnv []string `mapstructure:"allowed_env" json:"allowed_env,omitempty" yaml:"allowed_env,omitempty"`
// MCP transport: invoke Tool on Server with Input. Input values may
// contain "${field}" references resolved against the HookInput payload.
Server string `mapstructure:"server" json:"server,omitempty" yaml:"server,omitempty"`
Tool string `mapstructure:"tool" json:"tool,omitempty" yaml:"tool,omitempty"`
Input map[string]any `mapstructure:"input" json:"input,omitempty" yaml:"input,omitempty"`
// Prompt transport: run a single-turn prompt against Model (empty uses
// the default fast model). The literal "$ARGUMENTS" inside Prompt is
// replaced with the HookInput JSON.
Prompt string `mapstructure:"prompt" json:"prompt,omitempty" yaml:"prompt,omitempty"`
Model string `mapstructure:"model" json:"model,omitempty" yaml:"model,omitempty"`
}
Entry is one configured hook invocation. The Type discriminator selects which transport-specific fields are read; entries with no Type default to TypeCommand for back-compat with pre-v2 settings.
Matcher is a regular expression evaluated against the tool name for PreToolUse / PostToolUse; an empty Matcher matches every invocation. For non-tool events the field is ignored.
Timeout is per-hook in seconds. Zero means DefaultTimeoutSecs.
Per-type fields are kept on one flat struct so a Entry round-trips cleanly through YAML/JSON without a custom unmarshaller. A driver only reads the fields relevant to its Type; the rest are zero values.
func (Entry) ResolvedType ¶
ResolvedType returns Entry.Type, defaulting to TypeCommand when empty.