anthropics / anthropics/claude-code

Windows: a console window opens and steals keyboard focus while typing an @-mention in the Claude panel (VS Code extension)

Open
#89,071 0 comments 0 reactions 0 assignees View on GitHub
area:ide bug has repro platform:vscode platform:windows
Dominant language
Python
Stars
145k
Forks
23.1k
PR merge metrics
PR metrics pending

Description

## Summary

On Windows, typing an `@`-mention in the Claude Code panel pops up a console window that **takes the foreground**, swallowing the next keystrokes. It happens repeatedly while typing, because the file-search helper spawns `rg.exe` per invocation.

The cause is a single missing option: the `execFile` call that runs ripgrep for `@`-mention / fuzzy file search does not pass `windowsHide: true`. Node defaults that option to `false`, and the VS Code extension host is a GUI process with **no console to inherit**, so Windows allocates a brand-new visible console for the child.

This is specific to the VS Code extension. The same call from the terminal CLI inherits the terminal's existing console and is invisible.

## Environment

| | |
|---|---|
| Extension | `anthropic.claude-code` **2.1.241** (`win32-x64`) |
| VS Code | **1.134.0** (x64) |
| OS | **Windows 11 Pro, build 10.0.26200** |
| Default terminal application | **Windows Terminal** (Windows 11 default) |
| Mode | Native panel (not `claudeCode.useTerminal`) |

## Steps to reproduce

1. On Windows 11 with **Windows Terminal** as the default terminal application (Settings → System → For developers → Terminal), open a reasonably large repository in VS Code.
2. Open the Claude Code panel.
3. Type `@` in the prompt box, then keep typing a few characters of a filename.
4. Watch the desktop, not the panel.

**Actual:** one or more console windows open, sit on top of the editor for roughly two seconds each, take the foreground, and close. Keystrokes typed during that window land in the console instead of the prompt box. With Windows Terminal as the default, the popup is a full Terminal window, not a brief flash.

**Expected:** the file search runs invisibly. No window, no focus change.

## Measurement

Runtime probe, measured 2026-08-23 on Windows 11 Pro 26200. A parent process was created with `DETACHED_PROCESS` so that `GetConsoleWindow() == 0`, reproducing the extension host's state, and it spawned a console-subsystem child twice:

```
NO windowsHide (flags = 0) childPid=66360 hwnd=0x3610D4 visible=True
windowsHide = true (CREATE_NO_WINDOW) childPid=78716 hwnd=0x0 visible=False
```

`windowsHide: true` is what libuv maps to `CREATE_NO_WINDOW` + `STARTF_USESHOWWINDOW` / `SW_HIDE`. Without it, the console window is created and shown.

**Severity depends on the default terminal application**, also measured 2026-08-23:

| Default terminal application | Window lifetime | Took foreground |
|---|---|---|
| Windows Terminal (Windows 11 default) | **2340 ms** | **8 / 8 samples** |
| Legacy Console Host (`conhost.exe`) | 30 ms | 0 / 3 samples |

So on a stock Windows 11 install this is a two-second focus theft per search, not the sub-frame flash it is often described as.

## Where it is

Static analysis of the shipped, minified `extension.js` from the 2.1.241 `win32-x64` VSIX (2,947,529 bytes) — read from the bundle, **not** verified at runtime by symbol. Names are post-minification; the character offset is a pointer to the source location, not a patch target.

The `@`-mention file search builds ripgrep arguments and calls a helper:

```js
// ~char 2807944
async function JMe(e, t, r) {
let n = ["--files", "--follow", "--hidden"];
if (!(Gn("respectGitIgnore") ?? !0)) n.push("--no-ignore-vcs");
// ...builds `--glob !` entries from search.exclude / files.exclude
let o = await wvr(n, t);
// ...fuzzy-matches
}
```

and the helper spawns ripgrep with no `windowsHide`:

```js
// ~char 2806166 <-- the defect
async function wvr(e, t) {
return new Promise((r, n) => {
SM.execFile(Svr(), e, { cwd: t, maxBuffer: xvr, timeout: Evr }, (i, o) => { /* ... */ })
})
}
```

`Svr()` resolves to `rg.exe` on Windows, and is a memoised probe that itself runs an unhidden `execFileSync` (`rg --version`) at ~char 2806047 — one extra window on the first search of a session.

## Why the VS Code extension and not the CLI

A console-subsystem executable started from a process that **has** a console inherits it and creates no window. The terminal CLI always has one. The VS Code extension host is a GUI process with `GetConsoleWindow() == 0`, so Windows has to create a new console for the child — and on Windows 11 the console host is Windows Terminal, which opens as a real, focus-taking window.

This is why the same code is silent under the CLI entrypoint and loud under the extension. It also means the extension cannot rely on the CLI's behaviour as evidence that a call site is safe.

## Fix

One option on one call:

```js
SM.execFile(Svr(), e, { cwd: t, maxBuffer: xvr, timeout: Evr, windowsHide: true }, ...)
```

and the same on the `--version` probe at ~char 2806047.

There is no user-side workaround: no extension setting and no environment variable in the bundle sets `windowsHide`, and `processWrapper` / `CLAUDE_CODE_PROCESS_WRAPPER` covers only the background-agent supervisor and the sessions and workers it hosts — not these helper spawns.

## Related

- **#87860** — same call site, different defect: the `@`-mention search spawns unbounded ripgrep processes with no debounce, cache or cancellation (605 processes in ~2 min, observed on macOS). The two compound on Windows: every one of those processes is also a console window. Fixing #87860 would reduce the *number* of windows; only `windowsHide` removes them.
- There are many reports of console windows on Windows from the CLI side (#14828, #73709, #73901, #87394 and others). This report is deliberately narrower: it is one call site in the **VS Code extension**, triggered by typing, with a one-line fix.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by tracing the helper around ~char 2806166 in the shipped extension.js back to its unminified source, then inspect the memoised rg --version probe around ~char 2806047. Verify both ripgrep spawns use hidden Windows child processes and reproduce the @-mention search on Windows; done means no console window or focus change occurs.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js, vscode
Domain
desktop, tooling
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.