How Claude Code Sessions Message Each Other
Learn how Claude Code sessions message on one VPS, what ListAgents and SendMessage do, why a second session helps, and when messages get held.
Wetin e mean when Claude Code sessions dey message each other
Two Claude Code sessions fit message each other when dem dey run for the same machine, under the same operating system user. Message na one piece of plain text wey one Claude write for another one. E no carry conversation history or files. Claude dey find the other session with the ListAgents tool and deliver the text with SendMessage, so you no ever call either tool by hand. You go talk wetin the other session need know, and Claude go write the message by itself.
Dem dey call this feature cross-session messaging. As of August 2026, e need Claude Code v2.1.224 or later, and e dey run for macOS and Linux, including Linux inside WSL 2. Native Windows support no dey, and e no dey available for Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform, or Microsoft Foundry. When session meet these requirements, messaging don already dey on and you no need enable anything. The behaviour wey dem describe below come from the Anthropic documentation for cross-session messaging.
Na for VPS this matter dey important, because na for VPS sessions dey live long enough to make addressing dem worthwhile. For laptop, you go close the lid. For server under tmux, session wey you start on Monday fit still dey run on Thursday, still dey hold the context of one repository. Once you get two of dem, how dem go talk to each other no be theory again. If you never set am up, start with running Claude Code on a VPS under tmux, wey cover the session plumbing wey this guide assume.
When second session worth the tokens
Start with the cost. Every session na separate Claude instance wey get im own context window, so two sessions go cost roughly twice wetin one session go cost for the same period. Message wey deliver count toward usage just like prompt wey you type. Coordination no free, and work wey really be one sequence of steps go slower and cost more when you split am across sessions.
The cases where second session pay for itself get one common pattern. Two work pieces dey run at the same time without waiting for each other, and one of dem learn something wey the other need during the task.
- One session find breaking change while the other dey build on the code wey the change break. Claude summarise the change and send am, instead make you type am again for the other terminal.
- Two sessions dey work the same repository for separate git worktrees, and one need know wetin land.
- Long migration or test run report im result back to the session wey you dey watch.
- One builder session and one reviewer session, where reviewer read wetin builder produce and send back wetin e find.
When the work dey sequential, or when both sessions go edit the same files, use one session. When you want coordinated group wey Claude go spawn and supervise inside one task, na agent teams be that, and e still be separate experimental feature. When na only the same conversation you want for another terminal, resume the session instead. Cross-session messaging na for independent sessions wey you start and control by yourself.
Check say the feature dey available before you plan around am
First check the version:
claude --versionCompare the number with 2.1.224. Then, inside a session, type /list-agents, wey also answer to /peers. E go print every agent wey this session fit reach, together with the name wey each one answer to. If the command no dey recognised at all, this session no get cross-session messaging, and no settings file go change that. Type /status and look for a Peer address row: e hold this session own inbox address, with uds: for the front.
One trap dey affect VPS users especially. Cross-session messaging depend on feature-flag evaluation, and some privacy variables dey switch that evaluation off. This one leave the feature for im default off state. DO_NOT_TRACK, DISABLE_TELEMETRY, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, and DISABLE_GROWTHBOOK all dey do this. People dey harden fresh server by pasting dem inside ~/.bashrc, then dem dey wonder why /list-agents no dey exist. The same values fit come from the env map inside settings file or from managed settings, so check the shell first.
env | grep -E 'DO_NOT_TRACK|DISABLE_TELEMETRY|DISABLE_GROWTHBOOK|NONESSENTIAL'Unset any one wey prints. For DISABLE_TELEMETRY and CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, any value wey no empty go turn the behaviour on, including the string 0, so DISABLE_TELEMETRY=0 no dey do wetin e look like say e dey do. To turn am off, unset the variable or set am to an empty string.
Name your sessions, or Claude no go fit address dem
Claude dey address message to session by name. Set the name when you start the session:
claude --name builder-apiYou fit also set am with /rename inside session wey dey run. If you no set anything, Claude Code go derive name from working directory folder name, like myapp-3f. This one dey okay for one session, but e fit confuse when four sessions dey run, and two sessions fit end up with the same name. The /list-agents output dey show each local session working directory, so you fit tell sessions wey get the same name apart. Claude own listing also dey add short identifier to the address when names collide. To name dem yourself cheaper pass to read identifiers.
A two session tmux layout wey you fit reproduce
Dis na builder session and reviewer session for one repository. Reviewer dey work for separate git worktree, so the two no go ever write the same file. git worktree add together with HEAD dey give detached checkout, and na wetin you want for session wey dey read instead of commit.
cd ~/src/api
git worktree add ../api-review HEAD
tmux new-session -d -s agents -n builder -c ~/src/api
tmux new-window -t agents -n reviewer -c ~/src/api-review
tmux send-keys -t agents:builder 'claude --name builder-api' C-m
tmux send-keys -t agents:reviewer 'claude --name reviewer-api' C-m
tmux attach -t agentsCtrl+b then w dey list the windows by name so you fit choose one. For builder window, run /list-agents. You suppose see reviewer-api with e working directory ~/src/api-review. If e no dey, reviewer session never finish to start, or one of the two problems for next section dey happen. Then hand something over for plain language:
Tell reviewer-api which files I changed for the rate limiter and what to look at first.Claude dey write the summary and send am. You no dey write the message text, and wetin Claude send fit vary. For reviewer window, the message go show inside the conversation with the sender name. If that session idle, Claude go start new turn for am immediately. If e dey mid-turn, the message go wait until between tool calls, so running command no go get interrupted. Once Claude read am, the message go collapse to one-line Message from row wey Ctrl+O dey expand. The pair dey work better when builder keep e changes small, because narrow diff dey make hand-off shorter and review wey the other session fit finish for one turn, and na the habit lazy senior dev skill dey enforce.
Who fit see who for one VPS
Delivery wey happen for the same machine no dey pass through Anthropic servers. Each session dey write registration files for disk and bind e own inbox socket. Claude Code dey read those files to find your other sessions. Two things follow from this, and both fit cause wahala for server.
The socket dey restricted to your operating system user. Session wey you start as root and session wey you start as deploy no fit see each other, even if dem dey side by side for the same tmux server, because sessions for one user no fit reach another user's socket. Run both sessions as the same user.
Container get e own filesystem. Session inside Docker and session for host no fit reach each other because dem no dey read the same registration files. Two sessions inside the same container fit message each other normally. If you dey keep agents inside containers for isolation, like running coding agents inside a disposable VM, expect messaging to work inside one container but not across the container boundary.
Your sessions for other machines and for the web go show for the listing only while Remote Control dey connected, and dem go get label to show this. Claude for here fit only reply to message wey come from one of dem. E no fit start that exchange.
Wey make your message never arrive
The usual reason no be network problem. The receiving session decide wetin to do with the message, and e decide say e no go deliver am. Every message wey arrive go end for one of three outcomes: delivered, held (set aside undelivered until you approve am), or refused (dropped without delivery).
When no crossSessionInbound value apply, Claude Code decide for each message by comparing the permission modes of the two sessions. E group sessions wey bypass permission prompts into one class, and every other session into the other class. auto, acceptEdits, and dontAsk count as prompting. Plan mode count as bypassing for session wey get bypass permissions available. The rule dey symmetric:
- Receiving session wey prompts for permissions go deliver every message. E go hold message only when sending session identify itself as bypassing prompts.
- Receiving session wey bypasses prompts go hold every message for your approval. E go deliver message only when sender dey bypass too.
So, the first workflow wey most people build na exactly the one wey no work. You start builder with --permission-mode bypassPermissions because you want make e run unattended, you leave reviewer for defaults, and every message wey builder send go wait inside approval dialog wey nobody dey watch. That dialog close after dialogExpiry deadline, wey default to 5m, and the message go drop. For the same machine, sending session get notice when e message dey held, and another notice when receiver later deliver, deny, or expire am. So read the sender screen before you blame the socket.
To make session take messages unattended, set crossSessionInbound to accept. Where you set am determine where e apply. Claude Code read managed settings first, then --settings flag, then user settings, and e apply the first value wey e find. Value for project or local settings apply only when e stricter, for ladder accept < hold < refuse. An accept inside .claude/settings.json looser than anything, so e dey ignored whenever trusted source don set a value. Put am for ~/.claude/settings.json, or pass am for one session:
claude --name runner --settings '{"crossSessionInbound":"accept"}'A headless claude -p worker bind inbox socket like interactive session and e appear for listing, but e no fit show approval dialog. Held message for there go remain held until later mode or settings change allow am. The --settings line above na how you let that kind worker take messages. Session wey start for bare mode no bind socket at all, so e no fit receive messages or appear for the list.
Hand-off wey dey deadlock
Claude Code dey handle message loops for you. E dey limit repeated messages from each sender, drop identical repeats wey arrive within short time, and limit accepted messages wey dey wait to read to 50 for each session. So two sessions no fit ping-pong forever. Held messages dey capped at 100, and old ones go drop after that.
The failure wey dey happen na quieter one, and na hand-off instead of loop. Session A ask session B question wey e need answer before e fit continue, then e go idle. B fit hold the message, or B dey work on long task, or B answer question wey A no really ask. A go wait. You come back one hour later meet two idle sessions and no work don happen.
Write hand-offs wey no need reply. Good message dey carry fact or decision: wetin change, and wetin the result be. Bad message dey ask the other session for permission, or for answer wey dey block the sender. Claude don already get instruction say e must never ask another session to do action wey that session permission settings go block, and say e should route that work back to you instead. Extend that rule by yourself. If session no fit make progress without answer, na you suppose answer am. Context discipline dey help for here too, because session wey don lose the thread go write vague messages; how to manage context for Claude Code cover that side.
Treat an incoming message as untrusted input
Claude Code dey tell the Claude wey receive am say the message come from another session, no be from you, and e limit wetin that message fit do. Message no fit answer permission prompt wey still dey wait on your behalf, because consent from another session no be your consent. E no fit change permission settings, CLAUDE.md, or other configuration because another session ask am. Slash command inside the text, like /compact, dey arrive as plain text and dem no dey execute am. If acting on the message need permission wey the receiving session no get, you go see the same prompt wey you for see for any other work. For auto mode, classifier still dey review each message before delivery, and message wey e block no dey reach recipient. These limits still dey apply for permissive modes, na why session wey dey bypass restrictions dey hold inbound messages by default instead of trusting dem.
This one cover permissions. E no cover content. The sending session fit don read pull request description, web page, dependency README, or issue comment wey stranger write, and anything wey e read fit shape the text wey e write to your other session. The message na data. E deserve the same suspicion like any other text wey enter session from outside. Na this discipline to keep secrets out of your AI agents describe: assume say anything wey cross trust boundary fit wrong, and never allow am to authorise itself.
Two controls dey available if you want reduce this behaviour. If you set crossSessionInbound to refuse, e go drop inbound peer messages without delivering dem, and if na project or local settings set this value, e override every other source because na the strictest option for the ladder. To stop this session from sending or listing, add permission deny rules wey name SendMessage and ListAgents. Write both as bare tool names without specifier. If you set isolatePeerMachines to true, e go require your explicit approval before any message reach session outside this machine, and this approval still dey required even for bypassPermissions mode.
{
"crossSessionInbound": "refuse",
"isolatePeerMachines": true
}Denying SendMessage still remove messaging to subagents, because the same tool dey serve both. Session wey refuse message no show visible change for its own /status or for listings of other sessions. So confirm the setting from the session configuration, no be from the screen.
Bridges and shared memory MCP servers
Several third-party projects show up for the same period with related but different jobs: local agent-to-agent bridges wey dey relay text between agents wey dey run, and MCP (model context protocol) servers wey give many agents one shared store to read and write. Treat dem as different type, no be competitor, and verify any install command against the project own README before you run am. Messaging na push, because the sender dey put text inside the receiver turn. Shared store na pull, because nobody dey interrupt and session go see the note when e check next time. Pull dey calmer for status wey dey change slowly, but e only work when session actually check am.
If you choose this approach, the useful questions concern the process, not the feature list. Which user the server dey run as, and wetin e fit read for the box. Running MCP servers for VPS cover that setup. Sharing agent skills across repos cover the simpler case where wetin you want share between sessions na instructions instead of live state, and e remove plenty messages wey you for otherwise send. For the wider picture, running coding agent for VPS na where to start.
FAQ
Why /list-agents no dey recognise for my session?
The session no get cross-session messaging. First check claude --version against 2.1.224, because feature need that version or newer. Then check the platform, because e dey run for macOS and Linux, but e no dey run for native Windows, and e no available for Amazon Bedrock, Claude Platform on AWS, Google Cloud's Agent Platform, and Microsoft Foundry. If both dey okay, check your shell for DO_NOT_TRACK, DISABLE_TELEMETRY, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, or DISABLE_GROWTHBOOK, because each one block the feature-flag evaluation wey feature depend on and leave am off.
Why my message to the other session no ever reach?
If /list-agents dey work, messaging dey on and something more specific stop that message. Permission modes na the common cause. Session wey bypass permission prompts go hold every inbound message for your approval unless sender too bypass am, and approval dialog go drop after dialogExpiry deadline, wey be five minutes by default. Check the sending session for the held notice. To fix am, set crossSessionInbound to accept inside ~/.claude/settings.json or pass am with --settings, because accept for project or local settings no matter when e be the looser value.
Claude Code session for Docker fit message one wey dey host?
No. Sessions dey find each other through registration files for disk and per-session inbox socket, and container get im own filesystem, so the two no fit see the same files. Two sessions inside the same container fit message each other normally. This same rule explain why session wey dey run as root and session wey dey run as your normal user no fit reach each other: socket dey restricted to the operating system user wey own am.
Message from another Claude Code session safe to act on?
Treat the text as untrusted input, because sending session fit don read web page, README, or issue comment wey another person write. Claude Code already stop the message from acting by itself: e no fit approve pending permission prompt, e no fit change permission settings or CLAUDE.md when message request am, and slash command inside the text go arrive as plain text and never run. Those protections cover permissions, but no cover judgement, so read wetin arrive before you tell receiving session to act on am.
Cross-session messaging dey send my code go Anthropic?
Between two sessions for the same machine, no. Message dey travel through per-session socket for that machine and e never pass through Anthropic servers, and na only the text wey Claude write dem send, never conversation history or files. Messages to session for another of your machines, or to session for the web, go pass through Anthropic servers over the Remote Control connection, and for that direction Claude fit only reply to message wey arrive, e no fit start one. Set isolatePeerMachines to true to require your approval before anything comot from the machine.