[BUG] OSC 8 hyperlinks in custom statusline broken inside tmux — rendering layer analysis

Resolved 💬 7 comments Opened Mar 21, 2026 by rvishna89 Closed May 21, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

OSC 8 hyperlinks from custom statusline programs don't render as clickable links when Claude Code runs inside tmux. This is a re-report of #23438 (closed as stale/locked), now with root cause analysis.

Related issues: #21586, #19976, #14011

Root Cause: Claude Code renders its statusline output outside Ink's React component tree, writing directly to the terminal. Ink's rendering cycle erases and rewrites all managed terminal lines on every update. This destroys any OSC 8 hyperlinks that were written directly to stdout by external statusline programs.

Ink itself is not the problem. As of slice-ansi v8 and @alcalzone/ansi-tokenize v0.3+, Ink's character grid pipeline fully supports OSC 8 round-tripping. Hyperlinks that flow through the Ink React tree survive rendering. The issue is that statusline content bypasses this tree entirely.

Rendering pipeline walkthrough:

  1. External statusline program writes OSC 8 hyperlinks to stdout
  2. Ink's next render cycle calls eraseLines() to clear previous output
  3. Ink rewrites its grid-rendered content (which doesn't include the external hyperlinks)
  4. The hyperlink text appears but is no longer clickable — the OSC 8 sequences were erased

What Should Happen?

OSC 8 escape sequences from statusline programs should pass through Claude Code's rendering layer unchanged and render as clickable hyperlinks inside tmux, just as they do outside tmux.

Suggested fix: Route statusline content through the Ink component tree rather than writing it directly to the terminal:

  1. Render statusline output inside an Ink <Text> node (preserving raw OSC 8 sequences)
  2. Use Ink's <Link> component for statusline hyperlinks
  3. Ensure the statusline rendering region is excluded from Ink's eraseLines() scope

This is a Claude Code change only — no upstream Ink changes are needed.

Error Messages/Logs

No error messages. The statusline text renders visually, but hyperlinks are not clickable. Verified with `xxd` that the statusline binary outputs correct OSC 8 escape sequences — they are simply erased by Ink's render cycle.

Evidence that tmux is not the issue:
- `printf '\033]8;;https://example.com\033\\Click\033]8;;\033\\\n'` in the same tmux pane renders as a clickable link
- Same statusline works when running Claude Code outside tmux

Steps to Reproduce

  1. Configure a custom statusline that outputs OSC 8 hyperlinks:

``
\033]8;;https://example.com\033\\link text\033]8;;\033\\
``

  1. Start tmux with allow-passthrough on and hyperlinks enabled in terminal-features
  2. Run Claude Code inside tmux
  3. Observe that statusline hyperlinks are not clickable

Control tests (both pass):

  • Run printf '\033]8;;https://example.com\033\\Click\033]8;;\033\\\n' in the same tmux pane → clickable
  • Run Claude Code outside tmux with the same statusline → clickable

Environment: Claude Code 2.1.x, tmux 3.5a, Ghostty terminal, macOS

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.73

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

iTerm2

Additional Information

_No response_

View original on GitHub ↗

This issue has 7 comments on GitHub. Read the full discussion on GitHub ↗