- apps/cli/ is now the canonical CLI (was apps/cli-v2/). - apps/cli/ legacy v0 archived as branch 'legacy-cli-archive' and tag 'cli-v0-legacy-final' before deletion; git history preserves it too. - .github/workflows/release-cli.yml paths updated. - pnpm-lock.yaml regenerated. Broker-side peer-grant enforcement (spec: 2026-04-15-per-peer-capabilities): - 0020_peer-grants.sql adds peer_grants jsonb + GIN index on mesh.member. - handleSend in broker fetches recipient grant maps once per send, drops messages silently when sender lacks the required capability. - POST /cli/mesh/:slug/grants to update from CLI; broker_messages_dropped_by_grant_total metric. - CLI grant/revoke/block now mirror to broker via syncToBroker. Auto-migrate on broker startup: - apps/broker/src/migrate.ts runs drizzle migrate with pg_advisory_lock before the HTTP server binds. Exits non-zero on failure so Coolify healthcheck fails closed. - Dockerfile copies packages/db/migrations into /app/migrations. - postgres 3.4.5 added as direct broker dep. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
38 KiB
claudemesh v1 — Feature Inventory
Status: backlog reference Created: 2026-04-11 Purpose: Exhaustive audit of what v1 ships today. Every row in this document must still work after v2 lands. v2 is a refactor + CLI user flows, NOT a functional rewrite; this inventory is the regression checklist.
Source of truth:
apps/cli/src/— 22 files, ~12 k LOC (v0.10.5)apps/broker/src/— 23 files, ~11 k LOCpackages/db/src/schema/mesh.ts— 1,019 lines, 23 tables
0. Summary counts
| Surface | v1 count |
|---|---|
CLI commands (subcommands in index.ts) |
23 |
MCP tools (handlers in mcp/server.ts) |
79 |
Broker WS message types (dispatched in index.ts) |
85 |
| Broker HTTP endpoints | 18 |
Postgres tables in mesh schema |
23 |
| External backend services the broker manages | 5 (Postgres, Neo4j, Qdrant, MinIO, Docker) |
| Lines of source (CLI + broker, excluding tests) | ~23,450 |
1. CLI commands
All dispatched from apps/cli/src/index.ts. v1 ships 23 public subcommands plus the bare-command welcome wizard.
| Command | File | Purpose | Flags / args |
|---|---|---|---|
claudemesh (bare) |
commands/welcome.ts |
Interactive welcome wizard. Entry point for new users. | (none) |
launch |
commands/launch.ts (775 lines, biggest) |
Spawn a Claude Code session with mesh connectivity + MCP tools | --name, --role, --groups, --mesh, --join, --message-mode, --system-prompt, -y/--yes, -r/--resume, -c/--continue, --quiet, + passthrough to claude after -- |
create |
commands/create.ts |
Create a new mesh from a template | --template, --list-templates |
install |
commands/install.ts (538 lines) |
Register MCP server + status hooks with Claude Code (~/.claude.json, ~/.claude/settings.json) |
--no-hooks |
uninstall |
commands/install.ts |
Remove MCP server + hooks from Claude Code config | (none) |
join |
commands/join.ts (193 lines) |
Join a mesh via invite URL or token | positional <url> |
list |
commands/list.ts |
Show joined meshes, slugs, local identities | (none) |
leave |
commands/leave.ts |
Leave a joined mesh + remove its local keypair | positional <slug> |
peers |
commands/peers.ts |
List online peers with status, summary, groups | --mesh, --json |
send |
commands/send.ts |
Send a message to a peer, group, or all peers | positional <to> <message>, --mesh, --priority |
inbox |
commands/inbox.ts |
Drain pending inbound messages | --mesh, --json, --wait |
state |
commands/state.ts |
Get / set / list shared KV state in the mesh | positional <action> <key> [value], --mesh, --json |
info |
commands/info.ts |
Mesh overview: slug, broker, peer count, state keys | --mesh, --json |
remember |
commands/memory.ts |
Store a persistent memory visible to all peers | positional <content>, --mesh, --tags, --json |
recall |
commands/memory.ts |
Full-text search of mesh memories | positional <query>, --mesh, --json |
remind |
commands/remind.ts (142 lines) |
Schedule a delayed message. Also: remind list, remind cancel <id> |
positional <message>, --in, --at, --cron, --to, --mesh, --json |
sync |
commands/sync.ts |
Sync meshes from the user's claudemesh.com dashboard account | --force |
profile |
commands/profile.ts |
View or edit member profile (self or another member if admin) | --mesh, --role-tag, --groups, --message-mode, --name, --member, --json |
status |
commands/status.ts |
Check broker connectivity for each joined mesh | (none) |
doctor |
commands/doctor.ts (212 lines) |
Diagnose install, config, keypairs, PATH | 7 checks: Node >= 20, claude binary, MCP registered, hooks registered, config parses, file perms, keypairs valid |
mcp |
mcp/server.ts (2139 lines) |
Start MCP server on stdio (internal — invoked by Claude Code) | (none) |
seed-test-mesh |
commands/seed-test-mesh.ts |
Dev-only: inject a mesh into local config without invite flow | <slug>, <broker_url> |
hook |
commands/hook.ts |
Internal: handle Claude Code hook events (status updates from session lifecycle) | stdin JSON from Claude Code |
connect telegram |
commands/connect-telegram.ts |
Link a Telegram bot to a mesh | inline token prompts, calls broker /tg/token |
disconnect telegram |
commands/disconnect-telegram.ts |
Unlink Telegram bot | (none) |
Flag-first invocation rewrite
apps/cli/src/index.ts lines 339–355 implement a friction reducer: if the user types claudemesh --resume xxx or any flag-first invocation, the argv is rewritten to claudemesh launch --resume xxx before citty parses it. This lets users skip typing launch for common flag-only forms.
Must preserve in v2. Users may depend on this. Applies to --resume, --continue, -y, --mesh, --name, etc.
2. MCP tools (79 total)
Defined in apps/cli/src/mcp/tools.ts with schemas, implemented in apps/cli/src/mcp/server.ts with per-tool case handlers. Each MCP tool is a RPC that the CLI's MCP server handles locally or forwards to the broker via WS.
Grouped by domain family. Every tool listed here has a working handler in v1.
2.1 Messaging (4)
| Tool | v1 behavior |
|---|---|
send_message |
Send encrypted message to peer, group, or broadcast. Supports priorities: now (immediate), next (default), low. Broker queues if recipient offline. |
list_peers |
List connected peers in the mesh with presenceId, displayName, status, summary, groups, roleTag. |
message_status |
Query delivery state of a sent message by messageId. |
check_messages |
Drain pending inbox messages (push mode). |
2.2 Profile + identity (4)
| Tool | v1 behavior |
|---|---|
set_summary |
Set the current peer's work summary (visible to others). |
set_status |
Set status: idle, working, dnd. Priority-ranked by source (hook > manual > jsonl). |
set_visible |
Toggle visibility. Hidden peers skip list_peers and broadcasts but still receive direct messages. |
set_profile |
Update display name, role tag, groups, avatar, title, bio, capabilities. |
2.3 Groups (2)
| Tool | v1 behavior |
|---|---|
join_group |
Join a @group with optional role (lead, member, or free-form). |
leave_group |
Leave a @group. |
2.4 State KV (3)
| Tool | v1 behavior |
|---|---|
set_state |
Set a key-value pair in the mesh's shared state. Broadcasts state_change push to all peers. |
get_state |
Read a value by key. |
list_state |
List all state keys with values, authors, timestamps. |
2.5 Memory (3)
| Tool | v1 behavior |
|---|---|
remember |
Store a text memory with optional tags. Persists across sessions. |
recall |
Full-text search memories by query, ranked results. |
forget |
Delete a memory by ID. |
2.6 Files (8)
| Tool | v1 behavior |
|---|---|
share_file |
Upload a file to MinIO. Supports to: <peer> for E2E encryption (symmetric key wrapped with peer pubkey), or mesh-wide sharing. Supports persistent vs ephemeral storage. |
get_file |
Download a file by fileId. Returns a presigned MinIO URL. |
list_files |
List files in the mesh by scope, tags, author. |
file_status |
Query status of a file: who downloaded, when. |
delete_file |
Delete a file (owner only). |
grant_file_access |
Add another peer as a recipient of an already-encrypted file (re-wraps symmetric key). |
read_peer_file |
Read a file from another peer's working directory (requires peer online + sharing). |
list_peer_files |
List files in a peer's shared directory (tree of names, not contents). |
2.7 Vectors (Qdrant) (4)
| Tool | v1 behavior |
|---|---|
vector_store |
Store embedding with metadata in a named collection. |
vector_search |
Nearest-neighbor search in a collection with limit. |
vector_delete |
Delete a vector by ID. |
list_collections |
List collections in the mesh's Qdrant namespace. |
2.8 Graph (Neo4j) (2)
| Tool | v1 behavior |
|---|---|
graph_query |
Read-only Cypher MATCH query on the per-mesh Neo4j database. |
graph_execute |
Write Cypher (CREATE/MERGE/DELETE). |
2.9 Shared SQL (Postgres) (3)
| Tool | v1 behavior |
|---|---|
mesh_query |
SELECT-only query on the per-mesh Postgres schema. |
mesh_execute |
DDL + DML (CREATE TABLE, INSERT, UPDATE, DELETE). |
mesh_schema |
List tables + columns in the mesh's schema. |
2.10 Streams (4)
| Tool | v1 behavior |
|---|---|
create_stream |
Create a named stream for live data pub-sub. |
publish |
Push data to a stream. Subscribers receive in real-time. |
subscribe |
Subscribe to a stream. Events arrive as channel notifications. |
list_streams |
List active streams. |
2.11 Contexts (3)
| Tool | v1 behavior |
|---|---|
share_context |
Share session understanding with the mesh (summary + files_read + key_findings + tags). |
get_context |
Search contexts by query (file path, topic, etc.). |
list_contexts |
Show what peers currently know about the codebase. |
2.12 Tasks (4)
| Tool | v1 behavior |
|---|---|
create_task |
Create a work item (title, assignee, priority, tags). |
claim_task |
Claim an unclaimed task. |
complete_task |
Mark done with optional result summary. |
list_tasks |
Filter by status and/or assignee. |
2.13 Scheduling (3)
| Tool | v1 behavior |
|---|---|
schedule_reminder |
One-shot (deliver_at, in_seconds) or recurring (cron). Delivered to self or to. Persists across broker restarts. |
list_scheduled |
List pending scheduled messages. |
cancel_scheduled |
Cancel by ID. |
2.14 Mesh metadata — read (4)
| Tool | v1 behavior |
|---|---|
mesh_info |
Overview: peers, groups, state, memory, files, tasks, streams, tables. |
mesh_stats |
Resource usage per peer: messages in/out, tool calls, uptime, errors. |
mesh_clock |
Simulation clock status: speed, tick count, simulated time. |
ping_mesh |
Test messages through the full pipeline, measure round-trip per priority. Diagnoses push delivery issues. |
2.15 Mesh clock — write (3)
| Tool | v1 behavior |
|---|---|
mesh_set_clock |
Set simulation clock speed (1–100x). Peers receive heartbeat ticks at the simulated rate. |
mesh_pause_clock |
Pause simulation clock. |
mesh_resume_clock |
Resume paused clock. |
2.16 Skills (5)
| Tool | v1 behavior |
|---|---|
share_skill |
Publish a reusable skill (name + description + instructions + tags + when_to_use + allowed_tools + model + context + agent + user_invocable + argument_hint). Exposed as MCP prompts and skill:// resources. |
get_skill |
Load a skill's full instructions by name. |
list_skills |
Browse available skills, optionally filter by keyword. |
remove_skill |
Remove a shared skill. |
mesh_skill_deploy |
Deploy a multi-file skill bundle from zip or git repo. |
2.17 MCP registry tier 1 — peer-hosted (4)
| Tool | v1 behavior |
|---|---|
mesh_mcp_register |
Register a peer's local MCP server with the mesh (server_name, description, tools schema, persistent flag). Other peers can invoke via mesh_tool_call. |
mesh_mcp_list |
List MCP servers in the mesh with their tools + hosting peer. |
mesh_tool_call |
Call a tool on a mesh-registered MCP server. Routes: caller → broker → hosting peer → execute → result back. 30s timeout. |
mesh_mcp_remove |
Unregister a peer-hosted MCP server. |
2.18 MCP registry tier 2 — broker-deployed (7)
| Tool | v1 behavior |
|---|---|
mesh_mcp_deploy |
Deploy an MCP server from zip (via file_id), git URL, or npx package. Runs on broker VPS in Docker sandbox. Scope: peer (default), mesh, or {group/groups/role/peers}. Runtime: node / python / bun. Memory, network_allow, env with $vault: references. |
mesh_mcp_undeploy |
Stop and remove a managed MCP server. |
mesh_mcp_update |
Pull latest + restart a git-sourced server. |
mesh_mcp_logs |
Tail recent logs from a managed server. |
mesh_mcp_scope |
Get or set visibility scope. |
mesh_mcp_schema |
Inspect tool schemas for a deployed server. |
mesh_mcp_catalog |
List all deployed services with status, scope, tool count. |
2.19 Vault (3)
| Tool | v1 behavior |
|---|---|
vault_set |
Store encrypted credential. type: env (string, injected as env var via $vault:<key>) or type: file (file written to mount_path in container). |
vault_list |
List vault entries (keys + metadata only, no values). |
vault_delete |
Remove a credential. |
2.20 URL watch (3)
| Tool | v1 behavior |
|---|---|
mesh_watch |
Watch a URL for changes. Modes: hash (SHA-256 body), json (jsonpath extract), status (HTTP code). Polling interval (min 5s). notify_on: change | match:<val> | not_match:<val>. Custom headers. |
mesh_unwatch |
Stop watching by watch_id. |
mesh_watches |
List active watches. |
2.21 Webhooks (3)
| Tool | v1 behavior |
|---|---|
create_webhook |
Create an inbound webhook. Returns a URL external services (GitHub, CI/CD, monitoring) can POST to. Payload becomes a mesh message to all peers. |
list_webhooks |
List active webhooks. |
delete_webhook |
Deactivate by name. |
3. Broker WS protocol
apps/broker/src/index.ts dispatches 85 message types over a single WebSocket endpoint (WS_PATH). Each WS message is a client-initiated RPC; most of the 79 MCP tools above map 1:1 to a WS message. Some additional WS messages exist for connection lifecycle + internal routing.
3.1 Connection lifecycle (3)
hello— client authentication. Ed25519 signature over{meshId, memberId, pubkey, timestamp}. Broker verifies, creates presence row, replies withhello_ack.hello_ack— server → client, confirms authentication + sends restored peer state.get_clock— get current simulation clock state.
3.2 Messaging (4 WS ops)
send— send a message. Envelope contains sender, recipient (peer/group/*), priority, nonce, ciphertext.peer_dir_request/peer_dir_response— peer-to-peer directory request (read_peer_file under the hood).peer_file_request/peer_file_response— peer-to-peer file read.
3.3 Profile + presence (5)
set_status,set_summary,set_visible,set_profile,set_stats
3.4 Groups (2)
join_group,leave_group
3.5 State KV (3)
set_state,get_state,list_state
3.6 Memory (3)
remember,recall,forget
3.7 Files (5)
get_file,list_files,file_status,grant_file_access,delete_file
3.8 Vectors (3)
vector_store,vector_search,vector_delete,list_collections
3.9 Graph (2)
graph_query,graph_execute
3.10 Shared SQL (3)
mesh_query,mesh_execute,mesh_schema
3.11 Streams (4)
create_stream,publish,subscribe,unsubscribe,list_streams
3.12 Contexts (3)
share_context,get_context,list_contexts
3.13 Tasks (4)
create_task,claim_task,complete_task,list_tasks
3.14 Scheduling (3)
schedule,list_scheduled,cancel_scheduled
3.15 Mesh metadata (3)
mesh_info,peers_list(fromlist_peers),message_status
3.16 Simulation clock (4)
set_clock,pause_clock,resume_clock,get_clock
3.17 Skills (4)
share_skill,get_skill,list_skills,remove_skill,skill_deploy
3.18 MCP registry (11)
mcp_register,mcp_unregister,mcp_list,mcp_call,mcp_call_response(peer → peer relay)mcp_deploy,mcp_undeploy,mcp_update,mcp_logs,mcp_scope,mcp_schema,mcp_catalog
3.19 Vault (4)
vault_set,vault_get,vault_list,vault_delete
3.20 URL watch (3)
watch,unwatch,watch_list
3.21 Webhooks (3)
create_webhook,list_webhooks,delete_webhook
3.22 Audit (2)
audit_query,audit_verify
4. Broker HTTP endpoints
The broker serves both WS (/ws) and HTTP on the same port. HTTP endpoints are listed here by (method, path) with purpose.
| Method | Path | Purpose |
|---|---|---|
GET |
/health |
Health check: liveness probe |
GET |
/metrics |
Prometheus metrics endpoint |
POST |
/hook/set-status |
Receive hook status updates from CLI hook command (Claude Code session lifecycle) |
POST |
/join |
Accept v1 invite join (legacy) |
POST |
/invites/:code/claim |
v2 invite claim (public, unauthenticated) |
POST |
/upload |
Upload a file (returns fileId, used by share_file) |
GET |
/download/:id |
Download a file (returns content or presigned URL) |
POST |
/cli-sync |
CLI sync endpoint — fetches user's meshes from claudemesh.com dashboard via JWT, returns mesh list |
POST |
/tg/token |
Register a Telegram bot token for a mesh (connects via connect telegram CLI command) |
PATCH |
/mesh/:id/member/:memberId |
Update a member's profile (admin or self) |
GET |
/mesh/:id/members |
List mesh members |
PATCH |
/mesh/:id/settings |
Update mesh-level settings (owner/admin) |
POST |
/hook/:meshId/:webhookId |
Inbound webhook — external systems POST here to publish a mesh message |
GET |
/test/clock |
Dev-only: simulation clock state |
GET |
/test/flip |
Dev-only: test flip endpoint |
GET |
/test/html |
Dev-only: test HTML endpoint |
WS |
/ws |
WebSocket connection for mesh peers (all WS ops above) |
5. Database schema — mesh Postgres schema
23 tables in the mesh schema (managed via Drizzle). Defined in packages/db/src/schema/mesh.ts.
| Table | Purpose |
|---|---|
mesh.mesh |
Mesh identity. slug, name, ownerId, createdAt, settings. |
mesh.member |
Per-mesh member record. Stable, durable. pubkey, displayName, role, groups, joinedAt. |
mesh.invite |
Invite codes + metadata. |
mesh.pending_invite |
v2 invite handshake state (pending claim). |
mesh.audit_log |
Audit events per mesh. |
mesh.presence |
Ephemeral WS session — one row per active connection. Status, statusSource, statusUpdatedAt. |
mesh.message_queue |
Queued messages pending push delivery (priority ordered). |
mesh.pending_status |
In-flight status updates (10s TTL). |
mesh.state (meshState) |
Shared KV state per mesh. |
mesh.memory (meshMemory) |
Shared memories with full-text search. |
mesh.file (meshFile) |
File metadata (uploader, size, sha256, persistence, storage location). |
mesh.file_access (meshFileAccess) |
Per-recipient ACL on files. |
mesh.file_key (meshFileKey) |
Per-recipient wrapped symmetric keys for E2E encryption. |
mesh.context (meshContext) |
Shared context entries. |
mesh.task (meshTask) |
Tasks with lifecycle (open, claimed, completed, cancelled). |
mesh.stream (meshStream) |
Stream metadata. |
mesh.skill (meshSkill) |
Skill registrations (name, content, frontmatter, tags). |
mesh.webhook (meshWebhook) |
Inbound webhook registrations. |
mesh.service (meshService) |
Deployed MCP server state (container ID, scope, env, runtime, memory, logs). |
mesh.vault_entry (meshVaultEntry) |
Encrypted vault entries per (mesh, peer, key). |
mesh.scheduled_message |
Scheduled / recurring reminders (cron + one-shot). |
mesh.peer_state |
Per-peer state (groups, role, profile, message mode preference). |
mesh.telegram_bridge |
Telegram bot registration per mesh. |
6. Broker backend services
Five external services the broker manages at runtime. All currently work in v1 and ship in the default Docker Compose deployment.
| Service | Purpose | File | Per-mesh model |
|---|---|---|---|
| Postgres (Drizzle) | Primary data store for mesh schema. Also used for mesh_execute / mesh_query / mesh_schema shared-SQL tools via per-mesh schemas. |
db.ts |
Schema-per-mesh for shared SQL tools |
| Neo4j | Graph queries (graph_query, graph_execute). |
neo4j-client.ts |
Database-per-mesh (Enterprise) or labeled-node fallback (Community) |
| Qdrant | Vector embeddings + nearest-neighbor search. | qdrant.ts |
Collection naming: mesh_<meshId>_<collection>, 1536-dim default, cosine distance |
| MinIO | File storage for share_file / get_file. |
minio.ts |
Bucket-per-mesh: mesh-<meshId>. Persistent + ephemeral key paths. |
| Docker | Runs deployed MCP servers in sandboxed containers. | index.ts (deploy handler) |
Container-per-deployment. Read-only root, dropped caps, memory limits, network_allow. |
7. Broker core subsystems
7.1 Status engine (broker.ts, 2066 lines)
Battle-tested status model ported from claude-intercom. Rules:
- Status sources are ranked:
hook(3) >manual(2) >jsonl(1) - On status update:
- If status changed → bump everything, record new source
- If status unchanged, incoming source ≥ recorded → upgrade
- If status unchanged, incoming source < recorded:
- Recorded source still fresh → keep it (bump timestamp only)
- Recorded source stale → downgrade to honest attribution
HOOK_FRESHNESS_MSwindow (default 60s) for "fresh" classificationWORKING_TTL_MSafter whichworkingstatus reverts toidlePENDING_TTL_MS = 10_000for pending status cleanupTTL_SWEEP_INTERVAL_MS = 15_000for periodic cleanup
Must preserve — this is the correctness engine for set_status, list_peers, and Claude Code's status line.
7.2 Message queue + priority delivery
- Messages are stored in
mesh.message_queuewith priority (now,next,low) nowmessages bypass busy-gate and are pushed immediatelynextmessages wait for idle peerlowmessages are pull-only (delivered when peer explicitly drains viacheck_messages)- Queue is drained via
drainForMember(meshId, memberId)on WS message arrival or manualcheck_messages - Duplicate delivery prevention via
messageIdUUID tracking
7.3 Scheduled message delivery (index.ts in-memory + DB persistence)
- One-shot:
deliver_at(timestamp) orin_seconds - Recurring: standard 5-field cron expression
- Persists to
mesh.scheduled_messagetable — survives broker restart - On broker start, pending schedules are re-registered
- Delivery is via the normal
send_messagepipeline withsubtype: reminder
7.4 URL watch subsystem (index.ts)
- Poller runs in-process (worker per watch)
- Modes:
hash(SHA-256 of body),json(extract jsonpath value),status(HTTP status) notify_on: change | match:<val> | not_match:<val>- Persists to DB so watches survive broker restart
- Min interval 5s, max 24h
7.5 Telegram bridge (telegram-bridge.ts, 1711 lines)
Substantial subsystem. Provides Telegram Bot API integration:
- Bot token registration per mesh via
POST /tg/token - Long-polling or webhook mode
tg:<username>peer identity registration in the mesh's member table- Inbound Telegram messages → mesh
send_messageevents withsubtype: telegram - Outbound
send_message(to: "tg:<name>")→ Telegram Bot API call - Chat-to-mesh mapping (Telegram chat_id ↔ mesh peer)
- User discovery (
connectChat) - Bridge row persistence in
mesh.telegram_bridge
This is ~18% of the broker's total source. v2 must either:
- Port the logic into a standalone MCP connector (
apps/mcp-telegram/), or - Keep this file in the broker and wire it into the v2 architecture unchanged (my recommendation per the previous conversation — bundled into the broker image)
Either way, every behavior documented here must still work after v2 lands.
7.6 Auth + crypto (crypto.ts, broker-crypto.ts, jwt.ts)
- Hello signatures: Ed25519 signed tuple of
(meshId, memberId, pubkey, timestamp). Verified on every WS connection. Replay protection via timestamp window. - Invite verification: canonical invite payload (
canonicalInvite) signed by mesh owner, Ed25519 verified on claim - JWT: for
/cli-syncendpoint — the CLI obtains a JWT fromclaudemesh.comvia browser flow, passes it to the broker, broker verifies and returns the user's mesh list - File envelopes: client-side AES-GCM + per-recipient key wrapping (file_key table)
7.7 Rate limiting (rate-limit.ts)
- Per-peer rate limits on expensive operations
- Currently in-process (not Redis-backed)
- Enforces limits on
send,vector_store,mesh_execute,mesh_mcp_deploy, etc.
7.8 Metrics (metrics.ts)
Prometheus metrics exposed at /metrics:
- Request counts by op type
- Latencies p50/p99
- Connection counts per mesh
- Message delivery counts by priority
- Error rates
7.9 Audit log (audit.ts)
- Every mutation is audited to
mesh.audit_log - Tamper-evidence via hash chaining
- Accessible via
audit_queryandaudit_verifyWS ops
7.10 Member API (member-api.ts, 284 lines)
Exports:
updateMemberProfile()— used byPATCH /mesh/:id/member/:memberIdlistMeshMembers()— used byGET /mesh/:id/membersupdateMeshSettings()— used byPATCH /mesh/:id/settings
7.11 CLI sync (cli-sync.ts, 133 lines)
Exports handleCliSync() for POST /cli-sync. This is already the "CLI sync meshes from dashboard" feature — v2 will reuse this endpoint for its mesh-list refresh logic.
7.12 Webhook subsystem (webhooks.ts, 97 lines)
Handles POST /hook/:meshId/:webhookId inbound. Signature verification (HMAC), payload normalization, mesh message emission.
8. CLI core subsystems
8.1 WS client (ws/client.ts, 2191 lines)
The biggest CLI file. Implements the full WS protocol with:
- Connection management, reconnect with exponential backoff
- Message queue for offline buffering
- Request/response correlation via
_reqId - Ed25519 hello signature generation
- Crypto envelope wrapping for
send_messagepayloads - Push notification delivery (messages, state changes, system events)
- Per-mesh connection pooling (one WS per mesh)
8.2 MCP server (mcp/server.ts, 2139 lines)
Second biggest CLI file. Implements:
- MCP stdio transport (registered with Claude Code via
install.ts) - Tool registry from
mcp/tools.ts - Dispatch to 79 handlers (one per tool)
- WS client pooling (one connection per mesh)
- Crypto primitives for memory/state encryption
- Inline file-read helpers for
read_peer_file - Channel notification forwarding from broker → Claude Code via MCP elicitation
8.3 Crypto (crypto/*.ts)
keypair.ts— Ed25519 keypair generation + persistence (~/.claudemesh/keys/<mesh>.key)envelope.ts— NaClcrypto_boxenvelope wrappingfile-crypto.ts— AES-GCM file encryption + per-recipient key wrappinghello-sig.ts— Hello signature generation/verification
8.4 Auth + invite (auth/*.ts, invite/*.ts, lib/invite-v2.ts)
callback-listener.ts— local HTTP server that catches browser OAuth callback (forsynccommand)open-browser.ts— cross-platform browser launcherpairing-code.ts— pairing code displaysync-with-broker.ts— JWT-based sync from dashboardinvite/parse.ts— parse v1 invite URLsinvite/enroll.ts— enroll into a mesh from an invitelib/invite-v2.ts— v2 invite format (short-code + signed payload)
8.5 State + config (state/config.ts)
~/.claudemesh/config.jsonread/write (mesh list, keypairs, profile defaults)- 0600 permission enforcement
- Schema validation
8.6 TUI primitives (tui/*.ts)
colors.ts— hard-coded ANSI colorsindex.ts— input helpersscreen.ts— raw-mode screen controlspinner.ts— simple spinner
8.7 Templates (templates/index.ts)
dev-team,research,ops-incident,simulation,personal- Each template seeds initial state + preset groups
8.8 Tests
__tests__/crypto-roundtrip.test.ts— crypto round-trip verification__tests__/invite-parse.test.ts— invite URL parsing- No integration tests against a real broker
9. Infrastructure + deployment
9.1 Broker runtime (env.ts)
Environment variables the broker expects:
DATABASE_URL— Postgres connectionNEO4J_URL,NEO4J_USER,NEO4J_PASSWORDQDRANT_URLMINIO_ENDPOINT,MINIO_ACCESS_KEY,MINIO_SECRET_KEY,MINIO_USE_SSLSTATUS_TTL_SECONDS— working status timeoutHOOK_FRESH_WINDOW_SECONDS— hook source freshness windowTELEGRAM_BOT_TOKEN— for bridgeDASHBOARD_JWT_SECRET— for/cli-syncverificationPORT(default 8787)- Various feature flags
9.2 CLI runtime
- Node >= 20 required (checked in
doctor) claudebinary must be on PATH~/.claudemesh/directory with config + keys~/.claude.jsonMCP server registration~/.claude/settings.jsonstatus hooks registration
9.3 Deployment (Coolify/Docker Compose)
- Broker deployed via Coolify + Gitea CI on OVHcloud VPS (
ic.claudemesh.com) - WS endpoint:
wss://ic.claudemesh.com/ws - HTTP endpoint:
https://ic.claudemesh.com - Postgres, Neo4j, Qdrant, MinIO run as siblings in Docker Compose
- Deployed MCP sandboxes use the host Docker daemon via socket mount
10. Features not in the tool/WS surface (behavioral)
These are v1 behaviors that exist but aren't enumerated as tools. Each must still work after v2.
| Feature | Location | Notes |
|---|---|---|
Flag-first claudemesh --resume xxx routing |
cli/src/index.ts §339 |
Rewrites argv to launch --resume xxx |
Bare claudemesh → welcome wizard |
cli/src/index.ts §334 |
Runs runWelcome() |
| Status hook auto-registration | commands/install.ts |
Writes to ~/.claude/settings.json |
| Claude Code session hook handling | commands/hook.ts |
Receives stdin JSON, posts to /hook/set-status |
| Per-mesh keypair directory | crypto/keypair.ts |
~/.claudemesh/keys/<mesh>.key with 0600 perms |
| E2E file encryption with re-wrapping | crypto/file-crypto.ts + mesh_file_key table |
grant_file_access re-wraps symmetric key for new recipient |
| Priority message delivery | broker.ts |
now bypasses busy-gate, next waits for idle, low is pull-only |
| Hook > manual > jsonl status priority | broker.ts |
Documented in §7.1 |
| Simulation clock for test time | index.ts (broker) |
Peers receive heartbeat ticks at simulated rate |
| Audit log hash chaining | audit.ts |
Tamper-evident — tools call audit_verify to check |
| Dashboard-CLI sync | auth/sync-with-broker.ts + cli-sync.ts |
Browser JWT flow, fetches mesh list from dashboard |
| Telegram chat ↔ mesh peer mapping | telegram-bridge.ts |
Bidirectional routing via tg:<username> |
| Inbound webhook payload normalization | webhooks.ts |
External systems POST, becomes a mesh message |
| Rate limiting per peer per operation | rate-limit.ts |
In-memory token buckets |
| Prometheus metrics | metrics.ts |
/metrics endpoint |
11. Test coverage (v1)
| Test | File | Notes |
|---|---|---|
| Crypto round-trip | apps/cli/src/__tests__/crypto-roundtrip.test.ts |
Encrypt → decrypt verification |
| Invite URL parsing | apps/cli/src/__tests__/invite-parse.test.ts |
v1 and v2 formats |
| Broker tests | apps/broker/tests/*.test.ts |
broker.test.ts, invite-signature.test.ts, invite-v2.test.ts, hello-signature.test.ts, rate-limit.test.ts, encoding.test.ts, dup-delivery.test.ts, metrics.test.ts, logging.test.ts, integration/health.test.ts |
v1 test coverage is minimal for the CLI side. 2 unit test files for 12k LOC.
Broker has ~10 test files. They cover crypto primitives, invite flow, hello signatures, rate limiting, metrics — but not the 85 WS message handlers comprehensively.
12. The "must preserve" list (high-priority regression checks)
If v2 breaks any of these, it's a user-facing regression:
12.1 First-run experience
claudemeshbare command → welcome wizardclaudemesh installregisters MCP server + status hooks in Claude Code configclaudemesh join <url>enrolls into a mesh from a v1 OR v2 invite URLclaudemesh launchstarts Claude Code with mesh connectivity
12.2 Session lifecycle
- Status hooks fire correctly on Claude Code session start/stop/pause
set_statushonors priority (hook > manual > jsonl)list_peersshows live status with freshness gating- Status TTL sweeper runs every 15s
12.3 Messaging
send_message(to: peer, priority: "now")delivers immediatelysend_message(to: peer, priority: "next")waits for idlesend_message(to: "@group")broadcasts to group memberssend_message(to: "*")broadcasts to all mesh peers- Offline recipients receive queued messages on reconnect
- Duplicate delivery is prevented by
messageIdtracking
12.4 Cryptographic integrity
- Ed25519 keypair generation + persistence with 0600 perms
- Hello signature verification rejects replay within timestamp window
send_messageenvelopes are E2E encrypted (NaCl crypto_box)- File uploads are AES-GCM encrypted with per-recipient key wrapping
grant_file_accessre-wraps symmetric key for a new recipient
12.5 All 79 MCP tools
- Every tool in §2 dispatches correctly through the CLI's MCP server
- Every tool delegates to the broker WS protocol or local handler as appropriate
- No tool returns "not implemented" or throws an unexpected error
12.6 Broker backends
mesh_query/mesh_execute/mesh_schemawork against per-mesh Postgres schemagraph_query/graph_executework against per-mesh Neo4j databasevector_store/vector_searchwork against per-mesh Qdrant collectionshare_file/get_filework through per-mesh MinIO bucketmesh_mcp_deployspawns a Docker container with correct scope + env + network_allowvault_set+$vault:<key>env injection works end-to-end for deployed MCPs
12.7 Scheduled + URL watch
schedule_reminderwithcronsurvives broker restart (persisted in DB)mesh_watchpolls at the specified interval and notifies on change- Watch state persists across broker restart
12.8 Telegram bridge
connect telegramregisters bot token viaPOST /tg/token- Bot token is stored in
mesh.telegram_bridge - Inbound Telegram messages are routed as mesh messages
send_message(to: "tg:<username>")routes via Telegram Bot APIdisconnect telegramtears down the bridge cleanly
12.9 Dashboard sync
claudemesh syncbrowser flow completes and fetches mesh listPOST /cli-syncwith valid JWT returns user's dashboard meshes
12.10 Webhooks
create_webhookreturns a POST URL- External POST to webhook URL becomes a mesh message
- HMAC signature validation rejects unsigned requests
list_webhooks+delete_webhookwork
12.11 Doctor checks
- Node >= 20 check
claudebinary on PATH- MCP server registered in
~/.claude.json - Status hooks registered in
~/.claude/settings.json ~/.claudemesh/config.jsonexists + parses + 0600 perms- Mesh keypairs valid
13. What v2 is adding (net new)
Not part of the regression list, but tracked here so we don't lose sight of the forward-looking scope.
13.1 New CLI features (from user's stated v2 intent)
claudemesh login— device-code OAuth against claudemesh.com's Better Auth backendclaudemesh register— create a new account from the CLI (via browser handoff)claudemesh new— create a mesh from the CLI againstPOST /api/my/meshes(not via templates in the CLI — via dashboard API)claudemesh invite— generate an invite from the CLI viaPOST /api/my/meshes/:slug/invitesclaudemesh whoami— show current identity + token sourceclaudemesh logout— revoke server-side session + clear local credentials
13.2 Architecture improvements (from user's v2 intent)
- Feature-folder
services/layer with strict facade boundaries - ESLint + dependency-cruiser boundary enforcement
cli/vsui/separation (non-Ink I/O vs Ink rendering)entrypoints/folder with cli + mcp entries- Typed error classes per service with
toDomainErrorhelper - Coverage threshold enforcement in CI
13.3 Not in v1.0.0 scope (defer to v1.1+)
Everything from the Composer 2 review rounds that isn't Pass 1:
- Local-first SQLite source of truth (Lamport, sync daemon, publish transaction)
- Broker security hardening (role-per-mesh Postgres, Docker egress proxy, SSRF policy)
- ICU MessageFormat + per-locale budgets
- Accessibility token-signal matrix
- Tiered MCP catalog + audit process
- session_kind enum
- NFC peer_id normalization
- Write queue state machine
These stay in the .artifacts/specs/ as reference documents. They describe a good destination. They are NOT v1.0.0 requirements.
14. Known v1 technical debt / gaps (worth noting)
These aren't features — they're places where v1 is weaker than it could be. Document here so v2 doesn't blindly port the weaknesses.
- CLI auth is missing — v1 has no
login/logoutcommand. All account-level operations require the web dashboard. This is what v2 is adding. - Imperative command branching —
commands/launch.tsis 775 lines with nested flag handling. Cleaner in v2's flow pipeline. - Minimal CLI test coverage — 2 test files for 12k LOC. v2 should have colocated tests per service.
- Rate limiting is in-memory only — doesn't survive broker restart; not Redis-backed.
- No CLI-side caching — every
list_peers/mesh_infocall hits the broker. v2's local-first layer (Pass 2) addresses this. - Telegram bridge is a large monolithic file (1711 lines) — legitimate complexity, but v2 may want to modularize if it touches it.
- v1 wizard bleed-through —
launch→claudehandoff leaves ANSI state dirty. v2'sresetTerminal()choke point fixes this.
None of these are regressions if v2 keeps them as-is. v2 should not prioritize fixing them — fix them when they become a problem, not speculatively.
15. Reading this inventory
If you're implementing v2 Phase 1 (foundation layers): every tool in §2, every WS op in §3, every HTTP endpoint in §4, every DB table in §5 must have a place in the v2 folder structure. No new semantics, no improved algorithms — just move the working code.
If you're reviewing a v2 PR: check it against §12 ("must preserve" list). If the PR changes the behavior of anything in that list, it's a regression and needs explicit sign-off.
If you're writing v2 docs: reference this document. Every feature here is user-visible and documented in v1's README / slash-command help / tool descriptions. v2 docs should mention every feature from §2 as preserved.
End of inventory.