Typed library that provides an ORM wrapper for tmux, a terminal multiplexer.
—
Pane management in libtmux provides direct interaction with individual terminal instances within tmux windows. Panes represent the actual shell processes where commands are executed and output is captured.
Create and manage pane instances with proper resource management and context support.
@dataclasses.dataclass()
class Pane(Obj):
"""
tmux Pane object.
Pane instances can send commands directly to a pane, or traverse
between linked tmux objects.
"""
server: Server
def __enter__(self) -> Self:
"""Enter the context, returning self."""
def __exit__(
self,
exc_type: type[BaseException] | None,
exc_value: BaseException | None,
exc_tb: types.TracebackType | None
) -> None:
"""Exit the context, killing the pane if it exists."""
@classmethod
def from_pane_id(cls, server: Server, pane_id: str) -> Pane:
"""Create Pane from existing pane_id."""Access and update pane state, properties, and position information from tmux.
def refresh(self) -> None:
"""Refresh pane attributes from tmux."""
@property
def id(self) -> str | None:
"""Alias of Pane.pane_id."""
@property
def index(self) -> str | None:
"""Alias of Pane.pane_index."""
@property
def height(self) -> str | None:
"""Alias of Pane.pane_height."""
@property
def width(self) -> str | None:
"""Alias of Pane.pane_width."""
@property
def window(self) -> Window:
"""Parent window of pane."""
@property
def session(self) -> Session:
"""Parent session of pane."""Determine pane position within window layout.
@property
def at_top(self) -> bool:
"""True if pane is at top edge of window."""
@property
def at_bottom(self) -> bool:
"""True if pane is at bottom edge of window."""
@property
def at_left(self) -> bool:
"""True if pane is at left edge of window."""
@property
def at_right(self) -> bool:
"""True if pane is at right edge of window."""Execute tmux commands within the pane context.
def cmd(
self,
cmd: str,
*args: t.Any,
target: str | int | None = None
) -> tmux_cmd:
"""
Execute tmux subcommand within pane context.
Automatically binds target by adding -t for object's pane ID to the command.
Pass target to keyword arguments to override.
Parameters:
- cmd: The tmux command to execute
- *args: Additional command arguments
- target: Optional custom target override (defaults to pane ID)
Returns:
tmux_cmd object with stdout, stderr, and return code
"""Send commands and capture output from the pane's terminal session.
def send_keys(
self,
cmd: str,
enter: bool | None = True,
suppress_history: bool | None = False,
literal: bool | None = False
) -> None:
"""
Send keys/text to pane via tmux send-keys.
A leading space character is added to cmd to avoid polluting the
user's history.
Parameters:
- cmd: Text or input to send into pane
- enter: Send enter after sending the input (default True)
- suppress_history: Prepend space to command to suppress shell history (default False)
- literal: Send keys literally (default False)
"""
def enter(self) -> Pane:
"""
Send carriage return to pane.
Returns:
Pane instance for method chaining
"""
def capture_pane(
self,
start: t.Literal["-"] | int | None = None,
end: t.Literal["-"] | int | None = None
) -> str | list[str]:
"""
Capture text from pane.
Parameters:
- start: Starting line number (0=first visible line, negative=history, "-"=start of history)
- end: Ending line number (0=first visible line, negative=history, "-"=end of visible pane)
Returns:
List of strings containing pane content
"""
def display_message(
self,
cmd: str,
get_text: bool = False
) -> str | list[str] | None:
"""
Display message to pane.
Displays a message in target-client status line.
Parameters:
- cmd: Special parameters to request from pane
- get_text: Returns only text without displaying message in status line
Returns:
Message text if get_text=True, None otherwise
"""Control pane state, selection, and focus within window.
def select(self) -> Pane:
"""
Select pane.
Returns:
Pane instance for method chaining
"""
def clear(self) -> Pane:
"""
Clear pane.
Returns:
Pane instance for method chaining
"""
def reset(self) -> Pane:
"""
Reset and clear pane history.
Returns:
Pane instance for method chaining
"""Create new panes by splitting the current pane.
def split(
self,
/,
target: int | str | None = None,
start_directory: StrPath | None = None,
attach: bool = False,
direction: PaneDirection | None = None,
full_window_split: bool | None = None,
zoom: bool | None = None,
shell: str | None = None,
size: str | int | None = None,
environment: dict[str, str] | None = None
) -> Pane:
"""
Split window and return Pane, by default beneath current pane.
Parameters:
- target: Optional custom target-pane, used by Window.split
- start_directory: Working directory for new window (str or PathLike)
- attach: Make new window the current window after creating (default False)
- direction: Split direction (PaneDirection enum). If none specified, assume down
- full_window_split: Split across full window width/height rather than active pane
- zoom: Expand pane
- shell: Execute command on splitting the window
- size: Cell/row or percentage to occupy with respect to current window
- environment: Environmental variables for new pane (tmux 3.0+)
Returns:
Pane object for the created pane
"""Resize individual panes within window layout.
def resize(
self,
/,
# Adjustments
adjustment_direction: ResizeAdjustmentDirection | None = None,
adjustment: int | None = None,
# Manual
height: str | int | None = None,
width: str | int | None = None,
# Zoom
zoom: bool | None = None,
# Mouse
mouse: bool | None = None,
# Optional flags
trim_below: bool | None = None
) -> Pane:
"""
Resize tmux pane.
Parameters:
- adjustment_direction: Direction to adjust (Up, Down, Left, Right)
- adjustment: Amount to adjust by
- height: resize-pane -y dimensions
- width: resize-pane -x dimensions
- zoom: Expand pane
- mouse: Resize via mouse
- trim_below: Trim below cursor
Returns:
Pane instance for method chaining
Raises:
LibTmuxException, PaneAdjustmentDirectionRequiresAdjustment, RequiresDigitOrPercentage
"""
def set_width(self, width: int) -> Pane:
"""
Set pane width.
Parameters:
- width: Pane width, in cells
Returns:
Pane instance for method chaining
"""
def set_height(self, height: int) -> Pane:
"""
Set pane height.
Parameters:
- height: Height of pane, in cells
Returns:
Pane instance for method chaining
"""Control pane termination and cleanup.
def kill(
self,
all_except: bool | None = None
) -> None:
"""
Kill Pane.
$ tmux kill-pane.
Parameters:
- all_except: Kill all panes except this one
"""import libtmux
server = libtmux.Server()
session = server.new_session('work')
window = session.new_window('main')
pane = window.active_pane
# Get pane information
print(f"Pane ID: {pane.id}")
print(f"Pane Size: {pane.width}x{pane.height}")
print(f"Position: top={pane.at_top}, left={pane.at_left}")
# Refresh pane state
pane.refresh()import libtmux
server = libtmux.Server()
session = server.new_session('temp')
window = session.new_window('work')
with window.split_window() as pane:
# Work with pane
pane.send_keys('echo "Hello World"')
# Pane automatically cleaned up on exitimport libtmux
server = libtmux.Server()
session = server.new_session('commands')
window = session.new_window('terminal')
pane = window.active_pane
# Send commands
pane.send_keys('ls -la')
pane.send_keys('echo "Processing..."')
pane.send_keys('date', enter=True)
# Capture output
import time
time.sleep(1) # Wait for commands to complete
output = pane.capture_pane()
print('\n'.join(output))
# Clear pane for next commands
pane.clear()import libtmux
server = libtmux.Server()
session = server.new_session('interactive')
window = session.new_window('python')
pane = window.active_pane
# Start Python interpreter
pane.send_keys('python3')
time.sleep(1)
# Send Python commands
pane.send_keys('import os')
pane.send_keys('print(os.getcwd())')
pane.send_keys('x = 2 + 2')
pane.send_keys('print(f"Result: {x}")')
# Capture Python output
output = pane.capture_pane()
python_output = [line for line in output if line.strip()]
print(python_output)
# Exit Python
pane.send_keys('exit()')import libtmux
server = libtmux.Server()
session = server.new_session('layout')
window = session.new_window('multi_pane')
# Start with active pane
main_pane = window.active_pane
# Split vertically (right side)
right_pane = main_pane.split_window(vertical=True)
# Split main pane horizontally (bottom)
bottom_pane = main_pane.split_window(vertical=False)
# Split right pane horizontally
bottom_right = right_pane.split_window(vertical=False)
# Resize panes
main_pane.set_width(80)
right_pane.resize('left', 5)
# Send different commands to each pane
main_pane.send_keys('htop')
right_pane.send_keys('tail -f /var/log/syslog')
bottom_pane.send_keys('cd /tmp && ls -la')
bottom_right.send_keys('python3')import libtmux
server = libtmux.Server()
session = server.new_session('monitoring')
window = session.new_window('files')
# Create panes for different monitoring tasks
log_pane = window.active_pane
cpu_pane = log_pane.split_window(vertical=True)
disk_pane = log_pane.split_window(vertical=False)
# Set up monitoring in each pane
log_pane.send_keys('tail -f /var/log/system.log')
cpu_pane.send_keys('top -o cpu')
disk_pane.send_keys('watch df -h')
# Capture initial state
time.sleep(2)
for i, pane in enumerate([log_pane, cpu_pane, disk_pane]):
content = pane.capture_pane(start=-10) # Last 10 lines
print(f"Pane {i} content:")
print('\n'.join(content[-5:])) # Show last 5 lines
print("---")Install with Tessl CLI
npx tessl i tessl/pypi-libtmux