cmux-next: save and import Ghostty theme files (cx-wqn5.1)
Settings > Theme can now turn the theme in its preview into a real Ghostty theme file, and bring one in. The page already had the full picker with live preview and per-token edits. What was missing was a way to keep a custom theme as a file Ghostty and every cmux picker list.
- Save as Ghostty Theme… takes a name in an inline field (default " Custom"). It writes the previewed theme with its
appearance.themeEditsto$XDG_CONFIG_HOME|~/.config/ghostty/themes/<name>, then picks it. While the theme follows the system (light:A,dark:B), only the side in view changes. - Import Theme File… asks for the file in the cmux picker and copies it into the same folder, then picks it.
- A name already in use asks inline ("Replace it?") before replacing. An import's retry reuses the picked file through a token, so the page never sends a path.
- The theme catalog reloads after either one, so the new theme appears in every picker and its colors are available.
A theme file is Ghostty config, so only color keys are written or copied: palette, background, foreground, cursor-color, cursor-text, selection-* and bold-color. An imported command = or config-file = never reaches Ghostty. The tool also refuses:
- names that aren't one plain theme name (
/, leading.,=,#, quotes, pairs, over 255 bytes); - names of themes that ship with cmux;
- a base that isn't a theme name.
Both ops (cmux.settings.theme.save and cmux.settings.theme.import) run only for the person's own gesture on the Settings page, like other user-only settings writes.
The per-theme accent edit (bead cx-wqn5.1, part 2) follows in its own PR.
Testing
ThemeFileSaveTests(Swift Testing, 3 tests) passes on the fleet at c20ee7994a9c, with every CmuxNext suite green (run-swift-testing-suites.sh). The test was committed first, and at that commit the Swift build failed. The fleet log shows only SwiftPM's genericerror: fatalError, not the missing type, so that run is weak red evidence.webviews/src/pages/settings/themeFiles.test.tsx(5 tests: save with edits, follow-system pair, replace prompt, refused name, import with replace and with a cancelled picker) passes locally under bun. The settings suite andtest/ui-rules.test.tspass (115 tests), andbun run checkis clean.- The strings are in the Settings catalog for all 21 locales, and
strings.jsonis regenerated. - Not run: a live app check.
Changelog
Added: Settings > Theme can save the previewed theme with your edits as a Ghostty theme file, and import a theme file.
🤖 Generated with Claude Code