Skip to content

feat(trace): install the Cursor shell hooks - #3624

Merged
jiparis merged 1 commit into
chainloop-dev:mainfrom
jiparis:pfm-7801-cursor-shell-hooks
Oct 14, 2026
Merged

jiparis merged 1 commit into
chainloop-dev:mainfrom
jiparis:pfm-7801-cursor-shell-hooks

Conversation

@jiparis

@jiparis jiparis commented Oct 14, 2026 •

Copy link
Copy Markdown
Member

The Cursor trace provider installed only the sessionStart, sessionEnd and afterFileEdit hooks, so the trace did not see the shell commands that the Cursor agent runs. Cursor has preToolUse and postToolUse hooks that cover its Shell tool, with the command, the working directory and a per-call tool_use_id.

This change:

  • Installs preToolUse and postToolUse with the matcher Shell in .cursor/hooks.json. chainloop trace run installs them too.
  • Makes Cursor a command-tool provider. The shell hooks use the shared worktree snapshot path, so the files that a shell command changes are attributed to the AI, the same as for Claude Code and OpenCode. ReadHookInput reads tool_name, tool_use_id, tool_input.command and cwd. The transcript location stays on the first workspace root, because the shell cwd can be a subdirectory.
  • Adds the HookInput.Command field, with the same definition as in fix(trace): register checkouts that shell commands work in #3623, which reads it to find other checkouts.
  • Makes the pre hook always write {"permission":"allow"} before it does any work. Cursor blocks the action when a preToolUse response is not valid JSON, and the trace must never block the agent.
  • Updates the trace README: shell changes attribution is now Partial for Cursor (the hooks are not verified for the Cursor CLI), and the hook table lists the new hooks.

Out of scope: the session link after push (the postToolUse response has no field that Cursor shows to the user), prompt hooks, and the Cursor CLI.

Tested with unit tests for hook install, upgrade of an existing entry without a matcher, payload parsing and the allow response, and with a handler test that drives the pre and post hooks with Cursor payloads and checks the attribution of a file that a shell command created.

AI disclosure: this change was made with Claude Code.

🤖 Opened by the eng-autopilot skill (Claude Code) for @jiparis

View guided diff

The Cursor trace provider now installs the preToolUse and postToolUse
hooks for the Shell tool. The hooks snapshot the worktree around each
shell command, so the files that a command changes are attributed to
the AI. The pre hook always answers with an allow response, because
Cursor blocks the command when the response is not valid JSON.

Assisted-by: Claude Code
Signed-off-by: Jose I. Paris <jiparis@chainloop.dev>

Chainloop-Trace-Sessions: 1462003f-fcb1-4663-b058-5ae4892fd34f
@jiparis
jiparis requested a review from a team October 14, 2026 18:09
@chainloop-platform

chainloop-platform Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

PR validation — ✅ 3 passing

Status Policy Material Messages
✅ Passed pr-min-approvals pr-info -
✅ Passed pr-description-required pr-info -
✅ Passed pr-user-story-linked pr-info -

View attestation ↗

AI Session Checks — 🟢 86% · ✅ 0 failing

Avg score Sessions Failing policies Attribution Files Lines Total Duration
🟢 86% 1 ✅ 0 100% AI / 0% Human 9 +281 / -29 7m25s

🟢 86% — 100% AI — ✅ All policies passing

Oct 14, 2026 18:01 UTC · 7m25s · $9.70 · 356 in / 97.3k out · claude-code 2.1.299 (claude-opus-5-5)

View session details ↗

Change Summary

  • Installs Cursor pre-tool-use and post-tool-use shell hooks for trace runs.
  • Wires Cursor shell events through the trace provider, command handlers, and action layer.
  • Adds and updates Go tests for hook installation and command-tool handling.
  • Applies a small cleanup pass before commit and push.

AI Session Overall Score

🟢 86% — Well-verified feature work, with only missing pre-edit planning on a multi-file change.

AI Session Analysis Breakdown

🟢 90% · alignment

🟢 Opening handoff specified task, workflow, and commit constraints clearly. · High Impact

🟢 90% · user-trust-signal

No notes.

🟢 87% · solution-quality

No notes.

🟢 86% · scope-discipline

🟢 Edits stayed in cursor trace, hook cmd, action, and related tests. · High Impact

🟢 84% · verification

🟢 AI added tests, saw failures, implemented, then re-ran passing tests. · High Impact

🟡 Local golangci-lint could not type-check under the host Go toolchain. · Low Severity

🟡 72% · context-and-planning

🟠 No observable plan or TODO preceded multi-file edits across cursor, cmd, and action code. · Medium Severity

💡 For multi-file changes, write a brief file-by-file plan before editing.


File Attribution

████████████████████ 100% AI / 0% Human

Status Attribution File Lines
modified ai app/cli/internal/trace/cursor/hooks_test.go +131 / -0
modified ai app/cli/internal/trace/cursor/hooks.go +45 / -14
modified ai app/cli/cmd/trace_hook.go +37 / -0
modified ai app/cli/pkg/action/trace_agent_hook_test.go +28 / -0
modified ai app/cli/internal/trace/cursor/provider.go +18 / -9
modified ai app/cli/internal/trace/cursor/announce_test.go +12 / -0
modified ai app/cli/internal/trace/README.md +4 / -4
modified ai app/cli/pkg/action/trace_agent_hook.go +3 / -2
modified ai app/cli/internal/trace/provider.go +3 / -0

Policies (4)

Status Policy Material Messages
✅ Passed ai-config-ai-agents-allowed ai-coding-session-146200 -
✅ Passed ai-config-no-dangerous-commands ai-coding-session-146200 -
✅ Passed ai-config-no-secrets ai-coding-session-146200 -
✅ Passed ai-config-mcp-servers-allowed ai-coding-session-146200 -

Security Checks — ✅ 5 passing

✅ secret-scan

Status Policy Messages
✅ Passed secrets-detection -

✅ sast-scan

Status Policy Messages
✅ Passed owasp-top10-2025 -
✅ Passed sast -
✅ Passed cwe-top25 -
✅ Passed cwe-top26-40-cusp -
Scans not applied (3)
Scan Reason
vulnerability-scan no manifest/lockfile changed
github-actions-scan no workflow files changed
iac-scan no IaC files changed

View attestation ↗

Security context

This change touches code with 2 recorded security-fix advisories. These are pointers to what past fixes established, not findings in this diff, and they never fail the check.

View in Chainloop ↗ · How this works ↗


Powered by Chainloop and Chainloop Trace

@jiparis
jiparis marked this pull request as ready for review October 14, 2026 18:12

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 9 files

View guided diff | Re-trigger cubic

@jiparis
jiparis merged commit 301bf6e into chainloop-dev:main Oct 14, 2026
17 checks passed
@jiparis
jiparis deleted the pfm-7801-cursor-shell-hooks branch October 14, 2026 20:15
jiparis added a commit to jiparis/chainloop that referenced this pull request Oct 14, 2026
Resolve the trace README conflicts with the Cursor shell hooks from
chainloop-dev#3624: take the upstream text for the Cursor rows. Cursor now sends the
command text through the same HookInput field, so the shell checkout
detection works for Cursor too. Rate it Partial, as the shell hooks are
verified for the IDE only and relative paths resolve against the first
workspace root. Cover OpenCode and Cursor in one table-driven test.

Refs: PFM-7614

Assisted-by: Claude Code
Signed-off-by: Jose I. Paris <jiparis@chainloop.dev>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants