Files
stack/tools/tmux/README.md
T
jason.woltje 2f5a8d2cec feat(skills): skill lifecycle + ms-* skill set completion (#40, #41, #42)
- scripts/skill.sh: install (bundled or path) / activate / deactivate /
  uninstall (refuses while enabled) / list
- skills-enabled + skills-available dirs under the data root; a skill not
  in skills-enabled is not enabled or available for use
- pi adapter: MOSAIC_SKILLS -> --skill per dir; --no-skills when none
- agent.sh: seat definitions declare skills[]; resolution against
  skills-enabled refuses the launch loudly when missing
- ms-* skills completed (owner-authored canon, hands-off): ms-tools
  adapted to the runtime, ms-file-read/write/agent/conductor bodies
  written in the owner's style; ms-agent-watch + ms-unslop untouched
- tasks/USER.md onboarding fixtures; suite hardening (nested def path,
  user seed, mock-adapter dispatch evidence)

Suites: config 24, task 74, release 14, conductor 17, verify PASS.
RELEASE 0.0.12 packaged; health-gated activation on merge.

Closes #40, closes #41, closes #42
2026-09-03 16:23:57 -05:00

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 -s of 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 (-b base64 input).
  • auto-submit-drafts.sh — watchdog that flushes stable unsubmitted prompt drafts on a coordinator pane (default target mos-claude); run it as a long-lived process alongside the coordinator session.
  • agent-send.test.sh — regression + grammar lock for agent-send.sh.
  • test-send-message-socket.sh — smoke test for named-socket isolation.

Distribution

These live in the installed framework copy at ~/.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.