Skip to main content

pairmux

Blocking, observable tmux terminals for AI agents — with live human handoff.

Driving a raw terminal is hard for agents for three separate reasons:

  • Timing. After sending a command, an agent has no signal for when it is done, so it guesses sleep N — and reads half-finished output or wastes time.
  • Information quality. A raw capture-pane view is screen-oriented: it may contain ANSI-driven redraws, omit scrolled-off output, and does not provide a command exit code or completion signal.
  • Human access. Many automation interfaces do not expose the same live terminal to a human who needs to observe or provide authorized input.

pairmux is an ACI (Agent-Computer Interface) layer on top of tmux: blocking calls return on a command completion, a recognized prompt, a requested condition, or timeout; a journal retains raw pane output while CLI reads shape it for agents; and pairmux attach opens a native tmux client on the managed session so a human can collaborate in the same pane.

Requirements

  • tmux >= 3.2 (for stable pipe-pane and pane user-option behavior).
  • macOS 12+ or Linux, on x86-64 or ARM64. There is no native Windows build; use a supported Linux distribution inside WSL.
  • Released pairmux executables are static Go binaries. Core terminal state needs no background pairmux service, although tmux keeps its normal server and mcp serve is an explicit foreground process. Installing the PyPI wheel requires Python 3.9+; building from a checkout requires Go 1.25+ and make.

Install

Platform wheels bundle the binary, so uv or pipx installs pairmux like any other tool:

uv tool install pairmux
# or: pipx install pairmux

The published wheels target macOS 12+ and manylinux_2_17 (glibc 2.17+) on x86-64 and ARM64.

Homebrew distribution is deferred until release binaries are signed, notarized, and verified through Gatekeeper. Use a wheel, Linux package, source build, or checksummed archive in the meantime.

Verify your environment

pairmux doctor probes everything pairmux depends on and prints an actionable report:

pairmux doctor

The exact paths and shell list depend on the machine. A healthy Linux result has this shape:

ok
pairmux doctor

✓ tmux 3.4 at /usr/bin/tmux (>= 3.2)
✓ state dir writable: /home/alice/.local/state/pairmux/.sockets/<endpoint-id>
✓ live probe bash: hooks; dash: sentinel
✓ notifier notify-send at /usr/bin/notify-send (desktop notifications available)

The live probe line reports which completion-detection tier each shell reaches. Fish 4+ emits compatible OSC 133 marks natively; fish without a ready mark degrades to a $status sentinel. See Concepts.

Quick start

Every command that emits a single pairmux response accepts --json for a machine-readable pairmux.v1 envelope; without it you get a friendly text block. attach and watch are interactive human interfaces, while mcp serve reserves stdout for MCP JSON-RPC. Commands followed by JSON below explicitly enable --json.

1. Open a terminal

pairmux --json new --name build
{"schema":"pairmux.v1","ok":true,"status":"created","terminal":"build","mode":"hooks","next":["pairmux run build \"echo hello\""]}

This opens a tmux window and starts capturing output into a journal. zsh, bash, and compatible fish configurations normally report mode: hooks; other shells, or a failed hook-ready probe, report mode: sentinel. Always act on the returned mode and status rather than assuming either one.

2. Run a command and block for an actionable outcome

No sleep, no guessing — run returns when the command completes, a recognized prompt has been quiet long enough to trust, or its timeout expires. A completed command includes the exit code and duration:

pairmux --json run build "echo hello world"
{"schema":"pairmux.v1","ok":true,"status":"done","terminal":"build","mode":"hooks","exit_code":0,"duration_ms":101,"output":"hello world"}

3. Long-running commands: the run → wait → peek loop

If a command outlives --timeout (default 60s), run returns status: running with the current tail instead of failing. You then keep waiting or look whenever you like:

pairmux --json run build 'for step in 1 2 3; do echo "step $step"; sleep 1; done' --timeout 1s
pairmux --json wait build --idle 800 # returns on idle, input, pane death, or timeout
pairmux --json peek build # read-only snapshot, any time

See the long-running commands guide.

4. Interactive programs

Start a separate terminal for an interactive flow. When its command goes quiet on a recognized prompt, pairmux reports awaiting-input and tells you how to answer:

pairmux --json new --name confirm
pairmux --json run confirm 'printf "Continue? [y/N] "; read answer; printf "answer=%s\n" "$answer"'
pairmux --json send confirm --text y --enter
pairmux --json wait confirm --idle 800
pairmux --json peek confirm

For password, passphrase, and passcode prompts, the returned next omits send and recommends a human handoff. The CLI cannot enforce that policy, so the driving agent must never guess or send the secret itself. See interactive programs and human collaboration.

5. Humans jump into the same terminal

pairmux attach build # run from an interactive terminal outside tmux
pairmux watch # live dashboard of every terminal

attach refuses a non-TTY or nested tmux client. If you are already in tmux, detach to the outer shell first or use another terminal, then run pairmux attach; switch-client cannot cross tmux servers to pairmux's named socket.

Next steps

  • CLI Reference — every command and flag, plus the full envelope schema.
  • Concepts — why pairmux is built the way it is: tmux as a state engine, endpoint-isolated journals, completion modes, and the idle backstop.
  • Long-running commands guide — the complete run/wait/peek playbook.
  • Agent Skills — install targets and the repeatable cross-agent benchmark runner.