Documentation
¶
Overview ¶
Package cursorhooks runs Cursor-shaped hooks. Cursor hook handlers are shell command strings (or prompt-type entries, which testagent accepts but never fires — Cursor's prompt hooks are LLM-evaluated and testagent has no LLM). The Runner satisfies the same engine.HookSender / slash.ToolHookSender interfaces that internal/hooks and internal/codexhooks satisfy, so vendor selection is just choosing which struct to build at the cmd/cursor layer.
Unmodeled Cursor events (sessionStart, sessionEnd, userMessage, …) are not yet wired. OnSessionStart, OnSessionEnd, OnPreCompact, OnPostCompact, and OnPrompt are no-ops in this implementation.
Index ¶
- Constants
- type Matcher
- type Runner
- func (r *Runner) Close(_ context.Context) error
- func (r *Runner) OnPermissionRequest(ctx context.Context, toolUseID, toolName string, toolInput any) (hookresult.Result, error)
- func (r *Runner) OnPostCompact(_ context.Context, _ string) error
- func (r *Runner) OnPostToolUse(ctx context.Context, toolUseID, toolName string, toolInput, toolResponse any, ...) error
- func (r *Runner) OnPreCompact(_ context.Context, _ string) error
- func (r *Runner) OnPreToolUse(ctx context.Context, toolUseID, toolName string, toolInput any) (hookresult.Result, error)
- func (r *Runner) OnPrompt(_ context.Context, _, _ string) error
- func (r *Runner) OnSessionEnd(_ context.Context, _ string) error
- func (r *Runner) OnSessionStart(_ context.Context, _ string) error
- func (r *Runner) OnStop(ctx context.Context, lastAssistantMessage string, stopHookActive bool) error
Constants ¶
const ( // EventBeforeShellExecution fires before a shell command runs. EventBeforeShellExecution = "beforeShellExecution" // EventBeforeReadFile fires before a file is read. EventBeforeReadFile = "beforeReadFile" // EventBeforeMCPExecution fires before an MCP tool call. EventBeforeMCPExecution = "beforeMCPExecution" // EventPreToolUse fires before any tool use (catch-all gate). EventPreToolUse = "preToolUse" // EventSubagentStart fires before a subagent is launched. EventSubagentStart = "subagentStart" )
Gating event names — fire before the operation and return a permission decision. All are routed to PreToolUse aggregation in hookresult.
const ( // EventAfterShellExecution fires after a shell command completes. EventAfterShellExecution = "afterShellExecution" // EventAfterFileEdit fires after a file is written or edited. EventAfterFileEdit = "afterFileEdit" // EventAfterMCPExecution fires after an MCP tool call completes. EventAfterMCPExecution = "afterMCPExecution" // EventSubagentStop fires after a subagent exits. EventSubagentStop = "subagentStop" // EventAgentResponse fires when the agent emits a response. EventAgentResponse = "agentResponse" // EventStop fires when the agent session stops. EventStop = "stop" )
Advisory event names — fire after-the-fact; no decision returned.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Matcher ¶
type Matcher struct {
Pattern string
Command string
Type string // "command" (default) or "prompt"
Timeout int // seconds; 0 → defaultTimeout
LoopLimit *int // nil = use default 5 for loop-controlled events
FailClosed bool
}
Matcher is one runnable hook entry. Pattern filters tool-name for tool-scoped events ("" or "*" = match all; "Shell" = exact; "A|B|C" = any-of; otherwise interpreted as regex). Type is "command" by default; "prompt" entries are accepted in config but never fired because testagent has no LLM evaluator. Timeout is per-matcher wall-clock in seconds (0 → defaultTimeout). FailClosed, when true, treats a non-zero non-2 exit as a blocking denial instead of a non-blocking error.
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
Runner fires shell-command hooks for Cursor events.
func NewRunner ¶
func NewRunner(matchers map[string][]Matcher, sessionID, cwd, transcriptPath, permissionMode string, debugWriter io.Writer) *Runner
NewRunner returns a Runner wired to the given matcher map. matchers may be nil (no-op runner) or omit any Cursor events. sessionID, cwd, transcriptPath, and permissionMode are passed to every shell command via CURSOR_HOOK_* env vars. debugWriter is optional; nil silences trace output.
func (*Runner) Close ¶
Close is a no-op for Cursor runners. Cursor's hook schema has no async field, so there are no in-flight goroutines to drain. Satisfies the engine teardown contract.
func (*Runner) OnPermissionRequest ¶
func (r *Runner) OnPermissionRequest(ctx context.Context, toolUseID, toolName string, toolInput any) (hookresult.Result, error)
OnPermissionRequest routes to preToolUse gating — Cursor models permission decisions as the pre-tool gate, not a separate event.
func (*Runner) OnPostCompact ¶
OnPostCompact is a no-op — Cursor has no compact lifecycle event.
func (*Runner) OnPostToolUse ¶
func (r *Runner) OnPostToolUse(ctx context.Context, toolUseID, toolName string, toolInput, toolResponse any, durationMs int64) error
OnPostToolUse fires the appropriate advisory after-event for the tool. Shell → afterShellExecution; Edit → afterFileEdit; mcp__* → afterMCPExecution. No event fires for other tool names. Always returns nil error.
func (*Runner) OnPreCompact ¶
OnPreCompact is a no-op — Cursor has no compact lifecycle event.
func (*Runner) OnPreToolUse ¶
func (r *Runner) OnPreToolUse(ctx context.Context, toolUseID, toolName string, toolInput any) (hookresult.Result, error)
OnPreToolUse fires preToolUse for every tool, plus the tool-specific gating event when applicable (beforeShellExecution for Shell, beforeReadFile for Read, beforeMCPExecution for mcp__* tools). All results are aggregated into a single hookresult.Result via PreToolUse rules.
func (*Runner) OnSessionEnd ¶
OnSessionEnd is a no-op — Cursor has no documented session_end event.
func (*Runner) OnSessionStart ¶
OnSessionStart is a no-op — Cursor has no documented session_start event.