tmux-amq/README.md
tegwick e995cab1b8
Some checks failed
tamq-ci / test (push) Failing after 5s
feat: add shell-native message routing
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a03397-4d51-7fd1-8ff2-946eb22ea2bc
2026-08-24 20:42:35 +02:00

200 lines
6.5 KiB
Markdown

# 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, direct `@repo:` routing, JSONL export/replay, and a Unix-socket protocol
for a later coordination-engine adapter.
## 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, leaves tmux's ordinary interactive shells untouched, 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.
## Exchange messages manually
Each managed shell exports its own repository slug as `TAMQ_REPO`. From the
`flex-auth` window, queue a message using the repository command installed for
the session:
```bash
@audit-core: please review the auth boundary
```
The spelling without the trailing colon is equivalent:
```bash
@audit-core please review the auth boundary
```
These are tamq-owned executable commands beside the installed `tamq` command,
not shell-specific aliases. Set `TAMQ_COMMAND_DIR` before startup to select a
different writable command directory already present on your shell's `PATH`.
Tamq refuses to overwrite unrelated commands. The shims only use tamq's durable
send operation. The long form remains available:
```bash
tamq send '@audit-core: please review the auth boundary'
```
In the `audit-core` window, inspect and acknowledge it:
```bash
tamq inbox
tamq ack <message-id>
```
Human inbox output is safe to paste into an ordinary shell because every line
is a comment. It includes the durable id needed by `ack`:
```text
#flex-auth: please review the auth boundary [m-...]
```
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 comment 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`. Manual messages remain durable and pending until acknowledged. They
are never injected as terminal keystrokes, so they cannot corrupt a command
being typed in the target pane.
After upgrading from an earlier alpha, recreate the managed session once so
existing panes inherit the neutral shell contract, repository command `PATH`,
and manual 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
```
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. Explicit `tamq tap` mode is a full-duplex PTY proxy around a command. It forwards
bytes unchanged in raw terminal mode, propagates terminal resize and lifecycle
signals, and observes complete input lines for `@repo:` routing.
This keeps tmux-specific topology concerns separate from reusable terminal I/O
observation and message identity.
Neutral endpoints use manual delivery: messages stay in the durable inbox and
never become pane input. The legacy pane-delivery path is available only with
the explicit `tamq start --tap --command ...` opt-in; it remains subject to the
retry and acknowledgement limitations tracked by `TAMQ-WP-0003`.
The visible endpoint label is `tmux-amq-<PID>`; 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"
[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.