# tmux-amq Tmux Agentic Message Queueing (`tamq`) provides repository-aware tmux sessions and a local, durable message queue. It does not assume who or what uses a pane. The local alpha provides tmux endpoint lifecycle, local SQLite history and leases, readable `To:` routing, JSONL export/replay, and a Unix-socket protocol for a later coordination-engine adapter. Agents and operators should start with the concise [TAMQ messaging introduction](TamqMessagingIntroduction.md). ## Install and start a local session Prerequisites must be available on `PATH`: Python 3.11+, [uv](https://docs.astral.sh/uv/), tmux, and gita. Each repository must already have an exact gita slug and path. Install or upgrade `tamq` as an isolated user tool: ```bash make install command -v tamq tamq --version ``` Start an attached two-repository shell session: ```bash tamq flex-auth audit-core ``` This creates or reuses the managed `tamq` session, opens same-named windows in the exact gita paths, starts an ordinary shell behind tamq's transparent PTY observer, and attaches to the first window. The explicit form is equivalent: ```bash tamq start flex-auth audit-core ``` Set up the session without attaching, then attach later: ```bash tamq start --detach flex-auth audit-core tamq status tamq attach ``` No initial command runs unless requested. To run one explicitly in each newly created window, use `--command`; tamq runs exactly that command and makes no assumption about its purpose: ```bash tamq --command codex flex-auth audit-core tamq start --command 'htop --tree' flex-auth audit-core ``` `--cmd` remains an alias for `--command`. Repeated starts reuse existing windows and never run another initial command in them. Select an endpoint delivery mode at startup. `output` is the safe default; `inbox` keeps messages durable without displaying them: ```bash tamq --mode output flex-auth audit-core tamq --mode inbox flex-auth audit-core ``` `--no-display` remains a compatibility alias for `--mode inbox`. Experimental `pushy` mode places a routed message in the target input buffer without Enter. `trigger` places the same input and submits it exactly once: ```bash tamq --mode pushy --command codex flex-auth audit-core tamq --mode trigger --command codex flex-auth audit-core ``` All messaging-enabled windows use the same terminal-neutral PTY observer, whether they contain a shell, a tool, or an explicitly selected coding agent. An operator submits one addressed line: ```text To:audit-core: Please review the authentication change. ``` Protocol keywords are case-insensitive, so `to:`, `TO:`, `cmd:`, and their mixed-case forms work as well. Repository slugs remain exact. For full-screen terminal programs, tamq also recognizes `To:` immediately after a conservative worker-output gutter such as the `•` used to frame assistant output; operator prompt gutters are not worker output. A worker may extend its addressed first line with non-empty follow-up output. The first empty line terminates and sends the block: ```text To:audit-core: Please review the authentication change. Context: AUTH-WP-0004-T02. Expected reply: accepted or blocked. ``` Operator input is forwarded unchanged and is delivered with `/o`; a line originating in worker output has no suffix: ```text From:flex-auth/o: Please review the authentication change. From:flex-auth: Worker-generated message. ``` Every delivered physical line carries the same `From:` prefix and is never routable. The observer suppresses recent exact operator lines when a TUI echoes or redraws them, so the echo cannot become a second worker message. Ambiguous exact echoes fail closed. Pushy and trigger still cannot infer the foreground program or protect input already being edited, so both remain explicit experiments. Startup requires the readable-duplex, trigger, worker-block, and line-limit capabilities and replaces incompatible old broker or tap processes. ## Exchange messages manually Each managed window has its own repository identity. From operator input in the `flex-auth` window, queue a message with: ```bash To:audit-core: please review the auth boundary ``` The same line at the start of worker output begins a worker-originated message block. Non-empty follow-up rows are included until an empty row, a new `To:` line, or worker exit. The keyword may use any letter case, and a recognized full-screen output gutter may precede it. The `@`, `#`, reply shorthand, and interactive recipient composer from earlier alphas have been removed. Operator input can change allowlisted runtime state: ```text Cmd: mode=trigger Cmd: maxmsg=16 Cmd: maxin=2048 Cmd: maxout=65536 Cmd: reset-limits ``` `Cmd:` is recognized only on the operator-input path; identical worker output is inert. The transparent input contract means the line also remains visible to the foreground program. Small tamq-owned shell absorbers prevent ordinary shells from reporting `To:repo:` and `Cmd:` as missing commands; tamq refuses to overwrite unrelated files. The explicit CLI send form is: ```bash tamq send 'To:audit-core: please review the auth boundary' ``` With normal `output` delivery, the target pane visibly receives: ```text From:flex-auth/o: please review the auth boundary ``` This uses the pane's tmux-reported `/dev/pts/` device—the same Unix terminal-output mechanism underlying tools such as `write(1)`. For an ordinary shell with screen rows above its cursor, tamq confines scrolling to those rows, writes the delivery immediately above the input row, and restores the cursor. Thus a partially typed command remains in place. If no safe row exists, tamq uses ordinary line output; alternate-screen programs receive the conservative fallback and may redraw over it. Neither path uses `send-keys`, sends Enter, or places bytes on the foreground process's stdin, so the durable inbox remains authoritative. In the `audit-core` window, inspect and acknowledge it: ```bash tamq inbox tamq ack ``` Human inbox output uses the same framing. Use `--json` or `tamq history` to get the durable id needed by `ack`: ```text From:flex-auth/o: please review the auth boundary ``` To explicitly consume pending messages through a command, use an inbox filter: ```bash tamq inbox --filter 'cat >> msg.log' ``` The command runs once per pending message with the readable `From:` form on standard input. `TAMQ_MESSAGE_ID`, `TAMQ_SENDER_REPO`, and `TAMQ_TARGET_REPO` are set in its environment. A zero exit acknowledges that message; a non-zero exit leaves it and all later messages pending. Filters never run in the background and cannot be combined with `--all` or `--json`. Outside a managed window, use `tamq inbox --repo audit-core` and optionally `--json`. Output-displayed messages remain durable and pending until acknowledged. Neither `output` nor `inbox` mode injects terminal keystrokes. Pushy places input without Enter. Trigger waits for terminal paste detection to settle and then adds exactly one Enter. A short endpoint-startup grace protects the first input delivery while the foreground program initializes. Both input modes record accepted placement as `injected`, not recipient acknowledgement. Every session window has independent, session-lifetime running counters for accepted outbound messages, operator input lines, and normalized worker output lines. Defaults are 8, 1024, and 32768 respectively: ```bash tamq --maxmsg 16 --maxin 2048 --maxout 65536 flex-auth audit-core ``` The same defaults can be set as `maxmsg`, `maxin`, and `maxout` under `[tamq]` in the configuration file. A message is rejected once any counter is equal to its limit. Tamq displays the applicable count and `Cmd: reset-limits` resets all three counters for the current window. Counters survive tap and broker restarts within the same managed-session generation and are visible in `tamq status`. After upgrading from an earlier alpha, recreate the managed session once so existing panes inherit the neutral shell contract, repository command `PATH`, and terminal-output broker registration: ```bash tamq stop tmux kill-session -t tamq tamq flex-auth audit-core ``` For degraded tmux-only use, `tamq start --no-service ...` skips socket endpoint registration and durable messaging. Stop the broker and remove the managed tmux session explicitly when finished: ```bash tamq stop tmux kill-session -t tamq ``` For a runaway or stale installation, use the emergency cleanup command from a terminal outside the managed session. It is a dry run unless `--yes` is given: ```bash tamq cleanup tamq cleanup --yes make cleanup ``` Confirmed cleanup stops only the verified tamq broker, closes only a tmux session carrying tamq's management marker, disconnects transient endpoints, clears leases and line counters, removes the configured socket/PID/lock files, deletes only tamq-generated protocol absorbers (including legacy `@repo` shims), and removes owned stale `tamq-*` tmux sockets. Durable message history and unrelated tmux sessions or files are preserved. `make cleanup` is the convenient confirmed form and preserves that same scope. The command is idempotent; an ownership mismatch is reported instead of being removed. History remains a separate explicit operation. A reflected delivery incident can be selected by durable receipt direction, dry-run, and then removed without age-based purging: ```bash tamq purge --feedback-chain m-... tamq purge --feedback-chain m-... --yes ``` Uninstall the user tool from the checkout with `make uninstall`, or from anywhere with `uv tool uninstall tmux-amq`. ## Development ```bash uv run pytest uv run tamq --help uv run tamq --version uv run tamq start net-kingdom railiance-platform uv run tamq attach ``` The alpha includes the local SQLite queue, neutral tmux endpoint manager, strict gita target validation, manual inbox, control-mode client, and an explicit PTY tap for integration experiments. Coordination-engine integration remains a later phase. ## Terminal architecture `tamq` separates terminal coordination into three layers: 1. tmux control mode is the topology and output/control stream; 2. the local broker assigns endpoint/source identity and durably queues intent; 3. `tamq tap` is a full-duplex PTY proxy around every messaging-enabled shell or explicit command. It forwards bytes unchanged in raw terminal mode, propagates resize and lifecycle signals, observes operator input, and normalizes worker output for case-insensitive start-of-content `To:` routing, including conservative full-screen worker-output gutters. This keeps tmux-specific topology concerns separate from reusable terminal I/O observation and message identity. Normal endpoints use terminal-output delivery: each message is written once to the target pane's PTY output and stays pending in the durable inbox until acknowledged. `--mode inbox` selects inbox-only manual mode. Neither becomes pane input. Experimental `--mode pushy` places a sanitized `From:` block without Enter; `--mode trigger` performs the same placement, lets paste detection settle, and submits once. The PTY observer records explicit operator/worker provenance and suppresses echoed operator lines before they can route again. The older pane-delivery experiment remains available only with the explicit `tamq start --tap --command ...` opt-in. Both input paths remain subject to the retry and acknowledgement limitations tracked by `TAMQ-WP-0003`. The visible endpoint label is `tmux-amq-`; each boot also receives an instance nonce so PID reuse cannot collide with prior leases or receipts. ## Configuration Configuration is read from `${XDG_CONFIG_HOME:-~/.config}/tamq/config.toml` (or `$TAMQ_CONFIG`). Environment variables such as `TAMQ_SOCKET` and `TAMQ_STATE_DIR` take precedence. The purge and startup advisory defaults can be tuned without changing command lines: ```toml [tamq] state_dir = "/run/user/1000/tamq" purge_before = "365d" purge_max_size = "100MB" history_max_size = "100MB" delivery_poll_interval = "0.5" maxmsg = 8 maxin = 1024 maxout = 32768 [policy.profiles.diagnostics] safety_gated_max_attempts = 2 delivery_ack_mode = "acknowledged" ``` Policy profiles accept a safety-gated retry cap of at most nine attempts, but the alpha delivery path does not enforce attempt counting yet. Explicit acknowledgement exists, while `delivery_ack_mode` enforcement and bounded retry state are tracked in `TAMQ-WP-0003`. Use `--policy-profile` to select a profile; `--orwell` enables explicitly unsafe local diagnostics. The Unix socket service supports structured `ping`, `register`, `send`, `history`, `ack`, `endpoints`, and `disconnect` operations. Endpoint registrations and messages are persisted in the same local SQLite database; delivery remains delegated to the control-mode adapter.