Cross-session messages are delivered but never trigger the recipient's turn (desktop app, Windows)

Status Open
Reported on v2.1.227
Maintainer reply None cached
Activity 13 comments · opened Aug 12, 2026

Bug report — cross-session messages are delivered but never trigger the recipient's turn (Claude Code desktop, Windows)

Summary

mcp__ccd_session_mgmt__send_message reports Message sent to session ..., and the message
is genuinely delivered — it appears in the recipient's queue via list_events and renders
correctly in the recipient's window. But it does not cause the recipient session to run a
turn
. The recipient stays idle indefinitely (measured at 0.4% CPU). The message is only
processed once a human types something — anything — into the recipient's window.

There is no error, no notice, and no timeout. From the sender's side it is indistinguishable
from a broken channel, which is what sent us down three wrong diagnoses before we measured it.

Environment

| | |
|---|---|
| OS | Windows 11 Home 10.0.26200 |
| Claude Code | 2.1.227, entrypoint: "claude-desktop" (read from ~/.claude/sessions/<pid>.json) |
| CLI on PATH | 2.1.226 (~/.local/share/claude/versions/2.1.226) — a separate install, not the one running the sessions |
| Sessions | 9 local sessions across 8 project folders, all in permission mode "normal" |
| Transport | MCP server ccd_session_mgmt (list_sessions, send_message, list_events) |
| Date of measurements | 2026-08-12, ~22:28–22:40 local (UTC+2) |

Steps to reproduce

  1. Open two Claude Code desktop sessions, A and B, in different project folders, both in

permission mode normal.

  1. From A, call mcp__ccd_session_mgmt__send_message with B's session_id.
  2. Tool returns Message sent to session <id> ("<title>").
  3. Do not touch B's window.

Expected

B processes the incoming message and runs a turn (this is what the sender's tool description
implies: "The message arrives in the target session as a user turn").

Actual

B does nothing, with no indication that anything is pending on its side beyond the rendered
message. It stays idle indefinitely.

Confirming step

Type anything into B's window (we used the single word vas-y). B immediately runs a turn and
correctly processes every queued message, including ones that had been waiting for hours.

Measurements

Recipient is idle, not busy or hung. Two CPU samples of the recipient process, taken 15 s
apart while a message sat in its queue, versus the sender doing normal work:

recipient (pid 6372) : 5.859s -> 5.922s   delta = 0.06s over 15s   (0.4%)
sender    (pid 13340): 21.64s -> 22.56s   delta = 0.92s over 15s   (6%)

Queue holds, nothing fires. Two messages sent to the same recipient sat unprocessed for
about 6 hours and about 8 minutes respectively. Both were visible the whole time via
list_events against that session, with correct content and intact accented characters.

A single keystroke releases everything. The recipient's transcript records the user prompt
vas-y at 2026-08-12T20:36:59.471Z. The turn started immediately and the model's reply
quoted and acted on both queued messages.

Second, possibly separate issue: received messages are never written to the transcript

Received cross-session messages are never persisted to the recipient's .jsonl transcript
— not while queued, not while being processed, not after the turn completes successfully.

  • Scanned all 9 transcripts under ~/.claude/projects/*/: zero received envelopes.
  • In the turn described above, the model demonstrably read and acted on two queued messages;

the transcript records only the typed prompt vas-y.

Two consequences that actively mislead debugging:

  1. A transcript cannot be used to verify that a message was received, even for messages

that were received and fully acted upon.

  1. The list_events message count decreases when queued messages are dropped (we observed

335 -> 334 on one session). This reads as data loss. One of our sessions concluded from it
that messages were "delivered then removed without being processed", and built a whole
causal story on that number.

What we ruled out

| hypothesis | how it was eliminated |
|---|---|
| Version mismatch between sessions | All ~/.claude/sessions/*.json report 2.1.227 (one dead process at 2.1.222). Note: claude --version returns 2.1.226 because it queries the PATH CLI, not the desktop binary — this is itself a trap for anyone diagnosing. |
| HTML-entity encoding of the body (encoded="1") | The message renders fully decoded in the recipient's window, accents intact (screenshot available). |
| crossSessionInbound holding messages for approval | That setting only applies to a recipient running with bypassed permissions. All 9 sessions measured in mode "normal"; the key is absent from ~/.claude/settings.json. |
| Recipient blocked on a permission prompt | No dialog present, and typing an unrelated word releases the turn — a pending permission request would not be satisfied that way. |
| Recipient hung on MCP server startup | The recipient had a npx @playwright/mcp@latest child still starting; so did the sender, which was working normally. |

Possibly related changelog entries

  • 2.1.225 — *"Fixed cross-session messages staying parked without a notice or expiry in

headless sessions and during startup"*. "Parked" is exactly our symptom, and our messages
arrived shortly after the recipient restarted (recipient process start 22:28:53, message
sent ~22:30). Our sessions are interactive, not headless.

  • 2.1.224"Added cross-session SendMessage ... (macOS and Linux)". We are on Windows

and using the desktop app's ccd_session_mgmt MCP tools, which may be a different mechanism
from the CLI's SendMessage. We flag this as a lead, not a claim.

Questions

  1. Is "delivered but does not trigger a turn" the intended behavior for cross-session messaging

in the desktop app on Windows? If so, the sender's tool result (Message sent) and its
description ("arrives in the target session as a user turn") both suggest otherwise, and a
sender has no way to learn that the message is parked.

  1. If this is the "parked" condition fixed in 2.1.225, should it also apply to interactive

sessions outside startup?

  1. Is the non-persistence of received messages in the recipient's transcript intended? If so,

could the docs say it explicitly? It currently makes transcripts look like evidence of
non-delivery.

Unexplained, no reproduction — reported for completeness

Earlier the same day (around 16:00–16:50 local), the user observed four recipient sessions
showing a turn in error shortly after receiving a message from one particular sender
session. We could not reproduce this, and could not identify a cause: it is not the version
(no gap exists), not the encoding, and the same sender's later messages completed normally.
We mention it only in case it matches a known signature; we are not claiming a link.

View original on GitHub ↗

3 Comments

skinner · 18 days ago

possible dupe of #86012

I've looked at seven potential duplicates today and this is the first time I've seen anyone mention that typing a prompt into the recipient session makes it go. And it works for me! Vas-y! My workflow is now unblocked. FWIW in my hands, cross-session messages between an agent and its subagents do still seem to work fine.

skinner · 18 days ago

Ah, in my hands, prompting the recipient session doesn't let it see the cross-session message content though.

arthurmoraesfernandes-afk · 17 days ago

This looks like the "wedge" mechanism documented in the follow-up comment on #86298, with app-log evidence: an injected cross-session message that the CLI holds (consent gate) gets drained into the CLI at a turn boundary and is never "echoed" back as a user turn; the app then logs isRunning held by unechoed input at result … pendingEchoUuids: […] and treats the session as busy indefinitely — phantom turn, watchdog kills, and the user's own typed prompts queue/stall behind a turn that never ends until a priority=next send (typing another message force-flushes) or a restart reclaims it. The recover-by-typing behavior you observed is the priority-send flush of that queue.

Showing cached comments. Read the full discussion on GitHub ↗