Skip to main content

Blocking tmux terminal control for AI agents, with captured logs and live human handoff

Project description

pairmux

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

Documentation · CLI reference · Changelog · Source

pairmux is a small coordination layer over tmux with no separate pairmux service to supervise. Agents get actionable command outcomes and clean, bounded-by-default output; humans keep normal access to the same live terminal.

Why pairmux

  • Actionable waits. run blocks until a command completes, a recognized prompt appears, or its timeout expires. Completed runs include the exit code and duration; if no completion was observed by the deadline, the response reports running and does not kill the command.
  • Captured history. Managed terminals write pane output to a per-terminal journal. Routine reads stay bounded, while explicit log selectors retrieve a captured command or selected journal history. Truncated replies point to the command that fetches the rest.
  • Shared control. Humans can watch, attach, and leave a note. Read-only observation is lock-free; only one run writer is allowed per terminal, and a conflict returns E_BUSY.
  • Agent-readable replies. --json emits a versioned pairmux.v1 envelope with status, shaped output, recovery hints, and ordered next steps.

Install

uv tool install pairmux
# or
pipx install pairmux
# or, inside a dedicated environment
python -m pip install pairmux

The wheel contains a prebuilt native Go binary, so installation needs no Go toolchain or source build. Wheel installers must select Python 3.9 or newer; the installed pairmux executable itself contains no Python code.

PyPI package requirements and wheel targets:

  • tmux 3.2 or newer
  • macOS 12+ or manylinux_2_17 (glibc 2.17+)
  • x86-64 or ARM64 (aarch64)
  • no native Windows wheel; use a compatible Linux distribution inside WSL

Check the local environment after installation:

pairmux doctor

60-second quickstart

Create one managed terminal, then run commands in it:

pairmux --json new --name demo
pairmux --json run demo "echo hello from pairmux"

# A timeout returns status=running; it does not kill the command.
pairmux --json run demo "sleep 2; echo finished" --timeout 1s

# When status is running, keep waiting without sleep-and-guess polling.
pairmux --json wait demo --idle 800
pairmux --json peek demo

wait --idle refreshes terminal state after output becomes quiet; silence alone is not treated as completion. peek and log are read-only, so other agents can inspect the same terminal without taking its writer lock.

Teach your agent

pairmux embeds its Agent Skill, including the new → run → wait/send/log loop and safe human handoff guidance:

pairmux skill install --target codex --dry-run
pairmux skill install --target codex

Use --target all to update only the supported agent configuration directories that already exist. See the Agent Skills guide for all targets and install locations.

MCP clients can launch the built-in stdio server and use the core terminal operations as typed tools:

{
  "command": "pairmux",
  "args": ["mcp", "serve"]
}

Interactive work and human handoff

After 800 ms of output quiet, pairmux recognizes supported prompt patterns: confirmations, password/passphrase/passcode prompts, pager markers, press-key messages, and Python's >>>. It reports awaiting-input and never auto-answers. Replace the uppercase placeholders below before sending ordinary input:

pairmux send NAME --text VALUE --enter

For a secret-shaped prompt, the response recommends pairmux wait NAME --human --notify. A human can enter the same live pane with pairmux attach NAME, provide the input, and detach with the configured tmux binding (default Ctrl-b d). Running pairmux note NAME "ready" afterward records a message and releases an agent waiting with --human; it does not itself detach or enforce control ownership. This avoids routing the input through the agent-facing send command. Prompt recognition is heuristic, desktop notification is best-effort, and whether an application echoes or records input remains application-dependent.

How it works

pairmux does not implement another PTY or add a background service of its own. tmux remains the terminal-state engine; short-lived pairmux commands add completion detection, captured output, model-friendly shaping, and coordination around the live pane. pairmux attach starts a native tmux client against the correct managed session whenever a human needs to observe or take over.

pairmux is open source under the MIT License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pairmux-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.4 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

pairmux-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.3 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

pairmux-0.1.1-py3-none-macosx_12_0_x86_64.whl (1.4 MB view details)

Uploaded Python 3macOS 12.0+ x86-64

pairmux-0.1.1-py3-none-macosx_12_0_arm64.whl (1.3 MB view details)

Uploaded Python 3macOS 12.0+ ARM64

File details

Details for the file pairmux-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

  • Download URL: pairmux-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: Python 3, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pairmux-0.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 487c91f45909ce2bd129f9d3f2c910e7a252d4082dc37b5b9bc73a5b1c7d5a3a
MD5 b26b31b080fed20558bdb8f2f4bf1f4b
BLAKE2b-256 361e2e3e4c45585aedf37052db12d9182fd1a626d45ae836ef284a41707484de

See more details on using hashes here.

File details

Details for the file pairmux-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

  • Download URL: pairmux-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: Python 3, manylinux: glibc 2.17+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pairmux-0.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 fc2049db340d8335fc5c8ba0853ed61277dcb2a57ab84e5c4ba5479ddae20e63
MD5 a3b9ca24323ae73f7f16564bc6d8a7ed
BLAKE2b-256 6da61fb4379fc4840fbb1295a28709e4a71d1e3d25873d68051198068f89e80c

See more details on using hashes here.

File details

Details for the file pairmux-0.1.1-py3-none-macosx_12_0_x86_64.whl.

File metadata

  • Download URL: pairmux-0.1.1-py3-none-macosx_12_0_x86_64.whl
  • Upload date:
  • Size: 1.4 MB
  • Tags: Python 3, macOS 12.0+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pairmux-0.1.1-py3-none-macosx_12_0_x86_64.whl
Algorithm Hash digest
SHA256 289d95080dce1f4a55f9cf3fcdad9556e2c59213651fc62c3a68c1f542fe045f
MD5 1c417cb9436a82b69a0fe28fb40b94ad
BLAKE2b-256 bfe39c385feb11eeef8325970b5ed2b8523f150f6e3d8a8319b661333dd57fe3

See more details on using hashes here.

File details

Details for the file pairmux-0.1.1-py3-none-macosx_12_0_arm64.whl.

File metadata

  • Download URL: pairmux-0.1.1-py3-none-macosx_12_0_arm64.whl
  • Upload date:
  • Size: 1.3 MB
  • Tags: Python 3, macOS 12.0+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for pairmux-0.1.1-py3-none-macosx_12_0_arm64.whl
Algorithm Hash digest
SHA256 423fedab111f1336fba6fc5008be62f94dd3234cbecd48d3e037aa553f3e3896
MD5 0c320a3a64ede30600ec7b2026c04e25
BLAKE2b-256 9b2e114fbedafe64fed8cad046758ad583e9df07bc7e01452fb2622ec0577e9f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page