RSS Amplifier

Blake Crosley Blog · Aug 8, 2026

Cross-Session Messaging in Claude Code

0
Sign in to vote or save

Blake Crosley · Blake Crosley

Since v2.1.224, every interactive Claude Code session on a Mac or Linux box binds a Unix socket at startup, and any other session you run can drop a text message into it; mine sits at /tmp/cc-socks/38590.sock, with owner-only permissions.1 Native Windows gets a named pipe instead, since v2.1.239 by the release notes, and one late-bind exception sits under The Traps. Two tools drive the feature: ListAgents discovers which of your sessions are reachable, and SendMessage delivers to one of them by name.2 Nothing to enable, nothing to configure. If both sessions run v2.1.224 or later (v2.1.239 on Windows) on the same machine, they can already talk.

TL;DR

Claude Code sessions can now message each other: on one machine over local sockets that never touch Anthropic’s servers, and across machines through Remote Control (reply-only at launch; v2.1.225 added the ability to start those conversations by name).15 A message is plain text only, never conversation history, files, or permissions, and the receiving session treats it as input, not authority: it cannot approve prompts, change configuration, or execute commands.1 The feature turns a fleet of independent terminals into something closer to a team, and the best uses are coordination messages you used to ferry by hand: “the migration finished,” “I renamed that column,” “main is safe to rebase.” The sharpest trap is silent absence: four unrelated privacy environment variables can each quietly disable the feature, depending on their values.3 Since launch, Windows joined natively in v2.1.239, and v2.1.236 added notify_when_idle, which lets a session ask a same-machine peer for one notice when it next goes idle or exits.910

What Shipped

The v2.1.224 release added cross-session SendMessage with ListAgents discovery on macOS and Linux; v2.1.225 extended it so a session can also start a conversation with your Remote Control sessions on other machines, where previously it could only reply.45

Three surfaces let you see the machinery:

  • /list-agents (alias /peers) prints the session’s own name on its first line (the name your other sessions use to reach it, shown since v2.1.239), then every session Claude can reach: subagents inside the current session, the session’s live agent-team teammates (listed since v2.1.239; before that a reachable teammate looked absent), your other local sessions including background ones, and, while Remote Control is connected, your sessions on other machines and on Claude Code on the web.19
  • /status shows a Peer address row with the session’s own inbox socket, prefixed uds:.1
  • CLAUDE_CODE_MESSAGING_SOCKET, which Claude Code exports to hooks and Bash commands once the inbox is bound (see the late-bind note under The Traps), holds the session’s own socket path.16 More on why that matters below.

Verifying on my own machine on August 25, 2026, with Claude Code 2.1.246: the agent listing opened with the line “This session is blakecrosley-com-76 [04e18a] — the name other sessions use to message it (it is not listed below; a message to it would be a message to yourself).”, then 11 peer sessions as rows like “resumegeni-25 [10d770] · interactive · idle · started 21h ago”, names in the directory-plus-two-character-suffix form with a bracketed short identifier, states of idle, busy, and shell, a start age per row, and a separate Subagents block for the session’s own children. The socket files under /tmp/cc-socks/ carry srw------- permissions and the directory itself is drwx------: readable and writable by my user alone, which is the boundary on shared machines.1

Sessions answer to names. Set one with /rename or the --name flag; otherwise Claude Code derives one from the working directory, like my-app-3f.111 Since v2.1.232, when you start, resume, or rename an interactive session into a name another live session on the machine already uses, Claude Code leaves the name with the session that has it, renames yours to a name-word-word variant (something like auth-refactor-graceful-unicorn), and tells you.110 Collisions survive when one session runs an older version, when the shared name is one Claude Code generated, or when you start a background or -p session with a --name Claude Code doesn’t check at startup.11 The listing always shows each local session’s working directory, which tells same-named sessions apart when they run in different directories; for a shared name Claude also adds a short identifier to each row and uses it in the address. Claude falls back to the same short-identifier addressing when Claude Code couldn’t check everywhere your sessions run, such as an account whose cloud or Remote Control session list ran past the bounded page count it reads.1

What Changed Since Launch (August 2026)

Five releases in the two weeks after launch closed the Windows gap this post flagged, tightened naming and addressing, and closed four silent-failure modes the post did not flag:910

Release Change
v2.1.232 Unique names and @-mentions. Interactive sessions on one machine keep unique names (a collision renames the newcomer to a name-word-word variant and tells you); typing @ in the prompt mentions another live session by name, and Claude reaches it with SendMessage directly; /config gains a “Messages from your other sessions” row that writes crossSessionInbound (accept, hold, refuse) to user settings, alongside a “Dialog expiry” row. The same release hardened the auto-generated socket directory on shared /tmp: Claude Code now refuses a pre-planted symlink or another user’s directory instead of using it.110
v2.1.235 SendMessage refuses a message too large for cross-session delivery up front, instead of silently dropping it.10
v2.1.236 notify_when_idle: ask another session on the same machine to send one notice when it next goes idle or exits (both sessions v2.1.236+). Opt-in, one-shot, no polling. The same release refuses further messages up front once a rapid burst would exceed what the recipient’s inbox accepts, instead of reporting them sent while the recipient dropped them.110
v2.1.238 Delivery honesty: sending to a session on this machine that refuses inbound messages (crossSessionInbound: "refuse") now reports “refused” to the sender instead of a silent success, and a session whose inbox drops your messages (rate limit or full queue) tells your session instead of the messages vanishing.10
v2.1.239 Windows. Cross-session messaging works natively, with the same SendMessage and ListAgents tools; ListAgents now tells a session its own name (the one peers use to reach it) and lists live teammates, which previously looked absent; SendMessage to your own name says so instead of “no agent named …”.9

The practical effect: the “reporting long-runner” pattern below no longer needs a check-in prompt. The watching session asks the long-runner for one idle notice with notify_when_idle and hears back when the long-runner next goes idle or exits. Two of the four failure modes (a message too large, or a burst too fast for the inbox) now fail up front at the sender; the other two (a refused or dropped message) come back to an interactive same-machine sender as explicit reports.

The Trust Model Is the Interesting Part

Anthropic’s design answers a question most multi-agent systems fumble: what is a message from another agent worth? The answer here is precise: a message is information, never authority.1

When session A messages session B, four rules bind what arrives:1

  1. It cannot approve anything. A pending permission prompt in B ignores anything A says. Only you answer prompts.
  2. It cannot change configuration. Claude Code instructs the receiving Claude never to alter permission settings, CLAUDE.md, or any configuration because another session asked.
  3. Commands arrive as text. A /compact in the message body is eight characters of prose, never an executed command.
  4. Permission prompts still fire. If acting on the message needs a permission B lacks, you see the same prompt as for any other work.

Inbound delivery has its own gate. Each arriving message ends in one of three outcomes (delivered, held for your approval, or refused), controlled by the crossSessionInbound setting (accept, hold, refuse).1 When you set nothing, Claude Code decides per message using the two sessions’ permission modes, and the default logic is elegant: sessions that bypass permission prompts form one class, everyone else the other (plan mode counts as bypassing when the session has bypass available; auto, acceptEdits, and dontAsk count as prompting). A prompting session receives messages freely but holds anything arriving from a bypassing session; a bypassing session holds everything except messages from fellow bypassing sessions.1 The asymmetry is deliberate: a message must not ride a permissive session’s authority, a principle v2.1.224 applies inbound after v2.1.222 applied it outbound in auto mode, where the permission classifier reviews each send before dispatch.7

Held messages open an approval dialog showing sender and preview; unanswered dialogs expire after five minutes (tunable via dialogExpiry) and the message drops.1 A background session with no terminal attached keeps the dialog open past that deadline; once you attach, the message drops only if the dialog stays unanswered for a full deadline period.1 At most 100 messages hold at once.1 Two more controls narrow things further: isolatePeerMachines: true requires your explicit approval before any message leaves the machine, even in bypassPermissions mode, and a true from any settings scope wins, so a checked-in project file can tighten but never loosen it.1 Organizations can kill the feature entirely with deny rules on SendMessage and ListAgents plus crossSessionInbound: "refuse" in managed settings.1

How Messages Travel

Where the other session runs determines both transport and what you can send:1

Target Transport You can send
Same machine Per-session Unix socket (named pipe on native Windows), never through Anthropic servers New messages and replies
Your other machine Anthropic servers, arriving over that machine’s Remote Control connection Replies; new conversations as of v2.1.225, while Remote Control is connected5
Claude Code on the web Anthropic servers, straight to the cloud session Replies; new conversations to a cloud session that appears in the listing while Remote Control is connected1

When this post first ran, Anthropic’s docs page still described all cross-machine messaging as reply-only while the v2.1.225 release notes said SendMessage “can now start a conversation with your Remote Control sessions on other machines by name.” The docs have since caught up: the page now states that starting a conversation with a session on another of your machines requires v2.1.225 or later and a target that appears in the listing.15

The same-machine rule is filesystem visibility: sessions register in files on disk, so two sessions reach each other only when they see the same files. A session inside a container and one on the host cannot talk; two sessions inside the same container can.1

Delivery respects the receiving session’s rhythm: the receiving Claude reads a message between tool calls during an active turn, never interrupting a running tool, and Claude Code starts a fresh turn with the message when the session is idle.1 Delivered messages count toward usage like a prompt you typed.1

Five Patterns Worth Building

1. Worktree coordination. The obvious one, and the case the documentation illustrates with its own example message: sessions working the same repository in separate worktrees tell each other what landed.1 “Schema migration finished: the new column is tenant_id, and rebasing on main is safe now.” is the class of update that otherwise requires you to notice, switch terminals, and re-type. If several sessions share one checkout instead of worktrees, the coordination message becomes more valuable still: “I’m about to commit content/guides/, don’t stage it” prevents the classic shared-tree collision where one session commits another’s half-finished work.

2. Watcher and worker. Run a monitor session watching a deploy, a test suite, or a log, and have it message the session responsible for fixes the moment something breaks. The receiving session gets the finding as context, not as a command; it still decides, under its own permissions, what to do. Pair the watcher with background sessions and the notification hooks and you get an escalation chain that ends at a human only when it should.

3. The reporting long-runner. Kick off a migration or a long test run in one session, then have it report back to the session you actually watch.1 Status stops living in a terminal you forgot about. The inverse also works; ask from the watching side: “Ask the session running in my other terminal whether the migration finished” is a prompt, and Claude handles discovery, addressing, and phrasing itself.1 Since v2.1.236, skip the question: have your watching session set notify_when_idle on the long-runner and it reports back once, when it next goes idle or exits, with no polling from either side.110 Both sessions need v2.1.236+, and the limits follow the inbound controls. Every subscription carries a 12-hour cap: if no notice arrives by then, Claude Code drops the subscription and tells Claude to stop waiting. With refuse on the watched side, that session drops the request without recording or answering it, so the subscription expires unanswered at the cap; with refuse on the asking side, Claude Code never subscribes at all. With hold on either side the notice arrives degraded: the watched session leaves out its one-line status, and the asking session shows the notice in your transcript without delivering it to Claude.1

4. Unattended worker fleets. Headless claude -p sessions bind inbox sockets too, so a long-running -p worker can receive messages and appears in listings.8 The catch: a -p session cannot show the approval dialog, so a default-held message waits out the dialogExpiry deadline (five minutes by default; dialogExpiry takes 60s, 5m, 10m, or never), then drops and reports itself expired to a sender it can reach; only a mode or settings change inside that window delivers it.1 When the session ends with messages still held, Claude Code reports them as expired to each sender it can reach.1 Before v2.1.225, no deadline applied at all: a held message parked without notice or expiry, and a worker that ended with held messages told their senders nothing.1 To run a worker that takes messages unattended, start it with crossSessionInbound: "accept" in its --settings value: a per-worker grant, rather than an accept in user settings that would apply to every session you run.8 Bare-mode sessions skip the socket entirely and stay unreachable.8

5. Scripted inboxes. The quiet powerhouse: because Claude Code exports CLAUDE_CODE_MESSAGING_SOCKET to hooks and Bash commands, a script can post into a session’s own inbox.6 Claude Code verifies own-child messages: a hook or command posting back to its own session delivers without ceremony when no explicit crossSessionInbound applies.1 A git hook the session’s own commit triggered, a test wrapper it launched, a deploy script it ran: any hook or Bash command the session itself started can post a line of context back into that session. Claude Code has to verify the poster as its own child; when it can verify neither by process evidence nor by token, it treats the message as one that asserts no permission class, so a bypassing session holds it for your approval instead of delivering it.1 On native Windows the connection’s first line must be an auth line carrying CLAUDE_CODE_MESSAGING_TOKEN, or Claude Code closes the connection unread; that token is also the only way Windows verifies an own-child message.1 On Linux the process-evidence check works even after the posting process exits; on macOS only while it still runs. After it exits on macOS, and in a container where Claude Code is PID 1, Claude Code instead verifies a child that sent the session’s exported CLAUDE_CODE_MESSAGING_TOKEN in its auth line.1 Sandboxed commands need the socket allowed: sandbox.network.allowUnixSockets lists socket paths on macOS, and on Linux and WSL 2, where the seccomp filter cannot inspect paths, only sandbox.network.allowAllUnixSockets: true opens it; without that optional filter installed, the sandbox never blocks the socket in the first place.112

What It Refuses to Be

The limits are design decisions, and respecting them saves you from building the wrong thing.

Not an approval channel. Everything in the trust model exists to prevent one session from authorizing another’s actions. The design explicitly rules out any workflow shaped like “session A approves, session B executes.” Route authority through the human, always.1

Not context transfer. A message is text one Claude writes to another, never conversation history or files. Anthropic’s documentation says it plainly: to move a conversation, resume the session instead.1 Summarize; don’t dump.

Not agent teams. Independent sessions messaging each other is the peer-to-peer case. A coordinated team Claude spawns and supervises (structured protocol messages, a roster, shared task state) is the agent teams feature, and structured team messages deliberately stay inside a team.1 If you find yourself designing a message protocol on top of cross-session text, you want agent teams.

Not a chat loop. Claude Code rate-limits repeated messages per sender, drops identical repeats arriving in a short window, and caps unread accepted messages at 50 per session, so a message loop between two sessions starves itself out by design.1 v2.1.236 also refuses further messages up front once a rapid burst would exceed what the recipient’s inbox accepts, instead of reporting them sent while the recipient dropped them.10 Build request-and-response exchanges, not conversations.

The Traps

Privacy variables silently disable it. Cross-session messaging depends on feature-flag evaluation, and any of CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, DISABLE_TELEMETRY, DO_NOT_TRACK, or DISABLE_GROWTHBOOK can turn that evaluation off, taking messaging down with it, silently.3 The diagnostic is /list-agents: if the session doesn’t recognize the command, the session lacks the feature entirely; if it works but a send never arrives, something narrower applies: a deny rule, the receiver’s inbound controls, a target missing from the listing (Remote Control not connected, or the session fell past the bounded page count Claude Code reads), or a pre-v2.1.225 sender trying to start a cross-machine conversation.1 A target that never bound an inbox is not the silent case. A session behind a privacy variable, in bare mode, or across a container boundary never appears in /list-agents, so a send to it fails loudly as a name Claude Code can’t find, and since v2.1.234 SendMessage also says when it couldn’t check your session list completely instead of treating unseen sessions as absent.1310 The first session after an upgrade is a late bind, not a missing one: Claude Code binds the inbox and exports the socket variable as soon as the feature-flag fetch completes, and v2.1.228 fixed that first session sometimes starting without an inbox at all.110 The genuinely silent cases sit on the sending side. The docs promise the hold notice and its follow-up, the arrival-time refusal notice, and the drop notice only to an interactive sender on the same machine, so a cross-machine sender or a -p worker has no promised notice for those cases. Two reports do go to “each sender it can reach”: expiry of a default-held message, and refusal when a settings change drops held messages. A message parked by an explicit hold setting never expires, so no expiry report ever comes back for it.1

Platform and provider gaps. Native Windows arrived in v2.1.239; before that only Linux inside WSL 2 worked.19 Anthropic’s docs page puts the Windows floor at v2.1.234; the release notes first announce it in v2.1.239. Treat v2.1.239 as the safe floor.19 A session inside WSL 2 and a native Windows session on the same computer can’t reach each other either: they register under different home directories and listen on different socket types.1 Not available on Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform, or Microsoft Foundry.1

The one-way reply edge. A reply to a session on another machine, sent while the replying session is not connected to Remote Control, still arrives, but without a reply address, so the receiver cannot answer. Claude Code tells Claude as much when it sends, and v2.1.225 tightened the addressing: when Claude Code couldn’t check its own session list, it never swaps a confirmed cross-machine recipient for a same-named local session.5

Headless holds. The -p worker that mysteriously ignores messages is almost always a held-message problem: no dialog, no delivery. Set crossSessionInbound: "accept" on workers that should listen.8

Key Takeaways

For daily Claude Code users: - Run /list-agents once to see what your sessions can already reach; name important sessions with /rename so messages address cleanly. The Claude Code guide covers the session commands and settings the feature leans on. - Prompt for messages in plain language (“tell the session working on payments what we changed”) and let Claude write the message itself.1

For automation builders: - Post into sessions from hooks and scripts via CLAUDE_CODE_MESSAGING_SOCKET; own-child messages deliver without approval friction on Linux.16 - Give unattended -p workers crossSessionInbound: "accept" in their own --settings, not globally.8

For teams and security reviewers: - The feature ships with the right defaults: messages carry no authority, the defaults quarantine bypassing sessions, and isolatePeerMachines plus managed-settings deny rules give you per-machine and org-wide off switches.1 - Audit the four privacy environment variables before concluding messaging is broken. A refusing session looks identical in listings and in its own /status, so check the settings files that apply to that session rather than its status; since v2.1.238 a send from a session on the same machine also reports the refusal back.110

References


  1. Anthropic, “Message your other Claude Code sessions”, Claude Code documentation. Accessed August 8, 2026; re-verified August 25, 2026. 

  2. Anthropic, “Tools reference”, Claude Code documentation: ListAgents and SendMessage entries. 

  3. Anthropic, “Environment variables”, Claude Code documentation: feature-flag evaluation notes on CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, DISABLE_TELEMETRY, DO_NOT_TRACK, and DISABLE_GROWTHBOOK

  4. Anthropic, Claude Code v2.1.224 release notes, August 7, 2026 (UTC): “Added cross-session SendMessage: Claude Code sessions can now message each other, on any of your machines, with ListAgents to discover them (macOS and Linux).” 

  5. Anthropic, Claude Code v2.1.225 release notes, published August 8, 2026 (UTC): “SendMessage can now start a conversation with your Remote Control sessions on other machines by name (ListAgents shows them as name [ref]), instead of only replying after they message you first.” The same release states that Claude Code never swaps a confirmed Remote Control recipient for a same-named session on this machine “when its own list couldn’t be checked.” 

  6. Anthropic, “Environment variables”, Claude Code documentation: CLAUDE_CODE_MESSAGING_SOCKET, exported to hooks and Bash commands when the socket binds, and in a session that starts with messaging on, bound before any hook runs; the cross-session page adds “including SessionStart”. 

  7. Anthropic, Claude Code v2.1.222 release notes, August 4, 2026: “Improved auto mode safety: messages sent to other agent sessions via SendMessage are now evaluated by the permission classifier before dispatch.” The classifier review applies in auto mode (and in plan mode where the auto classifier reviews commands), not universally. The plan-mode clause comes from Anthropic, “Permission modes”, Claude Code documentation: “The classifier also reviews each message Claude sends to another agent with SendMessage, whether plain text or a structured agent team message, before Claude Code delivers it, both in auto mode and in plan mode while the classifier reviews commands; the send review requires Claude Code v2.1.222 or later.” 

  8. Anthropic, “Message your other Claude Code sessions: Non-interactive sessions”, Claude Code documentation: -p sessions bind inbox sockets and appear in the listing, a default-held message there waits out dialogExpiry, and unattended delivery requires crossSessionInbound: "accept" in the worker’s own --settings. The headless page describes bare mode under “Headless mode”

  9. Anthropic, Claude Code v2.1.239 release notes, August 21, 2026: “Windows: cross-session messaging is now available, so Claude Code sessions across your machines can message each other with SendMessage and find each other with ListAgents, as on macOS and Linux”; “ListAgents now tells a session its own name (the one peers use to message it), and SendMessage to your own name says so instead of "no agent named …"“; “ListAgents and /list-agents now list your live teammates (previously only subagents and other sessions appeared, so a reachable teammate looked absent).” 

  10. Anthropic, Claude Code release notes v2.1.228 (“Fixed cross-session messaging sometimes starting without an inbox in the first session after install or upgrade”), v2.1.232 (“Type @ in the prompt to mention another Claude session by name; Claude then uses SendMessage to reach that session directly”; “Interactive sessions on one machine now keep unique names: starting or renaming a session to a name another live session already uses gives it a name-word-word variant and tells you”; “Added /config rows for "Dialog expiry" and "Messages from your other sessions" (cross-session inbound accept/hold/refuse)”; “Hardened the auto-generated cross-session messaging socket directory on shared /tmp: a pre-planted symlink or another user’s directory is now refused instead of used”), v2.1.234 (“SendMessage and ListAgents now say when your account’s session list was too long to check completely, instead of treating unseen sessions as absent”), v2.1.235 (“SendMessage now refuses messages too large for cross-session delivery up front instead of silently dropping them”), v2.1.236 (“Added notify_when_idle to cross-session SendMessage: ask another Claude Code session on this machine to send one notice when it next goes idle — opt-in, one-shot, no polling (macOS and Linux)”; “SendMessage now refuses further messages to a session up front once a rapid burst would exceed what that session’s inbox accepts, instead of reporting them sent while they were dropped”), and v2.1.238 (refused-inbound and dropped-inbox reporting). Verified against the canonical CHANGELOG.md August 25, 2026. 

  11. Anthropic, “Sessions: Name your sessions”, Claude Code documentation. “In three cases Claude Code doesn’t rename the duplicate”: it doesn’t check AI-generated titles or default display names, it doesn’t check “the --name of a background or -p session at startup”, and it can’t rename a session on an earlier version of Claude Code. 

  12. Anthropic, “Settings reference: sandbox.network.allowUnixSockets, Claude Code documentation: “List the Unix socket paths sandboxed commands can connect to on macOS. Claude Code ignores this list on Linux and WSL2, where the seccomp filter can’t inspect socket paths; use allowAllUnixSockets there instead.” The allowAllUnixSockets entry adds that on Linux and WSL2 the seccomp filter blocks socket(AF_UNIX, ...) calls, which makes the key the only way to permit Unix sockets there. 

Read the original on blakecrosley.com

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.