Repository navigation
feat(coding/tui): follow the terminal background and the desktop appearance - #34
Merged
Merged
Conversation
rsbin1178
marked this pull request as ready for review
October 8, 2026 13:06
…opens The picker marks every row whose declared background is the opposite of the terminal's, and it read the canvas from whatever the startup probe answered, so a profile switch during a session left all of its marks describing the terminal the user had already left. Opening the picker now returns the same background query the startup probe uses: the answer takes the existing path, re-stamping the canvas, re-rendering the visible transcript and redrawing the marks. Bubble Tea gates that query on input being enabled, so no reply is left behind for the shell, and a run with NO_COLOR still asks for nothing because it paints no surfaces. The cost is one eight-byte write and one asynchronous answer per picker open.
`auto` followed the terminal's background colour, which a terminal reports once and only re-reports when asked, so a desktop that switched appearance while the profile stayed put left the theme where it was. The terminal can report that preference: `CSI ? 2031 h` enables unsolicited reports and the terminal answers `CSI ? 997 ; 1 n` for dark and `; 2 n` for light. Startup enables the mode through a raw write, the model handles the two decoded events, and the mode is reset with the other interaction modes on entry and exit. A report sets the canvas and then asks for the terminal's own background, which is what the canvas stamp, the painted surfaces and the picker marks describe: the reported value stands when the terminal answers no query, and a background answer that follows wins, so a dark desktop behind a light terminal profile keeps the light canvas. The extension's one-shot query is deliberately not sent, because that one does expect a reply and Bubble Tea only gates its own reply-carrying queries on input being enabled. Nothing is polled: the terminal speaks when something changes. Measured: three runs of a program test that feeds `CSI ? 997 ; 1 n` and `; 2 n` through the real input stack deliver the ultraviolet events to Update, and the model test pins that auto re-resolves while an explicit selection keeps its id and re-stamps its surfaces.
The theme section said `auto` follows "Bubble Tea's terminal background detection" and left it there, which no longer describes the behaviour: the terminal answers the background query itself, the picker re-asks it when it opens so its marks describe the current terminal, and a terminal that reports the desktop's light/dark appearance re-resolves `auto` when that changes.
rsbin1178
force-pushed
the
feat/tui-theme-detection
branch
from
October 8, 2026 13:07
3b3c4e4 to
0f4f934
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow the terminal background and the desktop appearance
autofollowed whatever the startup probe answered, so a profile switch during asession left the picker's marks — and the surface stamp — describing a terminal the
user had already left, and a desktop that switched light/dark while the profile
stayed put changed nothing at all.
This consolidates what was reviewed as #28, #29 and #30 into one pull request, kept
separate from the theme-system work because it is the only part here whose
behaviour depends on what the terminal implements.
What changes
The picker re-asks (
re-ask for the terminal background when the picker opens).Opening
/themereturns the same background query the startup probe uses, so themarks describe the terminal as it is now; the answer takes the existing path,
re-stamping the canvas, re-rendering the visible transcript and redrawing the marks.
Bubble Tea gates that query on input being enabled, so no reply is left for the
shell, and a run with NO_COLOR asks for nothing because it paints no surfaces. The
cost is one eight-byte write and one asynchronous answer per picker open.
The desktop appearance (
follow the desktop's light/dark appearance for auto).The standard VT extension reports the desktop's preference:
CSI ? 2031 henablesunsolicited reports, and the terminal answers
CSI ? 997 ; 1 nfor dark andCSI ? 997 ; 2 nfor light. Startup enables the mode through a raw write, the modelhandles the two decoded ultraviolet events, and the mode is reset with the other
interaction modes on entry and exit. A report sets the canvas and then asks for the
terminal's own background, which is what the surfaces and the marks describe: the
reported value stands when the terminal answers no query, and a background answer
that follows wins, so a dark desktop behind a light terminal profile keeps the light
canvas. The extension's one-shot query is deliberately not sent, because it expects
a reply and Bubble Tea only gates its own reply-carrying queries on input being
enabled. Nothing is polled.
Docs (
say what auto follows and when the picker re-asks).Evidence
ansi.LightDarkReport(true)and(false)through thereal input stack and requires the ultraviolet events to arrive at
Update(threeconsecutive runs, ~20 ms each). That is the one assumption the mechanism rests on,
because Bubble Tea leaves the event unmapped and hands it through.
autore-resolves on a report while an explicitselection keeps its id and re-stamps its surfaces, and that NO_COLOR ignores the
report exactly as it ignores the background answer.
CSI ? 2031 lreset on exit./themereturnsand that a NO_COLOR run asks for nothing at all.
TERM=xterm-256color go test ./...(89 packages),go test -race ./internal/coding/tui/and the CI's last-commit lint scope (--new-from-rev=HEAD~)are clean.
Terminal support for the extension varies — its own adoption table lists Contour,
Ghostty, Kitty, tmux, VTE 0.82+, Zellij, Helix, Neovim and Yazi, and not WezTerm,
Vim or iTerm2 — which is why the terminal background stays the primary reading and
its fallback, and why this work ships as its own pull request.
Based on the theme-system pull request, which must merge first.