Repository navigation
feat(trace): install the Cursor shell hooks - #3624
Conversation
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
PR validation — ✅ 3 passing
AI Session Checks — 🟢 86% · ✅ 0 failing
|
| 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 |
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
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>
The Cursor trace provider installed only the
sessionStart,sessionEndandafterFileEdithooks, so the trace did not see the shell commands that the Cursor agent runs. Cursor haspreToolUseandpostToolUsehooks that cover itsShelltool, with the command, the working directory and a per-calltool_use_id.This change:
preToolUseandpostToolUsewith the matcherShellin.cursor/hooks.json.chainloop trace runinstalls them too.ReadHookInputreadstool_name,tool_use_id,tool_input.commandandcwd. The transcript location stays on the first workspace root, because the shellcwdcan be a subdirectory.HookInput.Commandfield, with the same definition as in fix(trace): register checkouts that shell commands work in #3623, which reads it to find other checkouts.{"permission":"allow"}before it does any work. Cursor blocks the action when apreToolUseresponse is not valid JSON, and the trace must never block the agent.Out of scope: the session link after push (the
postToolUseresponse 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