[BUG] Markdown link labels never clickable in Orca/tmux — no OSC 8 emitted for unrecognized TERM_PROGRAM, FORCE_HYPERLINK=1 ignored

Status Open
Reported on v2.1.220
Maintainer reply None cached
Activity 4 comments · opened Aug 3, 2026

Bug Description

Markdown links ([label](url)) in assistant responses render as a styled label with no OSC 8 escape emitted, so the label is not clickable. Only bare URLs (linkified as plain text by the terminal itself) remain clickable. This happens whenever the terminal is not recognized — observed with TERM_PROGRAM=Orca (Orca embedded terminal) and TERM_PROGRAM=tmux (tmux inside Orca).

Setting FORCE_HYPERLINK=1 before launching has no effect (also noted in #72998, where the variable is ignored for the opposite purpose — disabling).

Steps to Reproduce

  1. Run Claude Code inside a terminal whose TERM_PROGRAM is not on the capability allowlist — e.g. Orca (TERM_PROGRAM=Orca) or any tmux session (TERM_PROGRAM=tmux, TERM=tmux-256color).
  2. Ask the assistant to print both forms:
  • markdown: [example](https://example.com/some/long/path)
  • bare URL: https://example.com/some/long/path
  1. Observe: the markdown label renders styled but is not clickable (no OSC 8 region, nothing on hover); the bare URL is clickable only because the terminal itself linkifies plain-text URLs.
  2. FORCE_HYPERLINK=1 claude — behavior unchanged.

Why the terminal is not the problem

| Layer | OSC 8 support | Evidence |
|---|---|---|
| Orca terminal | ✅ renders OSC 8 | stablyai/orca#6880 (test matrix in issue body: "rendered, clickable, URL hidden") |
| tmux 3.7b | ✅ supports the hyperlinks terminal-feature | binary contains the feature and Hls=\E]8;...; passthrough needs set -as terminal-features ",*:hyperlinks" |
| Claude Code renderer | ❌ no OSC 8 emitted for markdown labels | this report |

So in the direct-Orca case the chain is known-good end to end, yet no OSC 8 arrives; in the tmux case the user can open the tmux side with one config line, but that is moot while nothing is emitted upstream.

Expected

Either of:

  • honor FORCE_HYPERLINK=1 as an explicit user override of terminal capability detection (matching the supports-hyperlinks ecosystem convention), and/or
  • treat TERM_PROGRAM=tmux (tmux ≥ 3.4 supports the hyperlinks feature) and TERM_PROGRAM=Orca as hyperlink-capable.

The TERM_PROGRAM allowlist approach can never see through tmux nesting (the outer terminal's identity is not visible inside), so an env-var override is the only mechanism that works for every setup.

Related: #79839 (file-path OSC 8 regression in assistant responses), #72998 (FORCE_HYPERLINK ignored for disabling), #13008 / #77576 (file-path hyperlink requests), stablyai/orca#6880 (terminal-capability detectability for agent TUIs).

Environment Info

  • Platform: macOS 26.5.2
  • Terminal: Orca (embedded terminal, TERM_PROGRAM=Orca) and tmux 3.7b inside Orca (TERM_PROGRAM=tmux, TERM=tmux-256color)
  • Version: 2.1.220

View original on GitHub ↗

3 Comments

thinker0 · 2 months ago

Follow-up verification: with tmux's set -as terminal-features ",*:hyperlinks" applied, a manually printed OSC 8 sequence (printf '\e]8;;https://example.com\e\\label\e]8;;\e\\') renders as a clickable label through the full Orca → tmux chain. So the terminal path is now confirmed good end to end by direct test, not just by the references above — the only missing piece is the emission from Claude Code's assistant-message renderer.

terminal-point · 1 month ago

Also reproduces under herdr (a non-tmux Rust terminal multiplexer) — and pins the cause down to $TERM, not just $TERM_PROGRAM

Environment

  • Multiplexer: herdr 0.8.0, running Claude Code as an auto-detected agent pane
  • Host terminal: Kitty, connecting over plain SSH (not kitten ssh)

Key data point — same physical terminal, same SSH session type, only difference is whether herdr is in the middle:

| | outside herdr (plain SSH) | inside a herdr pane |
|---|---|---|
| TERM | xterm-kitty | xterm-256color |
| COLORTERM | truecolor | truecolor |
| TERM_PROGRAM | (empty) | (empty) |
| KITTY_WINDOW_ID | (empty) | (empty) |
| Markdown link ([label](url)) clickable? | ✅ yes | ❌ no — styled text only, no OSC 8, no hover state |

TERM_PROGRAM/KITTY_WINDOW_ID are empty in both cases (plain ssh doesn't forward these; only kitten ssh does), so those can't be what's flipping the behavior here. The only variable that changes is TERM itself: xterm-kitty outside herdr vs. the generic xterm-256color herdr substitutes for its pane environment — mirroring exactly what tmux does with TERM=screen-256color/tmux-256color.

Confirmed the terminal chain itself is not at fault: hand-crafted OSC 8 sequences sent directly via printf (including variants with SGR styling around the label, BEL terminator instead of ST, and an explicit id= parameter) all rendered correctly as clickable, hover-highlighted hyperlinks through the same herdr→SSH→Kitty chain where Claude Code's own markdown links fail. FORCE_HYPERLINK=1 had no effect either, consistent with what's already reported here and in #72998.

This suggests the detection logic currently treats TERM=xterm-kitty as sufficient signal on its own (since that's the only thing that changed between the working/non-working cases above), but that signal is inherently unavailable through any multiplexer that normalizes TERM for its own pane environment — not just tmux. Reinforces the issue's conclusion that only an honored FORCE_HYPERLINK=1 override can cover every setup, since TERM/TERM_PROGRAM allowlisting can't see through nesting of any kind (SSH without kitten ssh, tmux, herdr, or otherwise).

cameronalizadeh-distyl · 1 month ago

Data point that splits this into two different bugs: on 2.1.251, inside tmux, Claude Code does emit OSC 8 — I measured it rather than inferring from clickability. The sequences are sitting in tmux's grid (tmux 3.7c, TERM inside xterm-256color, outer terminal Alacritty 0.15.1):

$ tmux capture-pane -e -p | grep -ao ']8;;[^\]*' | head -2
]8;id=1rjmtji;https://linear.app/acme/project/…
]8;;https://github.com/acme/repo/pull/123

So for the tmux case, the label isn't clickable because of a downstream strip, not missing emission: tmux ≥ 3.4 parses and stores OSC 8 unconditionally, but only re-emits it to your terminal if the attached client negotiated the hyperlinks terminal feature — off by default for most TERMs. Check what your client actually negotiated:

$ tmux display -p '#{client_termfeatures}'
bpaste,focus,title        # no "hyperlinks" → tmux silently strips OSC 8 on output

Fix:

# .tmux.conf
set -sa terminal-features ',*:hyperlinks'

then detach and reattach — features are negotiated when the client attaches, so source-file or setting the option live does not upgrade an already-attached client. That reattach step is a trap: with the option set but the client attached from before, #{client_termfeatures} still lacks hyperlinks and nothing changes, which looks exactly like "the option doesn't work".

Layer-by-layer triage for anyone landing here with unclickable links in tmux:

  1. tmux capture-pane -e -p | grep -c ']8;;' — nonzero means Claude Code emitted; the problem is downstream (this comment). Zero means the renderer really didn't emit (the Orca half of this issue).
  2. tmux display -p '#{client_termfeatures}' — no hyperlinks means tmux is the strip; fix above.
  3. Both fine and still dead: your emulator. E.g. Alacritty refuses to open OSC 8 links while the running app holds mouse capture (alacritty/alacritty#8129, closed as intended).

Terminal-independent alternative: wfxr/tmux-fzf-url (since wfxr/tmux-fzf-url#42) and alberti42/tmux-fzf-links both extract OSC 8 targets from capture-pane -e, giving a keyboard-driven fzf picker that catches links whose URL isn't visible text — which copy-mode search and regex-only pickers structurally can't.

The Orca-direct case (unrecognized TERM_PROGRAM, nothing in step 1, FORCE_HYPERLINK=1 ignored) is a genuine renderer-side gate and none of the above helps it — that half stands.

Showing cached comments. Read the full discussion on GitHub ↗