Skip to content

feat(reporters): add OSC 8 hyperlinks for stacktrace file paths#9647

Open
Ujjwaljain16 wants to merge 7 commits intovitest-dev:mainfrom
Ujjwaljain16:feat/osc8-terminal-links
Open

feat(reporters): add OSC 8 hyperlinks for stacktrace file paths#9647
Ujjwaljain16 wants to merge 7 commits intovitest-dev:mainfrom
Ujjwaljain16:feat/osc8-terminal-links

Conversation

@Ujjwaljain16
Copy link
Copy Markdown
Contributor

Description

This adds optional OSC 8 hyperlink support to stacktrace file paths in terminal output. This allows compatible terminals (Ghostty, iTerm, VS Code, etc.) to make file paths clickable even if they wrap or contain special characters.

  • Links are enabled only when stdout is TTY
  • Disabled in CI or when VITEST_FORCE_TTY=false
  • Uses pathToFileURL for cross-platform support (handles Windows paths correctly)
  • Reporter-only change (no runtime logic affected)

Resolves #9565

Please don't delete this checklist! Before submitting the PR, please make sure you do the following:

  • It's really useful if your PR references an issue where it is discussed ahead of time. If the feature is substantial or introduces breaking changes without a discussion, PR might be closed.
  • Ideally, include a test that fails without this PR but passes with it.
  • Please, don't make changes to pnpm-lock.yaml unless you introduce a new test example.
  • Please check Allow edits by maintainers to make review process faster. Note that this option is not available for repositories that are owned by Github organizations.

Tests

  • Run the tests with pnpm test:ci.

Documentation

  • If you introduce new functionality, document it. You can run documentation with pnpm run docs command.

Changesets

  • Changes in changelog are generated from PR name. Please, make sure that it explains your changes in an understandable manner. Please, prefix changeset messages with feat:, fix:, perf:, docs:, or chore:.

export function createTerminalLink(text: string, file: string): string {
// Graceful fallback for non-TTY or CI
// Also check VITEST_FORCE_TTY to allow explicit disabling
if (!process.stdout?.isTTY || process.env.CI || process.env.VITEST_FORCE_TTY === 'false') {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That checks seems incomplete

  1. logger can accept a different stdout implementation, so using process.stdout is not sufficient
  2. CI is not a sufficient check for a CI environment, we have isCI already that you can use
  3. I am conflicted on VITEST_FORCE_TTY: 'false', what do you think, @AriPerkkio? Feels like the presence of a ENV should be a check (like NO_COLOR=anything)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please no new environmental variables for TTY checking.

I think this function should be no-op only when these two indicate so:

if ((this.outputStream as typeof process.stdout).isTTY) {

isCI from:

export { isCI, provider as stdProvider } from 'std-env'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also have import c from 'tinyrainbow'; c.isColorSupported. Didn't it also had nice baseline check?

Comment thread test/core/test/terminal-link.test.ts Outdated
const originalEnv = process.env
let originalIsTTY: boolean | undefined

afterEach(() => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of all of this mocking, it might be better to turn createTerminalLink into a pure function that accepts these as options

@netlify
Copy link
Copy Markdown

netlify Bot commented Mar 1, 2026

Deploy Preview for vitest-dev ready!

Built without sensitive environment variables

Name Link
🔨 Latest commit 69705ed
🔍 Latest deploy log https://app.netlify.com/projects/vitest-dev/deploys/69a463c05e9de7000816b335
😎 Deploy Preview https://deploy-preview-9647--vitest-dev.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@hi-ogawa
Copy link
Copy Markdown
Collaborator

hi-ogawa commented Mar 2, 2026

This would be also more beneficial in import durations reporting because we truncate the file name which does actually break IDE (e.g. vscode's integrated terminal) to auto link the file

// only show the arrow if there is more than 1 group
const pathDisplay = this.ellipsisPath(imp.importedModuleId, imp.external, groupedImports.length > 1 && index > 0)

try {
const href = pathToFileURL(file).href
// OSC 8 escape sequence
return `\u001B]8;;${href}\u001B\\${text}\u001B]8;;\u001B\\`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for OSC 8 hyperlink in output

4 participants