cmux-next: save and import Ghostty theme files (cx-wqn5.1)

Merged
TE
25d ago
+2281-17

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.themeEdits to $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 generic error: 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 and test/ui-rules.test.ts pass (115 tests), and bun run check is clean.
  • The strings are in the Settings catalog for all 21 locales, and strings.json is 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