[BUG] Desktop Linux: theme does not follow system light/dark changes at runtime — restart required (Electron ignores portal color-scheme signals)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Claude Desktop for Linux (official deb 1.20186.9, Electron 42.7.0 / Chrome 148.0.7778.280) with Appearance = "Match system" does not follow OS light/dark changes while running. Switching the system to dark is never picked up; switching to light is sometimes picked up (asymmetry explained below). Restarting the app always applies the correct theme.
Diagnosis (verified experimentally on Debian 13, KDE Plasma Wayland, xdg-desktop-portal 1.20.3 + xdg-desktop-portal-kde):
- Portal emits correctly: dbus-monitor shows org.freedesktop.portal.Settings.SettingChanged with org.freedesktop.appearance color-scheme = 1/2 on every switch, both directions. Read/ReadOne/ReadAll replies are spec-compliant (Settings interface v2).
- Reference Chromium on the same desktop works: in Chrome/Edge on the same session, matchMedia('(prefers-color-scheme: dark)') updates live in both directions.
- The app receives the signal but never reacts: the app's D-Bus connection has a match rule for org.freedesktop.portal.Settings on org.freedesktop.portal.Desktop, and strace on the main process shows the SettingChanged ... color-scheme u 1/2 message bytes being delivered into the process. Yet inside the app's own Chromium (probed via an in-app page), matchMedia('(prefers-color-scheme: dark)') is frozen — it reports false even while the system is dark, and no change events ever fire.
- Root cause: Electron on Linux derives nativeTheme from the GTK theme rather than the FDO settings portal; Chrome's portal-based dark-mode manager is browser-layer code Electron doesn't include (long-standing gap: electron/electron#25925). On KDE the GTK theme name is "Breeze" for both light and dark, so Electron evaluates "light" forever. The app does listen to nativeTheme.on("updated"), but the only events that fire are incidental GTK-settings reloads, which always evaluate to light — hence dark→light can apply at runtime while light→dark never does.
What Should Happen?
With Appearance = "Match system", the app should re-apply its theme immediately when the OS color scheme changes, in both directions, without a restart — like Chrome/Edge do on the same desktop.
Suggested fix: have the app's main process subscribe to org.freedesktop.portal.Settings SettingChanged for org.freedesktop.appearance/color-scheme directly (or re-read it on demand) instead of relying on Electron's GTK-based nativeTheme detection on Linux, and re-apply the effective theme on change. The startup path already resolves the correct value — only the runtime-update path is missing.
Error Messages/Logs
Steps to Reproduce
- Start Claude Desktop on Linux (KDE Plasma, Wayland) with the system in light mode, Appearance = Match system.
- Switch the system to dark, e.g.
plasma-apply-colorscheme BreezeDark. - App stays light indefinitely (tested >30 min; window focus changes make no difference).
- Restart the app → dark is applied.
Claude Model
None
Is this a regression?
No, this never worked
Last Working Version
_No response_
Claude Code Version
2.1.211 (Claude Code); Desktop app 1.20186.9
Platform
Other
Operating System
Ubuntu/Debian Linux
Terminal/Shell
Other
Additional Information
Environment: Claude Desktop for Linux 1.20186.9 (official apt package), Electron 42.7.0 / Chrome 148.0.7778.280, Debian 13, KDE Plasma (Wayland), app runs native Wayland (--ozone-platform=wayland), xdg-desktop-portal 1.20.3 with xdg-desktop-portal-kde backend.
This report is about the Claude Desktop app UI theme, not the CLI. Filed here because Desktop bugs are tracked in this repo.
Related but not a duplicate: #77171 (tray icon stops reacting to OS color-scheme changes; closed as invalid). Same underlying failure class — Electron on Linux not processing portal color-scheme updates — but this report is about the main app window UI, with the delivery path verified end-to-end (portal emits, D-Bus delivers into the process, matchMedia stays frozen).
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗