Skip to content

Resolve terminal relative paths from surface context - #8101

Closed
austinywang wants to merge 7 commits into
mainfrom
issue-8097-relative-path-autoresolve
Closed

austinywang wants to merge 7 commits into
mainfrom
issue-8097-relative-path-autoresolve

Conversation

@austinywang

@austinywang austinywang commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • Resolve terminal path tokens through one structured pipeline carrying an absolute existing path plus optional line and column metadata.
  • Resolve relative references against the clicked surface cwd, then validated repository and workspace roots; every result is existence-gated.
  • Preserve explicit URL and ordinary absolute-path behavior, while forwarding source locations to configured external editor commands.
  • Apply the same resolver to Ghostty open-URL callbacks and file-at-cursor affordances without changing the Ghostty submodule.

Fixes #8097
Related: #1678, #4675

Architecture

TerminalPathResolver in CmuxTerminalCore owns token normalization, source-location parsing, ordered root probing, URL exclusion, and existence gating. The app callback only builds TerminalPathResolutionContext from canonical per-surface panelDirectories and requestedWorkingDirectory metadata plus the tracked repository/workspace roots. PreferredEditorService remains the single external-editor launch path and receives the structured source location.

Testing

  • Regression commit b5342e8 fails the line and line-column cases before the implementation.
  • CmuxTerminalCore: 234 Swift Testing tests passed with swift test --disable-xctest.
  • CmuxWorkspaces: 150 Swift Testing tests passed with swift test --disable-xctest.
  • scripts/lint-pbxproj-test-wiring.sh passed: 493 test files checked.
  • scripts/check-pbxproj.sh passed.
  • Workspace package grouping and Package.resolved policy checks passed.
  • git diff --check passed.
  • Mandatory Swift file budget script was run. It reports only pre-existing origin/main overruns in unrelated files; touched tracked files remain below their checked-in caps and neither budget TSV changed.
  • No local app build, xcodebuild, XCUITest, or end-to-end app run was performed because this task explicitly routes app-target validation through GitHub Actions.

Localization

No user-facing strings, settings labels, shortcut metadata, docs text, or localization catalogs changed. The changed Swift files were searched for newly introduced UI text; no localization entries were required.

Review Trigger

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

Checklist

  • Focused package tests pass
  • Regression coverage added in a separate red commit
  • Project and test wiring checks pass
  • Localization audit complete
  • Bot reviews requested after the implementation commit
  • Required CI checks green
  • Review comments resolved

Summary by CodeRabbit

  • New Features
    • Terminal file opens can now pass optional line/column to the configured editor (:line / :line:column).
    • More accurate routing when opening terminal link targets, preserving source locations when applicable.
  • Bug Fixes
    • Improved relative-path and :line / :line:column parsing, including safer handling that won’t bypass file existence checks for location-suffixed tokens.
    • Open embedded-browser links more reliably, with correct external fallback when embedded routing isn’t available.
  • Tests
    • Expanded path/location resolution and click fallback coverage; added new URL target resolution tests and updated runtime stubs.

@vercel

vercel Bot commented Jul 14, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
cmux Ready Ready Preview, Comment Jul 15, 2026 3:23am
cmux-staging Building Building Preview, Comment Jul 15, 2026 3:23am

@coderabbitai

coderabbitai Bot commented Jul 14, 2026 •

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The changes add shared terminal path-resolution models and probing, preserve line and column metadata through file-opening flows, support configured-editor locations, extract browser helpers, and expand path, editor, browser, fallback-policy, and runtime-stub tests.

Changes

Terminal path and link opening flow

Layer / File(s) Summary
Path resolution contracts and parsing
Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/*
Adds resolution context and result types, plus parsing for path:line[:column] candidates.
Unified resolver pipeline
Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/*, Packages/macOS/CmuxTerminalCore/Tests/CmuxTerminalCoreTests/TerminalPathResolverTests.swift
Centralizes context-aware probing, fallback ordering, source-location preservation, and URL/path classification.
Terminal routing and editor opening
Sources/GhosttyTerminalView.swift, Sources/CommandClickFileOpenRouter.swift, Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/FileOpen/*, Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/FileOpen/*
Passes structured resolutions through command-click and OpenURL routing, cmux previews, external openers, and configured-editor commands.
Embedded browser routing extraction
Sources/GhosttyApp+EmbeddedBrowserLink.swift, Sources/TerminalBrowserHostNormalizer.swift, cmux.xcodeproj/project.pbxproj, cmuxTests/*
Moves embedded-browser opening and host normalization into dedicated compiled files and updates target-resolution tests.
Fallback policy and test runtime support
Packages/macOS/CmuxTerminalCore/Sources/.../TerminalCommandClickFallbackPolicy.swift, Packages/macOS/CmuxTerminalCore/Tests/.../TerminalCommandClickFallbackPolicyTests.swift, Packages/macOS/CmuxTerminalCore/Tests/GhosttyRuntimeTestStubs/*
Adds command-click fallback policy coverage and the scrollback-limit Ghostty runtime stub.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested reviewers: azooz2003-bit


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Cmux Swift Actor Isolation ❌ Error New app-side helper TerminalBrowserHostNormalizer is a pure stateless utility but isn’t marked nonisolated, so it can inherit unnecessary Swift 6 main-actor coupling. Mark TerminalBrowserHostNormalizer nonisolated (or otherwise isolate it explicitly) so the helper stays usable from non-main contexts.
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (23 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the main change: resolving terminal relative paths from surface context.
Description check ✅ Passed The description closely follows the template and includes summary, architecture, testing, review trigger, and checklist sections.
Linked Issues check ✅ Passed The changes implement relative-path resolution, cwd/root fallback, source-location support, and reuse across the requested path-opening flows.
Out of Scope Changes check ✅ Passed The added files and refactors all support path resolution, editor launching, or related link handling; no clearly unrelated changes stand out.
Cmux Swift Blocking Runtime ✅ Passed No added production diff lines introduce waits, sleeps, asyncAfter, main-sync, or manual locks; only path-resolution and editor-routing logic changed.
Cmux Browser Automation Off-Main ✅ Passed PR doesn’t touch the rule’s target files, and the changed files add path/URL routing only—no browser.* socket commands or worker-router changes.
Cmux Expensive Synchronous Load ✅ Passed No changed Swift file adds RestorableAgentSessionIndex.load() or other agent-history/transcript parsing; the edits are path resolution and editor-launch routing only.
Cmux Cache Substitution Correctness ✅ Passed No persistence/history/undo/snapshot path swapped a fresh read for a stale cache; the new directory state is live-evented and the mouse-release reference is transient.
Cmux No Hacky Sleeps ✅ Passed No covered non-Swift runtime files changed, and the touched C/header/pbxproj files add no fixed sleeps, timers, polling, or delay-based coordination.
Cmux Algorithmic Complexity ✅ Passed New scans are limited to tiny candidate sets; workspace/panel lookups are O(1), and the diff adds no large rescans or repeated sorts in hot paths.
Cmux Swift Concurrency ✅ Passed Diff only adds boundary hops (DispatchQueue.main.async, Task@MainActor in Process terminationHandler) and no new background queues, Combine state, or internal completion-handler APIs.
Cmux Swift @Concurrent ✅ Passed No changed production async helper needs @concurrent; the new work is synchronous or explicitly hops to MainActor, so the rule isn’t violated.
Cmux Swift File And Package Boundaries ✅ Passed PASS — core path parsing/editor-launch logic was extracted into small package types; app-target changes are thin glue, and no new production Swift file exceeds the boundary thresholds.
Cmux Swiftpm Lockfiles ✅ Passed PR only adds sources/tests and file refs in pbxproj; no .gitignore, Package.swift, or Package.resolved changes, and no SwiftPM package-reference edits.
Cmux Swift Logging ✅ Passed Touched production Swift changes add no print/NSLog/Logger violations; only new logs are #if DEBUG cmuxDebugLog diagnostics.
Cmux User-Facing Error Privacy ✅ Passed No production user-facing errors were added or changed; the diff shows no alerts, command output, recovery copy, or sensitive vendor/env/id leakage.
Cmux Full Internationalization ✅ Passed Diff only changes path-resolution/editor-launch logic and tests; no user-facing Swift copy, catalogs, Info.plist, or web locale files were introduced.
Cmux Swiftui State Layout ✅ Passed Touched SwiftUI file is an NSViewRepresentable bridge; no new ObservableObject/@published, GeometryReader, lazy-row store refs, or render-time state writes.
Cmux Architecture Rethink ✅ Passed Localized path-resolution refactor; no new timing/lock/observer workaround or split ownership was introduced, and the resolution owner/invariants stay clear.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed No touched Swift file adds or materially changes a standalone window/controller, or any cmux auxiliary-window identifier registration; changes are routing/path-resolution only.
Cmux Source Artifacts ✅ Passed All changed paths are intentional source, test, or project config files; no logs, caches, build output, temp dirs, or other artifact paths appear in the diff.
Cmux No Test Or Debug Seam In Production Source ✅ Passed No new test-only seam was added in production Sources/; the new #if DEBUG code in GhosttyApp+EmbeddedBrowserLink is logging around a real call path, not test observability.
Cmux No Ambient Global State ✅ Passed The diff adds only constructable/injected types and instance methods; no new file-scope API, top-level mutable state, or singleton-style runtime state was introduced.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-8097-relative-path-autoresolve

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.

@chatgpt-codex-connector

Copy link
Copy Markdown

To use Codex here, create a Codex account and connect to github.

@austinywang
austinywang marked this pull request as ready for review July 14, 2026 22:59
@greptile-apps

greptile-apps Bot commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR improves terminal file-link handling from detection through opening. The main changes are:

  • Structured path resolutions now carry path, line, and column data.
  • Relative terminal paths are resolved through surface and workspace context.
  • Ghostty open-URL and command-click paths use the shared resolver.
  • Preferred editor launches can receive source locations for supported editors.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalPathResolver.swift Adds structured path resolution with existence checks, fallback roots, URL exclusion, and source-location parsing.
Sources/CommandClickFileOpenRouter.swift Routes terminal file references through cmux or the configured editor based on file-route settings and source-location support.
Sources/GhosttyTerminalView.swift Threads structured terminal file references through Ghostty open-URL and command-click handling.
Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/FileOpen/PreferredEditorLaunchCommand.swift Builds editor launch commands that preserve source locations for known editor CLIs.
Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/FileOpen/PreferredEditorService.swift Extends preferred editor opening to accept optional line and column metadata.

Reviews (7): Last reviewed commit: "fix: address command-click review findin..." | Re-trigger Greptile

@cursor

cursor Bot commented Jul 14, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

Comment thread Sources/CommandClickFileOpenRouter.swift Outdated
Comment thread Sources/CommandClickFileOpenRouter.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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalPathResolver.swift (1)

94-155: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the older wrappers if you don’t need the compatibility surface
resolveVisibleLinePath and resolveQuicklookPath are only referenced by tests; production now routes through resolveVisibleLineReference and resolvePath. If no external callers depend on the old API, removing the wrappers would leave one path-resolution surface.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalPathResolver.swift`
around lines 94 - 155, Remove the legacy resolveQuicklookPath and
resolveVisibleLinePath wrappers from TerminalPathResolver, along with any tests
or references that require those compatibility-only APIs, so callers use
resolvePath and resolveVisibleLineReference directly. Preserve the existing
path-resolution behavior through the structured APIs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalPathResolver.swift`:
- Around line 10-23: Mark the three Sendable value/service types as explicitly
nonisolated: update TerminalPathResolver in
Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalPathResolver.swift:10-23,
TerminalPathResolution in
Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalPathResolution.swift:2-24,
and TerminalPathResolutionContext in
Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalPathResolutionContext.swift:2-21.
No other behavior changes are needed.

In `@Sources/GhosttyTerminalView.swift`:
- Around line 2970-3016: The relative-path candidate early return after file
resolution must not swallow already-resolved files. Update the
`TerminalPathResolver().isRelativePathReferenceCandidate(trimmedUrlString)`
condition to return early only when `resolvedFileReference` is nil, allowing
resolved non-cmux-routable files to continue to `resolveOpenURLTarget` and the
external editor fallback.

---

Outside diff comments:
In
`@Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalPathResolver.swift`:
- Around line 94-155: Remove the legacy resolveQuicklookPath and
resolveVisibleLinePath wrappers from TerminalPathResolver, along with any tests
or references that require those compatibility-only APIs, so callers use
resolvePath and resolveVisibleLineReference directly. Preserve the existing
path-resolution behavior through the structured APIs.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9ee6e6fa-f436-42b0-ac6c-317b6cbc7f19

📥 Commits

Reviewing files that changed from the base of the PR and between b5342e8 and 3761a00.

📒 Files selected for processing (13)
  • Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/String+TerminalPathTokens.swift
  • Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalPathResolution.swift
  • Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalPathResolutionContext.swift
  • Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalPathResolver.swift
  • Packages/macOS/CmuxTerminalCore/Tests/CmuxTerminalCoreTests/TerminalPathResolverTests.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/FileOpen/PreferredEditorService.swift
  • Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/FileOpen/PreferredEditorServiceTests.swift
  • Sources/CommandClickFileOpenRouter.swift
  • Sources/GhosttyApp+EmbeddedBrowserLink.swift
  • Sources/GhosttyTerminalView.swift
  • Sources/TerminalBrowserHostNormalizer.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/TerminalAndGhosttyTests.swift

Comment thread Sources/GhosttyTerminalView.swift
Comment thread Sources/CommandClickFileOpenRouter.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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/FileOpen/PreferredEditorLaunchCommand.swift`:
- Around line 15-20: Consolidate the editor-name checks used by
supportsSourceLocation and usesGotoFlag into one shared source of truth, such as
a common supported-editor collection or helper. Update both properties to reuse
it while preserving their existing behavior and editor-specific CLI flag
selection.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 688c6685-c2cb-4bd8-83c7-745ea32ffd29

📥 Commits

Reviewing files that changed from the base of the PR and between b7dc269 and 184dd17.

📒 Files selected for processing (14)
  • Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalCommandClickFallbackPolicy.swift
  • Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalPathResolution.swift
  • Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalPathResolutionContext.swift
  • Packages/macOS/CmuxTerminalCore/Sources/CmuxTerminalCore/PathResolution/TerminalPathResolver.swift
  • Packages/macOS/CmuxTerminalCore/Tests/CmuxTerminalCoreTests/TerminalCommandClickFallbackPolicyTests.swift
  • Packages/macOS/CmuxTerminalCore/Tests/CmuxTerminalCoreTests/TerminalPathResolverTests.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/FileOpen/PreferredEditorLaunchCommand.swift
  • Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/FileOpen/PreferredEditorService.swift
  • Packages/macOS/CmuxWorkspaces/Tests/CmuxWorkspacesTests/FileOpen/PreferredEditorServiceTests.swift
  • Sources/CommandClickFileOpenRouter.swift
  • Sources/GhosttyTerminalView.swift
  • cmux.xcodeproj/project.pbxproj
  • cmuxTests/TerminalAndGhosttyTests.swift
  • cmuxTests/TerminalOpenURLTargetResolutionTests.swift
💤 Files with no reviewable changes (1)
  • cmuxTests/TerminalAndGhosttyTests.swift

Comment on lines +15 to +20
var supportsSourceLocation: Bool {
guard let executableName else { return false }
return [
"code", "code-insiders", "codium", "cursor", "subl", "zed", "zed-preview",
].contains(executableName)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Two independent editor lists risk silently diverging.

supportsSourceLocation and usesGotoFlag each hardcode their own editor-name list. Adding a new VS Code fork to one list without updating the other would silently produce the wrong CLI syntax for that editor.

♻️ Consolidate into a single source of truth
+private enum KnownEditor: String {
+    case code, codeInsiders = "code-insiders", codium, cursor, subl, zed, zedPreview = "zed-preview"
+
+    var usesGotoFlag: Bool {
+        switch self {
+        case .code, .codeInsiders, .codium, .cursor: return true
+        case .subl, .zed, .zedPreview: return false
+        }
+    }
+}
+
 var supportsSourceLocation: Bool {
     guard let executableName else { return false }
-    return [
-        "code", "code-insiders", "codium", "cursor", "subl", "zed", "zed-preview",
-    ].contains(executableName)
+    return KnownEditor(rawValue: executableName) != nil
 }
 private var usesGotoFlag: Bool {
     guard let executableName else { return false }
-    return ["code", "code-insiders", "codium", "cursor"].contains(executableName)
+    return KnownEditor(rawValue: executableName)?.usesGotoFlag ?? false
 }

Also applies to: 40-43

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/macOS/CmuxWorkspaces/Sources/CmuxWorkspaces/FileOpen/PreferredEditorLaunchCommand.swift`
around lines 15 - 20, Consolidate the editor-name checks used by
supportsSourceLocation and usesGotoFlag into one shared source of truth, such as
a common supported-editor collection or helper. Update both properties to reuse
it while preserving their existing behavior and editor-specific CLI flag
selection.

This branch was successfully deployed

1 active deployment
Preview – cmux — 184dd17c Deployed Jul 15, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale-revisit Closed after 30+ days without activity; preserved for possible revisit or reopening.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Cmd+click auto-resolves relative paths against the session's cwd context

3 participants