import sys
from fastmux import *fastmux
fastmux controls and inspects tmux from Python. It exposes live Session, Window, and Pane objects for applications and agents that need to drive terminal programs or share a terminal with a user.
tmux() displays sessions, windows, and panes as a tree. tmux(target) returns a handle using standard target syntax, such as mysess:1.2, %5, or @3. A pane displays its current screen and exposes its transcript as an indexable, sliceable sequence of lines. Search works across panes, windows, or sessions with rg-style results.
Use send and send_keys to interact with a pane. fastmux.bg provides named background sessions that can be created or reused across tool calls and attached to by a user.
Install
pip install fastmuxYou will also need tmux itself installed and on your PATH.
Getting started
Start a throwaway session running anything you like. It’s created detached, so your terminal is untouched:
s = new_session([sys.executable,'-u','-c','import time\n'
'for i in range(30): print(f"line {i}")\n'
'time.sleep(600)'],
width=60, height=8)
p = s.pane
p.poll(wait_ms=2000) # wait for output to arrive
pline 23
line 24
line 25
line 26
line 27
line 28
line 29A Pane’s repr is its live screen. The whole transcript (scrollback included) works like a list of lines:
len(p), p[0], p[-1], p[5:7].lines(30, 'line 0', 'line 29', ('line 5', 'line 6'))
Split to the right, below, left, or above with rsplit, bsplit, lsplit, and asplit (no tmux -h/-v confusion). These operations preserve the current focus:
p.bsplit(size=3, cmd="top")
s.windows1: nbs* (2 panes) @0
1.1: [60x4] %0 python (active)
1.2: [60x3] %1 tmux
Pane methods support direct interaction and waiting:
p.send('ls\n')pastes text and polls for a response.p.send_keys('C-c')sends tmux key names.p.click('[menu]')clicks a coordinate or matching on-screen text.p.wheel()scrolls.p.wait()returns an exit status.
Use until='READY' to wait for a screen regex match, or settle_ms=300 to wait until the screen stops changing. See the full API documentation.
Search any scope (one pane, a window, a session, or every terminal you have) and get rg-style hits whose target can be pasted straight back into tmux():
hits = s.search('line 2')
hits0:1.1:2: line 2
0:1.1:20: line 20
0:1.1:21: line 21
0:1.1:22: line 22
0:1.1:23: line 23
0:1.1:24: line 24
0:1.1:25: line 25
0:1.1:26: line 26
0:1.1:27: line 27
0:1.1:28: line 28
0:1.1:29: line 29
tmux(hits[0].target)[-3:]line 27
line 28
line 29
── 0:1.1 %0 · lines 27-30 of 30And tmux() alone shows everything as a tree of sessions, windows, and panes:
tmux()0: 1 windows
1: nbs* (2 panes) @0
1.1: [60x4] %0 python (active)
1.2: [60x3] %1 top
s.kill()Background sessions
Named background sessions can be created in one tool call and controlled in later calls without retaining a Python handle. A user can attach to the same session.
fastmux.bg accepts a sid identifying a session name, a %pane_id, a handle, or None for the current pane. start_session creates a session or reuses an existing one:
from fastmux.bg import *sid = 'fastmux-demo-bg'
start_session(sid, width=60, height=8)
send(sid, 'echo $((6*7)) apples\n', wait_ms=2000)A user can watch or type in the session with tmux attach -t fastmux-demo-bg. Polling tracks output already seen by the caller. New output that arrived between polls satisfies the next poll(sid) immediately.
managed_sessions() lists sessions created by start_session. close(sid) kills the specified session:
managed_sessions()close(sid)