Claude Code sessions can now talk to each other and work as a team
- Separate Claude Code sessions can now message each other. When one terminal finishes a change, Claude tells another terminal on its own.
- What's sent is a short piece of plain text—no history, no files. Moving the whole context is a different feature.
- The key rule: a message from another session never counts as your authorization.
Sessions can now send each other messages
Run several Claude Code terminals at once—one on the frontend, one on migrations, one in another worktree—and those sessions used to be sealed off from each other. None knew what the others were doing; syncing meant manual copy-paste.
That wall now has a door. When one session learns something, Claude can hand it to another on its own. It doesn't wait for you to ask—if your change affects another session's work, it proactively goes and says hi.
users.name to users.display_name and tells weekly-digest in a single message. The session on the right receives a message starting with @user-profiles, figures out that "the stats query is still reading the old field," and updates the code on the spot. No copy-pasting between terminals. Video: AnthropicYou'll need Claude Code v2.1.224 or newer, running on macOS or Linux. If you meet the requirements, it's on automatically — no configuration needed.
To check if your setup supports it, run /list-agents (the command also works as /peers). If the command is recognized, the feature is on.
Tested by us: on this macOS machine, claude --version returned 2.1.225, just over the line. The environment variable CLAUDE_CODE_MESSAGING_SOCKET was indeed set, with the value /tmp/cc-socks/27983.sock — the inbox socket described in the docs was really bound. With only one session running, the list came back empty: no peers, so nothing to reach.
Start Claude Code in a terminal and you have a session; open three terminals and you have three independent sessions.
Like three coworkers at their own desks — soundproofed before, now with a slot to pass notes through.
A mailbox each session opens on the local machine, where other sessions drop messages.
Like the mailboxes by each apartment door — only people in the same building (machine and system user) can drop anything in.
A message is just plain text — no history, no files
This is the easiest thing to get wrong, so let's be clear.
A message is a piece of plain text from one Claude to another. Not conversation history, not a file, no context attached. The receiver only sees the sender's name and that text — what the other session talked about or which files it touched is completely invisible.
Here's the example message from the docs:
The DB migration is done; the new field is called tenant_id, so rebasing to main is safe now.
Example message from the official docs
That's it. One sentence.
So the boundary is clear: if what you want to move is the entire conversation — say, switching to another computer, or having a new session inherit the current context — messaging isn't the tool. That's what session resume is for.
Two tools, called by Claude itself — you don't send manually
Two tools power this: ListAgents discovers which sessions are reachable, and SendMessage delivers a message by name.
You never touch these tools. Claude decides whether to send, to whom, and even writes the wording itself. All you do is give a hint — "ask the session in the other terminal if the migration is done," or "tell the session working on the payment API what we just did." The actual message is Claude's call.
To see which sessions are reachable yourself, run /list-agents. The list has three categories:
Agents running inside the current session. Note that Agent team members don't show up here — Claude reaches them through the team's own roster.
Claude Code sessions running on the same machine, including background sessions. A session only appears here if it has bound an inbox socket.
Shown only when Remote Control is connected, labeled Remote Control — these include sessions on your other machines and in the web version. These can only reply, not initiate.
NAMINGWhere session names come from
Messages are delivered by name, and names have three sources: whatever you set with /rename, what you pass at startup with --name, or — if neither — Claude Code generates one from the folder name of the working directory, like myapp-3f.
Two sessions can end up with the same name. The /list-agents output includes each session's working directory to tell them apart, and Claude's own list adds a short identifier per row, used to pin down the right one when names collide.
Messages arrive between tool calls, with three possible outcomes
When a message reaches the other side, it doesn't interrupt whatever's in flight. The receiving Claude reads it in the gap between two tool calls, so a running command is never broken mid-step. If the session happens to be idle, the message simply starts a new turn.
As for whether it gets through, there are three outcomes:
Once a message is delivered, it's billed like a prompt you typed yourself. The receiver can also reply on the same channel — except in the one-way cross-machine case.
A message from another session is not your authorization
This is the most carefully designed part of the feature.
When session A messages session B, Claude Code explicitly tells B: this message comes from another session, not from your human user. Then it limits what B can do with it — four restrictions, each blocking a specific bad scenario:
A message from another session never counts as your authorization, and can't be used to answer a permission prompt waiting on you. This blocks: session A says "go ahead," and session B approves an operation you never green-lit.
The receiver is explicitly told never to change permission settings, CLAUDE.md, or any other config because another session said something. This blocks: starting from one message, gradually loosening your security settings.
If a slash command appears in the message text, it's treated as plain text. Claude Code won't run it. This blocks: sneaking a command in disguised as message content.
If acting on the message needs a permission, you'll see the exact same prompt as always. This blocks: using "another session asked me to do this" to bypass the normal approval flow.
The sending side has its own constraint: Claude is told never to ask another session to do something that was already refused, blocked, or simply not allowed by its own permission settings here. In that situation, it has to hand the work back to you rather than route around the block through another session.
Both sides add up to the same principle: cross-session messaging is a channel for passing information, not a channel for gaining privilege.
With no configuration, the two sessions' permission modes decide
When you haven't set anything, Claude Code looks at both sessions' permission modes. It sorts sessions into two buckets: ones that prompt you, and ones that skip prompts and act directly.
(plan mode counts as "skip" when the session has skip capability; auto, acceptEdits, and dontAsk all count as "prompt.")
The rule works like this:
| Receiver | Sender prompts | Sender skips prompts |
|---|---|---|
| Prompts | Delivered | Held for approval |
| Skips prompts | Held for approval | Delivered |
It looks convoluted at first, but the logic is straightforward: a session that acts without asking is the one that most needs protection from unsolicited messages, because it will just do whatever it receives. So the looser the permissions, the tighter the inbound gate.
A permission mode where Claude stops asking you each time and just executes.
Like giving your assistant a master key — efficient, but precisely because it doesn't ask you, any note that comes in from the outside needs your eyes first.
Your own inbound policy setting. Three values: accept delivers everything, hold holds everything, refuse drops everything.
Like setting a rule for your mailbox: take everything in, set it aside for me to review, or just seal the slot.
DIALOGWhat happens when a message is held
When a message is held, the receiver pops an approval dialog showing the sender and a preview. Three ways out:
- Approve — the message goes to Claude
- Reject, or just close the dialog — the message is dropped
- Leave it alone — after
dialogExpiry(default five minutes) the dialog closes on its own and the message is discarded
Held messages are capped at 100; beyond that, the oldest go. If the session's permission mode changes while a message is held, the rules are re-evaluated — what should pass now passes. If the mode becomes refuse, all held messages are dropped and every reachable sender gets a rejection notice.
The sender sees the activity too: it gets a notice when a message is held, then a follow-up on whether it was delivered, rejected, or expired. Only if a message is refused outright does the sender get no signal at all.
Same machine goes over a local socket; cross-machine is reply-only
Which path a message takes, and what you can send, depends on where the other session lives:
"Reply-only" means the other side has to message you first before you can respond. Want to proactively reach a session on another machine? That path doesn't exist.
VISIBILITYSame-machine reachability requires "seeing the same files"
Each session registers itself in files on disk and binds its inbox socket there. When Claude lists or contacts local sessions, it reads those files — so two sessions can reach each other only if they can see the same files.
This has a practical consequence: containers have their own filesystem, so a session inside a container and a session on the host can't reach each other. But two sessions in the same container can talk, and the same applies on self-hosted runners.
One more detail that's easy to trip on: for cross-machine replies, if you're not connected to Remote Control when you send, the message still goes through (via a direct request to the Anthropic server), but it carries no return address — the other side can't reply back. Claude is told this when it sends.
If you want every message leaving the machine to require your sign-off, set isolatePeerMachines to true. Once set, even in a mode that skips all permission prompts, a reply will ask you before it leaves the machine. A true at any settings level counts, so a project config committed to the repo can turn this on, but can't turn it off. Same-machine messages are unaffected.
claude -p sessions can receive too; the socket is available to scripts
Unattended claude -p sessions also bind the inbox socket, can receive messages, and show up in the list — so a long-running -p worker can take instructions.
But there's a catch: -p sessions can't show approval dialogs. So if a message gets held, it stays held until a later settings change releases it. To let an unattended worker receive messages on its own, set crossSessionInbound to accept in the startup --settings file. (Setting it at the user level also works, but that applies to every session you run.)
There's also a bare mode launch option — that one doesn't bind a socket, can't receive messages, and doesn't appear in the list.
SOCKETWhere the socket is, and how to use it
Two places to find the path:
- The
Peer addressline in/status, with auds:prefix on the path - The
CLAUDE_CODE_MESSAGING_SOCKETenvironment variable — available to hooks and Bash commands, and exported before any hook runs (including SessionStart). Each session exports its own; it never inherits the parent's
That means a script or a hook can drop a message into its own session. In our test the value was /tmp/cc-socks/27983.sock — the number is the session's process ID.
One platform difference worth noting. When a session's own child process (like a hook or Bash command) sends a message back in, it's delivered directly if the origin can be verified: Linux (including WSL 2) can verify even exited children; macOS only while the process is still alive; in containers where Claude Code is PID 1, it can't be verified at all. If verification is impossible, the message is treated like a normal one — so a permission-skipping session will hold it for your approval.
Whether sandboxed Bash commands can reach the socket is governed by the sandbox's Unix socket settings (sandbox.network.allowAllUnixSockets and sandbox.network.allowUnixSockets).
Receiving and sending shut off separately, each with a side effect
Receiving and sending are two independent switches, and you can flip just one:
| What you want off | How |
|---|---|
| Receiving | Set crossSessionInbound to refuse — incoming messages are all dropped without delivery. Set it in project or local settings; that overrides all other sources. |
| Sending, and being listed | Add permission denial rules naming SendMessage and ListAgents — both as bare tool names with no arguments. |
| The whole organization | Admins put both denial rules and refuse together in managed settings. |
Two side effects to know about:
First, denying SendMessage also kills the ability to message subagents and team members. Same tool serves both purposes, so what you meant as "keep sessions from bothering each other" also shuts down collaboration inside the session.
Second, once it's off, nothing from the outside shows it. Claude Code still binds the socket as usual, just silently drops everything that arrives. A refusing session carries no marker in its own /status or in anyone else's list — to confirm, you have to check its config.
How it maps against resume, Agent teams, and the rest
Claude Code has several "run multiple things" mechanisms, and it's easy to pick the wrong one. The docs include a dedicated comparison, worth copying down:
| What you want to do | Use this |
|---|---|
| Continue the same conversation in another terminal, or bring context into a new session | Session resume |
| A team that Claude spawns and directs itself | Agent teams |
| Watch and control many sessions from one place | Agent view |
| Drive a session personally from your phone or another device | Remote Control |
| Push external events (CI results, chat messages) into a session | channels |
| Send a note between your own independent sessions | Cross-session messaging, the subject of this article |
The one-line distinction: cross-session messaging is for your own independent sessions talking to each other. The ones Claude spawns and directs use the team roster; moving the whole context is resume's job.
Platform limits, provider restrictions, and message-loop throttles
| Condition | Requirement |
|---|---|
| OS | macOS and Linux (including Linux inside WSL 2). Native Windows doesn't have this feature |
| Version | v2.1.224 or newer |
| Providers | Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform, and Microsoft Foundry don't offer it |
| Environment variables | The telemetry-off variables (CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, DISABLE_TELEMETRY, DO_NOT_TRACK, DISABLE_GROWTHBOOK) also disable the feature flags this feature depends on |
This last one is the easiest to miss: you may have never intended to turn off messaging, just set an environment variable to reduce telemetry — and the feature has been off the whole time. These variables can come from your shell, an env section in a settings file, or admin configuration.
TROUBLESHOOTHow to check when messages aren't going through
Run /list-agents and split the diagnosis in two:
Command not recognized: this session doesn't have the feature at all. Go down the table above, starting with claude --version.
Command works, but the message never arrived: the feature is on; the problem is finer. Could be a permission denial rule removing the two tools, the receiver's inbound control holding or dropping the message, or the target living on another machine (which is reply-only).
LIMITSTwo hard limits
Plain text only. The structured protocol messages used inside Agent teams don't leave the team.
Message loops get cut off automatically. There's rate limiting per sender; identical duplicate messages arriving in quick succession get dropped, and each session caps unread messages at 50. So two sessions ping-ponging messages at each other will stop on their own — no rescue needed.
CLAUDE_CODE_MESSAGING_SOCKET set to /tmp/cc-socks/27983.sock, and an empty agent list in single-session mode. The docs don't specify a message length limit, don't clarify how the "100 held" cap relates to the "50 unread" queue, and don't detail how downstream actions triggered by a received message are billed. They mention that scripts can write to the socket but don't give a protocol format. All diagrams are ours, drawn from the docs.Claude Code sessions can now talk to each other — but they can't approve things for you
Breaking down the official docs: how Claude finds who can receive a message, what decides whether it gets through, and why this channel is welded shut against privilege escalation
↓ Read in one page · there's an animated figure
Sessions can pass notes to each other now — before, you were the copy-paste bridge
If you run several Claude Code terminals at once, they used to be soundproofed. When one session found something out, you had to copy it to the other window yourself. Now, with a recent-enough version, Claude will pass it over on its own — no prompting, no config.
Only a piece of plain text gets sent
The receiver sees the sender's name and a short note — like "Migration done; the new field is tenant_id, rebase is safe now." Nothing about what the other session discussed or which files it touched.
✘ No files
✘ No context
Claude decides whether to send — you never touch the tools
Two tools do the work: one finds which sessions are reachable, the other delivers the message. You don't click either. Claude decides whether to send, to whom, and how to phrase it. Your only job is a hint like "ask the session in the other terminal if the DB migration is done."
What another session says is not your consent
When a message arrives, Claude Code marks its origin clearly: this came from another session, not from you. Then it's locked into what it can and can't do.
✘ Can't change permission settings, CLAUDE.md, or any other config because of it
✘ Slash commands in the message are just text — they don't run
✘ Permission prompts still show up exactly as usual; no workaround
The bolder the session, the tighter the door
With no configuration, Claude Code decides based on both sides' permission modes:
| Receiver | Sender prompts | Sender skips prompts |
|---|---|---|
| Prompts | Delivered | Held for approval |
| Skips prompts | Held for approval | Delivered |
The logic: a session that acts without asking is the riskiest target for unsolicited messages, so the looser the permissions, the tighter the inbound gate.
Don't want the channel at all? Receiving and sending shut off separately: crossSessionInbound set to refuse kills receiving; a permission denial rule naming SendMessage and ListAgents kills sending — but that also kills the ability to call subagents inside a session. Versions running on Bedrock, AWS, Google Cloud, and Microsoft Foundry don't have this feature yet. The channel only covers your own independent sessions; resume, Agent teams, and the other multi-session mechanisms run on different tracks.
Does the frontend know?
paste into the other window
talk on their own
if the migration's done
Rebase is safe now
- × No history
- × No files
- × No context
approve things for me?
not from you
- × Can't approve perms for you
- × Commands in messages are just text
when does it get through?
the tighter the door
it really sent itself
back and forth
Approval stays yours