Real-time communication between Claude Code instances across multiple machines via WebSocket + MCP.
Enables Claude Code sessions on different machines to send messages to each other in real-time. Useful for:
- Context sharing - Share findings, file contents, or investigation results between sessions
- Task handoffs - Start a task on one machine, continue on another
- Coordination - Let one Claude Code instance know what another is doing
Machine A Machine B (Server Host)
┌─────────────────┐ ┌─────────────────┐
│ Claude Code │ │ Claude Code │
│ ↓ │ │ ↓ │
│ MCP Server │ │ MCP Server │
│ ↓ │ │ ↓ │
│ WebSocket ────┼── SSH Tunnel ─────┼─→ Relay Server │
│ (localhost) │ or direct │ (port 9999) │
└─────────────────┘ └─────────────────┘
| Component | Description |
|---|---|
server.js |
WebSocket relay server (runs via launchd) |
mcp-server.js |
MCP server spawned by Claude Code instances |
sessions/ |
Session identity registry for human-readable IDs |
git clone https://github.com/gvorwaller/claude-relay.git
cd claude-relay
npm installnode server.js
# [Claude Relay] Ready! Listening on ws://localhost:9999Add to your Claude Code MCP configuration (~/.claude.json):
{
"mcpServers": {
"claude-relay": {
"type": "stdio",
"command": "node",
"args": ["/path/to/claude-relay/mcp-server.js"],
"env": {
"RELAY_URL": "ws://localhost:9999"
}
}
}
}If machines aren't on the same network, use SSH port forwarding:
# On the remote machine, tunnel to the server host
ssh -N -L 9999:localhost:9999 server-host &
# Or use autossh for auto-reconnecting
autossh -M 0 -N -L 9999:localhost:9999 server-host &Assign human-readable IDs to Claude sessions (CC-1, CC-2, CODEX, etc.) for easier coordination.
Add to your ~/.zshrc or ~/.bashrc:
# Claude Relay Session Management
alias claude-session='source ~/claude-relay/sessions/register.sh'
alias claude-sessions='~/claude-relay/sessions/list.sh'Register a session (in terminal before starting Claude Code):
claude-session CC-1
# ✓ Registered: CLAUDE_RELAY_SESSION_ID=CC-1List all registered sessions:
claude-sessions
# === Registered Claude Sessions ===
# CC-1 PID: 12345 Started: 1/12/2026, 3:30:00 PM
# CWD: /Users/you/project
# CODEX PID: 67890 Started: 1/12/2026, 4:15:00 PM
# CWD: /Users/you/other-projectThe MCP server determines client ID in this order:
CLAUDE_RELAY_SESSION_ID- Shell alias sets this--client-idcommand line argumentRELAY_CLIENT_IDenvironment variable- Auto-generated:
hostname-pid
Sessions are tracked in ~/claude-relay/sessions/registry.json so all AI instances can see each other.
Once configured, Claude Code will have these tools:
| Tool | Description |
|---|---|
relay_send |
Send a message to peer Claude Code instance(s) |
relay_receive |
Get recent messages from peers |
relay_peers |
List currently connected instances |
relay_status |
Check connection health |
relay_sessions |
List all registered sessions (including offline) |
Send a message:
Use relay_send to tell CC-2: "Found the bug - it's in auth.js line 42"
Check for messages:
Use relay_receive to see if there are any messages from peers
See who's online:
Use relay_peers to list connected instances
View all registered sessions:
Use relay_sessions to see all Claude sessions, online and offline
# Copy the LaunchAgent
cp com.claude-relay.plist ~/Library/LaunchAgents/
# Edit the plist to fix paths for your system:
# - Update /usr/local/bin/node to your node path (use `which node`)
# - Update /Users/yourname/claude-relay to your install path
# Load it
launchctl load ~/Library/LaunchAgents/com.claude-relay.plistVerify it's running:
launchctl list | grep claude-relay
# PID Status Label
# 1234 0 com.claude-relay# Install autossh
brew install autossh
# Copy and edit the tunnel LaunchAgent
cp com.claude-relay-tunnel.plist ~/Library/LaunchAgents/
# Edit to set your server hostname and paths
# Load it
launchctl load ~/Library/LaunchAgents/com.claude-relay-tunnel.plistUse the interactive test client:
# Terminal 1: Start server
node server.js
# Terminal 2: Connect as client A
node test-client.js MACHINE_A
# Terminal 3: Connect as client B
node test-client.js MACHINE_B
# In either client:
send Hello from here!
peers
history| Variable | Default | Description |
|---|---|---|
RELAY_PORT |
9999 |
Port for relay server |
CLAUDE_RELAY_SESSION_ID |
(none) | Human-readable session ID |
RELAY_URL |
ws://localhost:9999 |
Relay server WebSocket URL |
# Server
node server.js [port]
node server.js 8888
# MCP Server
node mcp-server.js --client-id=LAPTOP --relay-url=ws://192.168.1.100:9999claude-relay/
├── server.js # WebSocket relay server
├── mcp-server.js # MCP protocol server for Claude Code
├── test-client.js # Interactive test client
├── package.json # Node.js dependencies
├── sessions/
│ ├── register.sh # Shell script to register session ID
│ ├── list.sh # Shell script to list sessions
│ └── registry.json # Session registry (auto-generated)
├── logs/
│ ├── relay.log # Relay server logs
│ └── relay-error.log # Relay server errors
├── com.claude-relay.plist # macOS LaunchAgent for relay server
└── com.claude-relay-tunnel.plist # macOS LaunchAgent for SSH tunnel
Connection refused:
- Ensure relay server is running:
lsof -i :9999 - If using SSH tunnel, verify it's active:
ps aux | grep ssh
MCP tools not appearing:
- Restart Claude Code after adding MCP config
- Check MCP server is connecting: look for "Connected!" in logs
Messages not arriving:
- Use
relay_peersto verify both instances are connected - Check message history with
relay_receive
Orphaned MCP processes:
- The MCP server includes a parent process watchdog
- If Claude Code exits unexpectedly, MCP servers self-terminate within 10 seconds
- To manually clean up:
pkill -f "claude-relay/mcp-server.js"
Session not showing correct ID:
- Ensure you ran
claude-session CC-1BEFORE starting Claude Code - Check with:
echo $CLAUDE_RELAY_SESSION_ID - The session ID is inherited from the shell environment
- The relay server has no authentication by default
- Designed for trusted local networks or SSH tunnels
- All traffic over SSH tunnel is encrypted
- Don't expose port 9999 to the internet without adding authentication
MIT