claude-code-relay
README.md
# 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.
## 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
```bash
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`:
```jsonc
{
"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:
```bash
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:
```bash
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:
```bash
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:
```bash
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
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues