OpenCode-Mesh
Message any session in 2 calls: peers first, exact target only. Run mesh_peers
to discover live peers, then mesh_send body-only text.
Use it
- Run
mesh_peers({})and pick the top-ranked live target. - Send
mesh_send({target:"<exact ses_id | agent@repo>", text:"<body only>"}); keep themsg_receipt. - Read the reply as a normal message; reply by reverse
mesh_sendto the sender id.
Answers
- Reach any session in 2 calls:
mesh_peersdiscovers,mesh_senddelivers, replies arrive as normal messages. - Never call
mesh_registerby hand: every open session is auto-registered; call only to set a custom description. - Never type the
[OC-MESH | SENDER: {agent} - {sessionID}]header yourself: the system prepends exactly one; send body text only. - Sends inject one at a time per process over per-target FIFO; overflow past
depth cap 100 rejects newest with
STORAGE_FULL. - Find peers in the ranked union; target an exact id or singleton
agent@repo, else 404PEER_NOT_FOUNDplusdidYouMean[0..5]with nothing sent. - Freshness windows are heartbeat 5m, active 10m, subagent 30m, primary 48h,
outbox 10m bound; attach is
ps-detected with focus unknown. - Triple 1MB guard refuses with 413
PAYLOAD_TOO_LARGEat entry, prefixed, and body sites. - Wake is default: each message starts a Runner turn unless silent deposits
history-only marked
(SILENT). - Stay quiet per message with
silent:true(legacynoReply:true) or silence everything withMESH_WAKE=0. - Bodies pass verbatim by default; opt in with
MESH_QUARANTINE=1to tag non-leading lookalikes.
Fix it fast
- Run
mesh_peersbefore everymesh_send; stale ids miss with 404 and send nothing. - Track any send via
mesh_peers({receipt:"msg_…"})for queued versus injected versus terminal state. - On 404 read
didYouMean[0..5], re-runmesh_peers, resend to the exact id. - History-only delivery needs
silent:trueper message orMESH_WAKE=0global; wake is default. - Never hand-write header lookalikes mid-text: verbatim default passes them
through,
MESH_QUARANTINE=1tags them. - Oversize text fails 413 before any send or queue; shrink
textand retry. - Fan-out stays off by default:
broadcast:trueor targetallneeds exactMESH_BROADCAST=1else 403BROADCAST_DISABLED; prefer peer-to-peer. - Keep pasted transcripts under
/tmproots free of passwords, tokens, and registry dumps. - Loopback-only wire
127.0.0.1:4096, dirs0700files0600,BasicviaOPENCODE_SERVER_PASSWORD.
Shapes
Run exact shapes only; no extra keys.
| Tool | Required | Optional |
|---|---|---|
mesh_send |
target, text |
silent, noReply (legacy), broadcast |
mesh_peers |
none | includeSelf, agent, description, cwd, repo, receipt |
mesh_register |
none | summary, description (alias) |
mesh_broadcast |
text |
silent, noReply (legacy) |
mesh_register upserts caller presence; returns registry snapshot, not ranked
union. mesh_broadcast aliases mesh_send with fixed target all plus
broadcast true.
Track queued rows by id via mesh_peers({ receipt: "msg_…" }); CLI carries no
receipt flag.
| State | Meaning |
|---|---|
queued |
Row exists, inject pending |
injected-progressing |
204 seen, reader unconfirmed |
dead-lettered |
Max attempts plus past TTL |
failed-permanent |
Terminal fail_reason, no such row, store unavailable |
Terminal check runs first; fail_reason wins over claimed or delivered. Send
shape stays {ok, via, target, title, id}; via reads admitted, queued, or
mixed on broadcast.
Wake is default; silent deposits history-only marked (SILENT).
| Input | Wire |
|---|---|
MESH_WAKE=0 |
noReply true, wins over per-message flags |
silent true |
noReply true |
noReply true (legacy, silent omitted) |
noReply true |
Wake (omit both, MESH_WAKE unset) |
Omit noReply key |
Tool spells silent; CLI spells --no-reply with no --silent flag. Row
silent 1 pins noReply on claim inject; row 0 wakes.
Send body-only text; never hand-write headers or wire keys. Direct POSTs
agent, parts, messageID, model, optional variant, plus noReply
spread to /session/{id}/prompt_async?directory=. Claim injects the same keys.
Loopback 127.0.0.1:4096 only; Basic header when password set, omitted when
unset; x-opencode-directory carries target scope.
Internals
Claimer polls every 2s; claims own rows only, oldest first. Store runs WAL plus
busy_timeout 5000 plus synchronous FULL. Crash rows release; clean shutdown
releases owned claims; success acks, failure releases. Presence auto-registers
on first touch; debounce one grace window; dispose deletes own ids only. Entry
sync keeps description plus summary in sync, directory plus cwd in sync,
derives repo from basename, falls back title to description, strips
daemon plus serveUrl plus servePort plus rank keys. Registry runs atomic
writes with cross-process lock; contention degrades, validation stays loud.
Wire carries receiver agent plus model as observed; never synthesize.
Slash-less model takes opencode prefix; absent token throws at parser,
resolves null at resolver. Precedence reads live, direct row, DB, registry; miss
reads null. Miss reasons read live-throw, live-miss-parse,
direct-fetch-miss, direct-parse-fail, db-throw, db-row-absent,
db-parse-fail, registry-absent, registry-unknown-agent,
registry-no-model. Unresolvable defers honestly: direct leg queues, claim leg
releases for redelivery.
Peers read join of DB existence plus registry overlay plus live confirmation.
Each id carries one liveSource: status, heartbeat-recent, db-truth,
stale. Null or empty view deletes zero; degraded reads registry-only. Rank
orders attach-first, directory, agent, busy plus recency, title; misses rank
last, never hides. Pick rank 1 first; status means send now, stale means
re-check first.
Password absent means no header; port.auth reads none. Env password wins;
Keychain runs only behind exact OPENCODE_MESH_KEYCHAIN_PROVIDER=1. Keychain
tries /usr/bin/security first with 5m cache, then secret-tool lookup on
Linux; USER sanitized to safe chars, miss sends no header. Default user reads opencode; OPENCODE_SERVER_USERNAME
overrides username only. Keep pasted transcripts under /tmp roots free of
passwords, tokens, registry dumps.
Full docs
- Install: https://github.com/divisionseven/opencode-mesh/blob/main/docs/getting-started.md#section-2-install
- Settings and limits: https://github.com/divisionseven/opencode-mesh/blob/main/docs/getting-started.md#section-8-authentication
- Fixes: https://github.com/divisionseven/opencode-mesh/blob/main/docs/troubleshooting.md
- Wire proof: https://github.com/divisionseven/opencode-mesh/blob/main/ARCHITECTURE.md
- Send proof: https://github.com/divisionseven/opencode-mesh/blob/main/src/tools/mesh_send.ts
- Peers proof: https://github.com/divisionseven/opencode-mesh/blob/main/src/tools/mesh_peers.ts
- Header proof: https://github.com/divisionseven/opencode-mesh/blob/main/src/frontmatter.ts
- Silent proof: https://github.com/divisionseven/opencode-mesh/blob/main/src/wake.ts
- Limits proof: https://github.com/divisionseven/opencode-mesh/blob/main/src/constants.ts
- Read the linked shipped page for detail before quoting limits or TTLs.
- Send shape is
{ok, via, target, title, id};viaisadmittedon 204 (NOT delivered, NOT read) orqueuedwith a row id.