[BUG] VS Code extension: some file links on Windows do nothing when clicked

Status Open
Reported on v2.1.246
Maintainer reply None cached
Activity 0 comments · opened Aug 26, 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?

Three defects on the "click a file path in the transcript to open it" path. All reproduce on any Windows install. Located by reading the shipped bundles (no sourcemaps), so I'm quoting the minified expressions rather than line numbers.

1. File-link labels show the full absolute path instead of the basename

webview/index.js, ReadCoalesced.header and 10 sibling sites:

let G = Y.file_path.split("/").pop() || Y.file_path;

POSIX-only basename. A Windows path contains no /, so pop() returns the whole string and the fallback never fires. The transcript renders:

<span class="toolNameText">Read </span>
<span class="toolNameTextSecondary"><a href="#">D:\foo\bar\baz\shots\final.png</a></span>

Expected final.png.

Fix: .split(/[\/]/).pop()

Same expression appears in the headers/permission prompts for Read, ReadCoalesced, Edit, Write, NotebookEdit and the plan-file link — 11 occurrences in the bundle, all basenames, all safe to convert.

---

2. openFile swallows the rejection for binary files, so image links do nothing

extension.js:

E$.window.showTextDocument(X).then((Y) => { /* reveal range */ })

No .catch. showTextDocument rejects on a binary file ("File seems to be binary and cannot be opened as text"), so clicking a link to a .png produces an unhandled rejection and zero user-visible feedback. The path resolution above it is correct; only the presentation call is wrong.

Fix: fall back to the default editor resolution:

E$.window.showTextDocument(X).then((Y) => { ... })
  .catch(() => E$.commands.executeCommand("vscode.open", X))

vscode.open routes images to the image editor and text to the text editor, so it is a safe fallback for the whole class, not just images.

---

3. Markdown links to absolute Windows paths are inert

When Claude writes a markdown link to an absolute path, two layers drop it.

3a. The markdown a component passes href straight through react-markdown's default URL sanitizer. C:/Users/... parses as scheme c:, which is not in the allowlist, so the rendered anchor is:

<a href="" target="_blank" rel="noopener noreferrer">claude-vscode-linkfix.sh</a>

3b. Even with the href intact, the path parser rejects it:

function Cx($) {
  ...
  let J = /^([^:#]+?)(?:[:#]L?(\d+)(?:-L?(\d+))?)?$/;

[^:#]+? forbids colons in the path segment — the colon is reserved for the :42 line suffix — so C:/… and D:\… can never match. Cx returns null, the click handler returns before reaching fileOpener.open, and the anchor does nothing.

Fix (3b): allow a leading drive letter —
/^((?:[A-Za-z]:)?[^:#]+?)(?:[:#]L?(\d+)(?:-L?(\d+))?)?$/
The rest of Cx's allowlist already accepts a drive path via its file-extension test.

Fix (3a) needs a urlTransform that lets drive-letter paths through while keeping the sanitizer for everything else — a blanket passthrough would re-admit javascript: hrefs in rendered model and tool output, so this one wants care on your side rather than a one-liner.

What Should Happen?

Links are basic stuff, but let me check.

Based on wikipedia, in computing, a hyperlink, or simply a link, is a digital reference providing direct access to data) by a user's) clicking or tapping.[[1]](https://en.wikipedia.org/wiki/Hyperlink#cite_note-1)

It should do that.

Error Messages/Logs

Steps to Reproduce

On Windows, in the vscode extension chat:

  1. Have Claude read any file → the link label is the full absolute path (1).
  2. Have Claude read a .png → click the link → nothing happens, no error (2).
  3. Have Claude write a markdown link to an absolute path such as C:/Users/you/notes.md → the anchor renders with an empty href and is not clickable (3).

#1 and #2 verified fixed locally by patching the shipped bundles with the two changes above.

Claude Model

None

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.1.246 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Other

Additional Information

Here is a patch that will fix 1+2, but that would need to be reapplied on every update.

#!/usr/bin/env bash
# Fix Windows file links in the Claude Code VS Code extension.
#   1. basename via split("/") -> whole path shown as the link label on Windows
#   2. openFile only calls showTextDocument -> rejects silently on binary files (png etc)
# Re-run after every extension update, then reload the VS Code window.
set -euo pipefail

EXT_DIR="${1:-}"
if [ -z "$EXT_DIR" ]; then
  EXT_DIR=$(ls -d "$HOME"/.vscode/extensions/anthropic.claude-code-*-win32-x64 | sort -V | tail -1)
fi
echo "target: $EXT_DIR"

W="$EXT_DIR/webview/index.js"
X="$EXT_DIR/extension.js"
for f in "$W" "$X"; do [ -f "$f.orig" ] || cp "$f" "$f.orig"; done

SEP='[\\/]'

sub() { OLD="$1" NEW="$2" perl -pi -e 'BEGIN{$o=$ENV{OLD};$n=$ENV{NEW}} s/\Q$o\E/$n/g' "$3"; }

sub '.split("/").pop()' ".split(/$SEP/).pop()" "$W"
sub 'z.end)}})}openConfigFile' 'z.end)}}).catch(()=>E$.commands.executeCommand("vscode.open",X))}openConfigFile' "$X"

echo "basename sites patched: $(grep -oF "split(/$SEP/).pop()" "$W" | wc -l)"
echo "openFile fallback:      $(grep -cF 'vscode.open",X' "$X")"
node --check "$X" && echo "extension.js parses"

View original on GitHub ↗