cursor: support Cursor CLI hook differences#522
Conversation
Cursor CLI never provides transcript_path on stop/sessionEnd hooks, breaking the turn-end handler. Fix by computing the path dynamically via GetSessionDir + ResolveSessionFile when transcript_path is null. Also updates GetSessionDir to include agent-transcripts/ in the path, adds support for both flat (CLI) and nested (IDE) transcript layouts in ResolveSessionFile, and enriches hook types with fields present in both IDE and CLI payloads. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Entire-Checkpoint: b1ed1e053951
PR SummaryMedium Risk Overview Updates transcript path resolution to match real Cursor storage: Refines Cursor hook payload structs ( Written by Cursor Bugbot for commit b8914c6. Configure here. |
|
cursor CLI log: |
|
cursor IDE log |
There was a problem hiding this comment.
Pull request overview
Adds Cursor CLI compatibility to the Cursor agent integration by handling missing transcript_path values and supporting both Cursor IDE and CLI transcript directory layouts.
Changes:
- Computes transcript refs dynamically for
stopandsessionEndhooks whentranscript_pathis missing (Cursor CLI behavior). - Updates Cursor transcript directory resolution to include
agent-transcripts/and supports both flat and nested transcript layouts. - Expands Cursor hook raw payload types and adds/updates unit tests for these behaviors.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| cmd/entire/cli/agent/cursor/types.go | Splits/extends raw hook payload structs to cover IDE vs CLI field differences. |
| cmd/entire/cli/agent/cursor/lifecycle.go | Resolves missing transcript_path by deriving a transcript ref from repo/worktree + Cursor session dir logic. |
| cmd/entire/cli/agent/cursor/lifecycle_test.go | Adds tests for CLI hooks missing transcript_path and ensures IDE-provided paths are preserved. |
| cmd/entire/cli/agent/cursor/cursor.go | Updates session dir to include agent-transcripts/ and makes transcript file resolution prefer nested layout. |
| cmd/entire/cli/agent/cursor/cursor_test.go | Adds coverage for flat vs nested transcript layout resolution and validates updated session dir suffix. |
| // Set up a temp dir that simulates the Cursor project dir with a flat transcript | ||
| tmpDir := t.TempDir() | ||
| transcriptDir := filepath.Join(tmpDir, "agent-transcripts") | ||
| if err := os.MkdirAll(transcriptDir, 0o755); err != nil { |
There was a problem hiding this comment.
Same as above: this comment says the temp dir simulates the Cursor project dir, but the env override is effectively the transcript/session dir (agent-transcripts). Consider rewording the comment to match what’s being overridden.
| // We prefer the nested path if it exists, otherwise fall back to flat. | ||
| func (c *CursorAgent) ResolveSessionFile(sessionDir, agentSessionID string) string { | ||
| nested := filepath.Join(sessionDir, agentSessionID, agentSessionID+".jsonl") | ||
| if _, err := os.Stat(nested); err == nil { |
There was a problem hiding this comment.
ResolveSessionFile falls back to the flat path for any os.Stat error on the nested path. If the nested file exists but stat fails for a non-NotExist reason (e.g., permission denied, broken symlink), this will silently return a likely-wrong flat path and hide the real error. Consider only falling back when os.IsNotExist(err) is true; otherwise keep the nested path (or surface the error by changing the function signature).
| if _, err := os.Stat(nested); err == nil { | |
| if _, err := os.Stat(nested); err == nil || !os.IsNotExist(err) { |
Entire-Checkpoint: ba0bcb8add65
Docs should say we support cursor ide and cursor cli
|
use #527 instead |
Summary
transcript_pathonstop/sessionEndhooks, breaking the turn-end handler. Fixes by computing the path dynamically viaGetSessionDir+ResolveSessionFilewhentranscript_pathis null.GetSessionDirto includeagent-transcripts/in the path, matching the real filesystem layout.<id>.jsonl) and nested (IDE:<id>/<id>.jsonl) transcript layouts inResolveSessionFile.sessionStartRaw,stopHookInputRaw,sessionEndRaw) with fields present in both IDE and CLI payloads.Test plan
mise run fmt && mise run lint && mise run test:ciall pass🤖 Generated with Claude Code