Skip to main content

Inter-Session Messaging

Advanced
What you'll learn
  • Why two Claude Code sessions on the same machine can't talk out of the box — and why you keep being the copy-paste bridge
  • The three shipping patterns for peer-to-peer session messaging: filesystem, local WebSocket bus, and MCP channels
  • How to install and use one working plugin end-to-end in under two minutes
  • The trust boundary you must set — a peer's message is arbitrary text arriving as an instruction
  • When to reach for this pattern vs. a subagent, a shared worktree, or just running everything in one session

The problem: you are the bridge

Open Claude Code in Terminal A on libfoo/ and Terminal B on app-that-uses-libfoo/. Terminal B hits a type error from the library. Today, you — the human — do the routing: read the error, switch terminals, paste it into A, wait for the fix, switch back, run the build again. Each context switch loses state on both sides.

This is exactly the pain in the closed Anthropic RFE claude-code#36181, opened March 2026: "When working on interdependent projects across multiple terminals, users currently must manually context switch between sessions." The issue is closed — but a native inter-session channel is not yet in Claude Code. So the community shipped its own.

The three patterns

Three independent open-source projects converged on the same problem in early 2026, each picking a different transport. They matter because the trade-offs are baked into the transport choice — not into any single project.

PatternTransportShips asLatencyMulti-machineDebuggable
File-based inboxJSON files under ~/.claude/session-bridge/sessions/<id>/{inbox,outbox}/9 bash scripts + jq~5–10s (3s poll)❌ single machinecat message.json
Local WebSocket buslocalhost WebSocket, session daemonClaude Code pluginms-level❌ single machine⚠️ needs bus dump
MCP channelsMCP server with Slack-style channels + semantic searchnpx claude-slacknetwork hop✅ works over network✅ query MCP

Pick the transport that matches how you already debug and how many machines you actually run agents on.

1. File-based inbox — PatilShreyas/claude-code-session-bridge (MIT, 65★)

Every session has a directory: ~/.claude/session-bridge/sessions/<6-char-id>/. Messages are JSON files with a status field that atomically flips pending → read. The receiver polls its inbox every 3 seconds. Author's own reason for skipping WebSockets and MCP: "They're debuggable. You can literally cat a message."

Session A becomes the listener; Session B asks it a question

# In session A (the library repo)
/bridge listen
# → prints A's 6-char session id, e.g. a1b2c3

# In session B (the app that consumes the library)
/bridge connect a1b2c3
/bridge ask "Which version of libfoo exports the parseDate() helper, and did its signature change?"

Session A answers from its live context — the loaded files, the recent tool results, its plan mode. Session B receives the reply as a message it treats as trusted human-adjacent input. That last sentence is the whole security story on this pattern; keep reading.

2. Local WebSocket bus — yilunzhang/claude-code-inter-session (MIT, 27★)

A local daemon binds a WebSocket on your loopback interface. Every connected session registers a name and can send, broadcast (payload cap 256 KB), or list peers. Delivery uses Claude Code's Monitor tool, so idle sessions burn no tokens and no polling loop runs. Requires Claude Code ≥ 2.1.105 and Python ≥ 3.10.

Install as a plugin marketplace, then use its slash commands:

Install the inter-session plugin and connect two terminals

# In any Claude Code session (run once per machine)
/plugin marketplace add https://github.com/yilunzhang/claude-code-inter-session
/plugin install inter-session

# Terminal A
/inter-session:inter-session connect libfoo

# Terminal B
/inter-session:inter-session connect app
/inter-session:inter-session send libfoo "Does parseDate() still accept a string?"

# Broadcast to everyone
/inter-session:inter-session broadcast "About to bump libfoo to 2.0 — hold merges."

3. MCP channels — theo-nash/claude-slack (MIT, 8★)

A full MCP server that exposes Slack-style abstractions: #general, per-project channels, DMs, and a semantic-search knowledge layer backed by Qdrant. Messages persist across restarts, which the other two do not. The trade-off: you now run a network service and its dependencies, and messages must flow through a tool call round-trip on each turn.

Start the MCP server and use it from an agent turn

# Start once (in its own terminal)
npx claude-slack

# In any Claude Code session, once claude-slack is added to your MCP config:
Post to #libfoo-consumers that parseDate() moved from utils to date-helpers in v2.0.
Then search the channel for prior questions about parseDate to make sure I answered them.

Use MCP channels when you want persistence (later sessions can search what earlier ones said) or when the peers live on different machines — the other two are single-machine only.

Pick the right transport

Guided walkthrough1 of 5
  1. If sessions run on different laptops or a remote box, only the MCP-channel pattern works. The file inbox and local WebSocket bus are single-machine by design.

The trust boundary you must not skip

Here is the part nobody's talking about clearly. In every pattern above, a message arrives at the receiving session as text the agent will treat as an instruction by default. That means: another session — or anything on your box that can write to the inbox/socket/MCP — can inject prompts into your agent.

Watch out
  • A peer message is untrusted input, not a user turn. Even on your own machine, the sender is another autonomous agent that may itself have been prompt-injected by a file it read.
  • Never run inter-session messaging with a wide-open tool set. Pair it with a Claude Code permissions profile that blocks destructive shell, arbitrary web fetches, and secret paths.
  • The WebSocket and file-based patterns have NO authentication of the sender by default. Any local process that can bind to the loopback socket or write to ~/.claude/session-bridge/ can pretend to be a peer.
  • Treat broadcasts as blast radius. A single poisoned message to 5 connected sessions is 5 compromised agents, not 1.
  • When in doubt, mediate: have the receiving session summarize the incoming message to you for approval before it acts on it — a lightweight hook or a prompt guardrail in the plugin's frontmatter does the job.

For the general threat model this fits inside, see Prompt Injection and Securing Agents. For MCP-specific bus risks, Invisible-Comment MCP Attacks is directly relevant — the same class of "message arrives with hidden instructions" bug applies to a Slack-style channel exactly as it does to a tool result.

When this beats a subagent — and when it doesn't

Peer sessions and subagents solve different problems. A subagent is a fresh Claude with a scoped tool set that you spawn to protect the main context or specialize a task; it starts empty and returns a result. A peer session is a long-running, human-driven Claude Code instance with its own files loaded, plan mode active, and a whole conversation of state — you're borrowing its context, not creating a new one.

Reach for inter-session messaging when the value is in the other session's live state: the library it's already reasoning about, the failing test it just ran, the commit it just staged. Reach for a subagent when the value is in running one bounded task in isolation. If you find yourself using inter-session messaging to fire off one-shot questions with no reliance on the peer's context, you probably want a subagent — or a shared worktree.

For long-form multi-agent workflows that outgrow both patterns, see Long-Running Agent Harnesses and Native Multi-Agent APIs.

Common mistakes

Pitfalls — flip each card for the fix
Press Enter or Space to flip the card. Use the left and right arrow keys to move between cards.Term shown.
1 / 5

Check yourself

0/3
  1. Two Claude Code sessions on the same laptop need to exchange messages, and you want them stored so a session opened tomorrow can search yesterday's context. Which pattern fits?
  2. Which security assumption is TRUE across the file-based inbox and the local WebSocket bus by default?
  3. You need to spawn a fresh Claude with a scoped tool set to run ONE bounded task and return a result. What should you use?
Key takeaways
  • Claude Code does not ship native inter-session messaging (yet); three community projects fill the gap using different transports.
  • Pick file-based for debuggability, WebSocket for sub-second latency on one machine, and MCP channels only if you need persistence or cross-machine peers.
  • A message from a peer session is untrusted input — treat it like any other prompt-injection surface and pair the bus with a tight permissions profile.
  • If you only need a scoped worker for one task, use a subagent instead; peer sessions are for borrowing another session's live state.
  • The official RFE (claude-code#36181) is closed but not implemented — watch the repo for a native version and expect the community projects to converge or die once it lands.

Sources & further reading