Repository navigation
Description
Summary
The MCP Apps pane viewer added in #149 draws a pane as plain text. Programs that colour their output (compilers, test runners, ls, prompts) lose that signal in the viewer, though tmux can supply it: capture-pane -e keeps the colour and style codes.
Motivation
Colour carries meaning on a terminal: red failures, green passes, highlighted matches. A viewer meant to show what is on the screen drops it.
Evidence
tmux does not replay the program's original bytes. It re-emits SGR codes from its grid, one code per attribute, with 39/49/0 resets, and it writes attribute codes of 10 or more as d:d (grid.c at 3.8):
{ GRID_ATTR_UNDERSCORE_2, 42 },
...
{ GRID_ATTR_OVERLINE, 53 },
...
if (s[i] < 10)
xsnprintf(tmp, sizeof tmp, "%d", s[i]);
else {
xsnprintf(tmp, sizeof tmp, "%d:%d", s[i] / 10,
s[i] % 10);That yields 4:2 to 4:5 for underline styles, and 5:3 for overline (SGR 53). A parser that reads 5:3 as SGR 5 with a sub-parameter shows blink instead. Observed with tmux 3.8a, after a pane printed printf '\033[4:3mcurly\033[0m \033[53mover\033[0m \033[4:2mdbl\033[0m\n':
$ tmux capture-pane -p -e | cat -v^[[4:3mcurly^[[0m ^[[5:3mover^[[0m ^[[4:2mdbl^[[0m
38/48/58 take ;5;n or ;2;r;g;b, always ;-separated, and OSC 8 hyperlinks may appear as \033]8;…. libtmux already exposes the flag as Pane.capture_pane(escape_sequences=True).
Proposal
Render the codes in the viewer page: a small SGR parser that turns each captured row into styled runs, placing the cursor by visible column. A local spike did this. The parser kept the visible text identical to the plain capture, handled the d:d forms, 256-colour and truecolor, and rendered a coloured pane in a browser host built on the ext-apps AppBridge.
How the page gets the codes is the open decision:
- An
escape_sequences: bool = Falseoption onsnapshot_pane, which the page sets on its refresh calls. This is what the spike did. It adds 170 bytes tosnapshot_pane's schema (6010 to 6180 in the tool-surface snapshot), paid by every client, for a feature only the viewer uses. app.readServerResource()on atmux://template that captures with-e. This costs no tool schema bytes. It needs the host'sserverResourcescapability, and hosts without it fall back to plain text.
Either way, the model's own snapshot_pane call arrives without codes, so the page should fetch a coloured frame as soon as it renders the first result.
References
- mcp(feat): Confirm kill_session, add pane viewer and icons #149 adds the viewer (
ui://libtmux-mcp/pane-viewer.html) - tmux
grid.cattribute table andd:demission at 3.8 - MCP Apps extension
Activity