Early preview · v0.1.0 · under construction Status & limitations

Sealmesh

How it works

Sealmesh has three roles. A daemon runs on each machine that has agents. A router runs once per GitHub organization. A reader is anyone running sealmesh who, the MCP server, or sealmesh chat.

laptop · daemonbuild box · daemon routerreader reads its own agentswhen asked reads its own agentswhen asked live connectionsroutes questionsno snapshotschat history, 7 days sealmesh whosealmesh-mcp outbound wssoutbound wssasks

A question, step by step

  1. Each daemon dials out to the router over a WebSocket (wss://…/v1/connect) and sends a hello carrying the GitHub token gh holds. Plain http is refused unless the router is on loopback.
  2. The router resolves the token to a GitHub login, checks the login is an active member of its organization, and registers the connection under that login. Your config never names your host or the org, so a client can't widen its own access.
  3. A reader runs sealmesh who. The router forwards the question to every connected daemon.
  4. Each daemon reads its agents' files at that moment, applies the repo and path allowlists, turns what is left into typed fields, logs who asked in its local audit log, and answers.
  5. The router cuts each answer down to repositories the reader's own token can read, and returns it. Nothing is cached.

Why the socket points outward

Laptops sit behind NAT, so the router could never dial in. Outbound is also the only direction that needs to work. The router never learns a home address, only which identity currently has a daemon attached. The daemon opens no listening TCP port. With room chat on, it also opens a Unix socket that only your user can reach.

Reachability is shown, never guessed

A machine is answering, not sharing (its off switch is on), throttled (connected, but asked too often), unreachable (no daemon connected) or unreadable. Those five read differently on purpose: a display that collapses them looks healthy while lying.

Timings and limits

Heartbeatevery 30 s; a connection silent for 90 s is dropped
Reconnectbackoff from 1 s up to 30 s
Queries per machinebursts of 10, refilling one every 6 s; more reads throttled
Reader access checks1,000 uncached checks per hour per reader
Access cache30 s by default, at most 300 s

How agents are read

Claude Code is read natively: Sealmesh finds its config folders (~/.claude*), reads jobs/*/state.json and sessions/*.json, and trusts a session only if its process is alive with a matching start time. Any other tool gets in through sealmesh declare or a [[provider]] block. See Agents & providers.

Claude Code's job files carry the raw prompt in intent and detail. Those fields are dropped where the file is read and have nowhere to go afterwards. Every field on the wire is an enum, a number, a timestamp or a validated identifier. A canary test plants a prompt in every free-text field of a fixture and fails the build if it appears anywhere in the output.

Something wrong or unclear? Open an issue.