Skip to content

New terminals ignore the selected terminal color scheme #3335

@gregpriday

Description

@gregpriday

Summary

When a terminal color scheme is selected in Appearance → Terminal, newly spawned terminals are always initialized with the default CSS-variable theme instead of the user's selected scheme. Only terminals that are already open when the scheme is changed receive the correct colors.

Current Behavior

  • User selects a terminal color scheme in Settings → Appearance → Terminal
  • User spawns a new terminal (any kind — agent or plain terminal)
  • The new terminal renders with the default theme, not the selected scheme
  • If the user then opens Settings and changes the scheme again while the terminal is visible, that terminal does update correctly
  • Terminals that were already open when the scheme was last changed continue to show the correct scheme

Reproducibility: Always

Expected Behavior

Any terminal spawned after a color scheme is selected should open with that scheme applied. The selected scheme should be the source of truth for all new terminal instances, not just for live terminals at the moment the setting changes.

Root Cause Analysis

Terminal instances are initialized in two places, and neither reads from useTerminalColorSchemeStore:

  1. TerminalRegistryController.prewarm() creates each new xterm instance by calling getXtermOptions() without a theme argument. It reads scrollback, performance mode, and font from their respective stores, but skips the color scheme store entirely. getXtermOptions falls back to getTerminalThemeFromCSS(), which resolves CSS custom properties for the default app theme — ignoring any scheme the user has selected.

  2. XtermAdapter.tsx terminalOptions memo (used when getOrCreate creates an instance during React mount) also calls getXtermOptions() without a theme, with the same fallback behavior. The memo's dependency array includes font and scrollback settings but not the color scheme.

Meanwhile, useTerminalConfig (the hook that syncs config to the terminal service) calls terminalInstanceService.applyGlobalOptions({ theme, ... }) whenever selectedSchemeId changes — which updates all existing instances. A freshly prewarmed terminal is created before this effect has any reason to re-run, so it permanently misses the scheme and remains on the default theme.

Evidence:

Acceptance Criteria

  • A terminal spawned after changing the color scheme opens with the selected scheme applied, without requiring the user to change the scheme again
  • The default scheme (CSS-variable-based) continues to work correctly for terminals when no custom scheme is selected
  • Changing the scheme while terminals are open continues to update all open terminals immediately
  • All terminal kinds (plain terminal, agent terminal, dock terminal) respect the selected scheme on creation

Edge Cases & Risks

  • The terminal color scheme store is initialized asynchronously from the backend config (terminalConfigClient.get()). If a terminal is spawned before the config loads, the scheme will not yet be known. The fix must account for this race condition — either by reading the store state at spawn time (which may still be the default if load is pending) or by ensuring newly created instances are patched once the config resolves.
  • Pre-warmed terminals from the pool are created before any user action, so they must also receive the correct scheme when they are eventually claimed by a spawn.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions