fix(agent-setup): preserve Cursor identity through tool execution
What & why
Cursor imports Claude hook settings. Superset’s imported command sets SUPERSET_AGENT_ID=claude, allowing a later duplicate hook to relabel a Cursor terminal and lose its runtime identity. This reproduces with a GPT model selected in Cursor; the label identifies the agent application, not its model.
Suppress imported events when the command identifies Claude, CURSOR_VERSION is present, and the event uses Cursor’s lowercase naming. Genuine Claude events remain supported, including Claude launched from Cursor’s environment. Bump the generated notification hook marker to v10.
Register native postToolUse and postToolUseFailure as Start so suppressing imported hooks does not leave shell/MCP activity at PermissionRequest. Match only Shell and MCP:<tool>: these are the tools whose existing native before-hooks set that state. Other tools gain no new status writes. Existing user hooks are preserved.
Cursor documents third-party hook imports and native hook matchers.
How I tested it
Cursor CLI 2026.09.02-c22c1a3, launched inside Superset with gpt-5.6-terra-low:
| Scenario | Observed result |
|---|---|
| Completed interactive turn, before fix | Native Stop / cursor-agent, then imported hook relabels the binding claude 511 ms later |
| Completed interactive turn, guarded hook | Binding remains cursor-agent |
| Shell success and nonzero exit, final matched configuration | Native post hook restores Start / cursor-agent |
| MCP success and deliberate error result, final matched configuration | Restores Start / cursor-agent; Cursor reports both through postToolUse |
| File read, final matched configuration | Native post hook excluded; imported duplicate suppressed |
| Session end | Native hook detaches the binding |
Temporary hook configuration was restored byte-for-byte. The completed-turn test used the interactive CLI; the final tool test used print mode. These are hook and host-binding observations, not a Cursor IDE qualification.
- Regression fails without the post-tool registrations:
PermissionRequestremains whereStartis required. - Bun 1.3.14: 301 package tests passed, 1,231 assertions across 14 files; package typecheck passed.
- Executable sequences cover shell/MCP success, failure and interruption, duplicate imported events, child file-tool exclusion, final Stop, and stable Cursor identity. Interruption is replay coverage, not a live user-cancel claim.
- Repository lint and full-repository typecheck passed locally. Independent diff review has no remaining actionable findings.
- CI on
de42799: all 11 jobs passed, including full tests, typecheck, desktop build and four CLI builds. - CodeRabbit review on
de42799: completed; its test nitpick is assessed below.
Existing Cursor shell/MCP child hooks can overwrite the parent terminal’s session binding. Captured child events reproduce that behavior through the unchanged base hook. This PR does not establish parent/child isolation or change terminal-turn failure classification.
Validation limits and retained failures
CodeRabbit suggested bypassing the matcher for the child Read assertion. The matcher is the provider boundary under test. Removing it in an isolated copy causes both child assertions to fail with Start / child-session instead of the parent’s PermissionRequest; the native CLI run independently confirms Read exclusion. The suggested bypass was not adopted.
The current preview failed because the fork lacks the Neon api_key; application deployment jobs were skipped.
The local desktop build was stopped after the same commit’s CI desktop build passed; no local build pass is claimed.
Local full-repository tests stop on missing service environment variables in four unchanged tRPC test files. A Bun 1.4.0 package run also failed an existing endpoint fast-path test; the repository-pinned Bun 1.3.14 run passed. Neither failure was erased or treated as a passing run.
The previous commit’s CI run passed 10 of 11 jobs; Intel macOS CLI dependency installation failed extracting workerd. Its preview failed because the Neon api_key was absent. Those runs remain unchanged.
Checklist
- PR title follows conventional commits (
type(scope): subject) -
bun run lintandbun run typecheckpass on the current commit in CI - "Allow edits from maintainers" is checked on fork PRs (applies when submitting upstream; this review targets the contributor fork)
Summary by CodeRabbit
-
New Features
- Added Cursor support for post-tool-use and post-tool-failure lifecycle events, limited to Shell and MCP operations.
- Preserved distinct Cursor and Claude notification handling when Cursor imports Claude hook settings.
- Maintained event and session identity in notification payloads for supported integrations.
-
Bug Fixes
- Prevented duplicate processing of lowercase lifecycle events between Cursor-specific and imported hooks.
- Improved event filtering across supported locales.