Three pending sessions ranked by leverage: ship 1.6.0 npm release, fix migration drift, build web chat UI.
7.7 KiB
claudemesh handoff — 2026-05-02
State of the world after a long session that shipped 1.5.0 and the v0.2.0 backend. Read this before the next session — it captures what's done, what's deployed where, what's not, and the architectural decisions worth knowing.
Where things stand
Released to npm
claudemesh-cli@1.5.0(latest tag, published earlier today). CLI-first architecture lock-in: zero-tool MCP, policy engine, bundledclaudemeshskill. Verified install + smoke-tested via cleannpm i -g.
In main but NOT released yet
Everything below is committed, deployed to the broker (wss://ic.claudemesh.com/ws) and the web app (Vercel claudemesh.com), but claudemesh-cli@1.5.0 on npm doesn't have any of it. Users won't see it until v1.6.0 publishes.
| Feature | Code path | Verified live? |
|---|---|---|
| Topics (schema, broker routing, CLI verbs, skill) | packages/db/src/schema/mesh.ts, apps/broker/src/broker.ts, apps/cli/src/commands/topic.ts |
✅ created #deploys-test, sent + persisted |
apikey create/list/revoke (CLI + broker WS) |
apps/cli/src/commands/apikey.ts, broker dispatch |
✅ full lifecycle exercised |
REST /api/v1/* (messages, topics, peers, history) |
packages/api/src/modules/mesh/v1-router.ts + api-key-auth.ts |
✅ posted via curl, history round-trips |
| Bridge peer (SDK + CLI) | packages/sdk/src/bridge.ts, apps/cli/src/commands/bridge.ts |
⚠️ code only — never run end-to-end |
Architectural commitments locked this session
- CLI-first, MCP push-pipe (1.5.0): MCP
tools/list = []. Inbound peer messages still arrive asexperimental.claude/channelnotifications. The bundled skill is the sole CLI-discoverability surface for Claude. - Topics complement groups, don't replace them (v0.2.0): mesh = trust boundary, group = identity tag, topic = conversation scope. Three orthogonal axes.
- Humans use REST + apikey, not browser WS (v0.2.0): the broker already plumbs
peer_type: "human". The real blocker was browser-side ed25519, which we sidestep by exposing REST. Web chat UI = thin client over/v1/*using dashboard session auth. - Spec lives at:
.artifacts/specs/2026-05-02-architecture-north-star.md(1.5.0) and.artifacts/specs/2026-05-02-v0.2.0-scope.md(v0.2.0 cut + design sketches).
Three pending sessions, ranked by leverage
Session A — Ship v1.6.0 npm release (~30 min, highest leverage)
Why first: backend is feature-complete but unreleased. Users still get the no-topics 1.5.0.
Steps:
- Bump
apps/cli/package.json1.5.0 → 1.6.0. - Update
apps/cli/README.mdmigration note (mention topics, apikey, bridge). - Add
## v1.6.0section todocs/roadmap.md. - Build + verify:
cd apps/cli && pnpm build && node dist/entrypoints/cli.js --version. npm publish --tag latest --access public --no-git-checks --ignore-scripts.git tag cli-v1.6.0 && git push github cli-v1.6.0— workflow builds 5 binaries + auto-bumps Homebrew/winget tap.- Verify on a clean prefix:
PREFIX=/tmp/cm16 mkdir -p $PREFIX && npm install -g --prefix $PREFIX claudemesh-cli@1.6.0 && $PREFIX/bin/claudemesh --help | grep -E "topic|apikey|bridge".
Session B — Migration drift fix (~1 day, highest pain reduction)
Why second: every schema change today requires manual psql -f migration.sql against prod. The drizzle _journal.json stops at idx 11, runtime migrator silently skips anything not in journal. Today's 0022_topics.sql and 0023_api_keys.sql were applied by hand. Future migrations will keep needing this until fixed.
Recommended approach:
- Replace
drizzle-orm/postgres-js/migratorinapps/broker/src/migrate.tswith a custom runner. - Scan
migrations/*.sqllexicographically (already namedNNNN_*.sql). - Track applied filenames in a new
mesh.__cmh_migrationstable (filename + sha256 + applied_at). - On startup: filter unapplied files, run them in transaction order under
pg_try_advisory_lock. Fail loud on hash mismatch (catches edits after deploy). - Backfill the table with all 0000-0023 entries one-time so prod is consistent.
- Drop the drizzle journal usage entirely (
migrations/meta/_journal.jsonbecomes dead state).
This unblocks every future feature touching DB.
Session C — Web chat UI (~2-3 days, highest visibility)
Why third: the demo. Backend is ready; this is pure React + REST.
Path: apps/web/src/app/[locale]/dashboard/(user)/meshes/[id]/topics/[name]/page.tsx (new).
Components needed:
- Topic header (members count, settings button).
- Message stream —
GET /api/v1/topics/:name/messages?limit=50. Poll every 5s for new (no WS yet — REST polling is fine for v0.2.0). - Compose box —
POST /api/v1/messageswith{topic, ciphertext, nonce}. - Members sidebar —
GET /api/v1/peers. - Apikey lifecycle: on first load, server-side issue an apikey for the dashboard user (using their existing NextAuth session) scoped to
read,sendon this topic. Stash in browser session storage.
Server-side helper for apikey issuance lives in packages/api/src/modules/mesh/api-key-auth.ts — refactor verifyBearer to also expose a createApiKeyForUser(userId, meshId, scope) helper for the dashboard handler.
Three less-urgent followups (don't block sessions A-C)
- Bridge end-to-end smoke test: never actually run between two meshes. Needs second test mesh + bridge member onboarding ritual. Worth doing before any blog post / external demo.
/v1/peersincludes only WS-connected agents, not humans (since humans are REST-only and never appear inpresence). Decide: synthetic presence rows for active apikey sessions? Or document that/v1/peersis "agents online"?- Topic ciphertext is plaintext base64 in the current implementation — no actual encryption. The schema names it
ciphertextfor forward-compat, but the code base64-encodes UTF-8. Real per-topic symmetric key derivation (HKDF from mesh root_key + topic_id) is a v0.3.0 item.
Production state worth knowing
- Broker:
wss://ic.claudemesh.com/ws, deployed via Coolify on OVHcloud VPS. Auto-redeploys on push togitea-vps main. Deploy ETA ~3 min. - Web:
claudemesh.com, Vercel auto-deploy on push togithub main. Deploy ETA ~2 min. - Postgres: container
eo1f5gydsgrg19b57e9s4zw7on the VPS. SSH viassh ovh, thendocker exec eo1f5gydsgrg19b57e9s4zw7 psql -U claudemesh -d claudemesh. - Test mesh:
openclawon the same broker has 5 active peers and one topic (#deploys-test). - Active apikey (from earlier today's smoke):
cm_OC12dRti…was revoked. None active right now.
Files most worth reading first in next session
.artifacts/specs/2026-05-02-architecture-north-star.md— the 7 architectural commitments..artifacts/specs/2026-05-02-v0.2.0-scope.md— design sketches for topics, REST, bridge.apps/cli/skills/claudemesh/SKILL.md— the canonical CLI surface; ships in npm tarball.- This file.
Memory not yet captured
Worth adding to ~/.claude/projects/-Users-agutierrez-Desktop-claudemesh/memory/MEMORY.md next session:
- Drizzle journal drift is a recurring trap — manual psql until session B lands. Save the exact apply ritual:
scp migrations/NNNN.sql ovh:/tmp/ && ssh ovh "docker cp /tmp/NNNN.sql <pg-container>:/tmp/ && docker exec <pg-container> psql -U claudemesh -d claudemesh -f /tmp/NNNN.sql". workspace:*deps breaknpm publish— keep SDK as devDependency inapps/cli/package.json; Bun bundles it into dist so runtime doesn't need it. Same trick for any other workspace-only build deps.- Commitlint hard-caps body lines at 100 chars — use
git commit -F /tmp/cm-commit.txtrather than-mheredocs. Heredocs that exceed the limit fail the husky hook silently.