Problem
The cmux theme picker (Settings > Appearance > Theme: Light / Dark / System) conflates two orthogonal concepts:
- App chrome appearance — whether the sidebar, window frame, and UI elements render in light or dark mode (
NSApp.appearance)
- Terminal color scheme — the Ghostty
theme that sets background, foreground, and palette colors inside the terminal
When a user selects "Dark" or "Light", cmux writes theme = light:X,dark:Y to config.ghostty (the managed Ghostty config). This Ghostty theme silently overrides all user-defined terminal colors — background, foreground, palette, etc. — in the user's own config file. There is no "Custom" or "None" option to opt out.
Why this is wrong
A user may want:
- Dark chrome (sidebar/UI) but their own custom terminal colors
- Light chrome but a dark terminal color scheme
- Any combination where the app appearance is independent of the terminal palette
There is no way to achieve this today. Selecting any non-System appearance permanently clobbers the user's custom Ghostty color config.
Root cause (architectural)
config.ghostty is cmux's managed Ghostty config, written on every appearance change. The theme picker writes theme = light:X,dark:Y unconditionally, with no escape hatch. The user's config file cannot override this because Ghostty's theme directive has higher specificity for color values.
Correct architecture
These must become two separate, independent controls:
1. App Appearance (Light / Dark / System)
- Controls
NSApp.appearance only
- Does NOT write any
theme = to config.ghostty
- Does NOT change terminal colors at all
2. Terminal Theme (separate picker)
- Options: named Ghostty themes (Andromeda, Apple Classic, …) plus a "Custom" option
- "Custom" = cmux writes nothing to the theme field; user's own Ghostty color config is respected in full
- When a named theme is selected: cmux writes
theme = <name> (unconditional, not light/dark split) OR theme = light:X,dark:Y if the user wants adaptive themes
- Default: "Custom" (no override)
Migration
- Existing users who have a theme set keep it
- New installs default to "Custom" terminal theme + "System" app appearance
- The managed zone in
config.ghostty for theme is only written when the user explicitly picks a named theme
Related
Problem
The cmux theme picker (Settings > Appearance > Theme: Light / Dark / System) conflates two orthogonal concepts:
NSApp.appearance)themethat sets background, foreground, and palette colors inside the terminalWhen a user selects "Dark" or "Light", cmux writes
theme = light:X,dark:Ytoconfig.ghostty(the managed Ghostty config). This Ghostty theme silently overrides all user-defined terminal colors —background,foreground,palette, etc. — in the user's own config file. There is no "Custom" or "None" option to opt out.Why this is wrong
A user may want:
There is no way to achieve this today. Selecting any non-System appearance permanently clobbers the user's custom Ghostty color config.
Root cause (architectural)
config.ghosttyis cmux's managed Ghostty config, written on every appearance change. The theme picker writestheme = light:X,dark:Yunconditionally, with no escape hatch. The user'sconfigfile cannot override this because Ghostty's theme directive has higher specificity for color values.Correct architecture
These must become two separate, independent controls:
1. App Appearance (Light / Dark / System)
NSApp.appearanceonlytheme =toconfig.ghostty2. Terminal Theme (separate picker)
theme = <name>(unconditional, not light/dark split) ORtheme = light:X,dark:Yif the user wants adaptive themesMigration
config.ghosttyfor theme is only written when the user explicitly picks a named themeRelated