Skip to content

OSC 8 hyperlinks file paths in tool titles#5189

Merged
badlogic merged 2 commits into
earendil-works:mainfrom
mpazik:feat/tool-title-hyperlinks
May 29, 2026
Merged

OSC 8 hyperlinks file paths in tool titles#5189
badlogic merged 2 commits into
earendil-works:mainfrom
mpazik:feat/tool-title-hyperlinks

Conversation

@mpazik

@mpazik mpazik commented May 29, 2026

Copy link
Copy Markdown
Contributor

Implements #5168.

Screenshot 2026-05-29 at 22 57 24

It wraps the path in read/write/edit/ls tool titles in an OSC 8 file:// hyperlink when the terminal advertises hyperlink support.

Most of the diff is refactoring: switching to a proper import type { Theme } and a new renderToolPath util that now handles the hyperlink.

Unchanged: grep, find show patterns in their titles, not paths. Their result lines are paths, but that is the same text returned to the model, so I left them as they are.

tmux hyperlink forwarding (pi-tui)

While testing I noticed the links don't work under tmux, so I added a separate commit for packages/tui/src/terminal-image.ts.

This commit is riskier because it executes tmux display-message to read the client's reported features.

I tried to be defensive about it: it runs only under tmux and has a short timeout. If that is not an option we can revert it and instead rely on config or a custom environment variable as a manual workaround.

To see the links under tmux (3.4+), tmux must know the outer terminal supports hyperlinks. It detects this automatically when the terminal's terminfo announces the Hls capability.
For terminals that don't (e.g. Ghostty), it needs to be set manually:

# ~/.tmux.conf
set -as terminal-features '*:hyperlinks'

Extensions

I considered providing an API for extensions, but I droped the idea as custom tools can already support hyperlinks with the existing API fairly easily:

import { resolve } from "node:path";
import { pathToFileURL } from "node:url";
import { getCapabilities, hyperlink, Text } from "@earendil-works/pi-tui";

renderCall(args, theme, context) {
  const styled = theme.fg("accent", args.path);
  const display = getCapabilities().hyperlinks
    ? hyperlink(styled, pathToFileURL(resolve(context.cwd, args.path)).href)
    : styled;
  return new Text(`mytool ${display}`, 0, 0);
}

mpazik added 2 commits May 29, 2026 22:02
Wrap the path shown in read/write/edit/ls tool titles in an OSC 8 file:// hyperlink when the terminal advertises hyperlink support.
The link target is always the absolute path, while the visible text stays relative/home-shortened and line annotations (e.g. :120-140) are kept out of the target.
…s them

detectCapabilities previously disabled hyperlinks under tmux unconditionally. tmux re-emits OSC 8 to the outer terminal only when the attached client advertises the 'hyperlinks' feature in client_termfeatures, and strips them otherwise.

Probe the running server with 'tmux display-message -p #{client_termfeatures}' and enable hyperlinks only when the feature is listed. The probe fails closed: any error (no tmux/server, timeout, old tmux) yields false. images stays null; only the hyperlink decision changed. The probe is injected into detectCapabilities so it stays testable without spawning a process.
@mpazik mpazik closed this May 29, 2026
@mpazik mpazik deleted the feat/tool-title-hyperlinks branch May 29, 2026 12:06
@mpazik mpazik changed the title Make file paths in tool titles clickable via OSC 8 hyperlinks OSC 8 hyperlinks file paths in tool titles May 29, 2026
@mpazik mpazik restored the feat/tool-title-hyperlinks branch May 29, 2026 12:08
@mpazik mpazik reopened this May 29, 2026
@badlogic badlogic added the inprogress Issue is being worked on label May 29, 2026
@badlogic badlogic merged commit ed1952c into earendil-works:main May 29, 2026
4 checks passed
@badlogic

Copy link
Copy Markdown
Collaborator

cheers!

@badlogic

Copy link
Copy Markdown
Collaborator

the tmux process spawn for capability detection isn't ideal, but i guess we can live with it. some visual artifact in ghostty when i cmd + hover -> underline extends to end of line. investigating and possibly fixing.

@mpazik

mpazik commented May 29, 2026

Copy link
Copy Markdown
Contributor Author

Thanks!

Regarding that issue with the underline extending. I belive it is a ghostty problem. I saw it multiple time, not sure what is related too. But there was PR for better link matching ghostty-org/ghostty#11200

I managed to reproduce it on the old version

Screenshot 2026-05-30 at 08 36 40

But let me know if you have any doubts, happy to double check it.

@mpazik

mpazik commented May 29, 2026

Copy link
Copy Markdown
Contributor Author

In my case the underline issue, happens only in tmux select mode (but not allways). Same issue happens for paths in git diff or micro editor.

Let me know if it is a similar case, or something different.

wincent added a commit to wincent/wincent-agent-plugins that referenced this pull request Jun 1, 2026
The pi-update prompt instructed the agent to patch
`@earendil-works/pi-tui`'s `dist/terminal-image.js` after every upgrade,
flipping the tmux/screen branch of `detectCapabilities` so OSC 8
hyperlinks would report as enabled inside tmux.

That workaround is no longer needed because Pi 0.78.0 includes
autodetection:

- earendil-works/pi#5189

Remove the entire Step 8 patching section, the intro sentence that
promised to apply the patch, and the Step 7 wording that branched into
Step 8. Step 7 now simply reports install success or failure.

Agent prompts used in preparing this commit:

> read @pi/prompts/pi-update.md which defines a pi prompt.
>
> note that the latest Pi release makes the patching of the tmux
> hyperlink code unnecessary: earendil-works/pi#5189
>
> so, update the prompt to remove all the content about patching.

> commit this

> try signing again

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
wincent added a commit to wincent/wincent that referenced this pull request Jun 1, 2026
As of:

- earendil-works/pi#5189

We no longer need to run a patched version in order to get hyperlinks
working in tmux.

Change-Id: kvuxuxnrmmtznvpxnropsotpqstnmkxl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

inprogress Issue is being worked on

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants