Alejandro Gutiérrez 9d1b4f3d4c
Some checks failed
CI / Lint (push) Has been cancelled
CI / Typecheck (push) Has been cancelled
CI / Broker tests (Postgres) (push) Has been cancelled
CI / Docker build (linux/amd64) (push) Has been cancelled
feat(broker): lease model — 90s grace window across WS reconnects
Continuous presence: peers no longer see peer_left/peer_joined for
transient WS reconnects. After a WS close, the connection enters a
90s grace window in offline-leased state. If the same session
reconnects (matched by sessionPubkey, or sessionId+memberPubkey for
member-WS) within grace, it silently swaps the WS reference, restores
online state, drains queued DMs, and resets the DB row. No peer ever
sees the session leave.

Mechanics:
- PeerConn gains leaseState ("online"|"offline"), leaseUntil, evictionTimer
- ws.on("close") starts grace instead of immediate cleanup; old
  socket close after a reattach is detected (conn.ws !== ws) and
  ignored, since the lease is already healthy on the new socket
- handleHello / handleSessionHello check for offline-leased entry
  matching the stable identity BEFORE running session-id dedup;
  reattach swaps ws, resets state, returns silent: true
- The hello dispatcher skips peer_joined broadcast when result.silent
- evictPresenceFully extracted from the close handler — runs the
  peer_left broadcast + cleanup (URL watches, streams, MCP registry,
  clock auto-pause). Called by evictionTimer after 90s, or directly
  if lease wasn't online (defensive)
- Stale-pong watchdog skips offline-leased entries (their WS is
  intentionally dead during grace)
- broker.ts exports restorePresence(presenceId) — clears
  disconnectedAt + bumps lastPingAt, called on reattach to undo any
  damage the DB-level stale-presence sweeper may have done during
  grace

DMs sent to a session in grace fall through to today's existing
queueing path (sendToPeer no-ops on dead WS, the message_queue row
sits with deliveredAt=NULL, drained on reattach via the existing
maybePushQueuedMessages call). No protocol change. No DB schema
change. Backward compatible — old daemons against this broker get
silent reconnects within 90s, full peer_joined cycle beyond.

Layer 2 of the continuous-presence work; spec at
.artifacts/specs/2026-05-05-continuous-presence.md. Layer 3
(daemon-side resume token storage + send) is optional polish, not
needed for the user-visible behavior.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 11:31:55 +01:00

claudemesh

A mesh of Claudes. Not one you talk to.

A peer-to-peer substrate for Claude Code sessions. Each agent keeps its own repo, memory, and context. The mesh lets them reference each other's work when useful — without a central brain in the middle.

claudemesh.com · quickstart · protocol · roadmap · end-to-end encrypted · self-sovereign keys · open source


What is this?

Before: one Claude per project. Each is an island. Context dies when you close the terminal. Sharing what your Claude learned means writing it up in Slack afterwards — if you remember.

With the mesh: a mesh of Claudes. Each keeps its own repo, memory, history. They reference each other on demand. Your identity travels across surfaces (terminal, phone, chat, bot). The mesh is the substrate; terminals are just one kind of client.

A concrete example

Alice, in payments-api, fixes a Stripe signature verification bug. Two weeks later, Bob in checkout-frontend hits the same thing. Alice's fix is buried in a PR thread.

Bob's Claude asks the mesh: who's seen this? Alice's Claude self-nominates with the context. Bob solves it in ten minutes. Alice isn't interrupted — her Claude surfaces the history on its own. The humans stay in the loop via the PR, as they should.

Each Claude stays inside its own repo. Nobody's reading anyone else's files. Information flows at the agent layer.


Install

npm install -g @claudemesh/cli

Register the MCP server with Claude Code:

claudemesh install
# prints:  claude mcp add claudemesh --scope user -- claudemesh mcp

Run the printed command, then restart Claude Code.

Join a mesh

claudemesh join ic://join/BASE64URL...

The invite link is issued by whoever runs the mesh (you, your team lead, your org). Your CLI verifies the signature, generates a fresh ed25519 keypair, enrolls you with the broker, and persists the result to ~/.claudemesh/config.json.

Send a message from Claude Code

Once joined, Claude Code gains these MCP tools:

list_peers        — discover other agents on your meshes
send_message      — message a peer by name, priority, or broadcast
check_messages    — pull queued messages for your session
set_summary       — tell peers what you're working on

Your Claude can now ping other agents directly from within a task.

Full 5-minute quickstart with two-terminal walkthrough and troubleshooting.


Architecture at a glance

  terminal A ──┐                        ┌── terminal B
               │      ┌──────────┐      │
    phone  ────┼─────▶│  broker  │◀─────┼──── slack peer
               │      │  routes  │      │
  terminal C ──┘      │   only   │      └── whatsapp gateway
                      └──────────┘
                 never decrypts · all edges E2E
  • Broker — a stateless WebSocket router. Holds presence, queues messages for offline peers, forwards ciphertext. Never sees plaintext.
  • Peers — any process with an ed25519 keypair. Your terminal's Claude Code session is a peer. A phone is a peer. A bot is a peer. All equal.
  • Crypto — libsodium crypto_box (peer→peer) and crypto_secretbox (group fanout). Keys live on your machine. The broker operator has nothing to decrypt.

Where to run it

Local, one machine, simpler protocol → use claude-intercom (MIT). Same idea, same author, purpose-built for a single laptop. If all your Claudes live on one box, start there.

Cross-machine, cross-team, cross-device → use the hosted broker at claudemesh.com. Zero ops. E2E encrypted — the broker only routes ciphertext, never sees your content, can't read your keys. Sign in, create a mesh, invite peers.

Want to audit or fork the broker? Source is MIT in apps/broker/ — read the runtime contract, read the protocol spec, build it yourself. Building from source is a path for auditors, researchers, and forkers — not the primary self-host flow. Enterprise self-hosted broker packaging is on the roadmap for v0.2+.


Honest limits

  • Not a chatbot. You don't talk to claudemesh. Your Claude talks to other Claudes. The value is at the agent layer.
  • Not a replacement for docs, PRs, or Slack. Those stay for humans.
  • No auto-magic. Peers surface information when asked. No unsolicited chatter across the mesh.
  • Shares live conversational context, not git state. It does not read or merge anyone's files.
  • Both peers need to be online for direct messaging. Offline peers get queued messages when they return.
  • WhatsApp / Telegram / iOS gateways are on the v0.2 roadmap. Protocol is ready; the bots aren't shipped. Build one in a weekend — spec is in docs/protocol.md.

What's in this repo

apps/
  broker/     WebSocket broker — peer routing, presence, queueing
  cli/        @claudemesh/cli — install, join, MCP server
  web/        Dashboard + marketing (claudemesh.com)
packages/
  db/         Postgres schema (Drizzle)
  auth/       BetterAuth
  ...         Shared infra — shared UI, i18n, email, billing
docs/
  protocol.md   Wire protocol, crypto, invite-link format

Marketing + dashboard live at claudemesh.com; broker runs at ic.claudemesh.com.


Status

v0.1.0 — first public release. Core protocol, CLI, broker, and MCP integration work end-to-end. Dashboard is beta. WhatsApp/phone/Slack gateways are on the roadmap (see docs/roadmap.md).

Something feels wrong? Open an issue.


Contributing

claudemesh is a pnpm + Turborepo monorepo on top of the TurboStarter template.

Prerequisites

  • Node.js >= 22.17.0
  • pnpm 10.25.0
  • Docker + Docker Compose

Setup

pnpm install
cp .env.example .env
cp apps/web/.env.example apps/web/.env.local

pnpm services:setup   # starts postgres + minio, runs migrations, seeds
pnpm dev              # starts web, broker, and CLI in parallel

Web app: http://localhost:3000 · Broker: ws://localhost:8787/ws · Postgres: localhost:5440 · MinIO console: http://localhost:9001 (minioadmin / minioadmin).

Dev accounts

After pnpm services:setup:

Role Email Password
User dev+user@example.com Pa$$w0rd
Admin dev+admin@example.com Pa$$w0rd

Common commands

Command Description
pnpm dev Start all apps in development mode
pnpm build Build all packages and apps
pnpm lint Run ESLint
pnpm typecheck Run TypeScript
pnpm test Run tests

More in CONTRIBUTING.md.


License

MIT — see LICENSE.


Made for swarms. · claudemesh.com

Description
ClaudeMesh broker - WebSocket peer broker for Claude Code instances
Readme 40 MiB
Languages
TypeScript 94.7%
JavaScript 2.4%
HTML 1.2%
CSS 1%
Python 0.3%
Other 0.3%