[BUG] Desktop: cross-session send_message from an SSH-remote session carries no sender mode, so bypass-mode receivers hold it and refuse it after 5 min

Status Open
Reported on v2.1.286
Maintainer reply None cached
Activity 1 comment · opened Oct 4, 2026

Summary: In Claude Desktop, a cross-session send_message whose sender is an SSH-remote session reaches the receiving CLI without a sender permission mode. When the receiver runs in bypassPermissions, the default mode-parity policy holds the message. Desktop has no approval UI for that hold, so the message expires at dialogExpiry (5 min) and is refused. The same message sent from a local session to the same receiver is delivered.

Environment

  • Claude Desktop 2.19675.0 (Windows 11 host), bundled ccd-cli 2.1.286
  • Sessions: local Windows sessions and SSH-remote macOS sessions in the same app, all bypassPermissions
  • No crossSessionInbound / dialogExpiry set anywhere (user, local, project, managed)

Symptom
mcp__ccd_session_mgmt__send_message (and SendMessage(to="local_…"), which takes the same route) to an idle session returns undelivered ("no sign of starting on it within 20s"). The message appears in the app transcript as a user turn but never reaches the receiving Claude.

Controlled comparison (same warm idle receiver, default policy)

| Sender | Result |
|---|---|
| Local Windows session (bypass) | delivered, ran |
| SSH-remote macOS session (bypass) | undelivered; host main.log shows the CLI refusing it ~300 s later |
| SSH-remote sender, receiver host set to crossSessionInbound: "accept" | delivered (warm and cold receivers) |
| Same, after reverting the setting | undelivered again (reproduced) |

Root cause (from the CLI code and logs)

  1. Desktop injects the message on the CLI's host stdin lane with origin.kind = "peer" but, for SSH-remote senders, without origin.fromMode. The CLI already reads it (hostInjected peer origin accepts origin.fromMode === "bypass" | "prompting"). The app seems to attest a local sender's mode but not to know/attest a remote session's mode.
  2. The receiver bypasses permissions, so the default parity policy holds it with cause no-mode-asserted (documented: the receiving session "delivers one only when the sending session identifies itself as also bypassing").
  3. Desktop has no approval surface for the hold, so it expires at dialogExpiry (default 5 min) and the CLI reports refused.

Log evidence

  • Host main.log, all 5 rotated logs: 76 peer inputs with a pairable start time. 6 were taken within 300 s (all ran); 70 were refused at 300–316 s (57 at exactly 300 s); none was refused before 300 s. Each time: drew no acknowledgement from the CLI in 45003ms — settled as undelivered, then CLI refused input … without running it ~300 s after hand-off.
  • Remote Control lane to the same idle sessions: delivered immediately (the envelope carries from-mode="bypass").
  • The running CLI reloads crossSessionInbound live; no restart is needed for the comparison above.

Expected: the app attests the sending session's permission mode for SSH-remote senders too, so bypass↔bypass messages deliver without turning off the parity check.

Also

  • On one send the app SIGTERM'd a 43-hour-old warm SSH-remote CLI and respawned it with --resume just to deliver (SSH daemon log: exited with code 143, signalled at client request). Possibly related to #92687.
  • The tool result says the receiver "may be waiting for approval there, or slow to start". It should name the actual hold cause (no-mode-asserted) and say that Desktop cannot approve it.

Workaround: set crossSessionInbound: "accept" on the receiving host (this turns off parity for every sender), or send over the Remote Control lane.

Related: #85888 (held message has no approval UI), #91372 (held vs delivered indistinguishable), #92383 (auto-mode sender dropped), #92687

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗