cursor

package
v0.11.4 Latest Latest
Warning

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

Go to latest
Published: Oct 6, 2026 License: MIT Imports: 22 Imported by: 0

Documentation

Overview

Package cursor implements the Agent interface for Cursor.

Index

Constants

View Source
const (
	HookNameSessionStart       = "session-start"
	HookNameSessionEnd         = "session-end"
	HookNameBeforeSubmitPrompt = "before-submit-prompt"
	HookNameStop               = "stop"
	HookNamePreCompact         = "pre-compact"
	HookNameSubagentStart      = "subagent-start"
	HookNameSubagentStop       = "subagent-stop"
)

Cursor hook names - these become subcommands under `entire hooks cursor`

View Source
const HooksFileName = "hooks.json"

HooksFileName is the hooks file used by Cursor.

Variables

View Source
var FileModificationTools = []string{"Write", "StrReplace"}

FileModificationTools lists the Cursor tool names that create or modify files.

Captured from a real Cursor session (testdata/real_session_tool_use.jsonl): Write creates or overwrites a file, StrReplace edits one in place. Cursor's read-only tools (Read, Grep, Glob, Shell) are deliberately absent — Shell can of course modify files, but the transcript records only the command string, so attributing files to it would mean parsing shell, not reading a path.

Cursor's names differ from Claude Code's (Write/Edit), so this list cannot be shared with claudecode.FileModificationTools.

Functions

func ExtractModifiedFiles added in v0.10.3

func ExtractModifiedFiles(lines []transcript.Line) []string

ExtractModifiedFiles extracts the files modified by Cursor tool calls in the given transcript lines, in first-seen order and deduplicated.

Cursor records tool_use content blocks in the same shape as Claude Code (message.content[i].type == "tool_use", with name and input), so this mirrors claudecode.ExtractModifiedFiles. The divergences are the tool names and the input key — see FileModificationTools and toolInput.

func NewCursorAgent

func NewCursorAgent() agent.Agent

NewCursorAgent creates a new Cursor agent instance.

Types

type CursorAgent

type CursorAgent struct {
	CommandRunner agent.TextCommandRunner
}

CursorAgent implements the Agent interface for Cursor.

func (*CursorAgent) AreHooksInstalled

func (c *CursorAgent) AreHooksInstalled(ctx context.Context) (bool, error)

AreHooksInstalled checks if Entire hooks are installed.

A missing config file is an answer, not a failure: that file is where the state lives, so its absence means no hooks. Anything that stops us reading the answer — an unreadable file, malformed config — is returned as an error, since "we could not tell" and "there are none" are different things to a caller deciding whether hooks can be left alone.

func (*CursorAgent) CallerSessionEnvVar added in v0.11.0

func (c *CursorAgent) CallerSessionEnvVar() string

CallerSessionEnvVar names the variable holding the session ID Cursor publishes into the environment of the processes its shell tool spawns, alongside CURSOR_AGENT. It is the same conversation ID every Cursor lifecycle event reports as its session ID, so it resolves against session state without translation.

func (*CursorAgent) ChunkTranscript

func (c *CursorAgent) ChunkTranscript(_ context.Context, content []byte, maxSize int) ([][]byte, error)

ChunkTranscript splits a JSONL transcript at line boundaries.

func (*CursorAgent) Description

func (c *CursorAgent) Description() string

Description returns a human-readable description.

func (*CursorAgent) DetectPresence

func (c *CursorAgent) DetectPresence(ctx context.Context) (bool, error)

DetectPresence checks if Cursor is configured in the repository.

func (*CursorAgent) ExtractModifiedFilesFromOffset added in v0.5.0

func (c *CursorAgent) ExtractModifiedFilesFromOffset(_ context.Context, path string, startOffset int) ([]string, int, error)

ExtractModifiedFilesFromOffset extracts files modified by tool calls appearing at or after startOffset, and returns the transcript's current line count.

A missing transcript is not an error: Cursor reports transcript_path as null in CLI mode, so ResolveSessionFile predicts a path that may not exist yet, and this runs on capture paths that must fail open (matching GetTranscriptPosition).

func (*CursorAgent) ExtractPrompts added in v0.5.0

func (c *CursorAgent) ExtractPrompts(sessionRef string, fromOffset int) ([]string, error)

ExtractPrompts extracts user prompts from the transcript starting at the given line offset. Cursor uses the same JSONL format as Claude Code; the shared transcript package normalizes "role" → "type" and strips <user_query> tags.

func (*CursorAgent) ExtractSummary added in v0.5.0

func (c *CursorAgent) ExtractSummary(sessionRef string) (string, error)

ExtractSummary extracts the last assistant message as a session summary.

func (*CursorAgent) FormatResumeCommand

func (c *CursorAgent) FormatResumeCommand(_ string) string

FormatResumeCommand returns an instruction to resume a Cursor session. Cursor is a GUI IDE, so there's no CLI command to resume a session directly.

func (*CursorAgent) GenerateText added in v0.5.6

func (c *CursorAgent) GenerateText(ctx context.Context, prompt string, model string) (string, error)

GenerateText sends a prompt to the Cursor agent CLI and returns the raw text response.

The prompt is piped via stdin rather than as a positional argument, avoiding argv size limits. --print triggers non-interactive mode; --force --trust are required for headless operation per cursor-agent --help.

func (*CursorAgent) GetSessionBaseDir added in v0.5.3

func (c *CursorAgent) GetSessionBaseDir() (string, error)

GetSessionBaseDir returns the base directory containing per-project session subdirectories. Unlike GetSessionDir, this does NOT use test overrides because the override points to a specific project dir, not the base containing all projects.

func (*CursorAgent) GetSessionDir

func (c *CursorAgent) GetSessionDir(repoPath string) (string, error)

GetSessionDir returns the directory where Cursor stores session transcripts. No relocation variable applies. Cursor's CLI bundle does resolve a data dir from CURSOR_DATA_DIR and advertises <data>/projects/<hash>/agent-transcripts to the model, but the transcript files are written by its native file service, which stays anchored on the real home: with the variable set, cursor-agent 2026.09.08 still writes them under ~/.cursor (verified locally). Following the variable here would point resume, attach and owner detection at a directory Cursor never writes to.

func (*CursorAgent) GetSessionID

func (c *CursorAgent) GetSessionID(input *agent.HookInput) string

GetSessionID extracts the session ID from hook input.

func (*CursorAgent) GetSupportedHooks

func (c *CursorAgent) GetSupportedHooks() []agent.HookType

GetSupportedHooks returns the hook types Cursor supports.

func (*CursorAgent) GetTranscriptPosition added in v0.5.0

func (c *CursorAgent) GetTranscriptPosition(path string) (int, error)

GetTranscriptPosition returns the current line count of a Cursor transcript. Cursor uses the same JSONL format as Claude Code, so position is the number of lines. Uses bufio.Reader to handle arbitrarily long lines (no size limit). Returns 0 if the file doesn't exist or is empty.

func (*CursorAgent) HookConfigRelPath added in v0.10.6

func (c *CursorAgent) HookConfigRelPath() string

HookConfigRelPath implements agent.HookConfigLocator.

func (*CursorAgent) HookNames

func (c *CursorAgent) HookNames() []string

HookNames returns the hook verbs Cursor supports. These become subcommands: entire hooks cursor <verb>

func (*CursorAgent) InstallHooks

func (c *CursorAgent) InstallHooks(ctx context.Context, force bool) (int, error)

InstallHooks installs Cursor hooks in .cursor/hooks.json. If force is true, removes existing Entire hooks before installing. Returns the number of hooks installed. Unknown top-level fields and hook types are preserved on round-trip.

func (*CursorAgent) Name

func (c *CursorAgent) Name() types.AgentName

Name returns the agent registry key.

func (*CursorAgent) ParseHookEvent

func (c *CursorAgent) ParseHookEvent(ctx context.Context, hookName string, stdin io.Reader) (*agent.Event, error)

ParseHookEvent translates a Cursor hook into a normalized lifecycle Event. Returns nil if the hook has no lifecycle significance.

func (*CursorAgent) PrepareTranscript added in v0.5.2

func (c *CursorAgent) PrepareTranscript(ctx context.Context, sessionRef string) error

PrepareTranscript waits for Cursor's transcript file to be flushed to disk. Cursor writes transcripts asynchronously; during mid-turn commits the file may not yet contain data. This polls until the file exists and is non-empty, or until the timeout expires.

func (*CursorAgent) ProtectedDirs

func (c *CursorAgent) ProtectedDirs() []string

ProtectedDirs returns directories that Cursor uses for config/state.

func (*CursorAgent) ReadSession

func (c *CursorAgent) ReadSession(input *agent.HookInput) (*agent.AgentSession, error)

ReadSession reads a session from Cursor's storage (JSONL transcript file). ModifiedFiles is populated from the transcript's tool_use blocks; see ExtractModifiedFiles. Git status remains the broader signal, since Cursor can also change files through Shell commands that record no path.

func (*CursorAgent) ReadTranscript

func (c *CursorAgent) ReadTranscript(sessionRef string) ([]byte, error)

ReadTranscript reads the raw JSONL transcript bytes for a session.

func (*CursorAgent) ReassembleTranscript

func (c *CursorAgent) ReassembleTranscript(chunks [][]byte) ([]byte, error)

ReassembleTranscript concatenates JSONL chunks with newlines.

func (*CursorAgent) ResolveSessionFile

func (c *CursorAgent) ResolveSessionFile(sessionDir, agentSessionID string) string

ResolveSessionFile returns the path to a Cursor session file. Cursor IDE uses a nested layout: <dir>/<id>/<id>.jsonl Cursor CLI uses a flat layout: <dir>/<id>.jsonl We prefer nested if the file OR directory exists (the directory may be created before the file is flushed), otherwise fall back to flat.

func (*CursorAgent) SidecarImages added in v0.9.0

func (c *CursorAgent) SidecarImages(ctx context.Context, sessionRef string) ([]agent.CompactedTranscriptAsset, error)

SidecarImages captures images that Cursor stores outside the JSONL transcript. Cursor keeps pasted/generated images in a per-session SQLite blob store (~/.cursor/chats/<workspace>/<session>/store.db), not the transcript Entire condenses, so they would otherwise be lost from the checkpoint. This locates that store for the session, shells out to the sqlite3 binary to read the image blobs, and returns them as checkpoint assets.

It is best-effort: when the store, the sqlite3 binary, or the expected schema is absent, or the store is too large, it returns no images and no error. sessionRef is the transcript path.

func (*CursorAgent) Type

func (c *CursorAgent) Type() types.AgentType

Type returns the agent type identifier.

func (*CursorAgent) UninstallHooks

func (c *CursorAgent) UninstallHooks(ctx context.Context) error

UninstallHooks removes Entire hooks from Cursor HooksFileName. Unknown top-level fields and hook types are preserved on round-trip.

func (*CursorAgent) WriteSession

func (c *CursorAgent) WriteSession(_ context.Context, session *agent.AgentSession) error

WriteSession writes a session to Cursor's storage (JSONL transcript file).

type CursorHookEntry

type CursorHookEntry struct {
	Command string `json:"command"`
	Matcher string `json:"matcher,omitempty"`
}

CursorHookEntry represents a single hook command. Cursor hooks have a command string and an optional matcher field for filtering by tool name.

type CursorHooks

type CursorHooks struct {
	SessionStart       []CursorHookEntry `json:"sessionStart,omitempty"`
	SessionEnd         []CursorHookEntry `json:"sessionEnd,omitempty"`
	BeforeSubmitPrompt []CursorHookEntry `json:"beforeSubmitPrompt,omitempty"`
	Stop               []CursorHookEntry `json:"stop,omitempty"`
	PreCompact         []CursorHookEntry `json:"preCompact,omitempty"`
	SubagentStart      []CursorHookEntry `json:"subagentStart,omitempty"`
	SubagentStop       []CursorHookEntry `json:"subagentStop,omitempty"`
}

CursorHooks contains all hook configurations using camelCase keys.

type CursorHooksFile

type CursorHooksFile struct {
	Version int         `json:"version"`
	Hooks   CursorHooks `json:"hooks"`
}

CursorHooksFile represents the .cursor/HooksFileName structure. Cursor uses a flat JSON file with version and hooks sections.

Jump to

Keyboard shortcuts

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