tmux

Tools to let Solveit view tmux buffers

Overview

The tmux tools module provides functions to capture and inspect content from tmux sessions, windows, and panes. These are particularly useful when working with Solveit’s AI assistant to debug terminal sessions, share command output, or monitor multiple processes.

Using as Solveit Tools

To give the AI assistant access to your tmux sessions, simply reference the tools using the usual ampersand notation – tmux_tool_info() will add a note with the full list for you:

dialoghelper.tmux tools: &`[pane, list_panes, panes, list_windows, windows, list_sessions, sessions]`

This allows the assistant to inspect your terminal state and help with debugging, process monitoring, or understanding command outputs across multiple panes.

Function Hierarchy

The module is organized from specific to broad:

Each capture function returns the visible terminal content plus additional scrollback history (default 500 lines, which can be modified by calling set_default_history(n)).

Common Use Cases with Solveit’s AI

Debug errors across terminals: When something breaks in one pane, the AI can see all your terminals at once to understand context:

My script is failing in pane 1, can you help?

The AI sees your error messages, the commands you ran, and even what’s happening in other panes (like log files you might be tailing).

Monitor long-running processes: Check on multiple jobs without switching windows:

How are my training runs doing?

The AI can inspect all your windows - seeing if processes completed, checking for errors, or summarizing outputs from different experiments running in parallel.

Reconstruct lost commands: When you can’t remember what you typed earlier:

What was that curl command I used in the other window?

The AI can search through all your session history to find specific commands, even if they’ve scrolled off screen or are in a different window.

Using as Python Functions

You can also use these functions directly in code to search and analyze terminal content. Here are some examples:

Find all lines containing “error” across all sessions:

all_content = sessions(n=2000)
errors = [(path, line)
          for path, content in flatten_dict(all_content)
          for line in content.splitlines()
          if 'error' in line.lower()]

Find which pane contains a specific command:

found = {path: content for path, content in flatten_dict(windows(n=1000))
    if 'docker run' in content}

Details

def shell_ret(*args, capture_output=True, text=True, shell=True, ret=True, **kwargs):
    "Shortcut for `subprocess.run(shell=True)`"
    o = subprocess.run(*args, shell=shell, text=text, capture_output=capture_output, **kwargs)
    return (o.stdout or o.stderr) if ret else o

source

shell_ret


def shell_ret(
    cmd:str, capture_output:bool=True, text:bool=True, ret:bool=True, host:str=None, # Optional SSH Host
    ip:str=None, # Optional SSH IP
    user:str=None, # Optional SSH user
    keyfile:str=None, # Optional SSH keyfile
):

Run shell command locally or over ssh (use host for alias, or ip/user/keyfile)

print(shell_ret('du -sh'))
568K    .
print(shell_ret('du -sh', host='hack'))
14G .

source

set_default_history


def set_default_history(
    n:int
):

Set the default number of lines to capture from tmux history

The set_default_history function sets a global default for how many lines of scrollback history to capture when using tmux tools. This avoids having to specify the line count every time you call a tmux function.

The default is initially 500 lines, which includes the visible terminal plus scrollback.


source

pane


def pane(
    n:int=None, # Number of scrollback lines to capture, in addition to visible area (None uses default_tmux_lines, which is 500 if not otherwise set)
    pane:int=None, # Pane number to capture from
    session:str=None, # Session name to target
    window:int=None, # Window number to target
    capture_output:bool=True, text:bool=True, ret:bool=True, host:str=None, # Optional SSH Host
    ip:str=None, # Optional SSH IP
    user:str=None, # Optional SSH user
    keyfile:str=None, # Optional SSH keyfile
):

Grab the tmux history in plain text

# print(pane(1))
# print(pane(1, host='hack'))

pane() captures the scrollback history from a specific tmux pane. You can specify which pane to capture using any combination of session, window, and pane numbers. If you don’t specify anything, it captures from the current pane.

n controls how many lines of scrollback to include beyond the visible area. If not specified, it uses the global default_tmux_lines value.


source

list_panes


def list_panes(
    session:str=None, # Session name to list panes from
    window:int=None, # Window number to list panes from
    capture_output:bool=True, text:bool=True, ret:bool=True, host:str=None, # Optional SSH Host
    ip:str=None, # Optional SSH IP
    user:str=None, # Optional SSH user
    keyfile:str=None, # Optional SSH keyfile
):

List panes for a session/window (or current if none specified)

list_panes() returns information about panes in current or specified window. Output includes pane numbers, dimensions, and active status.

print(list_panes(window=0))
0: [188x20] [history 1468/2000, 2851143 bytes] %3 (active)
print(list_panes(window=0, host='hack'))
0: [85x25] [history 1975/2000, 4839557 bytes] %3
1: [85x26] [history 2294/2000, 5024915 bytes] %21 (active)
2: [98x25] [history 2241/2000, 10188212 bytes] %5
3: [98x26] [history 0/2000, 1712 bytes] %22

source

panes


def panes(
    session:str=None, # Session name to target
    window:int=None, # Window number to target
    n:int=None, # Number of scrollback lines to capture
    capture_output:bool=True, text:bool=True, ret:bool=True, host:str=None, # Optional SSH Host
    ip:str=None, # Optional SSH IP
    user:str=None, # Optional SSH user
    keyfile:str=None, # Optional SSH keyfile
):

Grab history from all panes in a session/window

panes() returns a dictionary with pane numbers as keys and their captured content as values. Useful for getting a snapshot of all panes in a window at once.

from pprint import pprint
# pprint(panes(window=0, n=10))
# pprint(panes(n=10, host='hack'))

source

list_windows


def list_windows(
    session:str=None, # Session name to list windows from
    capture_output:bool=True, text:bool=True, ret:bool=True, host:str=None, # Optional SSH Host
    ip:str=None, # Optional SSH IP
    user:str=None, # Optional SSH user
    keyfile:str=None, # Optional SSH keyfile
):

List all windows in a session

list_windows() shows all windows in current or specified session. Output includes window numbers, names, pane counts, and markers for active (*) and previous (-) windows.

print(list_windows())
0: python3.12* (1 panes) [188x20] [layout ac80,188x20,0,0,3] @3 (active)
print(list_windows(host='hack'))
0: bash* (4 panes) [184x52] [layout c9b1,184x52,0,0{85x52,0,0[85x25,0,0,3,85x26,0,26,21],98x52,86,0[98x25,86,0,5,98x26,86,26,22]}] @0 (active)

source

windows


def windows(
    session:str=None, # Session name to target
    n:int=None, # Number of scrollback lines to capture
    capture_output:bool=True, text:bool=True, ret:bool=True, host:str=None, # Optional SSH Host
    ip:str=None, # Optional SSH IP
    user:str=None, # Optional SSH user
    keyfile:str=None, # Optional SSH keyfile
):

Grab history from all panes in all windows of a session

windows() returns a nested dictionary: window names/numbers as keys, each containing a dictionary of panes and their content. Captures entire session structure in one call.

# pprint(windows())
# pprint(windows(host='hack'))

source

list_sessions


def list_sessions(
    capture_output:bool=True, text:bool=True, ret:bool=True, host:str=None, # Optional SSH Host
    ip:str=None, # Optional SSH IP
    user:str=None, # Optional SSH user
    keyfile:str=None, # Optional SSH keyfile
):

List all tmux sessions

list_sessions() shows all tmux sessions. Output includes session names, window counts, creation time, and attachment status.

print(list_sessions())
jup: 1 windows (created Tue Dec  9 14:54:59 2025)
mx: 1 windows (created Wed Dec  3 16:27:09 2025)
solveit: 1 windows (created Mon Dec  1 13:34:56 2025)
solveit-test: 1 windows (created Mon Dec  1 16:46:51 2025)
print(list_sessions(host='hack'))
0: 1 windows (created Wed Oct  1 22:53:16 2025) (attached)

source

sessions


def sessions(
    n:int=None, # Number of scrollback lines to capture
    capture_output:bool=True, text:bool=True, ret:bool=True, host:str=None, # Optional SSH Host
    ip:str=None, # Optional SSH IP
    user:str=None, # Optional SSH user
    keyfile:str=None, # Optional SSH keyfile
):

Grab history from all panes in all windows of all sessions

sessions() returns complete tmux state: all sessions, windows, and panes with their content. Useful for capturing everything at once or debugging complex tmux setups.

# pprint(sessions())
# pprint(sessions(host='hack'))

source

flatten_dict


def flatten_dict(
    d, parent_key:str='', sep:str='//'
):

Flatten nested dict into list of (key_path, value) tuples

flatten_dict converts nested dictionaries into a flat list of (key_path, value) tuples. This is particularly useful with tmux tools since windows() and sessions() return deeply nested structures. By flattening them, you can easily search all content without writing nested loops.

The key paths show exactly where content was found (e.g., "session1//0:bash//1" tells you it’s from session1, window 0 named bash, pane 1), making it simple to trace back to the source location.

nested = {
    'session1': {
        '0:bash': {0: 'some content', 1: 'more content'},
        '1:vim': {0: 'editing file'}
    }
}
for path, content in flatten_dict(nested): print(f"{path}: {content}")
session1//0:bash//0: some content
session1//0:bash//1: more content
session1//1:vim//0: editing file