cursorhooks

package
v0.6.3 Latest Latest
Warning

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

Go to latest
Published: Jun 2, 2026 License: MIT Imports: 16 Imported by: 0

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

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

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

func (r *Runner) Close(_ context.Context) error

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

func (r *Runner) OnPostCompact(_ context.Context, _ string) error

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

func (r *Runner) OnPreCompact(_ context.Context, _ string) error

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) OnPrompt

func (r *Runner) OnPrompt(_ context.Context, _, _ string) error

OnPrompt is a no-op — no Cursor event models prompt-submit semantics.

func (*Runner) OnSessionEnd

func (r *Runner) OnSessionEnd(_ context.Context, _ string) error

OnSessionEnd is a no-op — Cursor has no documented session_end event.

func (*Runner) OnSessionStart

func (r *Runner) OnSessionStart(_ context.Context, _ string) error

OnSessionStart is a no-op — Cursor has no documented session_start event.

func (*Runner) OnStop

func (r *Runner) OnStop(ctx context.Context, lastAssistantMessage string, stopHookActive bool) error

OnStop fires stop hooks.

Jump to

Keyboard shortcuts

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