Skip to main content
Glama
katekyorock-ux

claude-code-relay

claude-code-relay

Relay messages between Claude Code sessions over MCP — without stealing window focus.

Run several Claude Code sessions in parallel and let them message each other. A message is injected into the target session's conversation in the background, as a <channel> block — no keystroke paste, no window jumping to the foreground. You keep typing where you are; the message just appears in the other session.

The problem

If you drive multiple Claude Code sessions at once, you eventually want them to talk — one hands work to another, or asks a question. The obvious way (paste into the target terminal) steals focus: the target window jumps to the front and your next keystrokes land in the wrong place. That makes genuine parallel work painful.

Related MCP server: peer-relay

The approach

claude-code-relay uses Claude Code's experimental channel capability. Each session runs a tiny MCP server that:

  1. listens on a local HTTP port, and

  2. pushes any received message into its own conversation via the notifications/claude/channel notification.

Delivery is a plain HTTP POST from the sender to the receiver's port. Background injection means the receive is focus-free.

 session "alice"                             session "bob"
   send.js  ──HTTP POST 127.0.0.1:8802──▶  channel.mjs  (MCP server)
                                                 │
                                                 ▼  notifications/claude/channel
                                    <channel source="claude-code-relay" from="alice">
                                       hey, can you take the migration?
                                    </channel>      ← appears in bob's conversation

Quick start

npm install
cp ports.example.json ports.json     # map session names -> ports

Register the receiver per project in .mcp.json, giving each session its own port via RELAY_CHANNEL_PORT:

{
  "mcpServers": {
    "claude-code-relay": {
      "command": "node",
      "args": ["./channel.mjs"],
      "env": { "RELAY_CHANNEL_PORT": "8801" }
    }
  }
}

Launch each Claude Code session with development channels enabled (experimental flag), on its own port:

RELAY_CHANNEL_PORT=8801 claude --dangerously-load-development-channels   # session "alice"
RELAY_CHANNEL_PORT=8802 claude --dangerously-load-development-channels   # session "bob"

Send a message from one session to another:

node send.js alice bob "hey, can you take the migration?"

It shows up in bob's conversation as a <channel> block. Bob replies the same way:

node send.js bob alice "on it"

Notes & caveats

  • Experimental flag. This relies on Claude Code's --dangerously-load-development-channels and the claude/channel capability. Both are experimental and may change between releases.

  • Receive-only channel. The channel only delivers into a session; there is no reply tool. Sessions reply by running send.js. Typing in the window sends nothing.

  • Localhost only. Servers bind 127.0.0.1 — this coordinates sessions on one machine.

  • ASCII session names are recommended (the sender name travels in an HTTP header).

  • One port per session. A duplicate spawn on a taken port exits cleanly (no churn).

Verify it works

mcp-probe.mjs starts the receiver as a real MCP server (over stdio, exactly as Claude Code would), sends a message over HTTP, and asserts it comes back as a notifications/claude/channel notification — the full injection path, end to end:

npm test
# -> E2E PASS: HTTP POST -> channel.mjs -> notifications/claude/channel -> MCP client

The only thing this can't assert headlessly is the final UI render, which is Claude Code's job.

License

MIT © TEAM ROCK

Related MCP Connectors

Related MCP Servers