agenthook

package
v0.21.3 Latest Latest
Warning

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

Go to latest
Published: Aug 19, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

Documentation

Overview

Package agenthook installs command hooks into supported agent harnesses and normalizes their input for Claude Code-style hook handlers.

Its public event and matcher vocabulary follows Claude Code. Agent profiles translate that vocabulary to the native config path, event names, tool names, and file format used by each harness. This lets applications describe one set of lifecycle hooks while support for new agents stays centralized in kit. Profiles are provided for Claude Code, Codex, GitHub Copilot CLI, Cursor, Factory Droid, Gemini CLI, Hermes Agent, and Qwen Code.

Applications identify their hooks with a stable marker embedded in the command. Reinstalling replaces commands carrying that marker even when the executable path changed, and uninstalling removes only those commands:

result, err := agenthook.Install(agenthook.AgentHermes, agenthook.InstallOptions{
	Executable: "/opt/example",
	Arguments:  []string{"agent-hook", "run", "--source", "example-agent-hook"},
	Marker:     "--source example-agent-hook",
	Hooks: []agenthook.Hook{
		{Event: agenthook.EventPreToolUse, Matcher: agenthook.ToolBash},
		{Event: agenthook.EventStop},
	},
})

Installing a Hermes profile does not enable hooks_auto_accept. Hermes retains its first-use consent flow for every event and command pair.

A command installed for multiple harnesses can use one typed Claude handler. Embed NoopHandler and override only the events the application needs:

type hooks struct {
	agenthook.NoopHandler
}

func (hooks) PostToolUse(
	ctx context.Context,
	input agenthook.PostToolUseInput,
) (agenthook.PostToolUseOutput, error) {
	return recordToolUse(ctx, input)
}

err := agenthook.Handle(ctx, agent, os.Stdin, os.Stdout, hooks{})

Handle translates native fields before typed dispatch, then translates the typed Claude-style output into the invoking harness's response format. CommonInput.Raw keeps the complete normalized payload so handlers can inspect extension fields.

Index

Constants

View Source
const ToolBash = "Bash"

ToolBash is the Claude Code tool name for shell execution. Profiles map this exact matcher to the corresponding native tool name, such as terminal in Hermes, Execute in Factory Droid, and run_shell_command in Gemini and Qwen.

Variables

This section is empty.

Functions

func ConfigPath

func ConfigPath(agent Agent) (string, error)

ConfigPath returns the current user's standard config path for agent, honoring the harness-specific home environment variable when one exists.

func Handle

func Handle(
	ctx context.Context,
	agent Agent,
	input io.Reader,
	output io.Writer,
	handler Handler,
) error

Handle normalizes one native agent payload, dispatches its Claude event to handler, and writes an agent-compatible hook response as JSON. Input must be one finite JSON object that reaches EOF; payloads larger than 16 MiB are rejected. Context cancellation governs handler execution, but cannot interrupt reads from an arbitrary io.Reader.

Types

type Agent

type Agent string

Agent identifies an agent harness with a supported command-hook profile.

const (
	AgentClaude  Agent = "claude"
	AgentCodex   Agent = "codex"
	AgentCopilot Agent = "copilot"
	AgentCursor  Agent = "cursor"
	AgentDroid   Agent = "droid"
	AgentGemini  Agent = "gemini"
	AgentHermes  Agent = "hermes"
	AgentQwen    Agent = "qwen"
)

func ParseAgent

func ParseAgent(name string) (Agent, error)

ParseAgent resolves a case-insensitive agent name.

type BackgroundTask

type BackgroundTask struct {
	ID          string `json:"id"`
	Type        string `json:"type"`
	Status      string `json:"status"`
	Description string `json:"description,omitempty"`
	Command     string `json:"command,omitempty"`
	AgentType   string `json:"agent_type,omitempty"`
	Server      string `json:"server,omitempty"`
	Tool        string `json:"tool,omitempty"`
	Name        string `json:"name,omitempty"`
}

BackgroundTask describes work that may resume a stopped Claude session.

type Commands

type Commands struct {
	Native     string
	POSIX      string
	Windows    string
	PowerShell string
}

Commands contains hook command lines for the current platform, POSIX shells, the Win32 argv convention, and PowerShell. Profiles select the command syntax their config fields require.

func BuildCommand

func BuildCommand(executable string, arguments ...string) (Commands, error)

BuildCommand quotes an executable and arguments for agent hook config. It returns an error when executable is blank.

type CommonInput

type CommonInput struct {
	SessionID      string          `json:"session_id"`
	PromptID       string          `json:"prompt_id,omitempty"`
	TranscriptPath string          `json:"transcript_path,omitempty"`
	CWD            string          `json:"cwd,omitempty"`
	PermissionMode PermissionMode  `json:"permission_mode,omitempty"`
	Effort         *Effort         `json:"effort,omitempty"`
	HookEventName  Event           `json:"hook_event_name"`
	AgentID        string          `json:"agent_id,omitempty"`
	AgentType      string          `json:"agent_type,omitempty"`
	TurnID         string          `json:"turn_id,omitempty"`
	Raw            json.RawMessage `json:"-"`
}

CommonInput contains fields shared by Claude hook events. Raw contains the complete normalized payload for applications that need extension fields not represented by the typed event.

type CommonOutput

type CommonOutput struct {
	Continue         *bool  `json:"continue,omitempty"`
	StopReason       string `json:"stopReason,omitempty"`
	SuppressOutput   bool   `json:"suppressOutput,omitempty"`
	SystemMessage    string `json:"systemMessage,omitempty"`
	TerminalSequence string `json:"terminalSequence,omitempty"`
}

CommonOutput contains control fields available to every Claude hook event.

type Decision

type Decision string

Decision is a top-level hook decision. Claude-shaped lifecycle controls use block; profiles whose native contract supports allow or deny retain those values at the encoder boundary.

const (
	DecisionAllow Decision = "allow"
	DecisionDeny  Decision = "deny"
	DecisionBlock Decision = "block"
)

type Effort

type Effort struct {
	Level string `json:"level"`
}

Effort describes the model effort level active for an event.

type Event

type Event string

Event is a Claude Code lifecycle event name. Profiles translate events to native names when a harness uses a different vocabulary.

const (
	EventSessionStart       Event = "SessionStart"
	EventUserPromptSubmit   Event = "UserPromptSubmit"
	EventPreToolUse         Event = "PreToolUse"
	EventPostToolUse        Event = "PostToolUse"
	EventPostToolUseFailure Event = "PostToolUseFailure"
	EventPermissionRequest  Event = "PermissionRequest"
	EventNotification       Event = "Notification"
	EventStop               Event = "Stop"
	EventSessionEnd         Event = "SessionEnd"
)

type Handler

Handler receives normalized, Claude-shaped hook events. Embed NoopHandler and override only the event methods an application needs.

type Hook

type Hook struct {
	Event   Event
	Matcher string
	Timeout time.Duration
}

Hook describes one command registration using Claude Code event and matcher names. An empty matcher observes every invocation of the event. A zero timeout omits the timeout field and lets the harness use its default.

type InstallOptions

type InstallOptions struct {
	ConfigPath        string
	Executable        string
	Arguments         []string
	Command           string
	CommandWindows    string
	CommandPowerShell string
	Marker            string
	Hooks             []Hook
}

InstallOptions describes an application's hooks. Set Executable and Arguments to have kit construct commands for every supported shell. Command, CommandWindows, and CommandPowerShell are raw overrides for the native, Win32 argv, and PowerShell forms respectively; do not combine them with Executable. Marker must be a stable, application-namespaced substring unique to commands the caller owns; it identifies those commands across binary path changes. Hooks defaults to every event supported by the selected profile.

type NoopHandler

type NoopHandler struct{}

NoopHandler implements Handler without taking any action. Applications can embed it and override only the event methods they handle.

func (NoopHandler) Notification

func (NoopHandler) PostToolUse

func (NoopHandler) PreToolUse

func (NoopHandler) SessionEnd

func (NoopHandler) SessionStart

func (NoopHandler) Stop

type NotificationInput

type NotificationInput struct {
	CommonInput
	Message          string           `json:"message"`
	Title            string           `json:"title,omitempty"`
	NotificationType NotificationType `json:"notification_type"`
}

NotificationInput is the typed Claude Notification payload.

type NotificationOutput

type NotificationOutput struct {
	CommonOutput
}

NotificationOutput is the typed response from a Notification handler.

type NotificationType

type NotificationType string

NotificationType identifies the kind of Claude notification.

const (
	NotificationPermissionPrompt    NotificationType = "permission_prompt"
	NotificationIdlePrompt          NotificationType = "idle_prompt"
	NotificationAuthSuccess         NotificationType = "auth_success"
	NotificationElicitationDialog   NotificationType = "elicitation_dialog"
	NotificationElicitationComplete NotificationType = "elicitation_complete"
	NotificationElicitationResponse NotificationType = "elicitation_response"
	NotificationAgentNeedsInput     NotificationType = "agent_needs_input"
	NotificationAgentCompleted      NotificationType = "agent_completed"
)

type PermissionBehavior

type PermissionBehavior string

PermissionBehavior allows or denies a Claude permission prompt.

const (
	PermissionBehaviorAllow PermissionBehavior = "allow"
	PermissionBehaviorDeny  PermissionBehavior = "deny"
)

type PermissionDecision

type PermissionDecision string

PermissionDecision controls a Claude PreToolUse request.

const (
	PermissionDecisionAllow PermissionDecision = "allow"
	PermissionDecisionDeny  PermissionDecision = "deny"
	PermissionDecisionAsk   PermissionDecision = "ask"
	PermissionDecisionDefer PermissionDecision = "defer"
)

type PermissionMode

type PermissionMode string

PermissionMode is the Claude Code permission policy active for an event.

const (
	PermissionModeDefault           PermissionMode = "default"
	PermissionModePlan              PermissionMode = "plan"
	PermissionModeAcceptEdits       PermissionMode = "acceptEdits"
	PermissionModeAuto              PermissionMode = "auto"
	PermissionModeDontAsk           PermissionMode = "dontAsk"
	PermissionModeBypassPermissions PermissionMode = "bypassPermissions"
)

type PermissionRequestDecision

type PermissionRequestDecision struct {
	Behavior           PermissionBehavior `json:"behavior"`
	UpdatedInput       json.RawMessage    `json:"updatedInput,omitempty"`
	UpdatedPermissions json.RawMessage    `json:"updatedPermissions,omitempty"`
	Message            string             `json:"message,omitempty"`
	Interrupt          bool               `json:"interrupt,omitempty"`
}

PermissionRequestDecision controls a Claude permission prompt.

type PermissionRequestInput

type PermissionRequestInput struct {
	CommonInput
	ToolName              string          `json:"tool_name"`
	ToolInput             json.RawMessage `json:"tool_input"`
	PermissionSuggestions json.RawMessage `json:"permission_suggestions,omitempty"`
}

PermissionRequestInput is the typed Claude PermissionRequest payload.

type PermissionRequestOutput

type PermissionRequestOutput struct {
	CommonOutput
	Decision *PermissionRequestDecision
}

PermissionRequestOutput is the typed response from a PermissionRequest handler.

type PostToolUseFailureInput

type PostToolUseFailureInput struct {
	CommonInput
	ToolName    string          `json:"tool_name"`
	ToolInput   json.RawMessage `json:"tool_input"`
	ToolUseID   string          `json:"tool_use_id,omitempty"`
	Error       string          `json:"error"`
	IsInterrupt bool            `json:"is_interrupt,omitempty"`
	DurationMS  int64           `json:"duration_ms,omitempty"`
}

PostToolUseFailureInput is the typed Claude PostToolUseFailure payload.

type PostToolUseFailureOutput

type PostToolUseFailureOutput struct {
	CommonOutput
	AdditionalContext string
}

PostToolUseFailureOutput is the typed response from a PostToolUseFailure handler.

type PostToolUseInput

type PostToolUseInput struct {
	CommonInput
	ToolName     string          `json:"tool_name"`
	ToolInput    json.RawMessage `json:"tool_input"`
	ToolResponse json.RawMessage `json:"tool_response"`
	ToolUseID    string          `json:"tool_use_id,omitempty"`
	DurationMS   int64           `json:"duration_ms,omitempty"`
}

PostToolUseInput is the typed Claude PostToolUse payload.

type PostToolUseOutput

type PostToolUseOutput struct {
	CommonOutput
	Decision             Decision
	Reason               string
	AdditionalContext    string
	UpdatedToolOutput    json.RawMessage
	UpdatedMCPToolOutput json.RawMessage
}

PostToolUseOutput is the typed response from a PostToolUse handler.

type PreToolUseInput

type PreToolUseInput struct {
	CommonInput
	ToolName  string          `json:"tool_name"`
	ToolInput json.RawMessage `json:"tool_input"`
	ToolUseID string          `json:"tool_use_id,omitempty"`
}

PreToolUseInput is the typed Claude PreToolUse payload.

type PreToolUseOutput

type PreToolUseOutput struct {
	CommonOutput
	PermissionDecision       PermissionDecision
	PermissionDecisionReason string
	UpdatedInput             json.RawMessage
	AdditionalContext        string
}

PreToolUseOutput is the typed response from a PreToolUse handler.

type Profile

type Profile struct {
	Agent             Agent
	DisplayName       string
	ConfigEnvironment string
	ConfigFilename    string
	SupportedEvents   []Event
}

Profile describes the stable, user-visible properties of an agent hook integration. SupportedEvents uses the Claude Code event vocabulary.

func LookupProfile

func LookupProfile(agent Agent) (Profile, bool)

LookupProfile returns a copy of the profile for agent.

func Profiles

func Profiles() []Profile

Profiles returns every supported agent profile in stable display order.

type Result

type Result struct {
	Agent      Agent
	ConfigPath string
	Changed    bool
	Data       []byte
}

Result reports the planned or completed config mutation. Data contains the complete resulting config and can be used by command-line dump operations.

func Install

func Install(agent Agent, opts InstallOptions) (Result, error)

Install merges the application's hooks into the selected agent config. Callers must serialize concurrent mutations of the same config path.

func PlanInstall

func PlanInstall(agent Agent, opts InstallOptions) (Result, error)

PlanInstall computes an install without writing the config file.

func PlanUninstall

func PlanUninstall(agent Agent, configPath, marker string) (Result, error)

PlanUninstall computes removal of every command containing marker without writing the config file. A missing config is a successful no-op.

func Uninstall

func Uninstall(agent Agent, configPath, marker string) (Result, error)

Uninstall removes every command containing marker from the selected agent config while preserving hooks owned by other applications. Callers must serialize concurrent mutations of the same config path.

type SessionCron

type SessionCron struct {
	ID        string `json:"id"`
	Schedule  string `json:"schedule"`
	Recurring bool   `json:"recurring"`
	Prompt    string `json:"prompt"`
}

SessionCron describes a scheduled session wakeup.

type SessionEndInput

type SessionEndInput struct {
	CommonInput
	// Reason is empty when the native hook has no Claude-equivalent reason.
	Reason SessionEndReason `json:"reason"`
}

SessionEndInput is the typed Claude SessionEnd payload.

type SessionEndOutput

type SessionEndOutput struct {
	CommonOutput
}

SessionEndOutput is the typed response from a SessionEnd handler.

type SessionEndReason

type SessionEndReason string

SessionEndReason identifies why a Claude session terminated.

const (
	SessionEndClear                     SessionEndReason = "clear"
	SessionEndResume                    SessionEndReason = "resume"
	SessionEndLogout                    SessionEndReason = "logout"
	SessionEndPromptInputExit           SessionEndReason = "prompt_input_exit"
	SessionEndBypassPermissionsDisabled SessionEndReason = "bypass_permissions_disabled"
	SessionEndOther                     SessionEndReason = "other"
)

type SessionSource

type SessionSource string

SessionSource identifies how a session started.

const (
	SessionSourceStartup SessionSource = "startup"
	SessionSourceResume  SessionSource = "resume"
	SessionSourceClear   SessionSource = "clear"
	SessionSourceCompact SessionSource = "compact"
	SessionSourceFork    SessionSource = "fork"
)

type SessionStartInput

type SessionStartInput struct {
	CommonInput
	// Source is empty when the native hook has no equivalent lifecycle concept.
	Source       SessionSource `json:"source"`
	Model        string        `json:"model,omitempty"`
	SessionTitle string        `json:"session_title,omitempty"`
}

SessionStartInput is the typed Claude SessionStart payload.

type SessionStartOutput

type SessionStartOutput struct {
	CommonOutput
	AdditionalContext  string
	InitialUserMessage string
	SessionTitle       string
	WatchPaths         []string
	ReloadSkills       bool
}

SessionStartOutput is the typed response from a SessionStart handler.

type StopInput

type StopInput struct {
	CommonInput
	StopHookActive       bool             `json:"stop_hook_active,omitempty"`
	LastAssistantMessage string           `json:"last_assistant_message,omitempty"`
	BackgroundTasks      []BackgroundTask `json:"background_tasks,omitempty"`
	SessionCrons         []SessionCron    `json:"session_crons,omitempty"`
}

StopInput is the typed Claude Stop payload.

type StopOutput

type StopOutput struct {
	CommonOutput
	Decision          Decision
	Reason            string
	AdditionalContext string
}

StopOutput is the typed response from a Stop handler.

type UserPromptSubmitInput

type UserPromptSubmitInput struct {
	CommonInput
	Prompt string `json:"prompt"`
}

UserPromptSubmitInput is the typed Claude UserPromptSubmit payload.

type UserPromptSubmitOutput

type UserPromptSubmitOutput struct {
	CommonOutput
	Decision               Decision
	Reason                 string
	AdditionalContext      string
	SessionTitle           string
	SuppressOriginalPrompt bool
}

UserPromptSubmitOutput is the typed response from a UserPromptSubmit handler.

Jump to

Keyboard shortcuts

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