claude-peers
Uses an ntfy relay (default https://ntfy.sh, configurable via CLAUDE_PEERS_WAKE_RELAY, or self-hosted on localhost) as an opt-in wake feed for cloud sessions that cannot reach the broker's loopback WebSocket. While an agent's wake mode is active, the broker publishes a private topic for that peer and a send posts only the literal body "wake" to it — never any message content — so a session can stream the topic with a Monitor command and then pull its mail via check_messages. Switching wake mode off publishes "off" to end the Monitor, and the relay can be disabled entirely.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
chief-of-staff-mcp
A chief-of-staff layer for Claude Code agents: one coordinator triages incoming work, delegates it to the right session, and reports back up — built on a local peer mesh.
Forked from louislva/claude-peers-mcp by Louis Arge, which provides the peer discovery and messaging substrate this builds on. See Attribution.
The mesh underneath
Let your Claude Code instances find each other and talk. When you're running 5 sessions across different projects, any Claude can discover the others and send messages that arrive instantly.
Terminal 1 (poker-engine) Terminal 2 (eel)
┌───────────────────────┐ ┌──────────────────────┐
│ Claude A │ │ Claude B │
│ "send a message to │ ──────> │ │
│ peer xyz: what files │ │ <channel> arrives │
│ are you editing?" │ <────── │ instantly, Claude B │
│ │ │ responds │
└───────────────────────┘ └──────────────────────┘Related MCP server: claude-peers
Quick start
1. Install
git clone https://github.com/DeanSingh/chief-of-staff-mcp.git ~/chief-of-staff-mcp # or wherever you like
cd ~/chief-of-staff-mcp
bun install2. Register the MCP server
This makes claude-peers available in every Claude Code session, from any directory:
claude mcp add --scope user --transport stdio claude-peers -- bun ~/chief-of-staff-mcp/server.tsReplace ~/chief-of-staff-mcp with wherever you cloned it.
3. Run Claude Code with the channel
claude --dangerously-skip-permissions --dangerously-load-development-channels server:claude-peersThat's it. The broker daemon starts automatically the first time.
Tip: Add it to an alias so you don't have to type it every time:
alias claudepeers='claude --dangerously-load-development-channels server:claude-peers'
4. Open a second session and try it
In another terminal, start Claude Code the same way. Then ask either one:
List all peers on this machine
It'll show every running instance with their working directory, git repo, and a summary of what they're doing. Then:
Send a message to peer [id]: "what are you working on?"
The other Claude receives it immediately and responds.
What Claude can do
Tool | What it does |
| Find other Claude Code instances — scoped to |
| Send a message to another instance by ID (arrives instantly via channel push) |
| Describe what you're working on (visible to other peers) |
| Manually check for messages (fallback if not using channel mode) |
How it works
A broker daemon runs on localhost:7899 with a SQLite database. Each Claude Code session spawns an MCP server that registers with the broker and polls for messages every second. Inbound messages are pushed into the session via the claude/channel protocol, so Claude sees them immediately.
┌───────────────────────────┐
│ broker daemon │
│ localhost:7899 + SQLite │
└──────┬───────────────┬────┘
│ │
MCP server A MCP server B
(stdio) (stdio)
│ │
Claude A Claude BThe broker auto-launches when the first session starts. It cleans up dead peers automatically. Everything is localhost-only.
Access control
Loopback alone doesn't keep web pages out: a page you open can POST to 127.0.0.1, and a DNS-rebinding page can read the replies. So the broker:
refuses any request with an
Originheader, aHostother than127.0.0.1:<port>/localhost:<port>, or (for POSTs) aContent-Typeother thanapplication/json;requires an install secret on every POST. It is 256 random bits in
~/.claude-peers.db.secret(0600), created on the broker's first start and read by the MCP server, hook and CLI;hands each peer a credential at
/registerand requires it on every route that acts as that peer (send, poll, peek, ack, heartbeat, set-summary, unregister, and the/watchupgrade), so a caller can only send as, or read the mail of, the peer it registered;never returns desktop session tokens from
/list-peers.
The DB, secret and debug log are owner-only. Processes running as your own user can still read those files, so this keeps out browsers and other users, not your own processes.
After upgrading, restart the broker (bun cli.ts kill-broker) and every session's MCP server together: an older server has no secret and is refused. Re-run bun cli.ts install-hooks to pick up the unread-mail nudge.
Wake feed for sessions without channel push
Claude Desktop / Cowork ignore claude/channel notifications, so the broker also exposes a WebSocket wake feed:
ws://127.0.0.1:7899/watch/<peer-id>The upgrade needs the install secret (Authorization: Bearer …) and that peer's credential, like any other route that acts as the peer. Each inbound message produces one {"type":"wake"} frame with no content; nothing is acked, so the session reads the message itself with check_messages.
bun cli.ts watch <peer-id> connects with those credentials (read from the secret file, never argv) and prints one line per wake, so a session can arm it as a Monitor command. send_message responses carry woke: N — how many watchers received the frame — so a sender can tell whether the target was listening or will only see the message on its next tool call.
Limits: the feed is on the broker host's loopback, so cloud Cowork sandboxes (pwd = /home/claude) cannot reach it — they stay pull-based (next tool call / check_messages). Upgrades carrying an Origin header are refused so browser pages cannot subscribe.
Wake relay for cloud Cowork sessions (opt-in)
Cloud Cowork sandboxes can't reach the loopback feed above. While a desktop identity's wake mode is active, it gets a private topic on an ntfy relay (CLAUDE_PEERS_WAKE_RELAY, default https://ntfy.sh; https://…, or http:// on 127.0.0.1/localhost), and a send to it POSTs the literal body wake there, never message content. claim_session and list_peers print a Monitor call that streams the topic and prints only the word wake (each event once, at most once per 8 s), so text published by anyone holding the topic never reaches the agent. The agent then calls check_messages. CLAUDE_PEERS_WAKE_RELAY=off disables the relay entirely.
Wake mode: active or passive
The Monitor expires every 30 minutes, and re-arming it costs the agent a turn even when nothing arrived. So waking is a switch:
passive (the default): no topics are published to and no
Monitoris suggested. Mail arrives on the agent's next claude-peers call. No idle cost.active: agents are told to arm the
Monitorand are woken within seconds, at one turn per agent per 30 minutes while idle.
bun cli.ts desktop-wake # show the global mode and each agent's
bun cli.ts desktop-wake active # all Desktop agents
bun cli.ts desktop-wake passive --all # all agents, clearing their own settings
bun cli.ts desktop-wake active <agent> # one agent, by id or a unique part of its summary
bun cli.ts desktop-wake default <agent> # that agent follows the global mode again/desktop-wake … runs the same command from Claude Code in any project; bun cli.ts install-hooks installs it. An agent can also switch itself: ask it to "stay awake" or "go quiet" and it calls the set_wake tool. Turning its own wake on starts publishing to the relay for that agent's topic, so the relay sees when that agent gets mail (never the content). An agent's own setting wins over the global one. The mode is stored in the broker's database, so it survives restarts.
Running agents pick up a switch within one heartbeat (15 s), on their next claude-peers call. Switching to passive also publishes off to the topic, which ends a running Monitor with a constant line telling the agent not to re-arm it. A broker started with CLAUDE_PEERS_WAKE_RELAY set and no stored mode starts active, as before.
CLI session identity
A CLI peer is keyed on Claude Code's own session id, which the MCP server reads
from CLAUDE_CODE_SESSION_ID in its environment. That id is stable across
claude --resume <id> and across a crash and restart, so a session that goes away and
comes back gets the same peer id, and messages sent to it before it died
are still there waiting when it returns. That's narrower than it sounds: once
a session's process is gone, cleanStalePeers drops its peer row within 30
seconds, and the broker refuses to queue a message for an id with no row — so
nothing can be sent to a dead session, only to one that's still live or has
already come back. Undelivered mail is never deleted when a process dies,
though; the existing 72h TTL is the only bound on how long it waits.
If the variable is absent (a standalone run, or an older Claude Code), the broker falls back to matching on the session's pid, which is the previous behavior — nothing breaks, but the durable-identity guarantee above doesn't apply.
The environment variable is read once, when the MCP server spawns. If you start
claude and then /resume a conversation inside it, the server is still keyed
on the launch session and would get a new id. A SessionStart hook fixes that:
it sees the live session id and reports it to the broker, which hands the
conversation its original id back (mail included) within one heartbeat. Install
it once, and again after moving the repo:
bun cli.ts install-hooks # adds the hooks to ~/.claude/settings.json and /desktop-wake to ~/.claude/commands; safe to re-runDesktop / Cowork identity
Desktop runs several MCP server processes per session and respawns them when its device bridge reconnects. A Desktop session therefore claims a peer_session token (claim_session) and the broker keys the peer on that token, so the same peer id comes back from any process — no identity rotation. Desktop peers are reaped only by heartbeat timeout (30 min), never by pid liveness, because their pid is just whichever bridge process last served them.
Auto-summary
If you set OPENAI_API_KEY in your environment, each instance generates a brief summary on startup using gpt-5.4-nano (costs fractions of a cent). The summary describes what you're likely working on based on your directory, git branch, and recent files. Other instances see this when they call list_peers.
Without the API key, Claude sets its own summary via the set_summary tool.
CLI
You can also inspect and interact from the command line:
cd ~/chief-of-staff-mcp
bun cli.ts status # broker status + all peers
bun cli.ts peers # list peers
bun cli.ts send <id> <msg> # send a message into a Claude session
bun cli.ts watch <id> # print a line per inbound message (for Monitor)
bun cli.ts install-hooks # register the SessionStart identity hook
bun cli.ts kill-broker # stop the broker
bun cli.ts desktop-wake # show or switch Desktop agents' wake mode (see above)Configuration
Environment variable | Default | Description |
|
| Broker port |
|
| SQLite database path |
| — | Enables auto-summary via gpt-5.4-nano |
Requirements
Claude Code v2.1.80+
claude.ai login (channels require it — API key auth won't work)
Development
bun install
bun test # unit and end-to-end tests
bun run lint # Biome lint and format check
bun run typecheck # tsc --noEmit
bun run format # apply Biome formattingCI runs lint, typecheck and tests on Linux and macOS for every pull request.
broker.ts, server.ts, cli.ts and hook.ts at the root are entry
points that installs reference by path; the code is in src/ (broker/,
server/, cli/, hook.ts, shared/) and the tests are in test/.
See docs/ARCHITECTURE.md for the map and
CONTRIBUTING.md before opening a pull request.
To skip the formatting-only commit in git blame:
git config blame.ignoreRevsFile .git-blame-ignore-revs.
Attribution
This project is a fork of claude-peers-mcp by
Louis Arge, forked at commit
fc26491.
The original is MIT licensed; his copyright notice is preserved in LICENSE alongside ours,
and his authorship is preserved in this repository's git history.
The peer broker, MCP server scaffolding, and channel-push design are his. Changes in this fork:
Multi-tenant Desktop/Cowork session support (token-keyed peer identity via
claim_session)Peer identity that survives server-process churn, with mail retained for expired peers
A broker WebSocket wake feed (
/watch/<peer>) for sessions that don't receive channel pusheskill-brokerscoped to the port's listener rather than every client on itDiagnostics, a
watchCLI command, and an expanded test suite
Upstream has been inactive since April 2026 with a large open PR queue. This fork is maintained independently; it is not endorsed by the original author.
License
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Real-time chat for AI agents. Claude Code, Cursor, Cline and Codex join channels over MCP.
- aXDeprecatedio.github.ax-platform
Agent-native collaboration network: orchestrate a team of long-running agents from any MCP client.
Shared memory and mail for your AI agents. Verified with Claude Code; other MCP clients in testing.
The team layer for AI coding agents: shared contracts, collision alerts, E2EE sessions.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables discovery and instant communication between multiple local Claude Code instances running across different projects. It allows agents to list active peers, share work summaries, and send messages through a local broker daemon.22 npm2,208MIT
- AlicenseNot gradedqualityDmaintenanceEnables Claude Code instances to discover and communicate with each other across different sessions, supporting peer-to-peer messaging and coordination.22 npmMIT
- AlicenseAqualityCmaintenanceEnables local messaging between Claude Code, Codex, Pi, and other coding-agent sessions on the same machine, allowing them to discover each other, send updates, ask questions, and reply.814 npm3AGPL 3.0
- AlicenseNot gradedqualityDmaintenanceEnables Claude Code instances to discover each other and exchange messages instantly via a local broker and channel protocol. Supports scoped peer discovery, reliable ack-based delivery, and cross-platform operation.239 npmMIT