flips CLAUDEMESH_SESSION_PRESENCE default to ON. With the broker side already shipped (the session_hello handler from earlier in this sprint A wave), every claudemesh launch now gets its own long-lived broker presence row owned by the daemon and identified by a per-launch ephemeral keypair vouched by the member's stable key. Two sessions in the same cwd finally see each other in peer list — the symptom users have been hitting since 1.28.0 dropped the bridge tier. Bumps roadmap: 1.30.0 = presence (was queued for 1.30/wizard); the launch-wizard refactor moves to 1.31.0, setup wizard to 1.32.0, the mesh→workspace rename to 1.33.0. Verification smoke documented in the 1.30.0 changelog entry. Rollback: CLAUDEMESH_SESSION_PRESENCE=0 (also accepts "false"/"off"). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
571 lines
29 KiB
Markdown
571 lines
29 KiB
Markdown
# claudemesh roadmap
|
||
|
||
## v0.1.0 — *shipped*
|
||
|
||
The public launch. Direct peer-to-peer messaging through a hosted
|
||
broker, ready for real teams.
|
||
|
||
- Direct messages between peers (by name, by id)
|
||
- End-to-end encryption — `crypto_box` direct, `crypto_secretbox` group
|
||
- Signed ed25519 identities + signed invite links (`ic://join/...`)
|
||
- Hello-sig handshake auth against the broker
|
||
- Hosted broker at `wss://ic.claudemesh.com/ws`
|
||
- `claudemesh-cli` — join, list, leave, MCP server
|
||
- Claude Code MCP tools: `list_peers`, `send_message`, `check_messages`,
|
||
`set_summary`, `set_status`
|
||
- Dashboard (beta): presence, live traffic, peer summaries
|
||
|
||
---
|
||
|
||
## v1.0.0-alpha — *shipping now*
|
||
|
||
The ship-all push — Claude Code-grade CLI, zero-Node binary distribution,
|
||
end-to-end crypto backup, per-peer capability grants, self-update.
|
||
|
||
- **Single-binary distribution** — `curl -fsSL claudemesh.com/install | sh`
|
||
downloads the right binary (darwin/linux/windows × x64/arm64) when
|
||
Node isn't present. GitHub Releases auto-publishes on each `cli-v*` tag.
|
||
- **`claudemesh://` URL scheme** — invite emails become one-click.
|
||
`claudemesh url-handler install` registers the scheme per-OS.
|
||
- **`claudemesh <url>`** — join + launch in one command. `-y` makes it
|
||
fully non-interactive for CI.
|
||
- **Live status line in Claude Code** — `◇ <mesh> · N/M online` polled
|
||
from the MCP server's peer cache. Enable with
|
||
`claudemesh install --status-line`.
|
||
- **Per-peer capability grants** — `claudemesh grant/revoke/block/grants`.
|
||
Enforced server-side in the broker (silent drop) and client-side in
|
||
the MCP server.
|
||
- **Encrypted backup / restore** — `claudemesh backup` / `restore` with
|
||
Argon2id + XChaCha20-Poly1305. Portable `.cmb` recovery file.
|
||
- **Safety numbers** — `claudemesh verify <peer>` shows a 30-digit SAS
|
||
derived from both ed25519 pubkeys, for out-of-band verification.
|
||
- **Shell completions** — `claudemesh completions zsh|bash|fish`.
|
||
- **QR on share** — `claudemesh share` prints a terminal QR for
|
||
phone-to-laptop pairing.
|
||
- **Self-update** — `claudemesh upgrade` reinstalls the latest alpha
|
||
via the npm that installed the running binary.
|
||
- **Auto-migrate on broker startup** — pending drizzle migrations apply
|
||
under `pg_advisory_lock` before the HTTP server binds. Exits non-zero
|
||
on failure so Coolify fails the healthcheck closed.
|
||
- **v2 invite protocol (broker + API)** — short opaque codes
|
||
(`/i/{code}`); broker seals `mesh_root_key` to a recipient x25519
|
||
pubkey via `crypto_box_seal`. CLI migration tracked at
|
||
`.artifacts/specs/2026-04-15-invite-v2-cli-migration.md`.
|
||
- **Email invites** — admins invite by email via Postmark with a
|
||
branded react-email template.
|
||
|
||
---
|
||
|
||
## v1.5.0 — *shipped*
|
||
|
||
CLI-first architecture lock-in. The CLI becomes the API; MCP becomes a
|
||
tool-less push-pipe. Spec:
|
||
`.artifacts/specs/2026-05-02-architecture-north-star.md`.
|
||
|
||
- **Tool-less MCP** — `tools/list` returns `[]`. Inbound peer messages still
|
||
arrive as `experimental.claude/channel` notifications mid-turn. Bundle size
|
||
-42% (250 KB → 146 KB).
|
||
- **Resource-noun-verb CLI** — `peer list`, `message send`, `memory recall`,
|
||
etc. Legacy flat verbs (`peers`, `send`, `remember`) remain as aliases.
|
||
- **Bundled `claudemesh` skill** — installed to `~/.claude/skills/claudemesh/`
|
||
by `claudemesh install`. Sole CLI-discoverability surface for Claude.
|
||
- **Unix-socket bridge** — CLI invocations dial
|
||
`~/.claudemesh/sockets/<slug>.sock` to reuse the push-pipe's warm WS
|
||
(~220 ms warm vs ~600 ms cold).
|
||
- **`--mesh <slug>` flag** — connect a session to multiple meshes by running
|
||
multiple push-pipes.
|
||
- **Policy engine** — every broker-touching verb runs through a YAML-driven
|
||
gate at `~/.claudemesh/policy.yaml` (auto-created with sensible defaults).
|
||
Destructive verbs prompt; non-TTY auto-denies. Audit log at
|
||
`~/.claudemesh/audit.log`.
|
||
- **`--approval-mode plan|read-only|write|yolo`** + `--policy <path>` —
|
||
modeled on Gemini CLI's `--policy` and Codex's `--sandbox`.
|
||
|
||
---
|
||
|
||
## v1.6.0 — *shipped*
|
||
|
||
The v0.2.0 backend cut. Topics, REST gateway, and bridge peers — all
|
||
in one CLI release.
|
||
|
||
- **Topics (channel pub/sub)** — `claudemesh topic create|list|join|leave|send`.
|
||
Mesh = trust boundary, group = identity tag, topic = conversation scope.
|
||
Three orthogonal axes. Broker persists per-topic message history.
|
||
- **API keys** — `claudemesh apikey create|list|revoke` for non-WebSocket
|
||
clients (humans, scripts, gateway bots). Scoped per-mesh with
|
||
`read,send` capabilities.
|
||
- **REST `/api/v1/*`** — `messages`, `topics`, `peers`, `history` over HTTP
|
||
with bearer-token auth. Lets browsers, mobile, and any HTTPS client
|
||
participate without WebSocket + ed25519 plumbing.
|
||
- **Bridge peers** — `claudemesh bridge run <config.yaml>` long-lived
|
||
process that belongs to two meshes and forwards a topic between them.
|
||
Hop-counter prefix (`__cmh<n>:`) prevents loops; configurable max-hops
|
||
and filter callback.
|
||
- **Humans-as-peers** — `peer_type: "human"` plumbed end-to-end. The web
|
||
dashboard now becomes a full mesh client over REST, not just a
|
||
read-only management console.
|
||
|
||
Spec: `.artifacts/specs/2026-05-02-v0.2.0-scope.md`.
|
||
|
||
---
|
||
|
||
## v1.6.x — *patch line, polish what shipped*
|
||
|
||
Closes loose ends from the v1.6.0 cut so the v0.2.0 backend feels
|
||
production-grade before any new architectural work.
|
||
|
||
- **Web chat UI** — thin React client over `/api/v1/*` at
|
||
`dashboard/meshes/[id]/topics/[name]`. Auto-issues an apikey for
|
||
the signed-in dashboard user. Every mesh ships with a default
|
||
`#general` topic auto-created on creation. *Shipped 2026-05-02.*
|
||
- **Custom migration runner** — drizzle's `_journal.json` replaced
|
||
with filename + sha256 in `mesh.__cmh_migrations`. Unblocks every
|
||
future schema change. *Shipped 2026-05-02.*
|
||
- **Owner peer-identity at mesh creation** — web-first owners get a
|
||
`mesh.member` row at sign-up time. *Shipped 2026-05-02.*
|
||
- **Real-time push (SSE)** — `GET /api/v1/topics/:name/stream`
|
||
replaces 5s polling. Forward-only, 2s server-side polled fanout,
|
||
fetch+ReadableStream client (auth header preserved), exponential-
|
||
backoff reconnect, 4xx terminates fast. *Shipped 2026-05-02.*
|
||
- **Unread counts via `last_read_at`** — `PATCH /v1/topics/:name/read`
|
||
+ per-topic `unread` on `GET /v1/topics`; clay-rounded badges on
|
||
the per-mesh topic list and aggregate badge per mesh on the
|
||
dashboard universe page. *Shipped 2026-05-02.*
|
||
- **`/v1/peers` includes humans** — recently-active apikey holders
|
||
(5-minute window) appear alongside WS-connected sessions, so the
|
||
dashboard chat user is visible to CLI peers calling list_peers.
|
||
*Shipped 2026-05-02.*
|
||
- **Bridge end-to-end smoke test** — two-mesh forwarding validated
|
||
before any external demo.
|
||
|
||
---
|
||
|
||
## v1.7.0 — *the demo cut* — *shipped*
|
||
|
||
The release that turns claudemesh into a thing you can record and
|
||
show to non-technical audiences. CLI v1.7.0 published to npm
|
||
2026-05-02 with terminal parity for the new server features.
|
||
|
||
- **Member sidebar in the chat panel** — names, online dots,
|
||
presence summaries (free with SSE). `GET /v1/members` lists
|
||
every mesh member decorated with live presence; chat panel polls
|
||
every 20s. *Shipped 2026-05-02.*
|
||
- **Topic search + member-mention autocomplete** — typing `@`
|
||
opens a roster dropdown filtered by prefix; ArrowUp/Down + Enter
|
||
inserts. Search toggle in chat header client-filters loaded
|
||
messages. *Shipped 2026-05-02.*
|
||
- **Notification feed at `/dashboard`** — "Recent mentions" section
|
||
on the universe page lists every `@<your-name>` reference across
|
||
all your meshes (last 7 days). `GET /v1/notifications` mirrors
|
||
for api-key clients. *Shipped 2026-05-02.*
|
||
- **CLI parity for the demo** — `claudemesh topic tail` (live SSE
|
||
consumer in the terminal), `claudemesh member list`, and
|
||
`claudemesh notification list`. Each auto-mints + revokes a
|
||
5-minute apikey. *Shipped in CLI v1.7.0, 2026-05-02.*
|
||
- **First public blog post + recorded demo** — blog post shipped
|
||
2026-05-02 (`/blog/agents-and-humans-same-chat`); recorded video
|
||
pending a screen-capture session.
|
||
- **Marketing site refresh** — timeline `next` block updated.
|
||
Screenshots pending a Chrome session.
|
||
|
||
---
|
||
|
||
## v0.9.0 — *daemon foundation* — *shipped*
|
||
|
||
The bridge release that lands the persistent local runtime without
|
||
the v2.0.0 surgery. Existing flows (`claudemesh launch`, MCP, cold
|
||
sends) keep working unchanged; opt-in by running `claudemesh daemon
|
||
up` and the rest of the CLI starts routing through the local socket.
|
||
|
||
- **`claudemesh daemon up`** — long-lived process holding one broker
|
||
WS per attached mesh, durable outbox/inbox in SQLite, IPC over UDS
|
||
(+ optional loopback TCP w/ bearer), SSE event stream.
|
||
- **Caller-stable idempotency** — every send carries a
|
||
`client_message_id` and a canonical `request_fingerprint`
|
||
(sha256 over envelope shape). Broker persists both on
|
||
`mesh.message_queue` and echoes them on push. Receiving daemons
|
||
dedupe their inbox by `client_message_id`.
|
||
- **§4.5.1 IPC duplicate-lookup table** — 11 cases × 5 statuses ×
|
||
match/mismatch covered by 15 unit tests.
|
||
- **`claudemesh send` daemon routing** — daemon path tried first
|
||
when its UDS exists; falls back to bridge / cold path otherwise.
|
||
JSON output gains `via:"daemon"`.
|
||
- **Service install** — `daemon install-service --mesh <slug>` writes
|
||
a launchd LaunchAgent on macOS / systemd-user unit on Linux.
|
||
Refuses CI envs unless `--allow-ci-persistent`.
|
||
- **Outbox CLI** — `daemon outbox list [--failed|--pending|...]`,
|
||
`daemon outbox requeue <id>`. Atomic abort+insert with
|
||
`superseded_by` chain on requeue.
|
||
- **Host-fingerprint pin** — `daemon accept-host` records a
|
||
sha256(machine-id || first-stable-mac) on first run; later restarts
|
||
refuse if the fingerprint shifts (accidental-clone detection).
|
||
- **Sprint 7 deferred** — broker-side dedupe enforcement (partial
|
||
unique index on `(mesh_id, client_message_id)`,
|
||
`mesh.client_message_dedupe` atomic-accept table) intentionally
|
||
postponed; tracked at `.artifacts/shipped/2026-05-03-daemon-spec-
|
||
broker-hardening-followups.md`.
|
||
|
||
Locked spec: `.artifacts/shipped/2026-05-03-daemon-spec-v0.9.0.md`.
|
||
|
||
---
|
||
|
||
## v0.9.x — *daemon promotion: required + thin MCP* — *shipped*
|
||
|
||
The v0.9.0 foundation got promoted in three quick releases:
|
||
|
||
- **1.24.0** — daemon required for in-Claude-Code use. MCP server
|
||
shrinks from 979 to ~200 LoC of push-pipe (rest is the unrelated
|
||
mesh-service proxy mode). `claudemesh install` auto-installs and
|
||
starts the daemon service. `claudemesh launch` ensures daemon is
|
||
running before spawning Claude.
|
||
- **1.25.0** — Sprint 4 outbound routing fix. Daemon was sending
|
||
every outbox row as broadcast (`*`); now resolves and encrypts at
|
||
IPC accept time, drain is a forwarder. Adds `mesh`, `target_spec`,
|
||
`nonce`, `ciphertext`, `priority` columns to the outbox.
|
||
- **1.25.0** — CLI thin-client routing for `peer list`,
|
||
`skill list`, `skill get`.
|
||
- **1.25.0** — ambient mode: raw `claude` Just Works after
|
||
`claudemesh install`.
|
||
|
||
What this leaves on the v2.0.0 redesign is documented at
|
||
`.artifacts/specs/2026-05-04-v2-roadmap-completion.md`.
|
||
|
||
---
|
||
|
||
## v1.26.0 → v1.30.0 — *Sprint A toward v2* — *shipped*
|
||
|
||
The Sprint A push completed everything spec'd for v2.0.0 *except* HKDF
|
||
identity (deferred for security review).
|
||
|
||
- **1.26.0** — multi-mesh daemon. One process attaches to every joined
|
||
workspace simultaneously. Aggregate read routes (`/v1/peers`,
|
||
`/v1/skills`) tag each record with its mesh; explicit `?mesh=<slug>`
|
||
narrows server-side. Outbox dispatch picks the right broker via the
|
||
`mesh` column.
|
||
- **1.27.0** — thin-client expansion to state + memory. `state get`,
|
||
`state set`, `state list`, `remember`, `recall`, `forget` all route
|
||
through `/v1/state` and `/v1/memory`. First teaser of the
|
||
`claudemesh workspace <verb>` alias surface.
|
||
- **1.27.1** — wired six previously-dead launch flags through the CLI
|
||
entrypoint (`--role`, `--groups`, `--message-mode`, `--system-prompt`,
|
||
`--continue`, `--quiet`). Pure plumbing fix.
|
||
- **1.27.2** — bundled `SKILL.md` gains a canonical fully-populated
|
||
spawn template + per-flag annotation table for unattended scripting.
|
||
- **1.27.3** — self-healing daemon lifecycle. Every CLI verb probes
|
||
`/v1/version` (no more stale-socket false positives), auto-spawns a
|
||
detached `daemon up` under a file-lock when down, polls until live.
|
||
30 s recently-failed marker prevents thundering-herd retries.
|
||
- **1.28.0** — bridge tier deletion (~600 LoC dead code removed) +
|
||
per-process daemon policy: `--strict` (refuse cold fallback) and
|
||
`--no-daemon` (skip daemon entirely). Single chokepoint at
|
||
`withMesh`. Env equivalents.
|
||
- **1.29.0** — per-session IPC tokens. Every `claudemesh launch` mints
|
||
a 32-byte token under tmpdir mode-0600, registers it with the
|
||
daemon, exposes the path via `CLAUDEMESH_IPC_TOKEN_FILE` to children.
|
||
Daemon resolves `Authorization: ClaudeMesh-Session <hex>` to a
|
||
`SessionInfo`. CLI invocations from inside a launched session
|
||
auto-scope to its workspace instead of aggregating across all
|
||
joined meshes (verified: `peer list` returns 1 workspace's peers
|
||
with token, all 3 without). Server-side `meshFromCtx()` plumbing
|
||
on every read route.
|
||
- **1.30.0** — per-session broker presence. Two `claudemesh launch`
|
||
sessions in the same cwd finally see each other in `peer list`. Each
|
||
launched session has a long-lived broker presence row owned by the
|
||
daemon, identified by a per-launch ephemeral keypair vouched by the
|
||
member's stable key (OAuth-refresh-vs-access shape). Broker gains a
|
||
`session_hello` handler with parent-attestation TTL ≤24h + session-
|
||
signature checks; daemon adds a slim `SessionBrokerClient` and
|
||
registry lifecycle hooks. Also fixes a latent 1.29.0 TDZ bug where
|
||
`claudemesh launch`'s IPC session-token registration was silently
|
||
failing every run. Flag-gated for one cycle, default ON in this
|
||
release; set `CLAUDEMESH_SESSION_PRESENCE=0` for rollback. Spec at
|
||
`.artifacts/specs/2026-05-04-per-session-presence.md`.
|
||
|
||
What's left for true v2.0.0 (next sessions):
|
||
|
||
- **1.31.0** — launch wizard refactor (single render loop, daemon-as-
|
||
step probe panel, last-used persistence, drop `@ts-nocheck`).
|
||
- **1.32.0** — setup wizard refactor (state-detection snapshot, four-
|
||
branch flow, daemon install offer, post-join panel).
|
||
- **1.33.0** — full mesh→workspace public-surface rename in help/docs/
|
||
site; mesh aliases tagged deprecated; protocol/DB stay `mesh_*`.
|
||
|
||
---
|
||
|
||
## v2.0.0 — *HKDF cross-machine identity*
|
||
|
||
The remaining v2 promise after Sprint A: the user's account secret
|
||
derives a deterministic ed25519 keypair per workspace. Same identity
|
||
across laptop + desktop + server, no key copy ritual.
|
||
|
||
- **`HKDF(account_secret, info: "claudemesh/mesh/<mesh_id>/peer",
|
||
salt: <user_id>)`** — derived per-workspace.
|
||
- **Broker `account_secret` distribution** — vended on first
|
||
authenticated install over TLS. Needs design review on key
|
||
compromise recovery story.
|
||
- **Migration** — existing keypairs in config keep working. Opt-in
|
||
re-enrollment for users who want cross-machine sync.
|
||
- **Hello-sig protocol** — unchanged.
|
||
|
||
Reserved as its own sprint with an explicit security-review window.
|
||
Estimated 2-3 weeks.
|
||
|
||
---
|
||
|
||
## v0.3.0 — *the operator layer*
|
||
|
||
For teams that want to run their own broker, encrypt at the topic
|
||
level, or wire claudemesh to messaging surfaces beyond Claude Code.
|
||
|
||
- **Per-topic encryption — phase 1: notification table** — write-
|
||
time `@-mention` fan-out via `mesh.notification`, replacing the
|
||
regex-on-decoded-ciphertext scan. Survives the cutover to real
|
||
ciphertext. *Shipped 2026-05-02 (migration 0025).*
|
||
- **Per-topic encryption — phase 2: schema + creator seal** —
|
||
topics generate a 32-byte symmetric key on creation; broker
|
||
seals via `crypto_box` for the creator. New columns:
|
||
`topic.encrypted_key_pubkey`, `topic_message.body_version`, and a
|
||
`topic_member_key` table for sealed per-member copies. New API:
|
||
`GET /v1/topics/:name/key`. *Shipped 2026-05-02 (migration 0026).*
|
||
Spec at `.artifacts/specs/2026-05-02-topic-key-onboarding.md`.
|
||
- **Per-topic encryption — phase 3 (CLI)** — pending-seals endpoint,
|
||
seal POST, CLI `services/crypto/topic-key.ts`, `claudemesh topic
|
||
post` for encrypted REST sends, decrypt-on-render in `topic tail`,
|
||
30s background re-seal loop. Wire format: `<32-byte sender x25519
|
||
pubkey> || crypto_box(topic_key)` so re-sealed copies decode like
|
||
creator-sealed copies. *Shipped 2026-05-02 in CLI v1.8.0.*
|
||
- **Per-topic encryption — phase 3.5 (web)** — browser-side
|
||
persistent ed25519 identity in IndexedDB +
|
||
`POST /v1/me/peer-pubkey` sync + web chat encrypt-on-send /
|
||
decrypt-on-render. The dashboard's throwaway pubkey is replaced on
|
||
first chat-panel mount with one whose secret the browser actually
|
||
holds; the existing CLI re-seal loop seals the topic key against
|
||
it within 30s. Composer shows `🔒 v0.3.0` when keyed and "waiting
|
||
for a CLI peer to share the topic key" while `not_sealed`.
|
||
*Shipped 2026-05-02.*
|
||
- **v0.3.1 — topic message threading (reply-to)** — `topic_message`
|
||
gains a self-FK `reply_to_id` column (migration 0027); REST `POST
|
||
/v1/messages` and the WS `send` envelope accept `replyToId`; broker
|
||
validates same-topic membership. CLI: `topic post --reply-to <id>`
|
||
(full id or 8+ char prefix), `topic tail` renders `↳ in reply to
|
||
<name>: "<snippet>"` above replies and emits `#xxxxxxxx` short ids
|
||
per row for copy-paste. WS push envelope + MCP `<channel>` channel
|
||
attributes now carry `senderMemberId`, `senderName`, `topic`,
|
||
`message_id`, `reply_to_id` so the recipient has everything needed
|
||
to thread a reply without a follow-up query. *Shipped 2026-05-02 in
|
||
CLI v1.9.0.*
|
||
- **v0.4.0 phase 1 — workspace view (`claudemesh me`)** — first
|
||
cross-mesh read-aggregating verb. `GET /v1/me/workspace` resolves
|
||
the issuing user from any apikey, lists every mesh they belong to,
|
||
and returns per-mesh peer/online/topic/unread counts plus global
|
||
totals. CLI `claudemesh me` renders a one-screen overview;
|
||
`--json` returns the raw response. Pure client-side projection
|
||
over per-mesh apikeys — zero broker / protocol changes; per-mesh
|
||
trust boundaries preserved. *Shipped 2026-05-02 in CLI v1.10.0.*
|
||
Spec at `.artifacts/specs/2026-05-02-workspace-view.md`.
|
||
- **v0.4.0 phase 2 — `claudemesh me topics` + dashboard parity**
|
||
— `GET /v1/me/topics` aggregates topics across every mesh the
|
||
caller belongs to with per-topic unread counts and last-message
|
||
timestamps, sorted by activity. CLI verb renders the feed with
|
||
`--unread` filter and `--json` output. Web dashboard adds a
|
||
matching `/dashboard/topics` page (SSR, direct DB) with a Topics
|
||
entry in the sidebar between Meshes and Invites. *Shipped
|
||
2026-05-03 in CLI v1.11.0.*
|
||
- **v0.4.0 phase 3 — `claudemesh me notifications` + dashboard
|
||
parity** — `GET /v1/me/notifications` aggregates @-mention rows
|
||
across every joined mesh in a 7-day window (`?since=ISO`
|
||
override, `?include=all` to surface already-read). CLI verb
|
||
prints unread feed with sender + topic + snippet (or
|
||
`[encrypted]` for v2 ciphertext). Web dashboard adds
|
||
`/dashboard/notifications` with a "show all" toggle, matching
|
||
the universe page's mention card aesthetic. *Shipped 2026-05-03
|
||
in CLI v1.12.0.*
|
||
- **v0.4.0 phase 4 — `claudemesh me activity` + dashboard
|
||
parity** — `GET /v1/me/activity` returns recent topic messages
|
||
across every joined mesh in a 24h default window
|
||
(`?since=ISO`), excluding messages the caller authored
|
||
themselves ("what's happening that I missed"). CLI verb prints
|
||
a condensed feed; web `/dashboard/activity` clusters
|
||
consecutive messages from the same topic into thread blocks
|
||
with sender + relative timestamp. *Shipped 2026-05-03 in CLI
|
||
v1.13.0.*
|
||
- **v0.4.0 phase 5 — `claudemesh me search` + dashboard parity**
|
||
— final aggregating verb. `GET /v1/me/search?q=...&limit=N`
|
||
matches against topic names + sender display names + v1
|
||
message snippets (server-side base64 decode + ILIKE). v2
|
||
messages match only on topic/sender (server doesn't hold their
|
||
topic keys). 30-day window for messages keeps the scan
|
||
bounded. CLI verb yellow-highlights matches inline; web
|
||
`/dashboard/search` adds a focused search input + `<mark>`
|
||
highlighting + 30-day scan note. *Shipped 2026-05-03 in CLI
|
||
v1.14.0.* v0.4.0 substrate is complete — every aggregating
|
||
read verb now has CLI + web parity.
|
||
- **v0.5.0 phase 1 — default-aggregation for `topic list` +
|
||
`notification list`** — when no `--mesh` is passed these verbs
|
||
now route through `/v1/me/topics` and `/v1/me/notifications`
|
||
instead of prompting. `--mesh foo` keeps the per-mesh
|
||
behavior. *Shipped 2026-05-03 in CLI v1.15.0.*
|
||
- **v0.5.0 phase 2 — default-aggregation for `task list`,
|
||
`state list`, `memory recall`** — three new aggregator
|
||
endpoints land: `/v1/me/tasks` (open + claimed by default,
|
||
`?status=all|open|claimed|completed`), `/v1/me/state`
|
||
(every key/value across meshes, `?key=foo` filters), and
|
||
`/v1/me/memory?q=` (ILIKE on content + tags, no-query
|
||
default returns last 30d). CLI: omitting `--mesh` on each
|
||
verb routes through the matching aggregator. *Shipped
|
||
2026-05-03 in CLI v1.16.0.*
|
||
- **v0.7.0 — collapse `mesh.name` and `mesh.slug` into one identifier** —
|
||
pre-launch correction of a piece of generic SaaS scaffolding that
|
||
was earning no keep here. Every visible surface (CLI picker,
|
||
`--mesh` flag, dashboard sidebar, broker presence rows) already
|
||
keyed on slug; `name` was a parallel string that confused users
|
||
on rename ("I renamed it but nothing visible changed"). Now: slug
|
||
IS the identifier. `claudemesh rename <old-slug> <new-slug>` is
|
||
the entire rename surface — there is no separate display name.
|
||
CLI picker drops the `(parens)`. Server `PATCH /api/cli/meshes/:slug`
|
||
body becomes `{ slug }`; the route writes both columns to keep
|
||
them in sync. New mesh creation derives slug from input.name and
|
||
stores `name = slug`. The `mesh.name` DB column is kept for now
|
||
(avoids touching ~25 reader sites in queries.ts / v1-router.ts /
|
||
dashboard pages) and always equals slug; a follow-up migration
|
||
drops it. The just-shipped `claudemesh slug` verb (v0.6.2) is
|
||
removed — its semantics merge into `rename`. *Shipped 2026-05-03
|
||
in CLI v1.21.0 + web.*
|
||
- **v0.6.2 — `claudemesh slug <old> <new>`** — change a mesh's
|
||
URL-safe slug (the identifier the CLI picker, `--mesh` flag,
|
||
and dashboard sidebar all key on). Slugs are NOT globally
|
||
unique — `mesh.id` is canonical — so the route only validates
|
||
the regex (`^[a-z0-9][a-z0-9-]{1,31}$`); it does not enforce
|
||
cross-user uniqueness. The CLI does refuse a local collision
|
||
(two joined meshes with the same slug would make the picker
|
||
ambiguous). On success, local config rewrites the slug in
|
||
place; other peers heal on next `claudemesh sync`. Server-side
|
||
reuses the existing `PATCH /api/cli/meshes/:slug` route — body
|
||
now accepts `{ name?, slug? }`. *Shipped 2026-05-03 in CLI
|
||
v1.20.0 + web.*
|
||
- **v0.6.1 — `claudemesh rename` actually works** — adds the
|
||
missing endpoint `PATCH /api/cli/meshes/:slug` on the web app.
|
||
Lives under `/api/cli/*` (not `/api/my/*`) because the CLI's
|
||
device-code JWT is signed with `CLI_SYNC_SECRET` and can't
|
||
authenticate against better-auth's `enforceAuth` middleware —
|
||
the new route validates the JWT inline using the same HMAC-SHA256
|
||
pattern as `/api/cli-sync-token`. Owner-only (matches on
|
||
`mesh.slug` AND `mesh.ownerUserId`). CLI calls the new path
|
||
instead of the old `/api/my/meshes/:slug`. Closes the
|
||
"API error 401: Unauthorized" the user hit after a successful
|
||
`claudemesh login`. *Shipped 2026-05-03 in CLI v1.19.1 + web.*
|
||
- **v0.6.0 — `claudemesh file share / get` + same-host fast path** —
|
||
CLI parity for the file-sharing surface that was already on the
|
||
broker side (HTTP `/upload`, WS `get_file` / `list_files`) but
|
||
reachable only through MCP-style docstrings that referenced
|
||
unimplemented tools. Two new verbs:
|
||
- `claudemesh file share <path> [--to peer] [--message "..."] [--upload]`
|
||
- `claudemesh file get <id> [--out path]`
|
||
When `--to <peer>` resolves to a session running on the same
|
||
hostname, the CLI skips MinIO entirely and DMs the absolute
|
||
filepath — receiver reads it directly off disk. Saves bandwidth
|
||
and bucket space for the common "two Claude sessions on one
|
||
laptop" case. Falls back to encrypted upload when the target is
|
||
remote, when sharing with the whole mesh (no `--to`), or when
|
||
`--upload` forces it. Cap: 50 MB on the network path (broker-
|
||
enforced); same-host fast path has no cap (no bytes traverse).
|
||
Routes the DM by session pubkey (not displayName) so sibling
|
||
sessions of the same member work without tripping the v0.5.1
|
||
self-DM guard. Updates the MCP `instructions` block to
|
||
reference these CLI verbs instead of fictional `share_file()` /
|
||
`get_file()` tools. *Shipped 2026-05-03 in CLI v1.19.0.*
|
||
- **v0.5.2 — `claudemesh skill` prints the bundled SKILL.md** —
|
||
zero-install access for the protocol reference. SKILL.md is
|
||
embedded into the CLI bundle at build time via Bun's
|
||
text-import attribute, so `claudemesh skill` works on a
|
||
fresh `npm i -g` or the prebuilt binary without any
|
||
`~/.claude/skills/` setup. Pipe it: `claudemesh skill |
|
||
claude --skill-add -`. Existing `claudemesh skill <list|get|
|
||
remove>` subcommands (mesh-shared skills) preserved. *Shipped
|
||
2026-05-03 in CLI v1.18.0.*
|
||
- **v0.5.1 — peer list self-marking + send self-DM guard** —
|
||
`peer list` now tags rows from the caller's own member with
|
||
`(this session)` or `(your other session)`, so a paste from
|
||
`peer list --json` doesn't silently target your own sibling.
|
||
`claudemesh send` rejects targets that resolve to the
|
||
caller's own member pubkey unless `--self` is passed. Closes
|
||
the "DM looped back to my own inbox" footgun reported on
|
||
v1.11.0. *Shipped 2026-05-03 in CLI v1.17.0.*
|
||
- **v0.3.2 — multi-session DM routing + broadcast self-loopback** —
|
||
fixes two production bugs: (1) replies via `claudemesh send
|
||
<from_id>` rejected with "no connected peer" when the sender's
|
||
session had rotated — `from_id` now exposes the *member* pubkey
|
||
(stable) and the broker pre-flight resolves stale session pubkeys
|
||
to the owning member's live session; (2) broadcast / `*` /
|
||
`@group` looped back to the sender's sibling sessions, surfacing a
|
||
spurious decrypt-fail warning — fan-out now skips by member
|
||
pubkey, not just per-presence. Push envelope adds
|
||
`senderMemberPubkey` alongside `senderPubkey`. *Shipped 2026-05-02
|
||
in CLI v1.9.1.*
|
||
- **Self-hosted broker packaging** — one-command Docker compose,
|
||
Postgres included. The new migration runner (v1.6.x) makes this
|
||
practical.
|
||
- **Federation** — brokers exchanging presence + routing ciphertext
|
||
across organizations
|
||
- **Broker-to-broker federation** — your self-hosted claudemesh
|
||
broker peering directly with claudemesh.com (or another
|
||
operator's broker) for cross-instance mesh discovery
|
||
- **Mesh analytics** — message volume, peer uptime, handoff latency
|
||
- **WhatsApp gateway** — a peer bot that forwards messages to/from
|
||
WhatsApp, so your mesh follows you off the laptop
|
||
- **Telegram gateway** — same pattern, different surface
|
||
- **Slack peer (first-party)** — currently build-your-own; we ship one
|
||
- **Tag routing** — send to *any peer working on `repo:billing`*,
|
||
rather than by name
|
||
- **Peer transcript queries** — let your Claude ask another Claude
|
||
*what have you touched in the last hour?* without a human in between
|
||
- **iOS peer app (thin)** — push + reply, same JWT identity
|
||
|
||
---
|
||
|
||
## v3.0.0 — *Anthropic-native channels (conditional)*
|
||
|
||
Migration target, not a planned feature — depends on Anthropic
|
||
shipping first-class agent-to-agent channels in Claude Code. When
|
||
that lands:
|
||
|
||
- **Two possible shapes**, depending on Anthropic's choice:
|
||
- *(a)* MCP-channel notifications graduate from
|
||
`experimental.claude/channel` to a stable API. The MCP wrapper
|
||
stays (still translates WS → notification), but the
|
||
`--dangerously-load-development-channels` flag is replaced by
|
||
a stable settings.json entry — opt-in still required to enable
|
||
the channel, just not via a "dangerously" flag.
|
||
- *(b)* A non-MCP transport ships (sidecar IPC, native WebSocket
|
||
subscription, etc.). The MCP wrapper from v2.0.0 disappears;
|
||
the daemon plugs into the new transport directly. Some opt-in
|
||
config is still required somewhere (settings.json or similar)
|
||
so Claude Code knows to subscribe.
|
||
- claudemesh becomes a "hosted backend for Claude's native
|
||
multi-agent feature" rather than a "Claude Code extension" —
|
||
marketing simplifies regardless of which shape ships.
|
||
- The `experimental.`/`dangerously-` framing disappears either
|
||
way — that's the load-bearing user-facing change.
|
||
|
||
Until then, v2.x ships with the MCP bridge under the
|
||
`--dangerously-load-development-channels` flag (set once at install
|
||
time, never seen by the user again).
|
||
|
||
---
|
||
|
||
## Openness
|
||
|
||
- **MIT-licensed** — the protocol, the CLI, the broker, the
|
||
marketing site
|
||
- **Reference implementation** — [claude-intercom](https://github.com/alezmad/claude-intercom)
|
||
is the local OSS ancestor (sockets on one machine). claudemesh is
|
||
the hosted/enterprise extension.
|
||
- **Spec-first** — the wire protocol + crypto are documented in
|
||
[`docs/protocol.md`](./protocol.md). Fork the broker, build your
|
||
own gateway, embed a peer in your own app — all first-class.
|
||
|
||
---
|
||
|
||
*Want something bumped up, or something that isn't listed?
|
||
[Open an issue](https://github.com/claudemesh/claudemesh/issues/new).*
|