Feature request: native OSC 8 clickable terminal links in interactive TUI

Open 💬 1 comment Opened Apr 15, 2026 by joeeeeey

Summary

I would love native support in Codex for terminal hyperlinks (OSC 8) in the interactive TUI, so that links render like:

  • visible text only: OpenAI Docs
  • clickable in terminals that support OSC 8 (for example iTerm2)
  • without also showing the raw URL inline when the link has a label

This is one of the most useful output affordances in Claude Code, and I think Codex would benefit a lot from it, especially for links to:

  • GitHub PRs / issues / Actions runs
  • local file paths
  • docs / dashboards / runbooks

Why this matters

As an infra engineer, I spend a lot of time hopping between:

  • GitHub
  • dashboards
  • logs
  • runbooks
  • local files
  • docs

Clickable terminal-native links make a big difference for speed and readability.

When a response contains many references, seeing only the label (instead of label (https://...)) is much easier to scan, especially in iTerm2.

Current behavior

In my current Codex setup, Markdown links are still rendered as expanded text in the interactive transcript, for example:

OpenAI Docs (https://platform.openai.com/docs)

What I want is:

OpenAI Docs

where OpenAI Docs is clickable in the terminal.

Terminal confirmation

I confirmed that my terminal supports OSC 8 hyperlinks.

In iTerm2, this works correctly:

printf '\e]8;;https://platform.openai.com/docs\aOpenAI Docs\e]8;;\a\n'

So the missing piece is not the terminal. The missing piece is native hyperlink rendering in Codex.

What I tried

I built a local wrapper around codex that attempts to post-process output and convert Markdown links like:

[OpenAI Docs](https://platform.openai.com/docs)

into OSC 8 hyperlinks.

Simplified version of the wrapper logic:

OSC8_START = "\x1b]8;;"
OSC8_END = "\x07"
BLUE = "\x1b[34m"
RESET_FG = "\x1b[39m"


def create_hyperlink(target: str, label: str) -> str:
    return f"{OSC8_START}{target}{OSC8_END}{BLUE}{label}{RESET_FG}{OSC8_START}{OSC8_END}"

I also added:

  • terminal support detection (iTerm2 / kitty / ghostty / etc.)
  • placeholder filtering so https://... does not become a broken clickable link
  • fallback bypass for non-interactive / JSON / server-like modes

What worked

For non-interactive or pseudo-terminal-controlled output, the wrapper can emit valid OSC 8 hyperlinks.

What did not work

For the interactive Codex TUI, the wrapper approach is unreliable because it is operating at the wrong layer.

It is trying to regex-match already-rendered terminal byte streams, rather than having access to semantic link tokens during rendering.

This caused problems like:

  • sometimes the user input echo got linkified instead of the assistant transcript
  • some transcript links still rendered as label (url)
  • the output could be affected by TUI redraw / diff rendering behavior

So I do not think a shell wrapper is the right solution for the interactive TUI.

What I think Codex should support natively

Ideally Codex would support OSC 8 hyperlinks in the same general way Claude Code appears to:

  1. Detect whether the terminal supports OSC 8 hyperlinks.
  2. Preserve semantic links at the rendering layer.
  3. Render labeled Markdown links as clickable labels instead of label (url).
  4. Optionally support file path links (file://...) too.
  5. Keep graceful fallback behavior when hyperlinks are unsupported.

Concrete feature request

Please consider adding native hyperlink support in the interactive Codex terminal UI for:

  • Markdown links: [label](url)
  • file paths
  • maybe GitHub refs or bare URLs that Codex already knows how to render semantically

Expected behavior in supporting terminals:

OpenAI Docs
PR #91
Codex Global AGENTS

with those labels clickable, rather than expanding into visible raw URLs.

Environment

  • Codex CLI: v0.120.0
  • Terminal: iTerm2
  • Platform: macOS

Closing note

I am filing this because I really want this feature, and I spent a fair amount of time trying to reproduce it externally before concluding that it likely needs to be implemented inside Codex itself.

If helpful, I am happy to share more details about the wrapper behavior and edge cases I ran into.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗