Skip to content

feat(cli): OSC 10 foreground query and inherit-fg auto theme mode#276

Merged
emal-avala merged 2 commits into
mainfrom
feat/osc10-foreground-query
May 5, 2026
Merged

feat(cli): OSC 10 foreground query and inherit-fg auto theme mode#276
emal-avala merged 2 commits into
mainfrom
feat/osc10-foreground-query

Conversation

@emal-avala
Copy link
Copy Markdown
Member

Summary

  • Symmetric OSC 10 (foreground) query alongside the OSC 11 (background) path that landed in feat(cli): detect terminal theme via OSC 11 #268. Both queries fire as one batch terminated by a single DA1 sentinel — one round-trip instead of two.
  • New [ui].inherit_fg config key (default false). When the configured theme is auto and inherit_fg = true, the resolved theme's text slot is replaced with the foreground RGB the terminal reported via OSC 10. Falls back cleanly to the theme default when detection failed or wasn't applicable. Explicit themes are taken at face value.
  • prime_terminal_colors() and detect_terminal_foreground() exposed on terminal_query; the OSC parser/sentinel/is_tty() gate from feat(cli): detect terminal theme via OSC 11 #268 are reused via a generalised parse_osc_color(input, code).

Detection is silent when stdin/stdout aren't a TTY (agent --serve, CI, piped input) — the is_tty() gate is shared with the OSC 11 path.

Test plan

  • cargo check --all-targets
  • cargo test --all-targets (unit + integration; pre-existing bwrap sandbox tests fail in this environment due to user-namespace permissions and are unrelated)
  • cargo clippy --all-targets -- -D warnings (clean)
  • cargo fmt --all -- --check (clean)

New tests:

  • parser_distinguishes_osc_10_from_osc_11 — same byte stream carries both replies; the OSC code selects the payload.
  • parses_osc_10_foreground_payload — direct OSC 10 reply parses; OSC 10 reply does not leak into an OSC 11 query.
  • simulated_query_writes_batch_and_stops_at_da1 (extended) — single batch (OSC 10, OSC 11, DA1), reader stops at the sentinel.
  • back_compat_query_system_theme_from_io_still_returns_theme — the legacy OSC 11 helper still works on top of the unified parser.
  • missing_osc_10_reply_returns_none_foreground_only — terminals that reply to OSC 11 but not OSC 10 yield a populated background and None foreground rather than failing both.
  • is_tty_is_false_under_cargo_test — sentinel for the TTY gate that prevents escape sequences in non-interactive contexts.
  • Theme override matrix in theme_runtime: detection succeeded / detection failed / inherit_fg disabled / configured theme not auto.
  • UiConfig defaults + TOML round-trip for inherit_fg.

Notes

  • Onboarding picker integration is left as a TODO — wiring a secondary toggle row into the current arrow-key picker would need a small state machine. Users opt in via ~/.config/agent-code/config.toml for now, documented in docs/configuration/settings.mdx.
  • Some terminals reply to OSC 10 with the colour they would otherwise use, even when a colour scheme has overridden it — this caveat is in the docs. inherit_fg is opt-in and contrast against the theme background is the user's call.

Closes ROADMAP 8.15.5. Builds on #268.

Extends terminal_query.rs with a single OSC 10 + OSC 11 + DA1 batch
so dark/light detection and the optional foreground inherit share one
round-trip. Adds [ui].inherit_fg (default false) — when the user's
configured theme is auto and inherit_fg is enabled, the resolved
theme's text slot is replaced with the OSC 10 foreground RGB.
Detection is silent when stdin/stdout are not a TTY.

- terminal_query: parse_osc_color(input, code) shared parser; new
  query_terminal_colors_from_io and prime_terminal_colors helpers;
  detect_terminal_foreground reads from a OnceLock cache populated by
  the unified batch.
- theme_runtime: init_with_options(theme_name, configured_name,
  inherit_fg) records the auto + inherit-fg state; current() applies
  the override when both flags are on and the cache hit succeeded.
- schema: UiConfig.inherit_fg with default false; toml round-trip
  test.
- repl + /theme command thread the new flag through.
- docs: auto-detection paragraph + inherit_fg subsection in
  configuration/settings.

ROADMAP 8.15.5 closed; onboarding picker exposure left as a TODO so
the patch stays scoped — users opt in via config today.
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b95f1171a4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/cli/src/ui/terminal_query.rs Outdated
Comment on lines 96 to 99
if let Some(theme) = colorfgbg_theme() {
let _ = FOREGROUND_RGB.set(None);
let _ = BACKGROUND_RGB.set(None);
return theme;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Populate foreground cache before COLORFGBG early return

When COLORFGBG is set, detect_system_theme_uncached returns immediately and explicitly stores None in FOREGROUND_RGB, so [ui].inherit_fg = true can never apply even though the user selected theme = "auto". This affects terminals/shells that export COLORFGBG: the background theme resolves, but foreground inheritance is silently disabled for the whole process because the OnceLock is initialized with None on this path.

Useful? React with 👍 / 👎.

detect_system_theme_uncached short-circuited on SYSTEM_THEME_ENV,
COLORFGBG, and TERM_PROGRAM=Apple_Terminal — explicitly storing
None into FOREGROUND_RGB and BACKGROUND_RGB on each early-return
path. The dark/light classification worked, but the OSC 10/11
round-trip that populates the actual RGB caches never ran when
any of those env vars was set.

Result: on the most common terminal/shell combination (any setup
that exports COLORFGBG), the user could set theme = "auto" and
inherit_fg = true, get a correctly-classified background theme,
and still see the default text slot — because the foreground
cache was forcibly initialised to None for the whole process.

Restructure so dark/light classification is computed from env vars
into an Option, the OSC batch always runs and populates both RGB
caches, and the final return prefers the env-derived theme when
available, falling back to luminance-derived from the OSC bg, and
finally to Dark. Env-derived classification still wins (it's what
the user explicitly told us); the OSC query is now strictly
additive — it populates the inherit_fg payload regardless of
whether classification needed it.
@emal-avala emal-avala merged commit 7feff5d into main May 5, 2026
14 checks passed
@emal-avala emal-avala deleted the feat/osc10-foreground-query branch May 5, 2026 03:23
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.

1 participant