Repository navigation
Reload the Ghostty config when its files change, and show config errors - #14859
Conversation
Watch every file the Ghostty config reads (top-level configs, config-file includes, user theme files) and reload through the existing Reload Configuration path after a 300 ms trailing debounce. Evaluations compare file contents off the main thread, so directory noise and cmux's own writes (cmux themes set, Settings) do not trigger a second reload, while an edit pending during a cmux-started reload is never absorbed. Watchers re-arm when the include/theme set changes; FileWatcher already follows atomic and move-aside saves. After each full config load, Ghostty's diagnostics feed a policy that shows a small non-activating notice once per distinct error set (first three errors, Open Config jumps to the line), hides it when the errors are fixed, and drops cmux's own inline-fragment diagnostics. Refs #1047, #1304, #570. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…to main windows cmux writes the config before reloading, so the write's event is usually still debouncing when .ghosttyConfigDidReload arrives. Always refresh the baseline on that notification so the pending evaluation is a no-op instead of a second reload. After re-arming on a new include/theme set, read the files once more so a write that landed before the new watcher attached still reloads. The notice now attaches only to main terminal windows and its buttons accept the first click on the non-activating panel. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 23 seconds. View limit detailsLimit details: You’ve used all 10 included reviews currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Repository: manaflow-ai/cmux/.coderabbit.yaml Review profile: ASSERTIVE Plan: Advanced Run ID: 📒 Files selected for processing (27)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
All contributors have signed the CLA ✍️ ✅ |
The notice is a non-activating child panel of a main window and never becomes key, so Cmd+W must keep closing the main window's panel rather than the notice. Document it in the lint's ignore list like the textbox completion popup. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Merge receipt for |
a64d59b tools: ui-lab renders view code in seconds; wire-app-sources.py (manaflow-ai#15049) 4e03ed2 fix(events): harden durable replay recovery (manaflow-ai#15054) ac51546 Settings: native terminal theme gallery (manaflow-ai#14996) 867e7a0 Add native Ghostty option rows to Settings > Terminal (manaflow-ai#15005) 7f97b0d ui-tests: wait for static preflight when a reused compile skips the gate (manaflow-ai#15051) c708e0c Add a chat view for the terminal's agent session (Claude Code, Codex) (manaflow-ai#14965) b762a3d ci: the picker fetches kept bases' trees, not just checks their commits (manaflow-ai#15053) 2570eed docs: refresh and trim contributor build guidance (manaflow-ai#15050) 20019d3 ci: re-run by cause: host faults to Blacksmith, code failures back to the minis (manaflow-ai#15045) 36ee3e9 Add Warn Before Closing Workspace setting (manaflow-ai#14979) 4df2317 CI: run changed UI test classes in PRs, keep UI runs off Blacksmith, probe the GUI session (manaflow-ai#14964) 9efe05e Owned-pool sweeper: page the marker listing back to the runs it adopts (manaflow-ai#15033) 6361554 fix(events): restore durable replay across restarts (manaflow-ai#15030) 0bc5145 ci: place side lanes on the light minis one per idle side runner (manaflow-ai#15047) 9d4e92b ci: the E2E rule's queue-round reason names the owned pools the run may take (manaflow-ai#15044) 9e6e216 Dogfood the app from CI with JSON tours (manaflow-ai#14928) fd3dcf6 ci: retry the picker's kept-base fetch and record how it went (manaflow-ai#15040) 3a64e0e Reload the Ghostty config when its files change, and show config errors (manaflow-ai#14859) f412b05 test: hit-test the browser portal tab strip with its own click (manaflow-ai#15031) 64d5235 test: route the reopen-last-closed shortcut through the test's own window (manaflow-ai#15036) 7037079 ci: take the gui token in the E2E test job's step, not at job start (manaflow-ai#15037) # Conflicts: # .github/workflows/ci-macos.yml # .github/workflows/ci.yml # .github/workflows/remote-daemon.yml # .github/workflows/test-e2e.yml
Editing
~/.config/ghostty/config(or any file it includes) now applies in cmux when you save, without pressing Cmd+Shift+, or restarting. When Ghostty rejects part of the config, release builds now tell you: a small notice in the corner of the window lists the first errors and opens the file at the offending line. Before this, those diagnostics were only written to a DEBUG log, so a typo or a missing theme silently fell back to defaults (#1304, #570).Closes #1047.
Live reload
GhosttyConfigLiveReloadCoordinator(CmuxTerminalCore) watches:~/.config/ghostty/config,config.ghostty,~/Library/Application Support/com.mitchellh.ghostty/config.ghosttyand legacyconfig, and the cmux Application Support configs;config-fileinclude (relative,?-optional, nested), re-armed when the include set changes;theme: an absolute path, or$XDG_CONFIG_HOME/ghostty/themes/<name>for each side of alight:…,dark:…pair. Bundled themes aren't watched.Each path uses the existing
FileWatcher, which also watches the nearest existing ancestor and reattaches after every event, so atomic saves, Vim-style move-aside saves and files created after launch keep working. A change arms a 300 ms trailing debounce; the evaluation reads a snapshot off the main thread and calls the existingAppDelegate.reloadConfigurationpath (same as Cmd+Shift+,) only when file contents differ from the last applied snapshot. When the include or theme set changes, the watchers are re-armed and the files re-read once, so a write that lands before the new watcher attaches still reloads.Reloads cmux starts itself (
cmux themes set, Settings, the menu) refresh that baseline through.ghosttyConfigDidReload. cmux writes the file before reloading, so the write's event is normally still debouncing when the reload finishes; the refreshed baseline turns it into a no-op instead of a second reload with the generic source (which could flash a single-theme change through app appearance). The trade-off: a user edit saved after Ghostty read the files but before that baseline refresh is picked up on the next save rather than immediately.There's no setting to turn it off; this matches
cmux.json, which already reloads on save without a toggle.Config error notice
After each full config load (launch and reload; not the soft or surface-only paths),
GhosttyApprecordsghostty_config_get_diagnosticmessages.GhosttyConfigDiagnosticsNoticePolicyshows the notice once per distinct set of errors, stays quiet on reloads that keep the same errors (appearance changes, font zoom), hides it when a clean load arrives, and shows it again if an error comes back. Diagnostics from cmux's own inline fragments (/__cmux_inline__/…) are dropped. The notice is a borderless, non-activating child panel in the top-right of the key (or frontmost) main terminal window: it never takes focus, dismisses after 20 s, and waits for a window if the launch-time load happens before one exists. It's placed once and doesn't follow a later window resize. "Open Config" opens the first file at its line through the preferred-editor service.cmux config doctorstill validatescmux.jsononly: it runs without the app socket, and the CLI doesn't link GhosttyKit, so exposing Ghostty diagnostics there needs a socket method. Left as a follow-up.Not in this PR
Single-sided
light:X/dark:Ytheme values (#10068) are already handled by #10358, so this PR leavesencodedThemeValuealone.Verification
Nothing here has been compiled or run locally (this machine is at ~140 load; builds are left to CI). What ran:
python3 scripts/verify-local.py --affected mf/main --swift-changed mf/main: swift-syntax (22 files), xcstrings, localization parity, project normalization, test wiring, package groups, feature-flag policy all pass.xcrun swiftc -parseon every changed Swift file../scripts/localize-changes: 5 new keys with de, fr, ar, es, zh-Hant, zh-Hans, ko, ja translations;localization_catalog.py checkreports 0 parity errors. No web copy changed.Tests added (CmuxTerminalCore package, Swift Testing), expected to run in CI:
GhosttyConfigLiveReloadCoordinatorTests: baseline and watch set at start, reload on content change, no reload on a content-free event, a burst debounced into one evaluation (gated clock, and the superseded debounce doesn't evaluate later), cmux's own write absorbed whether its event arrives before or after the reload notification, re-arming when an include is added, and a write that lands while re-arming.GhosttyConfigLiveReloadSnapshotTests: missing candidates watched, relative/optional/nested includes, include cycles, both theme sides, absolute theme paths, theme edits change contents.FileWatcherGhosttyConfigChangeSourceTests: real temp files for a move-aside-and-rewrite save, an include created later in a new directory, and cancel. These are smoke checks; inode reattachment itself is covered by the existingFileWatcherTests.GhosttyConfigDiagnosticsNoticePolicyTests: path/line parsing, dedupe across reloads, re-present on change, dismiss and re-present after a fix, inline/duplicate filtering, three-item cap.A review subagent read the diff for compile and concurrency errors and found none; its findings (the self-write ordering, the re-arm window, host-window choice, first-click on the non-activating panel) are fixed in the second commit.
Unverified: app-target compilation of the AppDelegate wiring, the notice panel and its layout, and live behavior (saving a config in a running tagged build, the notice appearing, its buttons responding to a first click, and Open Config jumping to the line). Those need the tagged build and dogfood. Watching the parent directory also means unrelated writes there (for example
browser_history.jsonnext to the cmux config) cost a debounced off-main read that ends without a reload.🤖 Generated with Claude Code
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by cubic
Editing the Ghostty config (or any file it includes) now reloads in cmux automatically when you save. When Ghostty rejects part of the config, release builds now show a notice in the window corner listing the first errors; previously these diagnostics only went to a DEBUG log, so a typo or missing theme silently fell back to defaults (#1304, #570).
Closes #1047.
Live reload
config-fileinclude, and user themes named bytheme.cmux themes set) refresh the baseline so their own write doesn't cause a second reload.cmux.json; there's no toggle.Config error notice
Written for commit 2ba2681. Summary will update on new commits.