Skip to content

fix: open terminal links on cmd-click even when mouse reporting is active - #71

Merged
austinywang merged 2 commits into
manaflow-ai:mainfrom
doronpr:fix-cmd-click-links-mouse-reporting
Jun 5, 2026
Merged

austinywang merged 2 commits into
manaflow-ai:mainfrom
doronpr:fix-cmd-click-links-mouse-reporting

Conversation

@doronpr

@doronpr doronpr commented Jun 3, 2026 •

Copy link
Copy Markdown

Fixes manaflow-ai/cmux#5128 — terminal links open in the external browser instead of the embedded one, but only while a fullscreen / alternate-screen TUI (which enables mouse reporting) is active.

Cause

Link hover state is refreshed (keyCallback, cursorPosCallback) only when mouse reporting is off, or shift is releasing the mouse from capture. Holding the ctrl/super link modifier isn't considered, so under a mouse-grabbing TUI over_link stays false, the link-click branch in mouseButtonCallback is skipped, and the click is reported to the program instead of opening the link.

Fix

Also refresh links when the ctrl/super link-activation modifier is held, even under mouse reporting — so cmd-click (macOS) / ctrl-click opens a link regardless of mouse capture, matching iTerm2 and macOS Terminal. The click is then swallowed by processLinks before the mouse-report path. The shared condition lives in mouseLinkRefreshAllowed (used by both gates); the pure logic is split into mouseLinkRefreshAllowedState for testing. That modifier is exactly what both link kinds already require to activate: OSC 8 (linkAtPos) and the default url link (hover_mods = ctrlOrSuper).

Tests

mouseLinkRefreshAllowedState unit test covers the truth table, including the regression case (mouse reporting on + ctrl/super held ⇒ links handled locally). zig fmt/ast-check clean; zig build test compiles, but the test binary can't link libSystem under zig 0.15.2 on macOS 26 in my environment, so I couldn't execute it locally — CI should.


AI disclosure (per AI_POLICY.md): developed with Claude Code (Claude Opus 4.8). Investigation, patch, and test were AI-assisted; I have reviewed the change and can explain it.

…tive

When a fullscreen/alternate-screen TUI (e.g. Claude Code) enables mouse
reporting, holding the ctrl/super link modifier did not let link hover/click
be processed locally. The gates in keyCallback and cursorPosCallback refreshed
link state only when mouse reporting was off or shift was releasing capture, so
a cmd-click was reported to the program instead of opening the link. Embedders
like cmux that route link opens to a built-in browser therefore fell back to
the OS default browser whenever a mouse-grabbing TUI was active.

Allow local link handling when the ctrl/super link-activation modifier is held,
even under mouse reporting (matching iTerm2 and macOS Terminal), via a shared
mouseLinkRefreshAllowed helper. The click is then swallowed by processLinks
before the mouse-report path, so the link opens consistently. Adds a unit test
for the pure decision logic.

Fixes manaflow-ai/cmux#5128

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 3, 2026 •

Copy link
Copy Markdown

Warning

Rate limit exceeded

@doronpr has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 46 minutes and 17 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8c942aa2-08f8-4d77-8a65-5422073e974a

📥 Commits

Reviewing files that changed from the base of the PR and between 1c7613c and 55d154a.

📒 Files selected for processing (1)
  • src/Surface.zig
📝 Walkthrough

Walkthrough

Surface.zig consolidates link-hover evaluation logic to consistently handle the ctrl/super link-activation modifier across keyboard and cursor events. New helper functions encode the eligibility rules and are applied uniformly to both input paths, with unit test coverage for the testable pure function.

Changes

Link-hover evaluation and modifier consistency

Layer / File(s) Summary
Link-evaluation helper functions
src/Surface.zig
New pure function mouseLinkRefreshAllowedState(...) centralizes link-hover eligibility rules based on mouse reporting, shift-capture, and modifiers (including ctrl/super detection); bound method mouseLinkRefreshAllowed() wraps the pure function.
Consistent keyboard and cursor hover refresh
src/Surface.zig
keyCallback and cursorPosCallback both refactored to call mouseLinkRefreshAllowed(), replacing previous inline mouse-event/shift-capture expressions and ensuring uniform behavior across input paths.
Unit test for link-evaluation state logic
src/Surface.zig
Test validates the pure helper across mouse reporting enabled/disabled, ctrl/super chord handling, and shift-capture allowed/disallowed combinations.

Possibly related PRs

  • manaflow-ai/ghostty#54: Both PRs modify Surface's cursorPosCallback to refresh link hover/open state on modifier-only changes; this PR gates hover refresh via the new mouseLinkRefreshAllowed() helper while the retrieved PR ensures cursorPosCallback runs when modifiers change.

Poem

🐰 A modifier chord now rings so clear—
Ctrl and Super, drawing near!
Links obey with steadfast grace,
From keyboard, mouse—same time, same place! ✨


🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'fix: open terminal links on cmd-click even when mouse reporting is active' directly and specifically describes the main bug fix in the PR, matching the primary change documented in both the summary and objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Git: Failed to clone repository. Please run the @coderabbitai full review command to re-trigger a full review. If the issue persists, set path_filters to include or exclude specific files.


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.

@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 `@src/Surface.zig`:
- Around line 3824-3828: The gate is using only terminal mouse_event flag;
change it to use the effective mouse-reporting state (respecting
config.mouse_reporting and runtime toggles) when calling
mouseLinkRefreshAllowedState. Replace the first argument expression
self.io.terminal.flags.mouse_event != .none with a call/reference to the
effective mouse-reporting boolean (e.g., a helper like
self.effectiveMouseReporting() or the evaluated expression that combines
self.config.mouse_reporting and terminal flags), keeping the other args
(self.mouseShiftCapture(false), self.mouse.mods) unchanged and ensuring the
effective state reflects runtime toggles.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: c6df9ba1-ca87-4b75-a8ed-03249c086b06

📥 Commits

Reviewing files that changed from the base of the PR and between 15b877e and 1c7613c.

📒 Files selected for processing (1)
  • src/Surface.zig

Comment thread src/Surface.zig
@greptile-apps

greptile-apps Bot commented Jun 3, 2026

Copy link
Copy Markdown

Greptile Summary

Fixes a bug where Cmd/Ctrl-click on a terminal link was silently swallowed by mouse reporting when a fullscreen TUI (e.g. an alt-screen app) had grabbed the mouse, causing link opens to fall back to the OS browser. The fix introduces a mouseLinkRefreshAllowed helper (and a pure mouseLinkRefreshAllowedState for testability) that allows local link evaluation when ctrl/super is held, matching iTerm2 and macOS Terminal behavior.

  • Core logic change: Both keyCallback and cursorPosCallback now call mouseLinkRefreshAllowed() instead of inlining the mouse-reporting gate; the new helper adds a third condition — exact ctrlOrSuper(.{}) held — alongside the existing "mouse reporting off" and "shift releasing capture" conditions.
  • Testability: The pure mouseLinkRefreshAllowedState function separates decision logic from Surface state, enabling the included truth-table unit test without constructing a full surface.
  • Scope: The bypass is hard-coded to the default ctrlOrSuper(.{}) chord; users with custom hover_mods configurations will not benefit from the fix under mouse reporting.

Confidence Score: 4/5

Safe to merge; the bypass fires only on the exact ctrl/super chord that link activation already requires, keeping the gate and the activation condition in lock-step.

The fix correctly mirrors the activation condition used inside linkAtPos in the new bypass gate. Custom hover_mods configurations won't benefit under mouse reporting, but that is a pre-existing design constraint acknowledged by the PR. One test matrix cell is absent but the behavior there is correct.

src/Surface.zig around mouseLinkRefreshAllowedState if custom link modifier support is added later.

Important Files Changed

Filename Overview
src/Surface.zig Introduces mouseLinkRefreshAllowed / mouseLinkRefreshAllowedState helpers to allow local link handling when ctrl/super is held under mouse reporting; applies them to both keyCallback and cursorPosCallback; adds a targeted unit test covering the truth table.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Mouse event: key change or cursor move] --> B{mods changed?}
    B -- No --> Z[No action]
    B -- Yes --> C[modsChanged: update self.mouse.mods]
    C --> D[mouseLinkRefreshAllowed?]
    D --> E{mouse_event == .none?}
    E -- Yes --> F[return true: evaluate links locally]
    E -- No --> G{mods.shift AND NOT shift_capture?}
    G -- Yes --> F
    G -- No --> H{mods == ctrlOrSuper exactly?}
    H -- Yes --> F
    H -- No --> I[return false: deliver to program]
    F --> J[mouseRefreshLinks]
    J --> K[linkAtPos]
    K --> L{link found?}
    L -- Yes --> M[over_link = true]
    L -- No --> N[over_link = false]
    M --> O[mouseButtonCallback: processLinks, open URL]
    I --> P[Mouse event reported to running program]
Loading

Reviews (1): Last reviewed commit: "fix: open terminal links on cmd-click ev..." | Re-trigger Greptile

Comment thread src/Surface.zig
) bool {
if (!mouse_event_active) return true;
if (mods.shift and !shift_capture) return true;
return mods.equal(input.ctrlOrSuper(.{}));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Bypass condition doesn't cover custom link modifiers

mouseLinkRefreshAllowedState bypasses mouse reporting only for the exact ctrlOrSuper(.{}) chord. For OSC 8 links that's the right check (it mirrors linkAtPos line 4413), but for regex links the activation mod comes from Config.link.highlight.hover_mods, which users can configure to something else (e.g. ctrl+alt). A user who configured a non-default hover_mods will see the bypass condition silently fail under mouse reporting because the exact-match against the default chord won't fire for their custom mod.

This is a design limitation that could be addressed by threading the configured hover_mods into this check, but it's out of scope for the current fix and the PR description acknowledges the default modifier scope.

Comment thread src/Surface.zig
Comment on lines +6562 to +6585
// Mouse reporting off: links are always evaluated, regardless of mods.
try std.testing.expect(mouseLinkRefreshAllowedState(false, false, .{}));
try std.testing.expect(mouseLinkRefreshAllowedState(false, false, ctrl_or_super));

// Mouse reporting on, no relevant mods: the event is reported to the app,
// links are not evaluated locally.
try std.testing.expect(!mouseLinkRefreshAllowedState(true, false, .{}));

// Mouse reporting on, ctrl/super link modifier held: links are evaluated
// so Cmd-click (macOS) / Ctrl-click opens a link even while a
// fullscreen/alternate-screen TUI has grabbed the mouse. This is the
// behavior that was missing in cmux issue #5128.
try std.testing.expect(mouseLinkRefreshAllowedState(true, false, ctrl_or_super));

// Mouse reporting on, shift held and shift-capture disallowed: evaluated
// (pre-existing shift-release-from-capture behavior, unchanged).
try std.testing.expect(mouseLinkRefreshAllowedState(true, false, .{ .shift = true }));

// Mouse reporting on, shift held but shift-capture allowed: reported.
try std.testing.expect(!mouseLinkRefreshAllowedState(true, true, .{ .shift = true }));

// Mouse reporting on, ctrl/super plus a non-shift modifier: not an exact
// link-activation chord, so the event is reported to the app.
try std.testing.expect(!mouseLinkRefreshAllowedState(true, false, input.ctrlOrSuper(.{ .alt = true })));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Test matrix is missing one cell

The truth table covers (mouse_event_active=true, shift_capture=false, ctrl_or_super) but not (true, shift_capture=true, ctrl_or_super). When shift capture is enabled and ctrl/super is the only mod, the function should still return true because mods.shift is false and we fall through to the mods.equal(ctrlOrSuper) check. Adding that assertion would prevent a future refactor from inadvertently gating the ctrl/super path on shift_capture.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@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 1 file

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/Surface.zig Outdated
Addresses review feedback on the PR. Pass isMouseReporting() (config +
terminal mode) into mouseLinkRefreshAllowedState instead of the raw
terminal mouse_event flag, mirroring the sibling mouse-report gate in
mouseButtonCallback/cursorPosCallback. This also handles links locally
when mouse reporting is disabled via config even though a program set the
mode (the program receives no mouse events in that case). Renames the
parameter to mouse_reporting and adds the shift-capture + ctrl/super test
cell so the ctrl/super path is never inadvertently gated on shift_capture.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@doronpr

doronpr commented Jun 3, 2026

Copy link
Copy Markdown
Author

Addressed the bot review in 55d154a:

  • CodeRabbit / cubic (P2 — effective mouse-reporting state): applied. The gate now passes isMouseReporting() (config + terminal mode) instead of the raw mouse_event flag, mirroring the sibling mouse-report gate in mouseButtonCallback/cursorPosCallback. This also handles links locally when reporting is disabled in config even though a program set the mode.
  • Greptile (P2 — missing test cell): applied. Added the (reporting=on, shift_capture=true, ctrl/super) assertion so the ctrl/super path can't be inadvertently gated on shift_capture.
  • Greptile (P2 — custom hover_mods for regex links): not changing. Out of scope for this fix: the exact ctrlOrSuper match covers OSC 8 hyperlinks and the default url link (hover_mods = ctrlOrSuper); threading per-link configured hover_mods is a larger, separate change. Noted as a known limitation.

AI disclosure: review triage and the above change were done with Claude Code (Claude Opus 4.8); reviewed by me.

@austinywang
austinywang merged commit 9eea29f into manaflow-ai:main Jun 5, 2026
4 checks passed
austinywang added a commit that referenced this pull request Jun 5, 2026
…ostty-org#5128 follow-up)

Follow-up to #71: keeps Cmd-click link-open from leaking a half-click to mouse-grabbing alt-screen TUIs. Merge commit keeps d1dbbec an ancestor of fork main for the cmux submodule pin.
austinywang added a commit that referenced this pull request Jun 5, 2026
…mux ghostty-org#5128)

Final follow-up to #71/#74: keeps a Cmd-held drag from leaking button-motion to mouse-grabbing TUIs. Merge commit keeps 76ead3e an ancestor of fork main for the cmux submodule pin.
austinywang added a commit that referenced this pull request Jun 5, 2026
…mux ghostty-org#5128)

Final review follow-up to #71/#74/#75: scopes the link-chord click/drag suppression to the left button and clears stale link hover when the chord drops via cursor mods. Merge commit keeps f241952 an ancestor of fork main.
hhsw2015 pushed a commit to hhsw2015/ghostty that referenced this pull request Jun 5, 2026
Follow-up to manaflow-ai#71. When the ctrl/super link-activation modifier is held over a
link in a mouse-reporting alt-screen app, mouseButtonCallback previously still
reported the left-button *press* to the program and only swallowed the later
*release* via processLinks (which runs only on release). That leaked a
half-click — a press with no matching release — to mouse-grabbing TUIs like
Claude Code and Codex, exactly the scenario the link fix targets.

Break out of the mouse-report path when over a link with the ctrl/super chord
held, suppressing both press and release from the program, mirroring the
existing shift-release-from-capture suppression. The release still opens the
link locally. Fixes manaflow-ai/cmux#5128.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
austinywang added a commit to manaflow-ai/cmux that referenced this pull request Jun 10, 2026
…ex) (#5406)

* Bump ghostty to 55d154a: open links on cmd-click under mouse reporting

Fixes #5128. Clicking a link inside a fullscreen alternate-screen TUI
(Claude Code, Codex) opened the OS default browser instead of honoring the
configured cmux link-open target. cmux's GHOSTTY_ACTION_OPEN_URL handler is
already mode-independent (resolveTerminalOpenURLTarget routes per
BrowserAvailabilitySettings, no mouse-mode branch); the gap was in ghostty
core, where link hover state was refreshed only when mouse reporting was off
or shift released capture, so a Cmd-click under a mouse-grabbing TUI never
fired open_url.

Bumps the ghostty submodule to 55d154a (previous pin 176bd55 + the two
link-fix commits from manaflow-ai/ghostty#71, merged into fork main). The fix
also evaluates links locally when the ctrl/super link modifier is held, using
the effective mouse-reporting state, matching iTerm2 and macOS Terminal.

Publishes and pins the matching GhosttyKit xcframework
(xcframework-55d154a...-crashsubdir-cmux-crash-v1) and updates docs/ghostty-fork.md.
No cmux Swift change is required (no cmux-only gap), so there are no new
user-facing strings to localize.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Re-pin ghostty to d1dbbec: suppress half-click leak on cmd-clicked links

Addresses codex/greptile review of the link fix: under mouse reporting a
Cmd-click over a link still leaked a half-click to the program because
mouseButtonCallback reported the press (link-open runs only on release). The
ghostty follow-up (manaflow-ai/ghostty#74) suppresses the whole click — press
and release — whenever the ctrl/super link chord is held, keyed on the modifier
like the existing shift-release path so cursor jitter can't leak a press or a
release. Eliminates the half-click in both directions.

Re-pins the ghostty submodule from 55d154a to d1dbbec, repoints the prebuilt
GhosttyKit release/checksum, and updates docs/ghostty-fork.md. d1dbbec is an
ancestor of manaflow-ai/ghostty main (PR #71 and #74 merged).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Re-pin ghostty to 76ead3e: full click+drag suppression for cmd-clicked links

Final review iteration (codex P2). After #74 suppressed the press/release of a
ctrl/super-chord link click, cursorPosCallback could still emit .motion reports
during a Cmd-held drag (click_state == .press), leaking button-motion to a
mouse-grabbing program. ghostty #75 mirrors the shift "grab override" for the
ctrl/super chord in the motion path, so the link chord now suppresses the whole
click+drag — press, release, and motion — consistently.

Re-pins the ghostty submodule from d1dbbec to 76ead3e and repoints the
prebuilt GhosttyKit release/checksum + docs. 76ead3e is an ancestor of
manaflow-ai/ghostty main (PR #71, #74, #75 merged).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Re-pin ghostty to f241952: scope link suppression + clear stale hover

Final review iteration (codex P2 x2). After #74/#75 suppressed the whole click+
drag for the ctrl/super link chord, two edges remained: the suppression fired for
any button (swallowing ctrl/super right/middle clicks instead of delivering them
to the program), and a stale link highlight/cursor could persist when the chord
was released through cursorPosCallback's mods. ghostty #76 scopes the suppression
to the left button and clears the hover by refreshing when over_link is set
(mirroring keyCallback's existing reset branch).

Re-pins the ghostty submodule from 76ead3e to f241952 and repoints the
prebuilt GhosttyKit release/checksum + docs. f241952 is an ancestor of
manaflow-ai/ghostty main (PR #71, #74, #75, #76 merged).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Re-pin ghostty to 59fb750: clear link-click latch unconditionally

Addresses the final review round on the link-under-mouse-reporting fix:
- codex P2: the suppression re-checked live modifiers, so releasing ctrl/super
  before the mouse button could leak the release. ghostty #77 latches the
  decision at left-button press (mouse.link_click_active) and applies it through
  the release.
- greptile P2: the latch was cleared only inside the mouse-reporting block, so
  toggling reporting off mid-click could leave it stale; it is now cleared
  unconditionally on left release.

Re-pins the ghostty submodule from f241952 to 59fb750 and repoints the
prebuilt GhosttyKit release/checksum + docs. 59fb750 is an ancestor of
manaflow-ai/ghostty main once #77 merges.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Re-pin ghostty to 9f014e9: unify link-click suppression and open

Final review round on the link-under-mouse-reporting fix (codex P2/P3): the
report-suppression latched at press but the link-open path re-derived from live
modifiers, so releasing ctrl/super before the button swallowed the click, and
the latch reset wasn't reached on the link-open early return. ghostty #78 makes
linkAtPos use the latched chord and attempts processLinks whenever the click is
latched, and clears the latch via a function-level defer. One press-time
decision now drives press/drag/release suppression and link opening.

Re-pins the ghostty submodule from 59fb750 to 9f014e9 and repoints the
prebuilt GhosttyKit release/checksum + docs. 9f014e9 is an ancestor of
manaflow-ai/ghostty main once #78 merges.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Re-pin ghostty to df789cd: only open latched link clicks that started on a link

Final review round (codex): the latched link-open path opened the link under the
release cursor for any in-flight ctrl/super click, so a chord drag that started
off a link and released over one opened that link (its press was suppressed).
ghostty #79 captures whether the press was over a link (link_press_over_link) and
only opens via the latched path when it was, so an off-link-started drag is
swallowed rather than opening a link it merely released over.

Re-pins the ghostty submodule from 9f014e9 to df789cd and repoints the
prebuilt GhosttyKit release/checksum + docs. df789cd is an ancestor of
manaflow-ai/ghostty main once #79 merges.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: pin merged GhosttyKit artifact

* Pin GhosttyKit checksum for merged ghostty 34cbf18 (#5128 + #5458)

Pins the SHA256 of the published prebuilt
xcframework-34cbf180d8917b802d61d9929cfb493594f2ab52-crashsubdir-cmux-crash-v1
that merges the surface registry serialization (#5458) into the alt-screen
Cmd-click link fix (#5128).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Refresh Swift file-length budget for ContentView/SessionIndexView

The origin/main merge (sidebar scroll + macOS 27 crash fixes, PR #5670) grew
Sources/ContentView.swift to 19161 and Sources/SessionIndexView.swift to 2877,
which exceed the inherited budget. Bump only those two entries to match; this is
upstream main debt surfaced by the merge, not a change from the ghostty bump.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
ShubhamPatilsd pushed a commit to emergent-inc/mosaic that referenced this pull request Jul 9, 2026
…ex) (#5406)

* Bump ghostty to 55d154a: open links on cmd-click under mouse reporting

Fixes #5128. Clicking a link inside a fullscreen alternate-screen TUI
(Claude Code, Codex) opened the OS default browser instead of honoring the
configured cmux link-open target. cmux's GHOSTTY_ACTION_OPEN_URL handler is
already mode-independent (resolveTerminalOpenURLTarget routes per
BrowserAvailabilitySettings, no mouse-mode branch); the gap was in ghostty
core, where link hover state was refreshed only when mouse reporting was off
or shift released capture, so a Cmd-click under a mouse-grabbing TUI never
fired open_url.

Bumps the ghostty submodule to 55d154a (previous pin 176bd550f + the two
link-fix commits from manaflow-ai/ghostty#71, merged into fork main). The fix
also evaluates links locally when the ctrl/super link modifier is held, using
the effective mouse-reporting state, matching iTerm2 and macOS Terminal.

Publishes and pins the matching GhosttyKit xcframework
(xcframework-55d154a...-crashsubdir-cmux-crash-v1) and updates docs/ghostty-fork.md.
No cmux Swift change is required (no cmux-only gap), so there are no new
user-facing strings to localize.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Re-pin ghostty to d1dbbec9b: suppress half-click leak on cmd-clicked links

Addresses codex/greptile review of the link fix: under mouse reporting a
Cmd-click over a link still leaked a half-click to the program because
mouseButtonCallback reported the press (link-open runs only on release). The
ghostty follow-up (manaflow-ai/ghostty#74) suppresses the whole click — press
and release — whenever the ctrl/super link chord is held, keyed on the modifier
like the existing shift-release path so cursor jitter can't leak a press or a
release. Eliminates the half-click in both directions.

Re-pins the ghostty submodule from 55d154a to d1dbbec9b, repoints the prebuilt
GhosttyKit release/checksum, and updates docs/ghostty-fork.md. d1dbbec9b is an
ancestor of manaflow-ai/ghostty main (PR #71 and #74 merged).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Re-pin ghostty to 76ead3eae: full click+drag suppression for cmd-clicked links

Final review iteration (codex P2). After #74 suppressed the press/release of a
ctrl/super-chord link click, cursorPosCallback could still emit .motion reports
during a Cmd-held drag (click_state == .press), leaking button-motion to a
mouse-grabbing program. ghostty #75 mirrors the shift "grab override" for the
ctrl/super chord in the motion path, so the link chord now suppresses the whole
click+drag — press, release, and motion — consistently.

Re-pins the ghostty submodule from d1dbbec9b to 76ead3eae and repoints the
prebuilt GhosttyKit release/checksum + docs. 76ead3eae is an ancestor of
manaflow-ai/ghostty main (PR #71, #74, #75 merged).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Re-pin ghostty to f24195271: scope link suppression + clear stale hover

Final review iteration (codex P2 x2). After #74/#75 suppressed the whole click+
drag for the ctrl/super link chord, two edges remained: the suppression fired for
any button (swallowing ctrl/super right/middle clicks instead of delivering them
to the program), and a stale link highlight/cursor could persist when the chord
was released through cursorPosCallback's mods. ghostty #76 scopes the suppression
to the left button and clears the hover by refreshing when over_link is set
(mirroring keyCallback's existing reset branch).

Re-pins the ghostty submodule from 76ead3eae to f24195271 and repoints the
prebuilt GhosttyKit release/checksum + docs. f24195271 is an ancestor of
manaflow-ai/ghostty main (PR #71, #74, #75, #76 merged).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Re-pin ghostty to 59fb750c0: clear link-click latch unconditionally

Addresses the final review round on the link-under-mouse-reporting fix:
- codex P2: the suppression re-checked live modifiers, so releasing ctrl/super
  before the mouse button could leak the release. ghostty #77 latches the
  decision at left-button press (mouse.link_click_active) and applies it through
  the release.
- greptile P2: the latch was cleared only inside the mouse-reporting block, so
  toggling reporting off mid-click could leave it stale; it is now cleared
  unconditionally on left release.

Re-pins the ghostty submodule from f24195271 to 59fb750c0 and repoints the
prebuilt GhosttyKit release/checksum + docs. 59fb750c0 is an ancestor of
manaflow-ai/ghostty main once #77 merges.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Re-pin ghostty to 9f014e98b: unify link-click suppression and open

Final review round on the link-under-mouse-reporting fix (codex P2/P3): the
report-suppression latched at press but the link-open path re-derived from live
modifiers, so releasing ctrl/super before the button swallowed the click, and
the latch reset wasn't reached on the link-open early return. ghostty #78 makes
linkAtPos use the latched chord and attempts processLinks whenever the click is
latched, and clears the latch via a function-level defer. One press-time
decision now drives press/drag/release suppression and link opening.

Re-pins the ghostty submodule from 59fb750c0 to 9f014e98b and repoints the
prebuilt GhosttyKit release/checksum + docs. 9f014e98b is an ancestor of
manaflow-ai/ghostty main once #78 merges.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Re-pin ghostty to df789cd4b: only open latched link clicks that started on a link

Final review round (codex): the latched link-open path opened the link under the
release cursor for any in-flight ctrl/super click, so a chord drag that started
off a link and released over one opened that link (its press was suppressed).
ghostty #79 captures whether the press was over a link (link_press_over_link) and
only opens via the latched path when it was, so an off-link-started drag is
swallowed rather than opening a link it merely released over.

Re-pins the ghostty submodule from 9f014e98b to df789cd4b and repoints the
prebuilt GhosttyKit release/checksum + docs. df789cd4b is an ancestor of
manaflow-ai/ghostty main once #79 merges.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: pin merged GhosttyKit artifact

* Pin GhosttyKit checksum for merged ghostty 34cbf180d (#5128 + #5458)

Pins the SHA256 of the published prebuilt
xcframework-34cbf180d8917b802d61d9929cfb493594f2ab52-crashsubdir-cmux-crash-v1
that merges the surface registry serialization (#5458) into the alt-screen
Cmd-click link fix (#5128).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Refresh Swift file-length budget for ContentView/SessionIndexView

The origin/main merge (sidebar scroll + macOS 27 crash fixes, PR #5670) grew
Sources/ContentView.swift to 19161 and Sources/SessionIndexView.swift to 2877,
which exceed the inherited budget. Bump only those two entries to match; this is
upstream main debt surfaced by the merge, not a change from the ghostty bump.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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.

Terminal links open in external default browser instead of cmux's built-in browser when a fullscreen (alt-screen) TUI is active

2 participants