--- name: tui-iteration description: Iteratively develop and refine Terminal User Interfaces (TUIs) by using tmux to spawn, observe, and interact with a running TUI process. Use this skill when asked to build, debug, or visually refine a TUI application — any time you need to "see" what the terminal renders and react to it, the way Playwright lets a browser agent iterate on web UI. --- This skill lets you act as a TUI design agent: launch a TUI in a controlled tmux pane, capture its rendered output, send keystrokes to interact with it, observe the result, and iterate — all from the CLI. The tmux pane is your "browser tab"; `capture-pane` is your "screenshot". --- ## Core Concept TUIs render to a virtual terminal buffer. `tmux` holds that buffer in memory at all times, even when the pane is not visible. You can: 1. **Spawn** a tmux session/pane and run the TUI inside it. 2. **Capture** the current rendered state (text + ANSI color codes) as a snapshot. 3. **Send** keystrokes or input to drive the TUI. 4. **Repeat** — capture → evaluate → send → capture — until the UI looks right. This is the TUI equivalent of Playwright's `page.screenshot()` + `page.click()` loop. --- ## Setup ### Create a dedicated session ```bash tmux new-session -d -s tui-dev -x 220 -y 50 ``` - `-d` — detached (runs in background, no need to attach) - `-s tui-dev` — session name; use this name in all subsequent commands - `-x 220 -y 50` — terminal dimensions (columns × rows); set to match your target environment ### Run the TUI in that session ```bash tmux send-keys -t tui-dev 'python my_tui.py' Enter # or tmux send-keys -t tui-dev 'cargo run' Enter # or any other start command ``` Give the process a moment to render before capturing: ```bash sleep 0.5 ``` --- ## Capturing State ("Taking a Screenshot") ### Plain text capture ```bash tmux capture-pane -t tui-dev -p ``` Prints the current pane content to stdout as plain text. Good for reading layout, text content, and cursor position. ### Capture with ANSI color codes preserved ```bash tmux capture-pane -t tui-dev -p -e ``` The `-e` flag includes escape sequences for colors and styling. Pipe to a file if you want to save a snapshot: ```bash tmux capture-pane -t tui-dev -p -e > snapshot.txt ``` Render that snapshot back to your terminal to visually inspect it: ```bash cat snapshot.txt ``` ### Capture a scrollback window (not just the visible area) ```bash tmux capture-pane -t tui-dev -p -S -100 ``` `-S -100` captures 100 lines above the visible area. Useful if the TUI printed startup logs. ### Save to a named tmux buffer (instead of stdout) ```bash tmux capture-pane -t tui-dev -b my-snapshot tmux show-buffer -b my-snapshot ``` --- ## Sending Input ("Clicking / Typing") ### Type text ```bash tmux send-keys -t tui-dev 'hello world' '' # Note: omitting Enter means no newline — useful for text fields ``` ### Press Enter ```bash tmux send-keys -t tui-dev '' Enter ``` ### Arrow keys and navigation ```bash tmux send-keys -t tui-dev '' Up tmux send-keys -t tui-dev '' Down tmux send-keys -t tui-dev '' Left tmux send-keys -t tui-dev '' Right ``` ### Special keys ```bash tmux send-keys -t tui-dev '' Tab tmux send-keys -t tui-dev '' Escape tmux send-keys -t tui-dev '' BSpace # Backspace tmux send-keys -t tui-dev '' DC # Delete tmux send-keys -t tui-dev '' Home tmux send-keys -t tui-dev '' End tmux send-keys -t tui-dev '' PPage # Page Up tmux send-keys -t tui-dev '' NPage # Page Down tmux send-keys -t tui-dev '' F1 # Function keys F1–F12 ``` ### Control sequences ```bash tmux send-keys -t tui-dev 'q' '' # Just the letter q (quit in many TUIs) tmux send-keys -t tui-dev '' C-c # Ctrl+C tmux send-keys -t tui-dev '' C-d # Ctrl+D (EOF) tmux send-keys -t tui-dev '' C-z # Ctrl+Z (suspend) ``` ### Hex / raw escape sequences (advanced) ```bash # Send Escape then [ then A (same as Up arrow in many terminals) tmux send-keys -t tui-dev $'\x1b[A' '' ``` --- ## Targeting Specific Panes If your session has multiple windows or panes: ```bash # target syntax: session:window.pane tmux send-keys -t tui-dev:0.0 '' Enter # session tui-dev, window 0, pane 0 tmux capture-pane -t tui-dev:1.0 -p # window 1, pane 0 ``` List all panes to find the right target: ```bash tmux list-panes -a ``` --- ## Resize the Terminal (Test Responsive Layouts) ```bash tmux resize-window -t tui-dev -x 80 -y 24 # classic 80×24 tmux resize-window -t tui-dev -x 120 -y 40 # wider ``` After resizing, most TUI frameworks emit a `SIGWINCH` and redraw automatically. Capture again after ~200ms. --- ## The Iteration Loop This is the core workflow. Repeat until satisfied: ``` 1. send-keys → trigger an action or type input 2. sleep 0.2 → give the TUI time to redraw 3. capture-pane -p -e → observe the new state 4. evaluate → does it look right? any errors visible? 5. go to 1 ``` Example shell loop for automated checking: ```bash # Press Down 5 times and snapshot each state for i in $(seq 1 5); do tmux send-keys -t tui-dev '' Down sleep 0.15 echo "--- Step $i ---" tmux capture-pane -t tui-dev -p done ``` --- ## Reading the Captured Output When you receive the text from `capture-pane -p`, look for: - **Borders and box-drawing characters** (`─`, `│`, `╭`, `╰`, `┌`, `└`, etc.) — indicate panels, modals, popups - **Highlighted / reversed rows** — often indicated by `[7m` in ANSI output (reverse video = selected item) - **Color shifts** — `[32m` green, `[31m` red, `[33m` yellow — often encode status - **Cursor position** — `tmux display-message -t tui-dev -p '#{cursor_x},#{cursor_y}'` - **Blank regions** — unexpected whitespace may mean a rendering bug or layout overflow To strip ANSI codes for pure text analysis: ```bash tmux capture-pane -t tui-dev -p -e | sed 's/\x1b\[[0-9;]*m//g' ``` --- ## Useful Diagnostic Commands ```bash # What is currently running in the pane? tmux display-message -t tui-dev -p '#{pane_current_command}' # Get pane dimensions tmux display-message -t tui-dev -p '#{pane_width}x#{pane_height}' # Get cursor position tmux display-message -t tui-dev -p 'cursor: #{cursor_x},#{cursor_y}' # Is the pane still alive? tmux list-panes -t tui-dev -F '#{pane_id} #{pane_dead} #{pane_current_command}' # Watch the pane live (attach briefly) tmux attach -t tui-dev # Detach again with: Ctrl+B then D ``` --- ## Teardown Kill the TUI process without destroying the session: ```bash tmux send-keys -t tui-dev '' C-c ``` Kill the whole session when done: ```bash tmux kill-session -t tui-dev ``` --- ## Workflow Summary | Goal | Command | |------|---------| | Create session | `tmux new-session -d -s tui-dev -x 220 -y 50` | | Start TUI | `tmux send-keys -t tui-dev 'CMD' Enter` | | Snapshot (plain) | `tmux capture-pane -t tui-dev -p` | | Snapshot (with color) | `tmux capture-pane -t tui-dev -p -e` | | Send keystroke | `tmux send-keys -t tui-dev '' Down` | | Type text | `tmux send-keys -t tui-dev 'text' ''` | | Resize terminal | `tmux resize-window -t tui-dev -x W -y H` | | Cursor position | `tmux display-message -t tui-dev -p '#{cursor_x},#{cursor_y}'` | | Kill process | `tmux send-keys -t tui-dev '' C-c` | | Kill session | `tmux kill-session -t tui-dev` | --- ## Tips - **Always `sleep` after `send-keys`** before capturing. TUIs need a render cycle. 100–300ms is usually enough; animations may need longer. - **Prefer `-e` captures when debugging visual issues** — color is often load-bearing information in TUIs (errors in red, selection in reverse video, etc.). - **Use a wide session** (`-x 220`) by default. Many TUI layout bugs only appear at narrow widths; you can always resize down to test. - **Scrollback is truncated** — `capture-pane` only sees the visible buffer plus scrollback history. If the TUI clears the screen on launch, earlier output is gone. - **Mouse events** can be sent via `tmux send-keys` using raw escape sequences, but most TUI iteration tasks don't need them — keyboard navigation is sufficient.