OSC 8 hyperlinks in custom statusline work in IDE terminals but not in real terminal emulators (Konsole)
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?
Custom statusline commands that output OSC 8 hyperlinks render correctly in IDE integrated terminals (VS Code, Cursor, etc.) but not in real terminal emulators like Konsole.
This is a follow-up to #21586, which was fixed in or before v2.1.42 for VSCode IDE terminals. The fix does not extend to standalone terminal emulators — the same statusline script that produces a clickable link in VS Code produces plain text in Konsole. Konsole has had buggy OSC behaviour in older versions, but this reproduction uses Konsole 24.12.3 (KDE Plasma 6 / Ubuntu 25.04), which has full OSC 8 support.
In v2.0.76, the OSC 8 link works correctly in both IDE terminals and Konsole. The regression was introduced somewhere between v2.0.76 and the current version.
What Should Happen?
The statusline text containing OSC 8 hyperlink sequences should render as underlined, clickable text in any terminal that supports OSC 8 — not just IDE integrated terminals. Konsole has full OSC 8 support and renders OSC 8 links correctly in all other contexts.
Error Messages/Logs
No error messages. The text simply renders as plain text instead of a hyperlink in Konsole, while the identical output renders correctly in VS Code's integrated terminal.
Steps to Reproduce
A full Dockerized reproduction environment is available: https://github.com/Nubebuster/statusline-regression which automates all the steps below that don't require user interaction.
Quick reproduction
- Create a minimal statusline script (
statusline.sh):
#!/bin/bash
printf '\e]8;;toclipboard://test-uuid\e\\uuid\e]8;;\e\\'
- Configure Claude Code to use it (
~/.claude/settings.json):
{
"statusLine": {
"type": "command",
"command": "/path/to/statusline.sh",
"padding": 0
}
}
- Run
claudein a VS Code integrated terminal → the "uuid" text in the statusline is underlined and clickable. ✅
- Run
claudein Konsole (or another real terminal emulator with OSC 8 support) → the "uuid" text is plain, not clickable. ❌
- Repeat step 4 with Claude Code v2.0.76 → the link works correctly in Konsole. ✅
Dockerized reproduction
git clone https://github.com/Nubebuster/statusline-regression.git
cd statusline-regression
chmod +x run.sh
./run.sh # select version to test
This opens a KDE Plasma desktop (via x11docker) with both VS Code and Konsole. Full instructions appear in the terminal. Compare behavior between v2.0.76 and latest.
Claude Model
N/A
Is this a regression?
Yes, this worked in a previous version
Last Working Version
2.1.2
Claude Code Version
2.1.44
Update, still present in: 2.1.79
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
Konsole (KDE)
Additional Information
Relationship to #21586
Issue #21586 reported that OSC 8 links in custom statuslines stopped working entirely in v2.1.3. That issue was closed after a fix in v2.1.42 restored functionality in IDE terminals. However, the fix appears to only work for terminals where the IDE handles escape sequence rendering (VS Code, Cursor, etc.). Real terminal emulators that implement OSC 8 natively (Konsole, iTerm2, etc.) are still affected.
Why this matters
IDE terminals are not the only environment where Claude Code is used. Konsole, iTerm2, Alacritty, and other terminal emulators all support OSC 8 and are common development environments. Claude Code itself uses OSC 8 for file path links, so terminal support is already assumed.
Technical context
The OSC 8 hyperlink format is a standard terminal escape sequence:
\e]8;;URL\e\\VISIBLE_TEXT\e]8;;\e\\
The statusline script output is byte-identical across versions — the regression is in how Claude Code passes the escape sequence through to the terminal, not in the script itself.
14 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Confirming this also affects Windows Terminal (v1.23) on WSL2 (Ubuntu).
Same behavior:
echo -e '\e]8;;URL\atext\e]8;;\a'in Windows Terminal (outside Claude Code): clickable ✅Tested with both cc-statusline (custom, BEL terminator) and him0/claude-code-statusline — neither produces clickable links in Windows Terminal.
Claude Code version: latest (as of 2026-02-23)
Ran into this on Windows Terminal (Windows 11) while building a custom statusline script. Spent time implementing OSC 8
file://links for the working directory andhttps://links for git branch→repo URLs — the escape sequences are byte-perfect (verified with xxd), ANSI SGR colors render fine, but OSC 8 links are completely inert. No clickable behavior, no underline, nothing.Would be helpful if the Claude Code docs for custom statuslines noted this limitation upfront. Right now the statusline docs show OSC 8 as a supported feature, which sends you down a rabbit hole of implementing something that doesn't work in standalone terminals. A quick screening of this repo's issues before developing would have saved the effort — but ideally the feature would just work as documented.
Platform: Windows 11, Windows Terminal 1.22, Claude Code 2.1.x, Git Bash shell.
/do-not-autoclose
Adding another data point: this also affects Ghostty 1.3.0 on macOS (Sequoia 26.3.1, M5 MacBook Air).
File paths in Claude Code output (e.g.
src/components/App.tsx:42) render as plain text. Cmd+click does nothing because the OSC 8 sequences aren't reaching the terminal. URLs work fine via Ghostty's built-in URL detection, but the file path hyperlinks that Claude Code is supposed to emit are completely absent.This was working on my previous machine with an older Claude Code version. Confirmed on Claude Code 2.1.79.
This is a significant productivity hit for anyone using Claude Code in a standalone terminal. File paths are output constantly and having to manually copy-paste them or navigate to find them defeats the purpose.
This is still reproduced in this x11docker isolation test:
https://github.com/Nubebuster/statusline-regression
Running
printf '\e]8;;toclipboard://test-uuid\e\\uuid\e]8;;\e\\\n'in a Konsole window in that KDE VM produces a clickable OSC8 link. Claude Code does not.Issue still present in
2.1.79 (Claude Code)Root cause analysis:
Claude Code uses ink (React-based terminal renderer) which re-renders all output through its own pipeline. Since ~v2.1.3, ink strips OSC 8 hyperlink sequences during this re-rendering — it interprets the visible text but discards the
\e]8;;url\e\\...\e]8;;\e\\wrapping.The fix in v2.1.42 (closing #21586) likely added an IDE-specific code path that preserves or restores OSC 8 for integrated terminals (checking
TERM_PROGRAM,VSCODE_PID, etc.), rather than fixing the underlying stripping in ink's rendering pipeline. Real terminal emulators (Konsole, iTerm2, Ghostty, Windows Terminal) don't match those checks, so they remain broken.Evidence: ink re-generates its own ANSI SGR codes around the visible text — the escape sequences in the output are not the same bytes the statusline command produced, they're ink's own rendering. This confirms ink is fully re-processing the content rather than passing it through. OSC 8 gets lost in that re-processing for non-IDE terminals.
A proper fix would be to preserve OSC 8 passthrough in ink's rendering for all terminal types, not just IDE-detected ones.
Workaround: PTY wrapper to re-inject OSC 8 links in custom statuslines
A Python PTY wrapper that sits between the terminal and
claude, intercepts output, and re-injects the OSC 8 sequences that Claude Code's Ink renderer strips. IDE terminals (VS Code, Cursor, Antigravity) are detected and skipped since they handle OSC 8 natively.The statusline script saves its raw output (with OSC 8 intact) to a temp file. The wrapper reads that file to learn the current
(visible_text, url)pairs, then patches them back into the output stream.Note: This workaround only restores OSC 8 links in custom statuslines. Claude Code's built-in file path hyperlinks (e.g.
src/components/App.tsx:42in conversation output) are also stripped by the same Ink rendering issue but cannot be restored from outside — that requires an upstream fix.<details>
<summary><strong>claude-osc8-wrapper</strong> (click to expand)</summary>
Save as
claude-osc8-wrapper, make executable, and set up as shown below.</details>
Statusline script change
Add this at the end of your statusline script, after building the final rendered output:
$outputshould be the complete rendered statusline string with OSC 8 sequences still present.Setup (Ubuntu/Linux)
This overrides the
claudecommand with the wrapper. The wrapper calls the realclaudebinary viaexecvpwhich finds it in$PATH(typically~/.local/bin/claude). When stdout is piped (non-interactive), the wrapper skips the PTY proxy and execsclaudedirectly.This worked for me:
~/.claude/settings.json:Repro:
CLAUDE_CODE_NO_FLICKER=1is the specific stripper (Ghostty + Warp, macOS)Adding a narrower repro and isolation that may help upstream —
FORCE_HYPERLINK=1is NOT sufficient on its own; the relevant lever isCLAUDE_CODE_NO_FLICKER.Environment
2.1.1381.3.1(also reproduced on Warp Terminal)Isolation matrix
| Env vars set on the claude process | OSC 8 click |
|---|---|
|
CLAUDE_CODE_NO_FLICKER=1,FORCE_HYPERLINK=1| ❌ broken — link rendered, click does nothing ||
FORCE_HYPERLINK=1(NO_FLICKER unset) | ✅ works — cmd+click opens the file |Env presence was verified directly on the running claude PID via
ps -E -p <pid>, not assumed from shell exports.Repro
Likely cause
The fullscreen render pipeline engaged by
CLAUDE_CODE_NO_FLICKER=1appears to strip OSC 8 sequences in a path that bypasses whatever guardFORCE_HYPERLINK=1is meant to install. The v2.1.42 IDE-terminal fix may only cover the scrollback (non-fullscreen) path.User-facing impact
Users who set
CLAUDE_CODE_NO_FLICKER=1for cleaner rendering currently must choose between (a) flickerless fullscreen + non-clickable file paths, or (b) flicker + clickable file paths. Worth documenting in terminal-config.md until upstream-fixed.This needs proper fixing in an update for new TUI fullscreen mode
So I'm not sure why or how but I think this is fixed for me. I was just able to click a link in my custom status line... specifically my PR link now works
Closing for now — inactive for too long. Please open a new issue if this is still relevant.
Partial workaround for statusline OSC being filtered: sequences that don't wrap visible text (OSC 9;9 cwd, OSC 0 title, progress) can be written to the console device directly from the statusline script — child processes inherit the session console, so CONOUT$ on Windows (or /dev/tty where the child has one) bypasses the filter. Write-up + scripts: https://github.com/ykdojo/claude-code-tips/issues/36
OSC 8 hyperlinks can't be fixed this way — they have to wrap the statusline text at its rendered position.