Skip to content

Fix Ghostty Settings config file selection - #1513

Closed
phongndo wants to merge 6 commits into
manaflow-ai:mainfrom
phongndo:fix/ghostty-settings-config-paths
Closed

phongndo wants to merge 6 commits into
manaflow-ai:mainfrom
phongndo:fix/ghostty-settings-config-paths

Conversation

@phongndo

@phongndo phongndo commented Mar 16, 2026 •

Copy link
Copy Markdown

Summary

  • Replaced the single-path ghostty_config_open_path() behavior behind Ghostty Settings… with cmux-side resolution that walks the expected top-level Ghostty config load order and opens all
    existing non-empty config files in TextEdit.
  • Added support for XDG_CONFIG_HOME so the settings action follows the same XDG root users expect when their Ghostty config is not under ~/.config.
  • Preserved symlinked config entrypoints so users with dotfiles-managed Ghostty configs do not get redirected to a different fallback file.

Why:

  • Ghostty Settings… was opening the wrong file for users whose real config lived in XDG locations such as ~/.config/ghostty/config.
  • In practice that meant the menu could open a nearly empty app-support config while the user’s actual active config lived elsewhere.
  • This change makes the settings action open the config files users are actually editing in the standard load-order locations used by cmux.

Closes #1476

Testing

  • Built and launched a tagged debug app with:
    • ./scripts/reload.sh --tag issue-1476
  • Added unit coverage for:
    • load-order resolution
    • fallback path selection
    • empty-file filtering
    • injected home-directory handling
    • custom XDG_CONFIG_HOME
    • symlinked config entrypoints
  • Verified the tagged app build succeeds locally.

Manual verification:

  • Verified the settings action behavior against the original issue scenario by checking that XDG-path config resolution is used instead of only opening the app-support Ghostty config path.

Note:

  • I did not complete a full local unit-test run because the local SwiftPM test invocation hit a pre-existing binary artifact cache issue unrelated to this patch. The tagged app build completed
    successfully.

Demo Video

  • Video URL or attachment: N/A

Review Trigger (Copy/Paste as PR comment)

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

Checklist

  • tested the change locally
  • I added or updated tests for behavior changes
  • I updated docs/changelog if needed
  • I requested bot reviews after my latest commit (copy/paste block above or equivalent)
  • All code review bot comments are resolved
  • All human review comments are resolved

Summary by CodeRabbit

  • New Features

    • Improved editor config discovery across XDG, home, and Application Support with canonical-path resolution, symlink handling, and deduplication.
    • Opens all discovered config files at once and auto-creates parent directories/files when editing a single, non-existent config.
    • More reliable disk loading that respects environment and bundle resource contexts and avoids reloading duplicate paths.
  • Tests

    • Added extensive tests for resolution order, symlink handling, deduplication, empty-file ignoring, and fallback behavior.

Copilot AI review requested due to automatic review settings March 16, 2026 07:46
@vercel

vercel Bot commented Mar 16, 2026

Copy link
Copy Markdown

@phongndo is attempting to deploy a commit to the Manaflow Team on Vercel.

A member of the Team first needs to authorize it.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai

coderabbitai Bot commented Mar 16, 2026 •

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Centralizes config discovery in GhosttyConfig, adds URL-backed resolution with canonicalization and non-empty filtering, exposes editorConfigURLs and cmuxAppSupportConfigURLs, updates GhosttyTerminalView to open all discovered configs (creating a fallback file when needed), and expands symlink/precedence tests.

Changes

Cohort / File(s) Summary
Config URL discovery & helpers
Sources/GhosttyConfig.swift
Replaced ad-hoc path checks with URL-backed resolution: added editorConfigURLs(...), cmuxAppSupportConfigURLs(...), defaultConfigURLs(...), canonicalConfigPath(...), existingNonEmptyConfigURL(...). Refactored loadFromDisk to use these helpers and added loadFromDiskForTests.
Terminal view integration
Sources/GhosttyTerminalView.swift
Switched to GhosttyConfig.editorConfigURLs(fileManager:); track canonical targets to avoid duplicates; pre-create parent dir + empty file when single non-existent fallback chosen; open multiple config URLs at once; removed low-level C-string helper.
Tests: config-resolution coverage
cmuxTests/GhosttyConfigTests.swift
Updated tests to reference GhosttyConfig.cmuxAppSupportConfigURLs; added extensive symlink, canonicalization, deduplication, load-order (XDG/legacy/AppSupport), non-empty filtering, and injected HOME/AppSupport scenarios.

Sequence Diagram

sequenceDiagram
    participant User
    participant Terminal as GhosttyTerminalView
    participant Config as GhosttyConfig
    participant FM as FileManager
    participant Workspace as NSWorkspace

    User->>Terminal: Click "Ghostty Settings"
    activate Terminal
    Terminal->>Config: editorConfigURLs(fileManager:, currentBundleIdentifier:, environment:, ...)
    activate Config
    Config->>FM: enumerate candidate URLs (XDG, HOME, AppSupport)
    FM-->>Config: existence/type/size info
    Config->>FM: resolve symlinks / canonicalize paths
    FM-->>Config: canonical path results
    Config-->>Terminal: prioritized non-empty URL list (or first-default fallback)
    deactivate Config

    alt URLs found
        Terminal->>Workspace: open(listOfURLs)
    else No URLs found
        Terminal->>FM: create parent dirs & empty fallback file
        FM-->>Terminal: success/failure
        Terminal->>Workspace: open(fallbackURL)
    end
    deactivate Terminal
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰
I hopped through XDG and Library lanes,
Untied symlinks, sorted all the chains.
I made a folder, left a tiny file,
Opened every config — one cozy pile.
A rabbit's tap: your settings reconciled.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix Ghostty Settings config file selection' clearly and concisely summarizes the main change: replacing single-path behavior with load-order-aware config file selection.
Linked Issues check ✅ Passed The changes comprehensively address all objectives in #1476: walking the config load order (#1) via new editorConfigURLs and cmuxAppSupportConfigURLs APIs, opening all existing non-empty config files (#2) via updated openConfigurationInTextEdit with multi-URL support, XDG_CONFIG_HOME support (#3), fallback creation of ~/.config/ghostty/config (#4), and symlink preservation (#5).
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the Ghostty Settings config file selection: new URL resolution APIs, test coverage, and config opening logic align with the linked issue requirements; no extraneous refactoring or unrelated features introduced.
Description check ✅ Passed PR description is well-structured with clear summary, testing details, and checklist completion. It follows the required template with all major sections covered.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can use your project's `swiftlint` configuration to improve the quality of Swift code reviews.

Add a configuration file to your project to customize how CodeRabbit runs swiftlint.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
Sources/GhosttyConfig.swift (1)

215-223: Inconsistent symlink handling with cmuxAppSupportConfigURLs.

The existingNonEmptyFileURL helper (used for XDG and mitchellh paths) handles both regular files and symlinks, but GhosttyApp.cmuxAppSupportConfigURLs (context snippet at Sources/GhosttyTerminalView.swift:1414-1448) only checks for type == .typeRegular, excluding symlinks.

If a user symlinks their cmux app support config (e.g., ~/Library/Application Support/com.cmuxterm.app/config → dotfiles location), it won't be discovered and opened, while symlinked XDG configs will work correctly.

Consider aligning the symlink handling in cmuxAppSupportConfigURLs to match the behavior here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/GhosttyConfig.swift` around lines 215 - 223, The
cmuxAppSupportConfigURLs path discovery excludes symlinks while
existingNonEmptyFileURL accepts them; update GhosttyApp.cmuxAppSupportConfigURLs
to treat symbolic links as valid config files the same way by checking for
symlink file attributes (e.g., URLResourceValues.isSymbolicLink or
FileAttributeKey.type == .typeSymbolicLink) in addition to regular files, and if
a symlink is found resolve or validate its destination is a non-empty file
before returning it so symlinked cmux config locations are discovered like
XDG/mitchellh paths handled by existingNonEmptyFileURL.
Sources/GhosttyTerminalView.swift (1)

1645-1649: Handle fallback file-creation failures explicitly before opening TextEdit.

Line 1645–Line 1649 currently ignore directory/file creation failures, but Line 1655 still attempts to open the URL list. If the fallback path is not writable, the settings action can silently fail.

Proposed hardening
         if let fallbackURL = fileURLs.first {
             let fallbackPath = fallbackURL.path
             if fileURLs.count == 1,
                !fileManager.fileExists(atPath: fallbackPath) {
-                try? fileManager.createDirectory(
-                    at: fallbackURL.deletingLastPathComponent(),
-                    withIntermediateDirectories: true
-                )
-                fileManager.createFile(atPath: fallbackPath, contents: Data())
+                do {
+                    try fileManager.createDirectory(
+                        at: fallbackURL.deletingLastPathComponent(),
+                        withIntermediateDirectories: true
+                    )
+                    let created = fileManager.createFile(atPath: fallbackPath, contents: Data())
+                    guard created || fileManager.fileExists(atPath: fallbackPath) else {
+#if DEBUG
+                        dlog("settings.open failed to create fallback config at \(fallbackPath)")
+#endif
+                        return
+                    }
+                } catch {
+#if DEBUG
+                    dlog("settings.open failed to prepare fallback config path error=\(error.localizedDescription)")
+#endif
+                    return
+                }
             }
         }

As per coding guidelines, "All debug events must be logged using the dlog() function, which is only available in DEBUG builds. All call sites must be wrapped in #if DEBUG / #endif preprocessor directives."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/GhosttyTerminalView.swift` around lines 1645 - 1649, Replace the
silent failures by explicitly checking the results of creating the parent
directory and the fallback file: use do/catch around
fileManager.createDirectory(at: fallbackURL.deletingLastPathComponent(),
withIntermediateDirectories: true) and check the Bool result of
fileManager.createFile(atPath: fallbackPath, contents: Data()); if either
operation fails, log the error/details using dlog(...) wrapped in `#if` DEBUG /
`#endif` and avoid proceeding to open the URL list / launch TextEdit (return or
throw early). Ensure you reference the existing symbols fallbackURL,
fallbackPath, fileManager.createDirectory(...), and fileManager.createFile(...)
so the failure is detected and handled before the code that opens the URL list
executes.
cmuxTests/GhosttyConfigTests.swift (1)

527-536: Consider removing redundant negative assertion.

The positive assertion on lines 517-526 already verified that the result equals [injectedConfig]. This negative assertion adds no additional coverage since if result == [injectedConfig], it logically follows that result != [otherConfig].

♻️ Proposed simplification
         XCTAssertEqual(
             GhosttyConfig.editorConfigURLs(
                 fileManager: fileManager,
                 currentBundleIdentifier: "com.cmuxterm.app.debug.issue-1476",
                 appSupportDirectory: appSupportDirectory,
                 homeDirectory: injectedHomeDirectory,
                 environment: [:]
             ),
             [injectedConfig]
         )
-        XCTAssertNotEqual(
-            GhosttyConfig.editorConfigURLs(
-                fileManager: fileManager,
-                currentBundleIdentifier: "com.cmuxterm.app.debug.issue-1476",
-                appSupportDirectory: appSupportDirectory,
-                homeDirectory: injectedHomeDirectory,
-                environment: [:]
-            ),
-            [otherConfig]
-        )
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmuxTests/GhosttyConfigTests.swift` around lines 527 - 536, Remove the
redundant negative assertion that compares GhosttyConfig.editorConfigURLs(...)
to [otherConfig]; the preceding positive assertion already confirms the result
equals [injectedConfig]. Locate the XCTAssertNotEqual block that calls
GhosttyConfig.editorConfigURLs with
fileManager/currentBundleIdentifier/appSupportDirectory/homeDirectory/environment
and referencing otherConfig, and delete that entire XCTAssertNotEqual assertion
to simplify the test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@cmuxTests/GhosttyConfigTests.swift`:
- Around line 527-536: Remove the redundant negative assertion that compares
GhosttyConfig.editorConfigURLs(...) to [otherConfig]; the preceding positive
assertion already confirms the result equals [injectedConfig]. Locate the
XCTAssertNotEqual block that calls GhosttyConfig.editorConfigURLs with
fileManager/currentBundleIdentifier/appSupportDirectory/homeDirectory/environment
and referencing otherConfig, and delete that entire XCTAssertNotEqual assertion
to simplify the test.

In `@Sources/GhosttyConfig.swift`:
- Around line 215-223: The cmuxAppSupportConfigURLs path discovery excludes
symlinks while existingNonEmptyFileURL accepts them; update
GhosttyApp.cmuxAppSupportConfigURLs to treat symbolic links as valid config
files the same way by checking for symlink file attributes (e.g.,
URLResourceValues.isSymbolicLink or FileAttributeKey.type == .typeSymbolicLink)
in addition to regular files, and if a symlink is found resolve or validate its
destination is a non-empty file before returning it so symlinked cmux config
locations are discovered like XDG/mitchellh paths handled by
existingNonEmptyFileURL.

In `@Sources/GhosttyTerminalView.swift`:
- Around line 1645-1649: Replace the silent failures by explicitly checking the
results of creating the parent directory and the fallback file: use do/catch
around fileManager.createDirectory(at: fallbackURL.deletingLastPathComponent(),
withIntermediateDirectories: true) and check the Bool result of
fileManager.createFile(atPath: fallbackPath, contents: Data()); if either
operation fails, log the error/details using dlog(...) wrapped in `#if` DEBUG /
`#endif` and avoid proceeding to open the URL list / launch TextEdit (return or
throw early). Ensure you reference the existing symbols fallbackURL,
fallbackPath, fileManager.createDirectory(...), and fileManager.createFile(...)
so the failure is detected and handled before the code that opens the URL list
executes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a438183a-0eff-48df-8490-faef93e30353

📥 Commits

Reviewing files that changed from the base of the PR and between 3b507d3 and e336ec2.

📒 Files selected for processing (3)
  • Sources/GhosttyConfig.swift
  • Sources/GhosttyTerminalView.swift
  • cmuxTests/GhosttyConfigTests.swift

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the “Open Configuration in TextEdit” behavior to locate and open the relevant Ghostty/cmux config files (in load order), with a fallback path when no existing configs are found.

Changes:

  • Added GhosttyConfig.editorConfigURLs(...) to resolve config file URLs (including XDG, legacy paths, and cmux app-support config).
  • Updated openConfigurationInTextEdit() to open all resolved config URLs and create the fallback config file/directory when none exist.
  • Added unit tests covering URL ordering, fallbacks, empty-file handling, XDG override, injected home dir, and symlink handling.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
Sources/GhosttyTerminalView.swift Uses new resolver to open multiple config files in TextEdit; creates fallback config path if needed.
Sources/GhosttyConfig.swift Introduces editorConfigURLs to compute candidate config locations and return existing non-empty configs (or a fallback).
cmuxTests/GhosttyConfigTests.swift Adds test coverage for the new URL resolution behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Sources/GhosttyConfig.swift Outdated
Comment thread Sources/GhosttyConfig.swift Outdated
Comment thread Sources/GhosttyTerminalView.swift Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="cmuxTests/GhosttyConfigTests.swift">

<violation number="1" location="cmuxTests/GhosttyConfigTests.swift:423">
P2: `testEditorConfigURLsIgnoresEmptyFiles` is ineffective: it expects the same XDG path that was just created as an empty file, so it cannot catch regressions where empty files are mistakenly treated as valid config files.</violation>
</file>

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread cmuxTests/GhosttyConfigTests.swift

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e336ec2e3f

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/GhosttyConfig.swift Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
Sources/GhosttyConfig.swift (1)

322-375: Finish threading the injected fileManager through reads.

loadFromDiskForTests(fileManager:) uses the injected manager for discovery, but readConfigFile falls back to FileManager.default for the actual read path. That makes the new injection point only half-effective.

♻️ Proposed refactor
-        for path in configPaths {
-            if let contents = readConfigFile(at: path) {
+        for path in configPaths {
+            if let contents = readConfigFile(at: path, fileManager: fileManager) {
                 config.parse(contents)
             }
         }
@@
-    private static func readConfigFile(at path: String) -> String? {
-        let fileManager = FileManager.default
+    private static func readConfigFile(
+        at path: String,
+        fileManager: FileManager = .default
+    ) -> String? {
         guard let url = existingNonEmptyConfigURL(
             for: URL(fileURLWithPath: path),
             fileManager: fileManager
         ) else { return nil }

Also applies to: 679-684

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/GhosttyConfig.swift` around lines 322 - 375, loadFromDiskForTests
currently uses the injected FileManager to build configPaths but still calls
readConfigFile(at:) which uses FileManager.default; update readConfigFile to
accept a FileManager parameter (e.g., readConfigFile(at:using:)) and change all
call sites—specifically the loop inside loadFromDiskForTests and the other
places referenced (around the other call site at the 679-684 region)—to pass the
injected fileManager; also update any helper functions that compute paths
(defaultConfigURLs, cmuxAppSupportConfigURLs) call sites to ensure they use the
same injected FileManager so all file reads and path resolutions are
consistently using the injected FileManager.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Sources/GhosttyConfig.swift`:
- Around line 185-193: The current xdgConfigRoot closure uses
NSString.expandingTildeInPath which expands ~ against the process user instead
of the injected homeDirectory and also allows non-absolute XDG_CONFIG_HOME
values; update logic in the xdgConfigRoot closure to: 1) detect a value starting
with "~" or "~/" and replace that leading component with the provided
homeDirectory path (do not call expandingTildeInPath), 2) if the value is not
absolute after this normalization, treat it as invalid and fall back to
homeDirectory.appendingPathComponent(".config", isDirectory: true), and 3) if
the value is absolute after normalization, return URL(fileURLWithPath:
normalized, isDirectory: true); also add a unit test for
editorConfigURLs/homeDirectory with environment["XDG_CONFIG_HOME"] set to a
tilde path to verify expansion uses the injected homeDirectory.

---

Nitpick comments:
In `@Sources/GhosttyConfig.swift`:
- Around line 322-375: loadFromDiskForTests currently uses the injected
FileManager to build configPaths but still calls readConfigFile(at:) which uses
FileManager.default; update readConfigFile to accept a FileManager parameter
(e.g., readConfigFile(at:using:)) and change all call sites—specifically the
loop inside loadFromDiskForTests and the other places referenced (around the
other call site at the 679-684 region)—to pass the injected fileManager; also
update any helper functions that compute paths (defaultConfigURLs,
cmuxAppSupportConfigURLs) call sites to ensure they use the same injected
FileManager so all file reads and path resolutions are consistently using the
injected FileManager.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b18fde29-2a41-4297-a48c-550da3b6317b

📥 Commits

Reviewing files that changed from the base of the PR and between e336ec2 and a150caf.

📒 Files selected for processing (3)
  • Sources/GhosttyConfig.swift
  • Sources/GhosttyTerminalView.swift
  • cmuxTests/GhosttyConfigTests.swift
🚧 Files skipped from review as they are similar to previous changes (1)
  • Sources/GhosttyTerminalView.swift

Comment thread Sources/GhosttyConfig.swift

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
Sources/GhosttyConfig.swift (1)

145-162: Optional: avoid duplicate stat calls for regular files.

existingNonEmptyConfigURL fetches file attributes and then immediately re-fetches them via hasNonEmptyRegularFileAttributes(at:) for regular files. You can reuse the first attributes payload to reduce I/O.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/GhosttyConfig.swift` around lines 145 - 162, The code performs two
stats for the same path: the outer attributes lookup and then a second call
inside hasNonEmptyRegularFileAttributes(at:); modify existingNonEmptyConfigURL
to reuse the attributes already obtained for url.path instead of calling
hasNonEmptyRegularFileAttributes(at:), by extracting the size from the earlier
attributes dictionary (attributes[.size] as? NSNumber) and returning url only if
type == .typeRegular and size.intValue > 0; you can keep
hasNonEmptyRegularFileAttributes(at:) for other callers or remove it if unused.
cmuxTests/GhosttyConfigTests.swift (1)

712-751: Optional: rename this test for intent clarity.

testEditorConfigURLsDeduplicatesCanonicalPathWhenCmuxConfigSymlinksToDefaultGhosttyConfig currently asserts both URLs are preserved and only canonicalized-set count is one. A name reflecting “preserves both entrypoints with shared canonical target” would reduce ambiguity.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmuxTests/GhosttyConfigTests.swift` around lines 712 - 751, Rename the test
function
testEditorConfigURLsDeduplicatesCanonicalPathWhenCmuxConfigSymlinksToDefaultGhosttyConfig
to a clearer name such as
testEditorConfigURLsPreservesBothEntrypointsWhenSymlinkedToSameCanonicalTarget;
update the function declaration and any references to it so that the intent
(that both entrypoint URLs are preserved even though their canonical/resolved
path is the same) is explicit, leaving the body intact which exercises
GhosttyConfig.editorConfigURLs and its resulting assertions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@cmuxTests/GhosttyConfigTests.swift`:
- Around line 712-751: Rename the test function
testEditorConfigURLsDeduplicatesCanonicalPathWhenCmuxConfigSymlinksToDefaultGhosttyConfig
to a clearer name such as
testEditorConfigURLsPreservesBothEntrypointsWhenSymlinkedToSameCanonicalTarget;
update the function declaration and any references to it so that the intent
(that both entrypoint URLs are preserved even though their canonical/resolved
path is the same) is explicit, leaving the body intact which exercises
GhosttyConfig.editorConfigURLs and its resulting assertions.

In `@Sources/GhosttyConfig.swift`:
- Around line 145-162: The code performs two stats for the same path: the outer
attributes lookup and then a second call inside
hasNonEmptyRegularFileAttributes(at:); modify existingNonEmptyConfigURL to reuse
the attributes already obtained for url.path instead of calling
hasNonEmptyRegularFileAttributes(at:), by extracting the size from the earlier
attributes dictionary (attributes[.size] as? NSNumber) and returning url only if
type == .typeRegular and size.intValue > 0; you can keep
hasNonEmptyRegularFileAttributes(at:) for other callers or remove it if unused.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 99e2d023-df1e-4204-ac05-041af0085512

📥 Commits

Reviewing files that changed from the base of the PR and between fe998c1 and 125c3d3.

📒 Files selected for processing (2)
  • Sources/GhosttyConfig.swift
  • cmuxTests/GhosttyConfigTests.swift

@phongndo

Copy link
Copy Markdown
Author

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@cubic-dev-ai

cubic-dev-ai Bot commented Mar 17, 2026

Copy link
Copy Markdown

@codex review
@coderabbitai review
@greptile-apps review
@cubic-dev-ai review

@phongndo I have started the AI code review. It will take a few minutes to complete.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai

coderabbitai Bot commented Mar 17, 2026

Copy link
Copy Markdown

@phongndo Sure, I'll review the changes in PR #1513!


🧠 Learnings used
Learnt from: CR
Repo: manaflow-ai/cmux PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-03-12T21:54:38.291Z
Learning: Ghostty changes must be committed in the `ghostty` submodule and pushed to the `manaflow-ai/ghostty` fork. Keep `docs/ghostty-fork.md` up to date with any fork changes and conflict notes.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 3 files

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

ctrlShiftBryan added a commit to ctrlShiftBryan/cmux that referenced this pull request Mar 26, 2026
Continuation of 59e2281

TURN 1: Checked for open PRs implementing a cmux-level keybindings config file; found none actively working on issue manaflow-ai#1486, with only PR manaflow-ai#1513 existing as an unrelated Ghostty config fix.

OVERALL: Investigated open PR status for keybindings config feature and confirmed issue manaflow-ai#1486 is requested but not currently being implemented.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@phongndo phongndo closed this by deleting the head repository Apr 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"Ghostty Settings" menu opens wrong config file

2 participants