Skip to content

fix: open Cmd+clicked links in mouse-tracking TUIs and answer XTVERSION - #418

Merged
forketyfork merged 2 commits into
mainfrom
fix/cmd-click-links-under-mouse-tracking
Oct 28, 2026
Merged

forketyfork merged 2 commits into
mainfrom
fix/cmd-click-links-under-mouse-tracking

Conversation

@forketyfork

Copy link
Copy Markdown
Owner

TLDR

Some terminal programs (Claude Code in fullscreen mode, Codex) take control of the mouse. When they do, Architect sends every click to the program. The click cannot tell the program that the Cmd key is pressed. Claude Code then ignores the click, so its links do not open. With this change, Architect opens the link itself when you Cmd+click it, also when the program controls the mouse. Architect also now tells programs its name and version when they ask for it (the XTVERSION query).

Issue

  • Cmd+click on a link in Claude Code's fullscreen TUI (tui = "fullscreen") does nothing in Architect.
  • Cmd+hover does not underline links or show the pointer cursor in Claude Code or Codex.
  • Architect does not answer XTVERSION (CSI > q). The query falls through to ghostty-vt's readonly handler, which has no PTY writer, so the query gets no reply.

Root cause, from recorded PTY output of Claude Code 2.1.312 and Codex 0.165.0 and their code:

  • Both apps switch to the alternate screen and enable SGR any-event mouse tracking (?1000h ?1002h ?1003h ?1006h) for their whole lifetime. Architect's Full-view handler sends every click and motion to the app before its own link handling runs.

  • SGR mouse reports have no bit for Cmd, so the app receives a plain left click.

  • Codex opens links on a plain stationary left click itself, so its links worked.

  • Claude Code finds the URL under the click, but opens it only if one of these is true:

    • the report has the Alt or Ctrl bit;
    • TERM_PROGRAM is ghostty or WarpTerminal on macOS;
    • the XTVERSION reply starts with ghostty.

    None of these is true in Architect. Replaying the clicks into a real Claude Code process confirms it: with a Ctrl bit or TERM_PROGRAM=ghostty, Claude Code runs open <url>; with Architect's plain click it does nothing.

Solution

  • Cmd+click on a link belongs to Architect. In Full view, a Cmd+left press over a link (OSC 8 or plain-text URL) opens the link even when the app tracks the mouse. Architect also swallows that click's press, drag and release, so the app never sees half a click. Repeat clicks of a Cmd double-click are swallowed without opening the link again. All other mouse events are reported as before.
  • Cmd+hover works under mouse tracking. The link under the pointer is underlined and the pointer cursor shows. Motion is still reported to the app. The underline only causes a repaint when the hovered link changes, not on every motion event.
  • XTVERSION reply. Architect answers DCS >| Architect <version> ST. The version comes from a new -Dversion build option (default dev). The release workflow passes the tag version, and so does the Homebrew formula.
  • ADR-018 in docs/ARCHITECTURE.md records the decision and the alternatives that were rejected: sending Cmd as the Alt bit, or identifying as Ghostty.

Context

  • Known limitation (recorded in ADR-018): Claude Code hard-wraps long URLs with cursor positioning rather than the terminal's soft wrap. Architect matches such a URL only within the clicked row. Making Claude Code emit OSC 8 (for example via FORCE_HYPERLINK=1) or a cross-row heuristic could follow up.
  • New tests replay sequences modeled on the recorded Claude Code (plain-text URL) and Codex (OSC 8) output. They cover the press decision and the hover underline, and a stream-level test covers the XTVERSION reply.

Test plan

  • Run Claude Code with tui = "fullscreen" in Architect, ask it to print a URL, Cmd+hover the URL (underline and pointer cursor appear), then Cmd+click it (the browser opens it once).
  • In Codex, Cmd+hover a link (pointer cursor appears) and Cmd+click it (it opens once, not twice).
  • In both apps, plain clicks, drags and scrolling still behave as before.
  • In a plain shell (no mouse tracking), Cmd+click on a URL still opens it, and double/triple-click still select a word or line.

Issue: Links shown by Claude Code's fullscreen TUI could not be opened with
Cmd+click in Architect, and Cmd+hover did not highlight links in Claude Code
or Codex. Architect also never answered the XTVERSION terminal query.

Solution: Claude Code and Codex enable SGR any-event mouse tracking, so
Architect reported every click and motion to the app. SGR reports cannot carry
Cmd, and Claude Code only opens links on plain clicks from terminals it
recognizes. Architect now owns Cmd+click on a link regardless of mouse
tracking: it opens the link and swallows the press, drag and release, and
Cmd+hover underlines the link. XTVERSION is answered as
"Architect <version>", with the version set by a new -Dversion build option
that the release workflow and Homebrew formula pass from the tag.
@forketyfork
forketyfork marked this pull request as ready for review October 28, 2026 15:06
@forketyfork
forketyfork requested a balanced review from Copilot October 28, 2026 15:29

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.

🟡 Changes recommended

Unresolved issues can swallow the first Cmd+click, trigger redundant redraws within OSC 8 links, and leak mouse gestures across session switches.

3 open issues
What changed in this PR

This PR makes Architect handle Cmd+clicked links inside mouse-tracking terminal applications and identify itself through XTVERSION replies.

Changes:

  • Opens links and displays Cmd+hover feedback in mouse-tracking TUIs, with gesture-consumption state and regression tests.
  • Adds versioned XTVERSION replies, supplying release versions through CI and Homebrew builds.
  • Documents the behavior, build option, and architectural decision.

Builds and tests were not run during this review.

File Description
src/​vt_stream.zig Handles XTVERSION queries and adds a response test.
src/​ui/​session_view_state.zig Tracks consumed link presses per session.
src/​ui/​components/​session_interaction.zig Adds Cmd+link handling, hover updates, and tests for mouse-tracking TUIs.
README.md Documents link interaction and XTVERSION support.
Formula/​architect.rb Passes the package version into the build.
docs/​development.md Explains the version build option.
docs/​ARCHITECTURE.md Records link-gesture ownership and rejected alternatives.
build.zig Defines the version option, defaulting to dev.
.github/​workflows/​release.yaml Passes the release tag version into release builds.

Review effort: Balanced

Issue: Review of #418 found three gaps. The swallowed release of a Cmd+click
was tracked per session, so switching sessions mid-click handed the release
and drag to another app. SDL's click count ignores modifiers, so a Cmd+click
right after a plain click was swallowed as a repeat without opening the link.
OSC 8 hover used the hovered cell as the whole link, so every move inside a
link repainted the terminal and only one cell was underlined.

Solution: Track the claim on the click in the interaction component, so the
release and drag are swallowed whatever session or view mode is active when
they arrive. Swallow a repeat click only when the previous press of the run
was Architect's own link click. Resolve an OSC 8 link to the full run of
adjacent cells with the same URI, following soft wraps, so hover compares a
stable range and underlines the whole link.
@forketyfork
forketyfork merged commit c5c188d into main Oct 28, 2026
4 checks passed
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.

2 participants