Lightweight tmux automation wrapper and renderer.
Project description
tmux-wrapper
tmux-wrapper is a Python module and CLI for driving a tmux session like a
human: type text, press key chords, inspect what changed, and scroll through
history.
It is aimed at agent workflows, test automation, and other situations where tmux should be treated as an interactive device instead of a bag of ad-hoc tmux CLI commands.
Installation
pip install tmux-wrapper
After installation, the CLI command is:
tmux-c
To print the bundled inline skill/help text:
tmux-c skill
Requirements
- Python 3.6+
tmuxinstalled and available onPATH
Core Model
Treat one tmux session as a serialized device.
For a given session:
- send one action
- wait briefly or inspect
- then send the next action
Do not overlap wrapper actions against the same session.
The most important mental model is:
tmux-wrapperis not a screenshot reader- it is an incremental observer whose output depends on the previous capture
Once you treat it that way, the workflow becomes much more predictable.
Main API
from tmux_wrapper import Keys, TMUXWrapper
type(text)sends literal text only.press(chords)sends one or more key chords.glance()is the default inspection method.view()is the fallback inspection method whenglance()is too compressed.scroll_up(lines=3)/scroll_down(lines=3)provide line-based history scrolling.snapshot()is intentionally disabled.
Inspection Semantics
glance()
glance() is the default inspection method.
It returns:
- newly added lines as
!!... - unchanged regions as
...[N unchanged line(s)] [Nothing Changed]when no new additions appeared
Example:
...[12 unchanged lines]
!!new output line
...[3 unchanged lines]
view()
view() is the fallback when you need more context.
Compared with glance():
- it keeps unchanged context lines
- it is better when you want the precise current screen region
- it is noisier than
glance()
Recommended Workflow
Default to glance(). Use view() only when glance() does not provide
enough context.
Python
from tmux_wrapper import Keys, TMUXWrapper
tmux = TMUXWrapper(session="demo")
tmux.glance()
tmux.type("echo hello")
tmux.glance()
tmux.press([(Keys.Enter,)])
print(tmux.glance())
print(tmux.view())
CLI
tmux-c demo glance
tmux-c demo type "echo hello"
tmux-c demo glance
tmux-c demo press Enter
tmux-c demo glance
tmux-c demo view
Command Entry Safety
- Before typing into an existing shell, inspect first.
- If the pane may still be running something, use
press Ctrl+C, then inspect again until you see a stable prompt. - If a shell line may already contain partial input, clear it before retyping.
- Prefer
press Ctrl+Cfor interrupting a running process. - Use
press Ctrl+Uonly when you specifically want to clear the current shell line. - Do not send
type "..."andpress Enterin the same parallel batch. - For long commands, prefer:
glancetypeglanceor a short waitpress Enterglance
- If the command text is visible at the prompt but did not execute, press
Enteronce and inspect. Do not retype until you know the line is clean.
Recommended shared-shell pattern:
tmux-c demo glance
tmux-c demo press Ctrl+C
tmux-c demo glance
tmux-c demo type "python your_long_running_command.py ..."
tmux-c demo glance
tmux-c demo press Enter
tmux-c demo glance
Common Patterns
Run a command
tmux-c demo type "pytest -q"
tmux-c demo press Enter
tmux-c demo glance
Interrupt
tmux-c demo press Ctrl+C
Pane navigation
tmux-c demo press Ctrl+B Left
tmux-c demo press Ctrl+B Right
Zoom toggle
tmux-c demo press Ctrl+B Z
Scroll through output
tmux-c demo scroll_up 20
tmux-c demo glance
tmux-c demo scroll_down 20
tmux-c demo glance
Practical Usage Notes
glance()is best for “what was added?”view()is better when you want the exact visible screen regionscroll_up()enters tmux history; it does not rerun the commandscroll_down 9999is a practical way to return to the bottom and usually exits copy mode too- When reading the top of a big file, the most reliable flow is:
- print the whole file once
- scroll up in small steps
- inspect with
glance()
- If you scroll too far in one jump, you may end up in older terminal history instead of the output you just produced
- The diff baseline persists per session, so always keep track of what the last capture was
- If the session becomes messy, the usual recovery pattern is:
press Ctrl+Cscroll_down 9999- inspect
- rerun the command
Session Behavior
TMUXWrapper(session="name")creates the session if it does not already exist.- If the wrapper created the session, object cleanup deletes it by default.
- Calling
delete()always deletes the session immediately. view()andglance()are stateful because they update the stored baseline.- CLI baseline state is persisted per session so separate
tmux-cinvocations can still diff correctly.
Development
Install development dependencies with uv:
uv sync --dev
Run tests with the repo default interpreter:
env -u VIRTUAL_ENV uv run pytest -q
Run the same suite against specific Python versions:
env -u VIRTUAL_ENV uv run --python 3.6 --group dev pytest -q
env -u VIRTUAL_ENV uv run --python 3.8 --group dev pytest -q
env -u VIRTUAL_ENV uv run --python 3.12 --group dev pytest -q
Build distributions:
env -u VIRTUAL_ENV uv build
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tmux_wrapper-0.1.4.tar.gz.
File metadata
- Download URL: tmux_wrapper-0.1.4.tar.gz
- Upload date:
- Size: 19.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9424ab1862ee25cf38255636e111850c5a2a62ee4f67683e76f6829fb37103af
|
|
| MD5 |
55e7772f6f71e0d69f9b3bb66c628a82
|
|
| BLAKE2b-256 |
184aa70cd888037660b8d559375a19dcd1993ac903626986997ef1b3ba58f58a
|
Provenance
The following attestation bundles were made for tmux_wrapper-0.1.4.tar.gz:
Publisher:
python-publish.yml on Randomizez/TmuxWrapper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tmux_wrapper-0.1.4.tar.gz -
Subject digest:
9424ab1862ee25cf38255636e111850c5a2a62ee4f67683e76f6829fb37103af - Sigstore transparency entry: 1277148760
- Sigstore integration time:
-
Permalink:
Randomizez/TmuxWrapper@40f6f379f31ba51cb6c21d6c7c5ffe20b53b7269 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/Randomizez
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@40f6f379f31ba51cb6c21d6c7c5ffe20b53b7269 -
Trigger Event:
push
-
Statement type:
File details
Details for the file tmux_wrapper-0.1.4-py3-none-any.whl.
File metadata
- Download URL: tmux_wrapper-0.1.4-py3-none-any.whl
- Upload date:
- Size: 16.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c1b6efbc77e4d44b2ed1218553be386d2714ad6a9747bcedc4f3b7ced8aa9eed
|
|
| MD5 |
f0ea086c11f3ef2069eb3244e5ab6b15
|
|
| BLAKE2b-256 |
3d77e389ea9109cf0f2739f1f3d194795ece65cc7879866e8aeff222bb888d21
|
Provenance
The following attestation bundles were made for tmux_wrapper-0.1.4-py3-none-any.whl:
Publisher:
python-publish.yml on Randomizez/TmuxWrapper
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tmux_wrapper-0.1.4-py3-none-any.whl -
Subject digest:
c1b6efbc77e4d44b2ed1218553be386d2714ad6a9747bcedc4f3b7ced8aa9eed - Sigstore transparency entry: 1277148880
- Sigstore integration time:
-
Permalink:
Randomizez/TmuxWrapper@40f6f379f31ba51cb6c21d6c7c5ffe20b53b7269 -
Branch / Tag:
refs/tags/v0.1.4 - Owner: https://github.com/Randomizez
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@40f6f379f31ba51cb6c21d6c7c5ffe20b53b7269 -
Trigger Event:
push
-
Statement type: