-
Notifications
You must be signed in to change notification settings - Fork 1
Description
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:
-
TerminalRegistryController.prewarm()creates each new xterm instance by callinggetXtermOptions()without athemeargument. It reads scrollback, performance mode, and font from their respective stores, but skips the color scheme store entirely.getXtermOptionsfalls back togetTerminalThemeFromCSS(), which resolves CSS custom properties for the default app theme — ignoring any scheme the user has selected. -
XtermAdapter.tsxterminalOptionsmemo (used whengetOrCreatecreates an instance during React mount) also callsgetXtermOptions()without atheme, 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:
src/controllers/TerminalRegistryController.ts—prewarm()builds xterm options from font/scrollback stores but omits the color scheme storesrc/components/Terminal/XtermAdapter.tsx—terminalOptionsmemo has no dependency on the color scheme storesrc/hooks/useTerminalConfig.ts—applyGlobalOptionsfires reactively on scheme change but cannot retroactively fix terminals created with the wrong initial themesrc/config/xtermConfig.ts—getXtermOptions()accepts an optionaltheme; when omitted it falls back togetTerminalThemeFromCSS()src/store/terminalColorSchemeStore.ts—getEffectiveTheme()returns the correctIThemefor the selected scheme
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.