Typed library that provides an ORM wrapper for tmux, a terminal multiplexer.
Project description
⚙️ libtmux
Drive tmux from Python: typed, object-oriented control over servers, sessions, windows, and panes.
🐍 What is libtmux?
libtmux is a typed Python API over tmux, the terminal multiplexer. Stop shelling out and parsing tmux ls. Instead, interact with real Python objects: Server, Session, Window, and Pane. The same API powers tmuxp, so it stays battle-tested in real-world workflows.
✨ Features
- Typed, object-oriented control of tmux state
- Query and traverse live sessions, windows, and panes
- Raw escape hatch via
.cmd(...)on any object - Works with multiple tmux sockets and servers
- Context managers for automatic cleanup
- pytest plugin for isolated tmux fixtures
- Proven in production via tmuxp and other tooling
Requirements & support
- tmux: >= 3.2a
- Python: >= 3.10 (CPython and PyPy)
Maintenance-only backports (no new fixes):
📦 Installation
Stable release:
pip install libtmux
With pipx:
pipx install libtmux
With uv / uvx:
uv add libtmux
uvx --from "libtmux" python
From the main branch (bleeding edge):
pip install 'git+https://github.com/tmux-python/libtmux.git'
Tip: libtmux is pre-1.0. Pin a range in projects to avoid surprises:
requirements.txt:
libtmux==0.50.*
pyproject.toml:
libtmux = "0.50.*"
🚀 Quickstart
Open a tmux session
First, start a tmux session to connect to:
$ tmux new-session -s foo -n bar
Pilot your tmux session via Python
Use ptpython, ipython, etc. for a nice REPL with autocompletions:
$ pip install --user ptpython
$ ptpython
Connect to a live tmux session:
>>> import libtmux
>>> svr = libtmux.Server()
>>> svr
Server(socket_path=/tmp/tmux-.../default)
Tip: You can also use tmuxp's tmuxp shell to drop straight into your
current tmux server / session / window / pane.
Run any tmux command
Every object has a .cmd() escape hatch that honors socket name and path:
>>> server = Server(socket_name='libtmux_doctest')
>>> server.cmd('display-message', 'hello world')
<libtmux...>
Create a new session:
>>> server.cmd('new-session', '-d', '-P', '-F#{session_id}').stdout[0]
'$...'
List and filter sessions
>>> server.sessions
[Session($... ...), ...]
Filter by attribute:
>>> server.sessions.filter(history_limit='2000')
[Session($... ...), ...]
Direct lookup:
>>> server.sessions.get(session_id=session.session_id)
Session($... ...)
Control sessions and windows
Learn more about Workspace Setup
>>> session.rename_session('my-session')
Session($... my-session)
Create new window in the background (don't switch to it):
>>> bg_window = session.new_window(attach=False, window_name="bg-work")
>>> bg_window
Window(@... ...:bg-work, Session($... ...))
>>> session.windows.filter(window_name__startswith="bg")
[Window(@... ...:bg-work, Session($... ...))]
>>> session.windows.get(window_name__startswith="bg")
Window(@... ...:bg-work, Session($... ...))
>>> bg_window.kill()
Split windows and send keys
Learn more about Pane Interaction
>>> pane = window.split(attach=False)
>>> pane
Pane(%... Window(@... ...:..., Session($... ...)))
Type inside the pane (send keystrokes):
>>> pane.send_keys('echo hello')
>>> pane.send_keys('echo hey', enter=False)
>>> pane.enter()
Pane(%... ...)
Capture pane output
>>> pane.clear()
Pane(%... ...)
>>> pane.send_keys("echo 'hello world'", enter=True)
>>> pane.cmd('capture-pane', '-p').stdout # doctest: +SKIP
["$ echo 'hello world'", 'hello world', '$']
Traverse the hierarchy
Navigate from pane up to window to session:
>>> pane.window
Window(@... ...:..., Session($... ...))
>>> pane.window.session
Session($... ...)
Core concepts
| libtmux object | tmux concept | Notes |
|---|---|---|
Server |
tmux server / socket | Entry point; owns sessions |
Session |
tmux session ($0, $1,...) |
Owns windows |
Window |
tmux window (@1, @2,...) |
Owns panes |
Pane |
tmux pane (%1, %2,...) |
Where commands run |
Also available: Options and Hooks abstractions for tmux configuration.
Collections are live and queryable:
server = libtmux.Server()
session = server.sessions.get(session_name="demo")
api_windows = session.windows.filter(window_name__startswith="api")
pane = session.active_window.active_pane
pane.send_keys("echo 'hello from libtmux'", enter=True)
tmux vs libtmux vs tmuxp
| Tool | Layer | Typical use case |
|---|---|---|
| tmux | CLI / terminal multiplexer | Everyday terminal usage, manual control |
| libtmux | Python API over tmux | Programmatic control, automation, testing |
| tmuxp | App on top of libtmux | Declarative tmux workspaces from YAML / TOML |
Testing & fixtures
Learn more about the pytest plugin
Writing a tool that interacts with tmux? Use our fixtures to keep your tests clean and isolated.
def test_my_tmux_tool(session):
# session is a real tmux session in an isolated server
window = session.new_window(window_name="test")
pane = window.active_pane
pane.send_keys("echo 'hello from test'", enter=True)
assert window.window_name == "test"
# Fixtures handle cleanup automatically
- Fresh tmux server/session/window/pane fixtures per test
- Temporary HOME and tmux config fixtures keep indices stable
TestServerhelper spins up multiple isolated tmux servers
When you might not need libtmux
- Layouts are static and live entirely in tmux config files
- You do not need to introspect or control running tmux from other tools
- Python is unavailable where tmux is running
Project links
Topics: Traversal · Filtering · Pane Interaction · Workspace Setup · Automation Patterns · Context Managers · Options & Hooks
Reference: Docs · API · pytest plugin · Architecture · Changelog · Migration
Project: Issues · Coverage · Releases · License · Support
The Tao of tmux — deep-dive book on tmux fundamentals
Contributing & support
Contributions are welcome. Please open an issue or PR if you find a bug or want to improve the API or docs. If libtmux helps you ship, consider sponsoring development via support.
Project details
Release history Release notifications | RSS feed
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 libtmux-0.53.0.tar.gz.
File metadata
- Download URL: libtmux-0.53.0.tar.gz
- Upload date:
- Size: 405.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d19af4cea0c19543954d7e7317c7025c0739b029cccbe3b843212fae238f1bd
|
|
| MD5 |
633c81e109769429fe06b5171768acde
|
|
| BLAKE2b-256 |
e728e2b252817cb181aec2f42fe2d1d7fac5ec9c4d15bfb2b8ea4bd1179e4244
|
Provenance
The following attestation bundles were made for libtmux-0.53.0.tar.gz:
Publisher:
tests.yml on tmux-python/libtmux
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
libtmux-0.53.0.tar.gz -
Subject digest:
1d19af4cea0c19543954d7e7317c7025c0739b029cccbe3b843212fae238f1bd - Sigstore transparency entry: 763814395
- Sigstore integration time:
-
Permalink:
tmux-python/libtmux@37812a7f731dc1aeee309e2a5e5ccc1d349e4e08 -
Branch / Tag:
refs/tags/v0.53.0 - Owner: https://github.com/tmux-python
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
tests.yml@37812a7f731dc1aeee309e2a5e5ccc1d349e4e08 -
Trigger Event:
push
-
Statement type:
File details
Details for the file libtmux-0.53.0-py3-none-any.whl.
File metadata
- Download URL: libtmux-0.53.0-py3-none-any.whl
- Upload date:
- Size: 77.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
024b7ae6a12aae55358e8feb914c8632b3ab9bd61c0987c53559643c6a58ee4f
|
|
| MD5 |
83e5e174a81824cf46f5d69d2e87eaf3
|
|
| BLAKE2b-256 |
0ed02e8bc5caa639ebb9f8801ba0be7070a28d48d8ed60e2a428d40f71fb88b8
|
Provenance
The following attestation bundles were made for libtmux-0.53.0-py3-none-any.whl:
Publisher:
tests.yml on tmux-python/libtmux
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
libtmux-0.53.0-py3-none-any.whl -
Subject digest:
024b7ae6a12aae55358e8feb914c8632b3ab9bd61c0987c53559643c6a58ee4f - Sigstore transparency entry: 763814397
- Sigstore integration time:
-
Permalink:
tmux-python/libtmux@37812a7f731dc1aeee309e2a5e5ccc1d349e4e08 -
Branch / Tag:
refs/tags/v0.53.0 - Owner: https://github.com/tmux-python
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
tests.yml@37812a7f731dc1aeee309e2a5e5ccc1d349e4e08 -
Trigger Event:
push
-
Statement type: