claude/channel research preview: field notes from building a cross-machine Claude-to-Claude mesh
What this is
Builder feedback on the claude/channel research preview, not a bug report. I built claude-mesh on it: a self-hosted relay (Hono + SQLite + SSE) plus a per-machine MCP stdio server, so Claude Code instances on different laptops can DM each other, broadcast to the team, thread replies, and route permission approvals to a teammate's Claude.
30-second demo: two machines, one relay. DM sent, roster listed, cross-machine reply arriving mid-session, thread stitched with in_reply_to.
Tested against Claude Code v2.1.218–2.1.219, Windows 11, claude.ai login. Inbound <channel> delivery is verified live end-to-end. The full write-up lives in CHANNELS-FEEDBACK.md; condensed version below.
Friction log (ordered by debugging cost)
- Channel notifications drop silently without the CLI flag. Tools load and work,
initializesucceeds, but everynotifications/claude/channelvanishes unless the session launched with--dangerously-load-development-channels server:<name>. The only evidence is one line in~/.claude/debug/*.txt. Cost me the single longest debugging session of the project. Suggestion: surface the skipped state in/mcp, and/or allow per-server channel enablement insettings.json. - The server can't tell whether channels are live. Declaring
experimental['claude/channel']gets no ack in theinitializeexchange, so my peer-agent streamed messages into the void with no way to warn the user. A capability echo in theinitializeresult would fix it. - claude.ai-auth-only keeps channels out of CI. Our end-to-end scenario tests drive a real
claude --printbinary and must skip by default, so the layer most exposed to wire-format drift is exactly the one CI can't watch. - Escaping/rendering guarantees are underspecified. Peer content is attacker-controlled in our threat model, so we property-tested our own
</channel>escaping (500-run fuzz) rather than rely on undocumented client behavior. A short "here is what the client guarantees about tag rendering" section would let builders lean on the platform. - Version gates are discoverable only by testing. Base channels need v2.1.80, permission relay v2.1.81. Found empirically. A capability/version matrix in the channels reference would save the next builder the bisect.
What worked well
The containment model (<channel> tags as a structural boundary for untrusted peer content), the server instructions string as a defense surface, first-answer-wins on permission relay, and a notification surface small enough to learn in an afternoon. The preview was solid enough to carry a full mesh with a five-layer injection defense, and that's a compliment.
Wishlist
A stability signal for the wire contract, settings-based enablement (friction item 1), capability echo (item 2), and any headless/CI story (item 3).
Happy to run experiments against new builds or provide more repro detail; every claim above points at code in the repo.