Duplicate notifications when using Claude hooks alongside Cursor

Where does the bug appear (feature/product)?

  • Cursor IDE

Describe the Bug

When using Cursor agent with Claude Code hooks enabled (.claude/settings.json), Claude Stop hooks are triggered even when I’m not using Claude CLI and using cursor.
This results in duplicate side effects (e.g., notifications, sounds, logging), even though:

  • no Claude CLI session is running
  • no hooks are configured in .cursor/hooks.json

Investigation shows that Cursor triggers additional internal background model sessions, which also fire Claude hooks.


Steps to Reproduce

  1. Add a Stop hook in .claude/settings.json with a visible side effect (e.g., log, sound, or notification)
  2. Add logging inside the hook to record:
  • model
  • session_id
  • output_tokens
  1. Ensure:
  • no claude CLI session is running
  • no .cursor/hooks.json notification hooks exist
  1. Send a single message using the Cursor agent
  2. Wait for completion
  3. Inspect logs

Expected Behavior

  • Only one corresponding side effect (notification, sound, log, etc.) should be produced per prompt.
  • Only one Claude Stop hook invocation should occur per user-triggered agent completion

Actual Behavior

  • Two separate Stop hook invocations occur:
    • one for the user-facing model (expected)
    • one for an internal Cursor model (unexpected)

Evidence

First invocation (user-facing)

{
"model": "claude-4.6-sonnet-medium-thinking",
"session_id": "abc",
"output_tokens": 2244,
"cursor_version": "3.0.16",
"env": {
"VSCODE_PID": "72199"
}
}

Second invocation (internal background session ~30s later)

{
"model": "composer-2-fast",
"session_id": "abc",
"output_tokens": 56,
"cursor_version": "3.0.16",
"env": {
"VSCODE_PID": "72199"
}
}

Key observations

  • Same VSCODE_PID → same Cursor process
  • Different session_id → separate session, not duplicate event
  • Low output_tokens → internal utility call
  • No CLAUDE_CODE_ENTRYPOINT → not a CLI session
  • Occurs consistently after each Cursor agent turn

Screenshots / Screen Recordings

(Not included — logs provided above)


Operating System

  • macOS (Apple M1)

Version Information

Version: 3.0.16 (Universal)
VSCode Version: 1.105.1
Commit: 475871d112608994deb2e3065dfb7c6b0baa0c50
Date: 2026-04-09T05:33:51.767Z (1 wk ago)
Layout: editor
Build Type: Stable
Release Track: Nightly
Electron: 39.8.1
Chromium: 142.0.7444.265
Node.js: 22.22.1
V8: 14.2.231.22-electron.0
OS: Darwin arm64 25.3.0


For AI issues: which model did you use?

  • Primary: claude-4.6-sonnet-medium-thinking
  • Internal observed: composer-2-fast

Additional Information

This appears to be caused by Cursor running internal background model sessions that also trigger .claude/settings.json hooks.

Impact:

  • All Claude hooks with side effects (notifications, sounds, logging, webhooks) execute multiple times per user action
  • Current workaround requires filtering by model name (e.g., ignoring composer-*), which is fragile

Suggested solutions:

  • Do not trigger Claude hooks for internal/background sessions, or
  • Add a field in the hook payload, e.g.:

{ “is_background”: true }

or

{ “hook_source”: “cursor_internal” }


Does this stop you from using Cursor?

  • No

Hi there!

We detected that this may be a bug report, so we’ve moved your post to the Bug Reports category.

To help us investigate and fix this faster, could you edit your original post to include the details from the template below?

Bug Report Template - Click to expand

Where does the bug appear (feature/product)?

  • Cursor IDE
  • Cursor CLI
  • Background Agent (GitHub, Slack, Web, Linear)
  • BugBot
  • Somewhere else…

Describe the Bug
A clear and concise description of what the bug is.


Steps to Reproduce
How can you reproduce this bug? We have a much better chance at fixing issues if we can reproduce them!


Expected Behavior
What is meant to happen here that isn’t working correctly?


Screenshots / Screen Recordings
If applicable, attach images or videos (.jpg, .png, .gif, .mp4, .mov)


Operating System

  • Windows 10/11
  • MacOS
  • Linux

Version Information

  • For Cursor IDE: Menu → About Cursor → Copy
  • For Cursor CLI: Run agent about in your terminal
IDE:
Version: 2.xx.x
VSCode Version: 1.105.1
Commit: ......

CLI:
CLI Version 2026.01.17-d239e66

For AI issues: which model did you use?
Model name (e.g., Sonnet 4, Tab…)


For AI issues: add Request ID with privacy disabled
Request ID: f9a7046a-279b-47e5-ab48-6e8dc12daba1
For Background Agent issues, also post the ID: bc-…


Additional Information
Add any other context about the problem here.


Does this stop you from using Cursor?

  • Yes - Cursor is unusable
  • Sometimes - I can sometimes use Cursor
  • No - Cursor works, but with this issue

The more details you provide, the easier it is for us to reproduce and fix the issue. Thanks!

Hey, thanks for the detailed report. The evidence with session_id/output_tokens/VSCODE_PID really helped. This is reproducible by design.

Quick version: the Stop hook from .claude/settings.json fires for every finished composer, including internal subagent sessions like Task/explore that go through composer-2-fast. That’s why you see two triggers for one user turn. We do have a separate HookStep.subagentStop for the Task tool, but the main stop still gets triggered by the composer for all completions, so there’s no source filtering right now.

I reported this to the team as a separate bug with your suggestion like adding is_background or hook_source to the payload, or not firing Stop for internal subagents. I can’t share an ETA.

For now, the only realistic workaround is what you suggested, filter by model name and ignore composer-* in the hook. I agree it’s fragile, but it’s the fastest option until there’s a fix.

1 Like