claude-code - 💡(How to fix) Fix Task notifications leak between concurrent sessions in the same cwd (Monitor + background Bash) [1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#48112Fetched 2026-04-15 06:32:51
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
0
Timeline (top)
labeled ×4commented ×1

Task notifications (background Bash via run_in_background and Monitor tool streaming events) leak between concurrent Claude Code sessions running in the same cwd on the same macOS user account. The leaked notifications arrive as <task-notification> user messages in the unrelated session's conversation, causing that session's LLM to see events it did not initiate.

This breaks session isolation, pollutes context, and can surface sensitive command output / paths from Session A into Session B.

Root Cause

Suspected root cause

Fix Action

Workaround

None that a user can configure. The harness unconditionally delivers task notifications to every same-cwd session. Users can avoid the issue only by running at most one claude instance per cwd.

Code Example

/private/tmp/claude-501/-Users-smith-Code-ServiceCentric/227bfe29-8410-4fdd-95ac-9d2633b57ef9/tasks/bjs5adjgu.output

---

{"type":"queue-operation","operation":"enqueue","timestamp":"2026-04-14T20:56:35.744Z",
 "sessionId":"10ecd45a-7642-450d-9d3a-b938d1f52a9d",
 "content":"<task-notification>\n<task-id>bjs5adjgu</task-id>\n<tool-use-id>toolu_01N3V6wkUetpVHqYhWZFcjBC</tool-use-id>\n<output-file>/private/tmp/claude-501/-Users-smith-Code-ServiceCentric/227bfe29-8410-4fdd-95ac-9d2633b57ef9/tasks/bjs5adjgu.output</output-file>\n<status>failed</status>\n<summary>Background command \"List remote branches\" failed with exit code 128</summary>\n</task-notification>"}

---

{"type":"user","role":"user","origin":{"kind":"task-notification"},
 "timestamp":"2026-04-14T20:57:32.435Z",
 "sessionId":"10ecd45a-7642-450d-9d3a-b938d1f52a9d",
 "message":{"content":"<task-notification>\n<task-id>bjs5adjgu</task-id>\n<tool-use-id>toolu_01N3V6wkUetpVHqYhWZFcjBC</tool-use-id>\n<output-file>/private/tmp/claude-501/-Users-smith-Code-ServiceCentric/227bfe29-.../tasks/bjs5adjgu.output</output-file>\n<status>failed</status>..."}}

---

/private/tmp/claude-501/<cwd-slug>/<session-id>/tasks/<task-id>.{output,meta}
RAW_BUFFERClick to expand / collapse

Summary

Task notifications (background Bash via run_in_background and Monitor tool streaming events) leak between concurrent Claude Code sessions running in the same cwd on the same macOS user account. The leaked notifications arrive as <task-notification> user messages in the unrelated session's conversation, causing that session's LLM to see events it did not initiate.

This breaks session isolation, pollutes context, and can surface sensitive command output / paths from Session A into Session B.

Environment

  • Claude Code: 2.1.108 CLI (reproduced on 2.1.107 in on-disk session logs)
  • macOS: 26.4 (build 25E246) on Apple Silicon Mac Mini
  • Shell: zsh
  • Setup: two VS Code windows open, each with an integrated-terminal tab running claude in a different (or same) project cwd.

Concrete evidence from my machine

Session A (owner):

  • cwd: /Users/smith/Code/ServiceCentric
  • sessionId: 227bfe29-8410-4fdd-95ac-9d2633b57ef9

Session B (unrelated, concurrent):

  • cwd: /Users/smith/Code/ServiceCentric (same cwd as A)
  • sessionId: 10ecd45a-7642-450d-9d3a-b938d1f52a9d

Session A started a background Bash task with id bjs5adjgu (a git ls-remote / "List remote branches" call). Its output file lives at:

/private/tmp/claude-501/-Users-smith-Code-ServiceCentric/227bfe29-8410-4fdd-95ac-9d2633b57ef9/tasks/bjs5adjgu.output

Note the session id 227bfe29-... embedded in the path — this unambiguously identifies A as the owner.

In Session B's conversation log (~/.claude/projects/-Users-smith-Code-ServiceCentric/10ecd45a-...jsonl) the notification appears twice — once as an internal queue enqueue and once as a real user-role message delivered to the LLM:

{"type":"queue-operation","operation":"enqueue","timestamp":"2026-04-14T20:56:35.744Z",
 "sessionId":"10ecd45a-7642-450d-9d3a-b938d1f52a9d",
 "content":"<task-notification>\n<task-id>bjs5adjgu</task-id>\n<tool-use-id>toolu_01N3V6wkUetpVHqYhWZFcjBC</tool-use-id>\n<output-file>/private/tmp/claude-501/-Users-smith-Code-ServiceCentric/227bfe29-8410-4fdd-95ac-9d2633b57ef9/tasks/bjs5adjgu.output</output-file>\n<status>failed</status>\n<summary>Background command \"List remote branches\" failed with exit code 128</summary>\n</task-notification>"}
{"type":"user","role":"user","origin":{"kind":"task-notification"},
 "timestamp":"2026-04-14T20:57:32.435Z",
 "sessionId":"10ecd45a-7642-450d-9d3a-b938d1f52a9d",
 "message":{"content":"<task-notification>\n<task-id>bjs5adjgu</task-id>\n<tool-use-id>toolu_01N3V6wkUetpVHqYhWZFcjBC</tool-use-id>\n<output-file>/private/tmp/claude-501/-Users-smith-Code-ServiceCentric/227bfe29-.../tasks/bjs5adjgu.output</output-file>\n<status>failed</status>..."}}

Same task-id and tool-use-id, same output-file owned by Session A — but landed in Session B's sessionId, in Session B's project-log directory, surfaced to Session B's LLM as a user message.

Symptoms observed in practice

  • While running /pr-feedback in Session X, I called the Monitor tool to poll for Copilot re-review activity every 30s. Session X received the heartbeat notifications as expected. But I also observed Session Y (running in another VS Code terminal) receiving the same notifications (<task-notification> entries describing my PR's check events). Session Y had no business seeing them.
  • Background Bash commands started via run_in_background: true in Session A produce <task-notification> messages in Session B's chat window.

Expected behavior

A task notification should only deliver to the session that created the task. Task IDs, tool-use IDs, and output-file paths are all scoped per-session, so the routing layer has the information to honor session boundaries.

Actual behavior

Notifications fan out to every Claude Code session whose cwd matches the originating session's cwd (evidence so far is same-cwd). The notifications are enqueued via queue-operation and then replayed as user-role messages with origin.kind: "task-notification", which means the unrelated session's LLM sees and can act on events it did not initiate.

Suspected root cause

The tmp task directory layout is keyed by a cwd slug:

/private/tmp/claude-501/<cwd-slug>/<session-id>/tasks/<task-id>.{output,meta}

But whatever watcher/dispatcher surfaces task events to the foreground conversation appears to enumerate the cwd-slug level and notify all sessions under it, rather than filtering to the <session-id> subdirectory that actually owns the task.

Repro steps

  1. Open two VS Code windows, each with a terminal in the same project directory (e.g. cd ~/some-repo).
  2. Run claude in both terminals to get two concurrent sessions.
  3. In Session A, ask Claude to start any background task, e.g. run a small gh api call in the background (triggers run_in_background: true).
  4. Observe Session B's chat: a <task-notification> describing A's background task appears as if the user sent it.
  5. Same happens with the Monitor tool — Session B receives every Monitor stdout event from A.

The effect is more dramatic with Monitor because it emits continuously: every heartbeat line from Session A's polling loop shows up in Session B.

Impact

  • Session isolation broken. The LLM in an unrelated session sees events from another session's work.
  • Context pollution. A Monitor that emits every 30s burns through the unrelated session's context with events it cannot act on.
  • Confidentiality risk. <task-notification> includes <summary> and <output-file> paths. The summary often embeds the command description (e.g. "Background command 'List remote branches' failed with exit code 128"), which can leak information about private repos or ongoing work in one session into another session that may belong to a different task/project.
  • Operator confusion. As the reporting user put it: "I have another Claude Code session running on this machine and it's seeing the monitor output from this session" — which is exactly what's happening, and exactly what broke trust in the Monitor tool for them.

Proposed fix

Route notifications strictly by sessionId. The task-directory structure already records the session id as /private/tmp/claude-501/<cwd-slug>/<session-id>/tasks/... — the dispatcher should read <session-id> and deliver only to that session's queue, rather than broadcasting to every session under <cwd-slug>.

If there's a legitimate reason to share the cwd-level directory (e.g. concurrent monitor access), the fix can stay at the delivery layer: check the task's owning session id before enqueuing into a session's inbox.

Workaround

None that a user can configure. The harness unconditionally delivers task notifications to every same-cwd session. Users can avoid the issue only by running at most one claude instance per cwd.

extent analysis

TL;DR

The most likely fix is to modify the notification dispatcher to route task notifications strictly by sessionId, ensuring that only the session that created the task receives the notification.

Guidance

  • Review the task directory structure and dispatcher logic to understand how notifications are currently being routed.
  • Modify the dispatcher to read the <session-id> from the task directory path and deliver notifications only to the corresponding session's queue.
  • Consider adding a check to ensure that the task's owning session id matches the session id of the queue before enqueuing the notification.
  • Test the modified dispatcher with multiple concurrent sessions to verify that notifications are being delivered correctly.

Example

No code snippet is provided as the issue does not contain specific code references. However, the proposed fix involves modifying the dispatcher logic to use the sessionId when routing notifications.

Notes

The issue highlights a significant security and usability concern, as sensitive information may be leaked between sessions. The proposed fix should be prioritized to ensure session isolation and prevent context pollution.

Recommendation

Apply the proposed fix to route notifications strictly by sessionId, as this will address the root cause of the issue and prevent session isolation breaks, context pollution, and confidentiality risks.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

A task notification should only deliver to the session that created the task. Task IDs, tool-use IDs, and output-file paths are all scoped per-session, so the routing layer has the information to honor session boundaries.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix Task notifications leak between concurrent sessions in the same cwd (Monitor + background Bash) [1 comments, 2 participants]