interclaude
Enables peer-to-peer communication between Claude Code sessions, allowing them to send messages, hand off tasks, and coordinate across worktrees without manual intervention.
README
interclaude
Your Claude Code sessions can talk to each other. π€
Open two terminals, and one Claude can message the other β ask it a question, hand off a task, coordinate a refactor across worktrees β with the reply surfacing right in the conversation. No copy-pasting between windows, no relaying through you. A peer's message just appears:
<channel source="interclaude" sender="hazel" ts="2026-06-16T21:14:03Z">
tests are green on main β rebase your branch when ready, then send me the diffstat.
</channel>
Peer messages are actionable by default, so this isn't just chat β it's two (or ten) agents genuinely collaborating. Split a big change across branches and let the sessions sync up. Have one session run the slow test suite while another keeps coding. Ask the session that wrote a module how it works. Fan a question out to everyone with a broadcast.
Quickstart
Two lines. The first installs the MCP server; the second installs the skill that teaches Claude when and how to use it:
claude mcp add --scope user interclaude -- npx -y github:alexgoodell/interclaude
npx skills add alexgoodell/interclaude
Then launch each session you want connected with the development-channels flag (this is what wires the inbound push β see Requirements):
claude --dangerously-load-development-channels server:interclaude
That's the whole setup. There's no broker to start by hand and no config to
edit β each session auto-registers under a memorable alias (hazel, otis,
β¦). Ask any session to run interclaude_list to see who's reachable, then
interclaude_send to message a peer.
<details> <summary>Alternatives: local clone, pinned alias, manual MCP config</summary>
npx re-resolves the repo on each session start. For a faster, offline-proof
launch, register a local clone instead:
git clone https://github.com/alexgoodell/interclaude && cd interclaude && npm install
claude mcp add --scope user interclaude -- node "$(pwd)/server.js"
Pin a specific alias instead of the auto-generated one:
INTERCLAUDE_ALIAS=alice claude --dangerously-load-development-channels server:interclaude
Register the server by editing ~/.claude.json directly instead of using
claude mcp add:
{
"mcpServers": {
"interclaude": {
"command": "node",
"args": ["/absolute/path/to/interclaude/server.js"]
}
}
}
Install the skill globally (all projects) rather than into the current one:
npx skills add alexgoodell/interclaude -g.
</details>
Requirements
- Node 20+
- Claude Code, launched with
--dangerously-load-development-channels server:interclaude. This flag is mandatory, not optional: it's what lets the server push a peer's message into your session as a<channel>block. Without it you get the outbound tools but no inbound messages β the half that makes interclaude worth using. Every participating session needs the flag.
How it works
session A session B
claude --dangerously-load-development-channels (same launch flag)
server:interclaude
β registers "proxy@feature-x" (alias "hazel") β registers "proxy@main" (alias "otis")
βΌ βΌ
server.js ββTCP/JSON :9877βββΆ broker.js βββTCP/JSONββ server.js
(per-session MCP adapter) (one detached (per-session MCP adapter)
β β² process, in-mem queues)
β βββ poll check() ~3s ββββββββββββ
βΌ
emit notifications/claude/channel
β <channel source="interclaude" sender="otis" β¦> appears in A's next turn
Three small files do the work:
broker.jsβ a localhost TCP rendezvous (:9877) speaking line-delimited JSON. Holds in-memory message queues keyed by session name, plus an alias map and last-seen times. Auto-spawned detached the first time any session needs it; if two sessions race to spawn it, the port bind picks a single winner. Messages to a not-yet-registered recipient queue until it shows up, and each message is delivered exactly once.server.jsβ the per-session MCP channel adapter. Registers a name derived from the session's git worktree and branch, polls the broker every few seconds, and pushes incoming messages into the conversation asnotifications/claude/channelevents. Exposes the outbound tools below. If the broker dies, the poll loop respawns it and re-establishes presence, so a running session recovers on its own.client.jsβ the shared wire client (request), name derivation (deriveName), and broker auto-spawn (ensureBroker), used byserver.jsand the tests.
The bundled skill (skills/interclaude/SKILL.md, installed by the second
quickstart line) teaches an agent when to reach for these tools β and the one
rule that trips agents up: replies must go through interclaude_send, because
your transcript text never reaches a peer.
Naming and addressing
- A session's canonical name is
<worktree>@<branch>(e.g.proxy@main), derived from its working directory at startup. Outside a git repo it falls back to the directory basename.INTERCLAUDE_NAMEoverrides it. - Collisions disambiguate automatically. A second session claiming a live
name is assigned
name-2,name-3, β¦ and adopts the assigned name. A name frees up ~10 seconds after its holder stops polling, so restarting a session gets its old name back. - Every session auto-claims a memorable alias (
hazel,otis, β¦) from a built-in name pool at startup, skipping names held by live peers. Canonical names collide constantly β every session in one repo starts on the same branch β so the alias is the primary handle, and outgoing messages are labeled with it. Pin a specific alias withINTERCLAUDE_ALIAS, or replace it at runtime with theinterclaude_aliastool. A session holds one alias at a time, and an alias expires with its session, so dead sessions don't squat on good names.
Tools
| Tool | Purpose |
|---|---|
interclaude_send |
Send to a peer by name or alias (optional structured data payload) |
interclaude_broadcast |
Send to every other registered session |
interclaude_list |
Who's reachable (names, aliases, last-seen, live flag) |
interclaude_alias |
Claim/replace this session's short alias |
Convention: a message is a request to act unless it begins with fyi:,
which marks it informational β the receiving agent acknowledges but doesn't
act. This is a prompt convention in the server's instructions, not enforced by
the broker.
Configuration
| Variable | Default | Meaning |
|---|---|---|
INTERCLAUDE_PORT |
9877 |
Broker port (localhost only) |
INTERCLAUDE_NAME |
auto (worktree@branch) |
Override this session's name |
INTERCLAUDE_ALIAS |
auto-generated | Pin this session's alias instead of auto-generating one |
INTERCLAUDE_POLL_INTERVAL |
3000 |
Inbound poll interval, ms |
Broker lifecycle and troubleshooting
The broker is a single detached process that outlives any one session. Queues are in-memory only: if the broker dies, undelivered messages are lost, but every running session's poll loop respawns it and re-registers automatically β no restart needed.
Check what the broker sees (run from this directory):
node -e "import('./client.js').then(async ({request}) => \
console.log(JSON.stringify(await request(9877, {action:'list'}), null, 2)))"
Force a clean slate (the next session poll respawns it):
pkill -f 'interclaude/broker.js'
Every poll re-asserts both the session's presence and its alias, so names and aliases alike survive a broker restart without any manual re-claiming.
Trust model
No authentication, by design β every participant is one of your own local
sessions on one machine, and any of them can drive another's tools through
channel messages. The broker binds to 127.0.0.1 only; do not expose the port
beyond localhost. If interclaude ever grows a remote transport or untrusted
peers, that is the moment to add pairing/allowlisting.
Development
node --test
Unit tests cover the broker's routing/aliasing/disambiguation and the client
helpers. The channel push itself can't be unit-tested β it's verified
end-to-end by launching two real sessions and exchanging a message, which is
the completion bar for any change to server.js.
interclaude/
broker.js # rendezvous: in-memory queues + alias map over TCP/JSON
client.js # wire client + name derivation + broker auto-spawn
server.js # per-session MCP channel adapter (inbound push + outbound tools)
test/ # unit tests (node:test)
skills/ # bundled agent skill (npx skills add)
License
MIT
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.