Last summer I lost an afternoon to something stupid. I had two Claude Code sessions open in the same directory, each on a different article. One switched branches to finish a pull request. The other noticed nothing, did its work properly, committed, and pushed. “Everything up-to-date”, said git. The fix was sitting on a branch nobody was looking at.
That had a boring fix: one worktree per session. It has been in my project rules ever since and it has not happened again. But the underlying situation stayed. Two sessions working the same project, each blind to the other.
Since Claude Code 2.1.224 they can reach each other.
What it is
Two tools, neither needing installation or configuration: ListAgents shows which of your sessions are reachable, SendMessage delivers text to one of them. Inside a session you look with /list-agents, also available as /peers.
Exactly one thing travels: text one Claude writes for another. No conversation history, no files, no context. If you want to carry a conversation into another window, resume that session instead; this is not built for that.
You do not have to phrase the message yourself. “Tell the session working on the API what we just changed” is enough, and Claude writes it.
On the receiving end it arrives between two tool calls, so a running command is never cut in half. If that session is sitting idle, it opens a new turn with the message. Once delivered it counts toward your usage exactly like a prompt you typed yourself.
Where the message goes
This is the part I care about most, and it is not at the top of the announcement.
| Where the other session runs | How the message travels | What you can send |
|---|---|---|
| On this machine | Over a per-session socket, never through Anthropic | New messages and replies |
| On another of your machines | Through Anthropic, over that machine’s Remote Control connection | Since 2.1.225 new messages too, before that replies only |
| Claude Code on the web | Through Anthropic, straight to the cloud session | Replies |
So two sessions on your own laptop talk locally. The same tool call aimed at your work machine takes an entirely different route. For a public project that hardly matters. For work involving client material it is the question you ask up front.
Locally it works because each session registers itself in files on disk and binds its inbox socket there. Two sessions can find each other only when they see those same files. A container has its own filesystem, so something inside a container and something on the host cannot reach each other. Two sessions inside the same container can.
Who is allowed to do what here
An incoming message is a new way into a session, which immediately raises the question of what someone can get done through it.
The answer is strict, and it was already strict before this feature existed. A message arriving via another session does not carry your authority. The receiver refuses relayed permission requests, and auto mode blocks them. Since 2.1.222 an outgoing message also passes the permission classifier before it leaves at all.
On top of that, the receiving session decides what happens to a message: deliver it, hold it until you approve, or refuse it. With no setting of your own, Claude Code looks at both sessions’ modes. Sessions fall into two classes: the one that skips permission prompts, and everything else, which includes auto mode, acceptEdits and dontAsk.
- If the receiving session normally asks for permission, the message comes through. It is only put in front of you when the sender identifies itself as skipping prompts.
- If the receiving session skips prompts, every message is put in front of you. Unless the sender does the same.
When something is held you get a dialog showing the sender and a preview of the text. Leave it for five minutes and the dialog closes and the message is dropped. That is the dialogExpiry default, and you can change it.
To switch it off entirely, add a deny rule on the two tools; SendMessage and ListAgents then disappear from the session.
The caveat
It does not fix my problem. That lost commit last year was not a communication failure but a filesystem one. Two processes in one directory, one HEAD. A message saying “I just switched branches” arrives after the damage, and by then the question is no longer whether you know but whether you can undo it. So the one-worktree-per-session rule stands. New features are rarely a reason to retire old discipline, even when the documentation lists coordinating worktrees as an example.
A session gains an entrance. That is the point, and it is well fenced: no authority, no relayed permission requests, a classifier in front. But it is still text entering your session that you did not type, and that then counts toward your usage. With two sessions you can follow that. With six, half of them in auto mode, that approval dialog is another window you click through after two days. We know this pattern by now.
The two routes look identical. Locally the message stays on your machine; to another machine it passes Anthropic. In both cases Claude does the same thing: one call, one confirmation. The difference is not in what you see. If you work with material you would not casually send out, that is a habit you have to build deliberately, because the interface will not remind you.
What I do myself: leave it on between sessions on this laptop, since that is where the benefit is and where it stays local. To my other machine I put it behind approval. And the worktrees stay.
Frequently asked questions
Do I need to install or enable anything?
No. From version 2.1.224 it is on as soon as a session meets the requirements. If /list-agents is not recognised, that session does not have the feature.
Watch for the trap that cost me an hour. I had eight sessions running, all on 2.1.222, while claude --version in my terminal happily reported 2.1.226. My first thought was that a running session holds onto its start version and a restart would sort it. True enough, but not the cause here.
The desktop app carries its own pinned Claude Code, separate from whatever sits on your PATH:
ls ~/Library/Application\ Support/Claude/claude-code/
# 2.1.222
One version, and that is the one every window starts. Restarting hands you 2.1.222 again. What needs updating is the app itself, not the session.
Per session you can check the registration file:
grep -h '"version"' ~/.claude/sessions/*.json
Anything below 2.1.224 there tells you where to look.
Where do those sessions live?
In ~/.claude/sessions/, one JSON file per session, carrying the process id, the working directory, the version, a derived name and a peerProtocol number. That is also where each session binds its inbox socket. Which explains straight away why two sessions can only find each other when they see those same files, and why a container falls outside that.
The file appears when a session starts and disappears when it stops, so that directory is a reliable picture of what is running now rather than what once ran. Useful quite apart from this feature: it is the fastest way to see how many sessions you have open and in which directories. There is a command for it too:
claude agents --json
Why does ListAgents see nobody while my sessions are clearly running?
Because being registered is not the same as being reachable, and that cost me most of my time. claude agents --json shows every running session, including the ones that do not have this feature at all. ListAgents shows only the ones holding an inbox open.
The difference is a single field. A session that listens carries a messagingSocketPath in its registration file, with a real socket behind it:
grep -l messagingSocketPath ~/.claude/sessions/*.json
ls /tmp/cc-socks/
No messagingSocketPath, no inbox. For me that applied to all nine sessions on 2.1.222, and it is the cleanest test there is: no version arithmetic, just look for the field. A session also binds that socket only once it has fully started. I had one that stalled in its startup hooks, and it registered itself perfectly well while listening to nothing.
Does this work on Windows?
Not on native Windows. It does work on macOS and Linux, including Linux inside WSL 2. It is also unavailable on Amazon Bedrock, Claude Platform on AWS, Google Cloud’s Agent Platform and Microsoft Foundry.
Can another session change my code through a message?
No. Only text travels, and that text does not carry your authority. A relayed permission request is refused, and blocked in auto mode. What the receiving Claude then does falls under that session’s own permissions.
Does my message pass through Anthropic?
Between two sessions on the same machine, no; that runs over a local socket. To another machine or a web session, yes, over the Remote Control connection.
What if the receiving session is mid-task?
Nothing gets interrupted. The message arrives between two tool calls. If the session is idle, it opens a new turn with it.
Sources
- Claude Code Docs, Message your other Claude Code sessions
- Claude Code CHANGELOG, versions 2.1.166, 2.1.222, 2.1.224 and 2.1.225
Checked on 10 August 2026 against the documentation and the changelog. What is written above about the cross-machine route comes from the documentation, not from my own observation: every session I had running was still on 2.1.222 at that point, below the 2.1.224 requirement, and none of them could reach another. The observation about the registration file is my own, since that is exactly how I found out.
