Repository navigation
feat(trace): skip Claude Code and Cursor hooks when the Chainloop CLI is missing - #3691
Conversation
PR validation — ✅ 3 passing
AI Session Checks — ⏭️ bypassed by labelAI Coding Session Check BypassedThis PR carries the Learn more about Chainloop Trace. Security Checks — ✅ 5 passing✅
|
| 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
✅ Nothing this change touches has a recorded security-fix history.
View in Chainloop ↗ · How this works ↗
Powered by Chainloop and Chainloop Trace
There was a problem hiding this comment.
1 issue found across 5 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="app/cli/internal/trace/provider.go">
<violation number="1" location="app/cli/internal/trace/provider.go:404">
P2: The shared wrapper hard-codes POSIX `sh`, so Claude and Cursor hooks fail on Windows installations without Git Bash instead of skipping cleanly. Generate a Windows-compatible guard alongside the POSIX command, or use each provider’s platform-specific command fields.</violation>
</file>
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
There was a problem hiding this comment.
All reported issues were addressed across 6 files (changes from recent commits).
Reply with feedback, questions, or to request a fix.
View guided diff | Re-trigger cubic
|
Thanks for your contribution, @bercedev. I'm merging this. |
… is missing The generated hook commands called chainloop directly, so opening a repository with the hooks installed but no CLI on PATH failed every hook with exit 127. They are now wrapped in a command -v guard that exits 0 when the CLI is missing and execs it otherwise, as the Codex hooks do. Re-running chainloop trace init upgrades unguarded entries. Signed-off-by: berce <75228263+bercedev@users.noreply.github.com>
…grading hooks
Cursor blocks the shell command when a preToolUse hook writes no valid response, so the missing-CLI guard of that hook now prints the same {"permission":"allow"} as AllowToolUse (new GuardHookCommandWithOutput). Upgrading an unguarded Claude hook replaced its whole group and dropped any user handler in it; the Chainloop handler is now updated in place, or moved to a group of its own when its matcher changed.
Signed-off-by: berce <75228263+bercedev@users.noreply.github.com>
removeHookEntry dropped every group that held a Chainloop handler, together with any user handler in it. It now strips only the Chainloop handler and drops the group when nothing else is left. Signed-off-by: berce <75228263+bercedev@users.noreply.github.com>
…kCommand The Codex provider kept its own copy of the guard's shell string. It now uses trace.GuardHookCommand, like the Claude Code and Cursor providers, and derives the prefix it strips when recognising its handler from the same function. The Windows prefix stays in the Codex package, since only Codex uses it. Signed-off-by: berce <75228263+bercedev@users.noreply.github.com>
0cd4a59 to
c619fbd
Compare
|
signed now, all four commits show as verified on github. same content as before (no changes beyond the signatures, rebased on the same base). |
|
Merging. Thanks @bercedev ! |
Closes #3687
The Claude Code and Cursor hooks run
chainloop trace hook …directly, so in a repository with the hooks committed but without the CLI onPATH, every hook fails with exit 127 before Chainloop's best-effort handling can run. This wraps them in the guard from the issue, the same one #3684 added for Codex:sh -c 'if ! command -v chainloop >/dev/null 2>&1; then exit 0; fi; exec chainloop trace hook claude post-tool-use'trace.GuardHookCommand(command)builds that string. Both providers use it, so the guard is defined in one place..claude/settings.json):buildHookEntrywrites the guarded command.addHookEntrynow treats an entry as up to date only if both its matcher and its Chainloop command match. Previously it compared only the matcher, so an unguarded entry from an earliertrace initwould never have been upgraded. A smallchainloopHookCommandhelper finds the Chainloop handler in a group..cursor/hooks.json):buildHookEntrywrites the guarded command, andaddHookEntrycompares against it. Cursor's flat entry format is unchanged.trace initstays idempotent, and the Git hooks and the pre-pushrequireTraceenforcement are untouched.execpasses stdin and stdout through and keeps the CLI's exit status when it's present.Tests, in both
claude/hooks_test.goandcursor/hooks_test.go:TestInstalledHooksWithoutCLIruns every hook command withPATHholding onlysh. Each one exits 0 with no output, and every installed command contains the guard.TestInstalledHookPreservesIOAndExitStatusruns against a stubchainloopthat echoes its arguments and stdin and exits with 0 or 37. The output and exit code come through unchanged.TestInstallUpgradesUnguardedHooksstarts from a settings file with a barechainloop trace hook … post-tool-useentry next to a user hook.InstallHooksreplaces it with exactly one guarded entry, keeps the user hook, and a second run changes nothing.go test ./app/cli/internal/trace/...,go vetandgofmt -lare clean (Go 1.27.3, offline). Againstmain'shooks.gothe new install and upgrade tests fail. The runtime tests skip on Windows, as Codex's do.One question: Codex also sets a
commandWindowswith acmd.exe/whereguard. As far as I know Claude Code needs Git Bash on Windows, soshshould be available there, but I couldn't check it on Windows. I don't know of an equivalent override field for Cursor, so Cursor on Windows needsshonPATH. If that's a concern, I can make the Cursor guard platform-specific at install time.