feat(daemon): multi-mesh — attach to all joined meshes simultaneously
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

The 1.26.0 step that finally delivers ambient mode for multi-mesh
users. Daemon holds Map<slug, DaemonBrokerClient>; one process, one
PID per user, all your meshes online concurrently.

run.ts: claudemesh daemon up with no --mesh attaches to every joined
mesh from config. --mesh <slug> still scopes to one (legacy mode).
The daemon_started log line reports meshes: [...] instead of mesh.

drain.ts: dispatches each outbox row to the broker keyed by row.mesh
(column added in 1.25.0). Legacy rows with mesh=NULL fall back to the
only broker if there's exactly one, otherwise mark dead with a clear
error.

ipc/server.ts:
- GET /v1/peers aggregates across all attached meshes; each peer
  record gains a mesh field. ?mesh=<slug> narrows server-side.
- GET /v1/skills aggregates similarly; /v1/skills/:name walks meshes
  and returns first match.
- POST /v1/send requires mesh field on multi-mesh daemons; auto-picks
  on single-mesh; returns 400 with attached list if ambiguous.
- POST /v1/profile accepts optional mesh; without it, fans out to all
  attached meshes (consistent presence).

CLI: trySendViaDaemon now forwards expectedMesh as the body's mesh
field (was informational, now authoritative). claudemesh send
--mesh A and --mesh B from the same shell both route to the right
broker via the same daemon process.

Verified: aggregated peer list across 3 attached meshes; cross-mesh
sends from CLI reach status=done with correct broker_message_ids.

Released as 1.26.0 on npm.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Alejandro Gutiérrez
2026-05-04 02:14:43 +01:00
parent 0e3a5babd9
commit cb90f1ca60
6 changed files with 233 additions and 88 deletions

View File

@@ -1,5 +1,57 @@
# Changelog
## 1.26.0 (2026-05-04) — multi-mesh daemon
The daemon now attaches to **all joined meshes simultaneously** by
default. Ambient mode (raw `claude` after `claudemesh install`) finally
delivers what v2.0.0 promised: one daemon process, one PID per user,
all your meshes available concurrently with no manual switching.
### What changed
- `claudemesh daemon up` (no `--mesh` flag) attaches to every joined
mesh. One `DaemonBrokerClient` per mesh, all in one process. Pass
`--mesh <slug>` to scope to a single mesh (legacy mode).
- `daemon_started` log line now reports `meshes: [...]` (array) instead
of `mesh: <slug>` (single).
- Outbox dispatch picks the broker via the `mesh` column added in
1.25.0. Legacy rows (mesh=NULL) fall back to the only broker if
there's exactly one; otherwise mark dead with a clear error.
### IPC surface
- `GET /v1/peers` aggregates across all attached meshes; each peer
record gains a `mesh` field. `?mesh=<slug>` narrows server-side.
- `GET /v1/skills` aggregates similarly. `GET /v1/skills/:name` walks
attached meshes and returns the first match (or `?mesh=<slug>` to
scope).
- `POST /v1/send` requires `mesh` field when the daemon is attached
to multiple meshes; auto-picks the only one in single-mesh mode.
Returns 400 with the attached mesh list if ambiguous.
- `POST /v1/profile` accepts optional `mesh` field — without it,
applies the update to every attached mesh (presence stays
consistent across meshes by default).
### CLI integration
- `claudemesh send --mesh <slug>` forwards the mesh in the daemon
request body. The CLI's `expectedMesh` argument was previously
informational; now it's authoritative for routing.
- `claudemesh peer list` already aggregates because the IPC endpoint
does — no change needed in the verb.
- Verified end-to-end: `claudemesh send --mesh A` and
`claudemesh send --mesh B` from the same CLI invocation both reach
`outbox.status=done` with broker-issued IDs, dispatched to the
correct broker per row.
### What this unlocks
Ambient mode for users with N meshes. Run `claudemesh install` once,
then `claude` from anywhere — channel push, slash commands, and
resources flow through the daemon for every joined mesh
simultaneously. No more "which mesh is the daemon attached to?"
mental overhead.
## 1.25.0 (2026-05-04) — Sprint 4 outbound routing + ambient mode
### Daemon outbound routing (Sprint 4)