Documentation
¶
Overview ¶
Package hookexec implements port.HookRunner by running a configured shell command per lifecycle HookPhase. The HookEvent is serialized to JSON and written to the hook process's stdin; the process's exit code carries the outcome:
0 → allow (HookOutcome.Block == false)
2 → block (HookOutcome.Block == true); the message is read from
stdout (preferred) or stderr
other != 0 → error (the hook itself failed)
Mutation: on an ALLOW (exit 0), if the hook's stdout is a JSON OBJECT it is parsed as a control envelope: a "mutated" field (raw JSON) becomes HookOutcome.Mutated — the rewritten action payload the loop applies (a {"prompt": ...} object for UserPromptSubmit, the rewritten tool-args object for PreToolUse) — and an optional "message" string becomes HookOutcome.Message. Plain (non-JSON-object) stdout is treated as a message string exactly as before, so existing hooks are unaffected. (A JSON object is detected only when stdout begins with '{', so a hook printing arbitrary prose never trips it.)
A nil or empty hook map means "no hooks configured": every event is allowed. Execution honours the caller's context and a per-run timeout.
Index ¶
Constants ¶
const DefaultTimeout = 30 * time.Second
DefaultTimeout bounds a single hook invocation when no timeout is supplied.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Option ¶
type Option func(*Runner)
Option configures a Runner.
func WithShell ¶
WithShell overrides the shell used to interpret hook commands (default "/bin/sh"). Each command is run as `<shell> -c <command>`.
func WithTimeout ¶
WithTimeout sets the per-invocation timeout. A non-positive value resets to DefaultTimeout.
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
Runner implements port.HookRunner over OS process execution. Construct it with New. The zero value runs no hooks (allows everything).
func New ¶
func New(hooks map[governance.HookPhase]string, opts ...Option) *Runner
New constructs a Runner that runs the given phase → shell-command map. A nil or empty map yields a Runner that allows every event.
func (*Runner) Run ¶
func (r *Runner) Run(ctx context.Context, ev governance.HookEvent) (governance.HookOutcome, error)
Run executes the hook registered for ev.Phase. With no hook for the phase the event is allowed. The HookEvent is delivered as JSON on the hook's stdin.