Upstream the 2026-07-09 live hot-fix from web1: send-message.sh used a fixed tmux buffer name (__mosaic_send) shared by all concurrent senders on one server — load-buffer overwrote load-buffer and paste-buffer -d deleted underneath peers, cross-delivering or dropping messages. Bit the fleet during the simultaneous restart (standing briefs swapped between sessions). Buffer name is now unique per invocation (PID + nanoseconds). Also brings auto-submit-drafts.sh (coordinator draft-flush watchdog, until now only a loose file in the deployed ~/.config/mosaic/tools/tmux/) under source control, and extends test-send-message-socket.sh with a concurrency lock: 5 parallel sends to distinct panes, asserting no drop and no cross-delivery. The lock fails 3/3 runs against the pre-fix script and passes post-fix. Without this, the next framework redeploy would regress the live fix.
4.3 KiB
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.