Skip to main content

pairmux

Let AI agents drive interactive terminal programs — and hand off to a human when they can't.

Homepage · Documentation · CLI reference · Changelog · Source

pairmux is a small Agent-Computer Interface layer over a terminal multiplexer, with no service for you to install or supervise. It runs natively on macOS, Linux and Windows: it uses tmux when tmux is installed on macOS or Linux, and otherwise its own built-in multiplexer (a PTY on Unix, ConPTY on Windows). Agents get a real terminal with persistent shell state and actionable command outcomes; humans keep normal access to the same live terminal — watch, take over, hand back.

Why pairmux

  • A real PTY. Exec-style agent shell tools run commands without a terminal, so REPLs, psql, ssh password prompts, docker exec -it, git rebase -i, pagers, and TUIs are impossible there. pairmux makes them drivable.
  • Human handoff on credentials and judgment calls. A recognized secret prompt never suggests an answer; wait --human --notify, attach, and note turn a blocked credential prompt into a resumable checkpoint — and the wait ends as soon as the human answers, note or no note.
  • Persistent shell state. source venv/bin/activate, export, and nvm use happen once in a live shell instead of being re-composed into every command.
  • Actionable waits and captured history. run blocks until completion, a recognized prompt, or timeout (never killing the command); journals retain full output with exit codes, and --json emits a versioned pairmux.v1 envelope with ordered next steps.

Install

With uv installed, add a persistent pairmux command to PATH:

uv tool install pairmux
pairmux version
pairmux doctor

This ordinary install retains your environment and uv configuration, including index overrides, and may reuse cache. Check command -v pairmux for an older installation shadowing the new one.

Update (v0.6.0+)

From v0.6.0 onward, update the currently running, verified persistent uv tool installation (including one created by the installer):

pairmux update

v0.5.3 and older have no update command. First use uv tool install --upgrade pairmux with your normal configuration to obtain v0.6.0+ when available, then use the new command.

The updater needs uv installed. It clears all inherited UV_* settings, ignores uv configuration, and reinstalls from https://pypi.org/simple with no persistent cache or source builds, replacing old exact pins, constraints, indexes, and extras. It selects the latest compatible stable wheel, never below the running version's numeric core; recognized alpha/beta/rc builds can advance to that core's final or a later stable release, but dev/snapshot builds are refused.

A version change returns updated; a same-version reinstall returns refreshed, not a no-op. Failures return E_UPDATE with a recovery hint, without a guaranteed rollback. Recover with the original manager, or uv tool install --upgrade pairmux for uv installs (normal configuration applies). It does not update Homebrew, RPM, pipx/pip, manual/development installs, or temporary uvx runs, and does not touch tmux. There are no command-specific options, automatic updates, sudo, or uv bootstrap/update; global --json is supported.

Optional temporary run with uvx

uvx pairmux version
uvx pairmux doctor

uvx remains supported. It uses a temporary tool environment, which uv may cache, or reuses an existing uv-managed installation; it does not promise the latest version or a fresh download every time. Temporary runs cannot use pairmux update.

Alternative installer

The inspectable installer persistently installs pairmux with uv from the public PyPI index:

curl -fsSL https://pairmux.treeleaves30760.com/install.sh | bash

To review it before execution, download successfully first, inspect the file, then run it:

installer_dir=$(mktemp -d) &&
curl -fsSL https://pairmux.treeleaves30760.com/install.sh -o "$installer_dir/install.sh" &&
less "$installer_dir/install.sh" &&
bash "$installer_dir/install.sh"

The one-line pipe executes downloaded code; it is not a substitute for that review. The installer clears all inherited UV_* settings, ignores uv configuration, and uses https://pypi.org/simple with no persistent cache and wheels only. Normal uv commands use your regular configuration. See installation guidance for PATH setup and other supported methods (pipx install pairmux or python -m pip install pairmux in a dedicated environment).

On Windows, the PowerShell installer applies the same PyPI-only uv policy natively, without administrator rights:

irm https://pairmux.treeleaves30760.com/install.ps1 | iex

Set $env:PAIRMUX_INSTALL_TARGET = 'wsl' first to install into a WSL distribution instead.

Requirements

The PyPI pairmux wheels contain a prebuilt native Go binary, so installation needs no Go toolchain or source build. Wheel installers require Python 3.9 or newer; the installed pairmux executable itself contains no Python code. If needed, the installer obtains uv from Astral's official installer, and uv may obtain managed Python from Astral's upstream Python distributions. Only the pairmux wheel comes from PyPI in that installer flow; uv/Python may come from Astral upstream.

PyPI package requirements and wheel targets:

  • macOS 12+, manylinux_2_17 (glibc 2.17+), or Windows 10 version 1809+ (ConPTY)
  • x86-64 or ARM64 (aarch64) on every operating system
  • tmux is optional. On macOS and Linux, pairmux uses tmux when it is installed (the tmux backend needs tmux 3.2 or newer, installed separately with your system package manager) and its built-in multiplexer otherwise. Windows always uses the built-in multiplexer. Set PAIRMUX_BACKEND=builtin or PAIRMUX_BACKEND=tmux to override the automatic choice. Neither the wheels nor the installers supply tmux or run sudo to install it.
  • WSL remains supported: inside WSL, pairmux installs and runs as on any other Linux system

From a source checkout, without PyPI

If you can clone the repository but cannot reach PyPI, install a development build from the clone with no build dependencies: python -m pip install . or uv tool install . builds the binary with a local Go 1.25+ toolchain, or packages a release binary you downloaded from GitHub Releases when you set PAIRMUX_PREBUILT_BINARY to its absolute path. Such builds get a development version and are not pairmux update targets. See the source install guide.

The quickstart below assumes the persistent pairmux command is on PATH. For temporary use, prefix each command with uvx.

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
pairmux skill install -t all

-t is an alias for --target. Use -t all to update only the supported agent configuration directories that already exist, including Cline, Roo Code, Kilo Code, and Factory Droid. 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 (on the tmux backend, with the configured tmux binding, default Ctrl-b d; see the CLI reference for the built-in backend). 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

A terminal multiplexer remains the terminal-state engine: tmux when it is installed on macOS or Linux, otherwise pairmux's own built-in server, which drives a PTY on Unix and ConPTY on native Windows. Short-lived pairmux commands add completion detection, captured output, model-friendly shaping, and coordination around the live pane. pairmux attach connects a human to the same managed terminal whenever a human needs to observe or take over.

pairmux is open source under the MIT License.

Metadata

Release files for pairmux 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Built distributions (wheels)

Table of built distributions (wheels) for pairmux 1.1.0
File
pairmux-1.1.0-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
pairmux-1.1.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
pairmux-1.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
pairmux-1.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl Python 3 none Linux glibc 2.17+ ARM64 Details
pairmux-1.1.0-py3-none-macosx_12_0_x86_64.whl Python 3 none macOS 12.0+ x86-64 Details
pairmux-1.1.0-py3-none-macosx_12_0_arm64.whl Python 3 none macOS 12.0+ ARM64 Details

Total release size: 10.6 MB

Release files / pairmux-1.1.0-py3-none-win_arm64.whl

Download URL pairmux-1.1.0-py3-none-win_arm64.whl
Size 1.7 MB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
b99ea7ab57b03326e56f22616db6401e36a4d1d99946967ac0d5f54e76528efd
BLAKE2b-256 checksum
How to use checksums
f60b39921e02a10108344a1ef677a15ccacc9139617d7c061a124057e092f5cc
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release files / pairmux-1.1.0-py3-none-win_amd64.whl

Download URL pairmux-1.1.0-py3-none-win_amd64.whl
Size 1.9 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
f6e410dc60c96661b4a2fe5db6b951856cc98096090a6407c2f8632acc34a1ea
BLAKE2b-256 checksum
How to use checksums
1902d4ca7a4c0ceaf086525415fb558c37300eceb94b1dee8304fd6109a6e1ef
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release files / pairmux-1.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL pairmux-1.1.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 1.8 MB
Tags Linux glibc 2.17+ x86-64 Python 3
SHA-256 checksum
How to use checksums
4eea446a36c20825ac7deb36dc7a5dffc8524d634015e8013b73f22901f81423
BLAKE2b-256 checksum
How to use checksums
76d3d36411c202f81ee38b01d595c15ae6e817ab63bc2e009f428d02d727a2f5
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release files / pairmux-1.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL pairmux-1.1.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 1.7 MB
Tags Linux glibc 2.17+ ARM64 Python 3
SHA-256 checksum
How to use checksums
100ab9737d278c5ccfe65cb620c598103fc692d96c5fb33127680b86c4a09c65
BLAKE2b-256 checksum
How to use checksums
e7f31a67c718dbdd34b8cd44243963d3f7013dff2d7994f21ab15bbb8bff936e
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release files / pairmux-1.1.0-py3-none-macosx_12_0_x86_64.whl

Download URL pairmux-1.1.0-py3-none-macosx_12_0_x86_64.whl
Size 1.8 MB
Tags Python 3 macOS 12.0+ x86-64
SHA-256 checksum
How to use checksums
eb5291bf251cfd5b3b222c6ee9ed3b9b7970d6bc3acd3af3e15c8d3a55ab8d99
BLAKE2b-256 checksum
How to use checksums
9e8b71766ed6804f1d5a5ee976d4766030ca0761ffc421df8559237c6474e74e
Upload date
Uploaded using Trusted Publishing?
What is 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}

Release files / pairmux-1.1.0-py3-none-macosx_12_0_arm64.whl

Download URL pairmux-1.1.0-py3-none-macosx_12_0_arm64.whl
Size 1.7 MB
Tags Python 3 macOS 12.0+ ARM64
SHA-256 checksum
How to use checksums
e91be6d7a2257cb2e8153194b3139425686d39ba4c50355221590bd666dfb6c6
BLAKE2b-256 checksum
How to use checksums
ba78c1579d31ddb63a890943d7bf993e525b811bc5841c7990554132081cf0c0
Upload date
Uploaded using Trusted Publishing?
What is 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}

Security for pairmux 1.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page