hook

package
v0.2.0-alpha.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 6, 2026 License: Apache-2.0 Imports: 1 Imported by: 0

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

View Source
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.

View Source
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.

View Source
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.

View Source
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

func ParseConfig(data []byte) (Config, error)

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

func (h *Config) EachEntry(fn func(*Entry))

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.

func (Config) Entries

func (h Config) Entries(event string) []Entry

Entries returns the configured hooks for the named event, in declared order. Unknown events return nil.

func (Config) IsEmpty

func (h Config) IsEmpty() bool

IsEmpty reports whether the configuration has no hooks at all.

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

func (e Entry) ResolvedType() string

ResolvedType returns Entry.Type, defaulting to TypeCommand when empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL