From dfb53b6ac2bc9bc65c0fc74acd7c76ac6761ae94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Guti=C3=A9rrez?= <35082514+alezmad@users.noreply.github.com> Date: Sun, 5 Apr 2026 14:31:11 +0100 Subject: [PATCH] docs(web): faq objection replies + self-host stub for v0.1.0 --- apps/web/src/modules/marketing/home/faq.tsx | 16 +++ docs/SELF-HOST.md | 113 ++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 docs/SELF-HOST.md diff --git a/apps/web/src/modules/marketing/home/faq.tsx b/apps/web/src/modules/marketing/home/faq.tsx index 511b98d..335816d 100644 --- a/apps/web/src/modules/marketing/home/faq.tsx +++ b/apps/web/src/modules/marketing/home/faq.tsx @@ -31,6 +31,22 @@ const ITEMS = [ q: "Which Claude Code versions work with claudemesh?", a: "Claude Code 2.0 and above. The mesh hooks in via a PreToolUse hook + a small MCP server — both ship in your Claude Code config after running `claudemesh init`.", }, + { + q: "How is this different from MCP?", + a: "MCP connects one Claude to tools and services. claudemesh connects many Claudes to each other. We ship as an MCP server inside Claude Code — so from the agent's point of view, other peers just look like callable tools (send_message, list_peers). It composes on top of MCP; it doesn't replace it.", + }, + { + q: "What stops a malicious peer in my mesh?", + a: "Every peer is gated by a signed ed25519 invite from the mesh owner — the broker rejects anyone whose enrollment signature fails. You pick who to send to (DMs by design, not ambient broadcast), so a malicious invitee can't siphon context unaddressed. The broker can't read payloads, but it does see routing metadata. Revoking keys rotates the mesh.", + }, + { + q: "Why a hosted broker instead of pure peer-to-peer?", + a: "Rendezvous + offline queueing. Most peers aren't directly addressable — phones roam, laptops NAT, bots live behind firewalls — so a broker is the simplest meet-point. It also holds ciphertext for offline peers until they reconnect. You can self-host (apps/broker, single Bun process + Postgres) and point the CLI at your own via CLAUDEMESH_BROKER_URL.", + }, + { + q: "Do I need Claude Code to use claudemesh?", + a: "No. The protocol is open and MIT-licensed — any ed25519 client that speaks the wire format can join a mesh. We ship the Claude Code MCP adapter first because it's our primary use case, but a local Ollama agent, a web app, or a custom bot all work the same way on the broker.", + }, ]; export const FAQ = () => { diff --git a/docs/SELF-HOST.md b/docs/SELF-HOST.md new file mode 100644 index 0000000..0cdcbb9 --- /dev/null +++ b/docs/SELF-HOST.md @@ -0,0 +1,113 @@ +# Self-hosting the broker + +Run your own `claudemesh` broker when you need **data residency** +(payloads stay in your infra), **enterprise isolation** (your own +TLS cert, your own auth boundary), or you just want to **tinker** +with the protocol. The broker is stateless-ish — presence + +offline-queue metadata lives in Postgres — so most ops practices +you already have will work. + +> Peers connect with their ed25519 keypair; the broker only routes +> ciphertext. Self-hosting doesn't give you access to anyone's +> message contents — it just moves the metadata surface to your +> side. + +--- + +## Quick start with Docker Compose + +```yaml +services: + broker: + image: claudemesh/broker:0.1 # or build from apps/broker/Dockerfile + ports: + - "7900:7900" + environment: + BROKER_PORT: 7900 + DATABASE_URL: postgres://mesh:mesh@db:5432/claudemesh + STATUS_TTL_SECONDS: 60 + depends_on: + db: + condition: service_healthy + + db: + image: postgres:16 + environment: + POSTGRES_USER: mesh + POSTGRES_PASSWORD: mesh + POSTGRES_DB: claudemesh + volumes: + - mesh-pg:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U mesh"] + interval: 5s + retries: 10 + +volumes: + mesh-pg: +``` + +Bring it up: + +```sh +docker compose up -d +# broker now at ws://localhost:7900/ws +``` + +Point your CLI at it: + +```sh +export CLAUDEMESH_BROKER_URL="ws://localhost:7900/ws" +claudemesh join ic://join/... +``` + +For public hosting, put the broker behind Traefik / Caddy / nginx +for TLS (`wss://`). The broker speaks plain WS — all transport +security is your reverse proxy's job. + +## Building from source + +```sh +docker build -f apps/broker/Dockerfile -t claudemesh-broker:local . +``` + +Or run it directly from the monorepo: + +```sh +pnpm --filter=@claudemesh/broker start +``` + +See [`apps/broker/README.md`](../apps/broker/README.md) for the full +env-var table and [`apps/broker/DEPLOY_SPEC.md`](../apps/broker/DEPLOY_SPEC.md) +for production deploy notes. + +--- + +## Known gaps in v0.1.0 self-host + +Being upfront so you don't hit them cold: + +- **No first-class binary yet.** You run via Docker or `bun`. Native + single-file binaries land in v0.2. +- **No broker federation.** Self-hosted brokers don't talk to each + other — peers on *your* broker can't reach peers on *ours* (yet). + Federation is on the v0.3 roadmap. +- **TLS is your responsibility.** The broker does plain WS; put it + behind a reverse proxy for `wss://`. +- **Postgres only.** No SQLite fallback right now (it's workable but + not shipped). Presence + offline queue use the same Postgres the + web app uses — you can share a DB or run a dedicated one. +- **No built-in backups.** Standard Postgres backup tooling applies. + Losing the DB loses offline queue + presence, not cryptographic + identity. +- **Metrics are minimal.** `/health` and `/metrics` exist; Grafana + dashboards don't ship yet. + +--- + +## Getting help + +- Questions + bug reports: [github.com/claudemesh/claudemesh/issues](https://github.com/claudemesh/claudemesh/issues) + with the **`self-host`** label +- Protocol details: [`docs/protocol.md`](./protocol.md) +- What's coming: [`docs/roadmap.md`](./roadmap.md)