- F5 (rev-code-02 blocker): sign test-send-message-glyph-agnostic.sh into test-enumeration-exclusions.txt beside its tmux siblings; the CI image ships no tmux, so the suite stays manually run (#1017 burndown). - Adoption finding: the verdict suite hard-coded SEND to its sibling and ignored the SEND env var, so a red-first run against the shipping blob silently measured the patched copy instead (measured: shipping run printed PASS=4; with SEND honored it is PASS=3 FAIL=1, fixture 2 red, matching the recorded review numbers). SEND is now honored with the sibling as default, same contract as the glyph suite. - F6/D19: framework FLEET-COMMS.md claimed 'rc=2 is the normal result when the target is an idle pi seat'. Post-fix rc=0 is normal for idle and busy pi seats; rc=2 on a healthy seat is a real report. Never-retry advice kept, softened to 'may be in the pane' for the unconfirmed arm. Live verification on sb-it-1-dt (tmux 3.7b, pi glm-5.3 low, scratch session): idle pi - shipping rc=2 'may be UNDELIVERED' while the seat consumed the message and answered; patched rc=0 delivered, answered. Busy pi mid-turn - shipping rc=2 while the pane accepted both messages as steering input ('Steering: ...', 'Alt+Up to edit all queued messages'); patched rc=0 delivered, both consumed and acted on after the turn. Both D11 signatures: verdict now matches reality.
Inter-Agent tmux Comms — Standard & Tooling
Reliable, self-identifying messaging between Mosaic agents running in tmux panes (Claude Code / Codex / OpenCode REPLs), across hosts.
The addressing standard (required)
Every cross-agent tmux message MUST begin with an addressing preamble:
[<src_host>:<src_session> -> <dst_host>:<dst_session>] <message>
host=hostname -sof the machine the agent runs on (e.g.web1,sb-it-mgr-0-lt).session= the tmux session name (e.g.mos-claude,rev0-4,installer-1).- Replies FLIP the preamble: the recipient answers with
[<dst> -> <src>] ....
Why: a fresh or context-wiped agent always knows who sent a message and to whom. No ambiguity about origin or lane after a tmux wipe / session restart.
Example exchange:
[web1:mos-claude -> sb-it-mgr-0-lt:installer-1] status on #29?
[sb-it-mgr-0-lt:installer-1 -> web1:mos-claude] Q2 done, opening PR #34.
The helper: agent-send.sh
Prepends the preamble automatically (auto-detecting your own host:session) and
delivers reliably to local OR remote panes.
# Local target (same host, default tmux server)
agent-send.sh -s <dst_session> -m "message"
# Local target on a Mosaic fleet socket
agent-send.sh -L mosaic-fleet -s '=coder0' -m "message"
# Remote target (over ssh)
agent-send.sh -H user@host -s <dst_session> -m "message"
# From a file / stdin
agent-send.sh -H user@host -s <dst_session> -f msg.txt
echo "msg" | agent-send.sh -s <dst_session>
Key flags: -L named tmux socket · -s dst session (required) · -H ssh target for remote · -n dst
hostname for the preamble (else auto-resolved) · -m/-f/stdin body · -S
override source label · -v verbose · -r N Enter-flush attempts.
For durable fleet use, prefer exact tmux targets such as =coder0. The helper
normalizes exact session targets to pane-qualified targets internally so pane
commands do not fall back to tmux's prefix matching behavior.
Named socket isolation
Durable Mosaic fleets should use a dedicated tmux socket, for example:
tmux -L mosaic-fleet ls
agent-send.sh -L mosaic-fleet -s '=coder0' -m "status?"
send-message.sh -L mosaic-fleet -t '=coder0' -m "raw pane message"
This keeps fleet operations away from the user's default tmux server. It is the safe rollout path on hosts that already have manual tmux sessions.
Why a helper exists (the submission gotcha)
Pasting into an interactive REPL via raw tmux send-keys is unreliable: a
trailing Enter is frequently swallowed and the message sits as an unsubmitted
draft ("Press up to edit queued messages"). Over an ssh -> nested tmux hop the
plain Enter keyname often does not register at all — C-m is needed.
send-message.sh solves this for a local pane: bracketed-paste the body
(so multi-line content doesn't submit early), pause, then send Enter as its own
keystroke and flush with a second, verifying against a draft heuristic.
agent-send.sh solves the remote case by shipping send-message.sh over ssh
(ssh host bash -s -- ... < send-message.sh) and running it local to the target
pane — so the reliable send-keys always happens on the pane's own host. The remote
needs only bash + tmux + base64; no mosaic install required there. The
message crosses the wire as base64 (-b) to avoid all shell-quoting hazards.
Files
agent-send.sh— inter-agent wrapper (preamble + local/remote dispatch).send-message.sh— low-level reliable single-pane submitter (-bbase64 input).auto-submit-drafts.sh— watchdog that flushes stable unsubmitted prompt drafts on a coordinator pane (default targetmos-claude); run it as a long-lived process alongside the coordinator session.agent-send.test.sh— regression + grammar lock foragent-send.sh.test-send-message-socket.sh— smoke test for named-socket isolation.
Distribution
These live in the installed framework copy at
~/.config/mosaic/tools/tmux/. install.sh rsyncs the framework source tree
to each host, so to propagate permanently, land both files in the framework
source repo and re-run the installer on each host. Until then, agent-send.sh
already works against any reachable host because it ships send-message.sh over
ssh per-send — no pre-install on the target host is needed to send to it.