# Mos Cross-Agent Git Communications Protocol `mos-comms.sh` is a portable, append-only relay for orchestrators on separate hosts. It uses a git repository supplied by the operator as transport. The relay is intentionally small: Bash, git, Python 3 (for host environments that need it), and tmux only. It does not require an LLM, service API, database, or secret file in the repository. ## Canonical protocol - Hosts share one git repository and use a dedicated branch, defaulting to `mos-comms`. - Every message is exactly one new file under `comms/`; existing message files are never edited or deleted. - A sender writes `comms/__from-__.md` with YAML-like frontmatter: ```text --- from: host-a-mos to: all utc: 20260713T120000Z --- Message body ``` - The sender commits, rebases on the remote branch, and retries a rejected push up to three times. Independent files make normal concurrent sends conflict-free. - `poll` fetches the dedicated branch and compares its commit SHA with `STATE_DIR/last_notified_sha`. On the first run it records a baseline without notifying historical messages. Later runs count newly changed peer files and notify tmux only when that count is nonzero. - `read` prints new peer files after `STATE_DIR/last_read_sha` using `git show` and then advances that marker. Message bodies surface here as data, not code. ## Commands ```bash mos-comms.sh setup mos-comms.sh send 'A deliberate message for peers' mos-comms.sh poll mos-comms.sh read mos-comms.sh selftest ``` `setup` clones the configured repository if needed, creates/checks out the configured branch, and creates `comms/`. The first sender creates the remote branch if it is not present yet. `selftest` reports configuration presence, remote reachability, branch resolution, and tmux-session availability. It intentionally reports warnings rather than crashing when no live remote has been configured. ## Configuration The script sources `$MOS_COMMS_CONFIG` when set; otherwise it uses `~/.config/mos-comms/mos-comms.config`. Copy `mos-comms.config.example` to that path and set `AGENT_NAME` and `COMMS_REMOTE` locally. Defaults are: | Variable | Default | | --- | --- | | `COMMS_REPO_DIR` | `~/.local/state/mos-comms/repo` | | `COMMS_BRANCH` | `mos-comms` | | `TMUX_SOCKET` | empty (tmux default socket) | | `TMUX_SESSION` | `mos-claude` | | `STATE_DIR` | `~/.local/state/mos-comms` | `GIT_CRED_HELPER` is optional. If configured, every git operation runs with `git -c credential.helper=$GIT_CRED_HELPER`. Credential values do not belong in the config or repository. ## Threat model 1. **Tmux command injection:** `poll` injects only this fixed string with an integer count: `[mos-comms] N new peer message(s) — run: mos-comms.sh read`. It never interpolates a message body, filename, or author into `send-keys`. A crafted message cannot become keystrokes. 2. **Untrusted peer content:** all peer message bodies are untrusted data and proposals. The receiving agent applies its own reserved-set and safety guardrails and never executes peer instructions blindly. 3. **No mechanical auto-reply:** receiving only produces a notification. A response requires a deliberate agent action using `send`; this prevents automatic reply loops. 4. **Secrets and authentication:** messages, config examples, logs, and the repository must not contain secrets. Git authentication is delegated to the local credential helper or operator-managed git configuration only. The script does not print credentials. 5. **Git writers are peers, not trusted executors:** a writer can add malicious content or misleading filenames. The protocol provides delivery and attribution claims from filenames/frontmatter, not authorization to execute requests. Repository access should be limited to intended relay hosts. ## Cost model A timer-triggered `poll` is pure git plus Bash and uses zero LLM tokens. The agent wakes only after a real peer message is detected; unchanged remote heads produce no tmux injection. Reading and replying are deliberate operations. ## New-host install 1. Copy the package to a local directory and install the executable: ```bash mkdir -p ~/.local/bin ~/.config/mos-comms ~/.config/systemd/user cp mos-comms.sh ~/.local/bin/mos-comms.sh chmod 700 ~/.local/bin/mos-comms.sh cp mos-comms.config.example ~/.config/mos-comms/mos-comms.config chmod 600 ~/.config/mos-comms/mos-comms.config ``` 2. Edit the **local-only** config. Set a unique `AGENT_NAME` and the operator-provisioned `COMMS_REMOTE`. Configure git credentials separately (or set a credential-helper name, never a token value). 3. Confirm prerequisites and create the local checkout: ```bash ~/.local/bin/mos-comms.sh selftest ~/.local/bin/mos-comms.sh setup ``` 4. Install and enable the per-user timer: ```bash cp systemd/mos-comms.service systemd/mos-comms.timer ~/.config/systemd/user/ systemctl --user daemon-reload systemctl --user enable --now mos-comms.timer systemctl --user list-timers mos-comms.timer ``` 5. Send a deliberate test message from one host, then run `read` on the other host after its poll notification. Keep the relay branch dedicated to this protocol; do not share it with source-code work.