Skip to content

Answer OSC 10/11/12 color queries so TUIs detect the terminal theme#202

Merged
nedtwigg merged 3 commits into
mainfrom
codex-too-dark
Jul 3, 2026
Merged

Answer OSC 10/11/12 color queries so TUIs detect the terminal theme#202
nedtwigg merged 3 commits into
mainfrom
codex-too-dark

Conversation

@nedtwigg

@nedtwigg nedtwigg commented Jul 2, 2026

Copy link
Copy Markdown
Member

Problem

TUIs like Codex query the terminal's foreground/background/cursor colors via OSC 10/11/12 to adapt their UI — Codex blends its composer "pill" against the detected background. Dormouse never answered these queries, so on a light theme the pill rendered an unreadable near-black (dark text on a dark fill).

Fix (end to end)

  • Parser answers the query. TerminalProtocolParser now replies to OSC 10/11/12 ; ? from the active theme, emitting a kind:'response' event and consuming the query — the same seam the iTerm2 CSI > q reply already uses. Only the ? report form is intercepted; set requests and the no-provider case fall through to xterm.js.
  • Standalone adapters supply a color provider backed by the live xterm theme (shared themeColorProvider).
  • VS Code parses in the extension host (no DOM), so the webview pushes resolved colors up via a new dormouse:themeColors message; the router caches them and feeds them to its parsers. VS Code now matches standalone.
  • Windows. The in-box ConPTY silently swallows color queries, so we spawn with node-pty's bundled OpenConsole (useConptyDll: true), which forwards them like Windows Terminal does. Verified end to end against the real PTY path (the required conpty.dll/OpenConsole.exe already ship in both bundles).
  • COLORTERM=truecolor. Advertise 24-bit color (xterm.js renders it; the PTY is spawned xterm-256color with no other depth hint).
  • Cleanup. Extracted a shared, DOM-free lib/css-color.ts (parseColor/toHex) so the OSC reply reuses the theme parser instead of a second hex parser; it also accepts rgb()/rgba() theme colors now.

Not covered

Codex on Windows doesn't query OSC at all (it reads env/registry), so its pill there needs a separate env hint (COLORFGBG/TERM_PROGRAM_BACKGROUND) — scoped but intentionally left as a follow-up. This PR fixes OSC color-query answering generally (Codex on macOS/Linux, vim, and other querying TUIs).

Tests / specs

  • Parser color-query + formatOscColorResponse unit tests; VS Code adapter theme-push test; COLORTERM spawn assertions.
  • Specs updated: terminal-escapes.md, vscode.md, auto-update.md.

🤖 Generated with Claude Code

nedtwigg and others added 2 commits July 2, 2026 12:22
TUIs like Codex query the terminal's fg/bg/cursor colors (OSC 10/11/12)
to adapt their UI — e.g. Codex blends its composer "pill" against the
background. Dormouse never answered, so on a light theme the pill came
out an unreadable near-black. Fix it end to end:

- TerminalProtocolParser now answers OSC 10/11/12 `?` queries from the
  active theme (via an optional color provider), emitting a `kind:'response'`
  reply and consuming the query — same seam as the iTerm2 CSI>q response.
- Standalone adapters supply a provider backed by the live xterm theme
  (shared `themeColorProvider`). VS Code parses in the extension host
  (no DOM), so the webview pushes resolved colors up via a new
  `dormouse:themeColors` message and the router feeds them to its parsers.
- Windows: the in-box ConPTY swallows color queries, so spawn with
  node-pty's bundled OpenConsole (`useConptyDll: true`), which forwards
  them like Windows Terminal does. Verified end to end.
- Advertise 24-bit color with `COLORTERM=truecolor` (xterm.js renders it;
  we spawn `xterm-256color` with no other depth hint).

Specs updated (terminal-escapes, vscode, auto-update) and tests added.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
parseColor/toHex lived privately in themes/flatten-alpha.ts; the OSC
color-query reply added its own hex parser. Promote the primitives to a
neutral, DOM-free lib/css-color.ts so both reuse one parser instead of
two. formatOscColorResponse now accepts rgb()/rgba() theme colors (not
just hex), which more VS Code themes emit, and rounds/clamps channels.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 2, 2026

Copy link
Copy Markdown

Deploying mouseterm with  Cloudflare Pages  Cloudflare Pages

Latest commit: e8c2661
Status:⚡️  Build in progress...

View logs

@dormouse-bot dormouse-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Traced the response path end to end and it holds up: the query is consumed and answered on both surfaces (VS Code host writes replies back via ptyManager.write in message-router.ts; standalone reuses the existing kind:'response' seam), the optional colorProvider leaves every existing new TerminalProtocolParser() call site unchanged, and parseColor/toHex moved into css-color.ts byte-for-byte. Nicely tested across both providers.

One trivial cleanup below.

Comment thread lib/src/lib/terminal-protocol.ts Outdated
Co-authored-by: dormouse-bot <ned.twigg+dormouse-bot@diffplug.com>
@nedtwigg nedtwigg merged commit f13ea08 into main Jul 3, 2026
4 of 5 checks passed
@nedtwigg nedtwigg deleted the codex-too-dark branch July 3, 2026 00:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants