Windows: Console window flashing when executing tools

Open 💬 41 comments Opened Dec 20, 2025 by guanknow

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?

## Description
When using Claude Code on Windows (Windows Terminal), a console window briefly flashes/appears every time a tool is executed (Bash, Grep, Glob, Read, etc.).

## Environment

  • OS: Windows
  • Terminal: Windows Terminal
  • Platform: win32

## Steps to Reproduce

  1. Run Claude Code on Windows
  2. Execute any command or let Claude use any tool
  3. Observe brief window flash

## Expected Behavior
Tools should execute without visible window flashing.

## Possible Solution
When creating child processes on Windows, use CREATE_NO_WINDOW flag or STARTUPINFO.dwFlags = STARTF_USESHOWWINDOW with wShowWindow = SW_HIDE.

## Workaround
Currently using WSL as a workaround.

---

What Should Happen?

11

Error Messages/Logs

Steps to Reproduce

11

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.0.74

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗

41 Comments

GigiTiti-Kai · 6 months ago

I'm also experiencing this issue, and it extends beyond just tool execution.

Additional Context

The console window flashing also occurs when plugin hooks execute. For example, the claude-mem plugin registers hooks for SessionStart, UserPromptSubmit, PostToolUse, and Stop events that run node and bun commands. Each execution creates a visible console window.

What I tried (unsuccessfully)

  1. VBS wrapper with hidden window - Wrapped commands in a VBS script using WScript.Shell.Run with vbHide flag. Failed due to quote escaping issues with cmd /c.
  1. PowerShell -WindowStyle Hidden - Wrapped commands with powershell -WindowStyle Hidden -Command "...". The PowerShell window was hidden, but the spawned node.exe/bun.exe processes still created their own console windows.

Root Cause

On Windows, console applications (like node.exe, bun.exe) create console windows by default when spawned. The only reliable way to prevent this is to use the CREATE_NO_WINDOW flag when calling CreateProcess().

Environment

  • OS: Windows 11
  • Terminal: Windows Terminal
  • Claude Code with claude-mem plugin

Request

Please consider implementing CREATE_NO_WINDOW for all child process spawning on Windows, including:

  • Tool execution (Bash, Grep, etc.)
  • Plugin hook execution
  • MCP server processes

This would significantly improve the Windows user experience.

TheDan64 · 6 months ago

I've recently started to experience this on windows and it's a really bad user experience. You can't do anything else while claude is running or it'll get in the way

EngDawood · 6 months ago

yes , it's very annoying

PakAbhishek · 6 months ago

Hook execution also affected - critical UX impact for plugin users

User Experience Impact:

I'm experiencing this same issue with plugin hooks, not just tool execution. Every time a claude-mem plugin hook executes (SessionStart, UserPromptSubmit, PostToolUse, Stop), a Node.js console window flashes on screen, often stealing keyboard focus mid-sentence. This happens dozens of times per session and significantly disrupts workflow.

Root Cause:

The issue is in Claude Code's hook execution function (appears to be GE1() in the bundled CLI). The spawn call is missing the windowsHide option:

Current Code:

let V = spawn(command, [], {env: K, cwd: a1(), shell: true})

Required Fix:

let V = spawn(command, [], {
  env: K,
  cwd: a1(),
  shell: true,
  windowsHide: process.platform === 'win32'
})

Precedent:

This exact fix was already implemented in:

  • claude-agent-sdk-typescript (Issue anthropics/anthropic-sdk-typescript#103)
  • Standard Node.js practice for Windows subprocess spawning

Why Workarounds Don't Work:

All attempted workarounds fail because:

  • PowerShell -WindowStyle Hiddencmd.exe spawns first before PowerShell
  • VBScript wrappers → Can't handle stdin properly (hooks need JSON input via stdin)
  • Batch files with start /b → Still creates initial cmd.exe window
  • PATH shims → Would also flash windows

The ONLY solution is fixing the spawn call at the source.

Impact Scope:

This affects:

  • ✅ All Windows users of Claude Code
  • ✅ Every tool execution (Bash, Read, Write, etc.)
  • ✅ Every plugin hook execution (SessionStart, UserPromptSubmit, PostToolUse, Stop)
  • ✅ MCP server startups via hooks

Business Impact:

For professional Windows users, this makes Claude Code nearly unusable. The constant window flashing:

  • Disrupts typing mid-sentence
  • Breaks focus during code reviews
  • Makes screen recording unprofessional
  • Prevents use in client-facing environments

Request:

Could this be prioritized for the next patch release? The fix is a one-line change that would immediately improve UX for all Windows users. I'm happy to test a beta build if that would help.

Environment:

  • OS: Windows 11 64-bit
  • Claude Code version: v2.1.2
  • Plugin: claude-mem v9.0.0
  • Terminal: PowerShell 7.x

Thank you for considering this!

roy-enginner · 5 months ago

Hi team — adding an update since my duplicate report (#16880) was closed.

I can still reproduce the same “console window flash” on Windows when tools run, now on the VS Code extension as well:

  • Claude Code for VS Code extension: 2.1.11
  • OS: Windows 11
  • Where it happens: VS Code (integrated terminal / Claude panel) — every Bash/tool invocation triggers a brief node.exe/console window flash

The worst part is that the flashing window steals foreground focus while it appears. During that moment I can’t interact with VS Code (keyboard input gets interrupted / clicks can be lost), so it effectively blocks other work. This is not just distracting — it actively breaks workflow.

Could you share the current status and when you expect a fix (e.g., a target version or timeframe)?
Thanks.

jphoenix-dev · 5 months ago

This is extraordinarily disruptive when using CC on Win11. One workaround is to use an admin terminal but doing so creates its own downstream issues and shouldn't be necessary. This is seriously impacting workflow - desperate for a fix.

Update: Another workaround for those finding this really annoying; commands run by agents don't appear to trigger the flashing cmd window issue (at least for me on win11, Terminal, CC CLI, non-admin account), so if you can delegate a task via agents I recommend doing so.

DamianReeves · 5 months ago

FYI I was plagued by this issue (it was immensely annoying) and finally today I got it fixed, this did the trick (note I have my git installed via scoop):

{
  "autoUpdatesChannel": "stable",
  "env": {
    "SHELL": "C:\\Users\\redacted\\scoop\\apps\\git\\2.52.0\\bin\\bash.exe"
  }
}
Jetski5822 · 5 months ago

Omg, please fix this - its pretty much impossible to use Claude Code in a windows env with this popup.

I may need to try @DamianReeves workaround.

blueberrynotstraw · 5 months ago

I also suffer from this issue, and it makes Claude Code nearly unusable. I may give up usage of it entirely, or always run it on a 2nd desktop.

I experience this through CMD line Claude, as well Claude through VSCode

I had no luck attempting @DamianReeves 's workaround

Clinteastman · 5 months ago

This is so annoying. Constantly having terminal windows flashing up when I'm working is a pain. Can we please have a fix for this?

jarrieta86 · 5 months ago

Same issue here. Using Claude Desktop (not CLI) on Windows 11 with working directory on WSL (\\wsl.localhost\Ubuntu\home\...).

Every message triggers a visible /usr/bin/bash --login -i -c cygpath -u \\wsl.localhost\... window for git repo detection. The window flashes briefly and steals focus, making it very disruptive.

Attempted workarounds (none worked):

Setting SHELL to cmd.exe in ~/.claude/settings.json
Setting SHELL to powershell.exe
Removing SHELL env entirely
The windowsHide: true fix on child_process.spawn() would resolve this.

Environment:

Windows 11
Claude Desktop (latest)
Git for Windows installed (C:\Program Files\Git\cmd\git.exe)
Working directory: WSL Ubuntu via \\wsl.localhost\

rsparacia · 4 months ago

Also experiencing the same issue here, rendering Claude Code incredibly tedious to use. Using Claude Code CLI (native installer) on Windows 11

Every Bash tool execution spawns a visible Git Bash window (/usr/bin/bash --login -i -c) that flashes open and closed.
The window steals focus mid-typing, making the experience very disruptive.

Attempted workarounds (none worked):

  • Setting CLAUDE_CODE_SHELL to powershell in ~/.claude/settings.json
  • Setting CLAUDE_CODE_SHELL to pwsh (PowerShell Core, freshly installed)
  • Setting Windows Terminal as default terminal app
  • Launching Claude Code from pwsh instead of default terminal

The windowsHide: true fix on child_process.spawn() would resolve this.

Environment:

  • Windows 11 Enterprise 10.0.26100
  • Claude Code native installer (~/.local/bin/claude.exe)
  • Git for Windows installed (AppData\Local\Programs\Git)
  • PowerShell Core installed
  • Windows Terminal as default terminal
ilude · 4 months ago

Regression: not present in 2.1.42, confirmed in 2.1.47

This issue appears to be a regression introduced between v2.1.42 and v2.1.47. On v2.1.42, no CMD window flashing or focus stealing occurs during tool execution. On v2.1.47, every tool call spawns a visible console window that steals keyboard focus.

Timing aligns with the new "session environment" / shell snapshotting mechanism introduced in v2.1.45, which also caused other Windows regressions (#26481, #26610, #26746). The new shell mechanism likely changed how child processes are spawned, dropping the windowsHide flag or spawning via a different code path that doesn't suppress console windows.

Environment:

  • OS: Windows 11 (MSYS2 / Git Bash)
  • Terminal: Windows Terminal
  • Working version: v2.1.42
  • Broken version: v2.1.47
jphoenix-dev · 4 months ago

This issue appears to have been fixed, at least for me (Win 11, CC CLI, v2.1.50 but v2.1.47 also worked) - CC is saying it can see windowsHide: true" in the bash shell spawn and I'm not getting flashing cmd windows on tool usage on my non-admin user account. Can't see anything in the changelog, but great its addressed.

Edit: worth noting I'm still on the original npm version of CC CLI, not the new "native" install approach, in case that makes a difference.

ilude · 4 months ago

Linking this here: https://github.com/anthropics/claude-code/issues/28138#issuecomment-3959696822

Is this going to get addressed? I am stuck on 2.1.42 which seems to be the last working version before this bug was introduced!

I dug into it and here is what I can tell based on the available info to the public:

Windows: Console window flashing regression introduced in v2.1.45

Since v2.1.45, every tool call, hook execution, and MCP server startup on Windows spawns a visible cmd.exe/conhost.exe window that flashes on screen and steals keyboard focus. v2.1.42 is the last version without this behavior.

This has been reported independently by many users across 14+ issues over the past two months with no official response. Posting this as a consolidated comment with root cause analysis to hopefully get some traction.

What happens

When Claude Code executes any tool (Bash, Grep, Glob, Read, etc.), runs a hook, or starts an MCP server, a black console window briefly appears and steals keyboard focus. If you're typing in another application, keystrokes get swallowed. If you have hooks running on every prompt or tool call, the flashing is nearly continuous. It makes Claude Code effectively unusable on Windows without pinning to v2.1.42.

Root cause analysis

The regression aligns precisely with the introduction of the session environment / shell snapshotting mechanism in v2.1.45. Here's the evidence:

  1. v2.1.27 originally fixed console window flashing by adding windowsHide: true to child_process.spawn() calls
  2. v2.1.45 introduced shell snapshotting — a mechanism that captures and replays the user's shell environment. This created new spawn call sites that don't carry the windowsHide: true fix from v2.1.27
  3. The error message "Session environment not yet supported on Windows" (#26610) confirms the feature shipped without full Windows support
  4. The onecmd leak in $SHELLOPTS (#26481) shows the snapshotting mechanism uses bash -o onecmd to capture environment, and this flag leaks into user sessions
  5. Technical investigation in #27115 confirmed that windowsHide: true IS set in 12 places in the binary, but the ConPTY/SEA binary context causes conhost.exe allocation anyway — the new spawn paths introduced by shell snapshotting likely bypass or override these settings

Additional changes in v2.1.45 that may contribute:

  • "Propagating API provider environment variables to tmux-spawned processes" — if env construction was refactored, spawn options may have been lost
  • "Improved memory usage for shell commands that produce large output" — likely touched spawn call sites

v2.1.47 made things worse with "Fixed hooks silently failing on Windows by using Git Bash instead of cmd.exe" (#25981), which created yet another spawn path. That same version also introduced hook path mangling on Windows (#26746) where backslash separators get stripped.

Related issues

Primary reports:

  • #14828 — Console window flashing when executing tools (9 👍, 13 comments, open since Dec 2025)
  • #27115 — Plugin hooks spawn visible cmd.exe/conhost.exe despite windowsHide:true
  • #28138 — Bash commands spawn visible black console windows
  • #20814 — Constant console window popups and zombie node.exe processes
  • #19391 — Windows popup issue

Duplicate/related reports:

  • #19012 — Hook commands cause brief console window flash (contains COMSPEC wrapper workaround)
  • #17230 — Feature request: add windowsHide option for hooks
  • #16880 — Console window flashes on every Bash tool execution (closed as dup)
  • #15572 — Console windows flash, missing windowsHide option (closed as dup)
  • #24708 — MCP stdio servers flash visible CMD windows (closed as dup)
  • #26440 — Bash popup at startup due to -i flag in cygpath call (closed as dup)
  • #21375 — Bun console window appears when starting Claude Code
  • #23229 — Persistent bun.exe terminal window with EPERM error

Same-root-cause regressions from v2.1.45:

  • #26481 — Bash tool returns exit code 1 (onecmd in SHELLOPTS)
  • #26610 — "Session environment not yet supported on Windows"
  • #26746 — Hook paths broken (backslash stripping)

Workarounds

| Workaround | Effectiveness |
|------------|--------------|
| Pin to v2.1.42 + DISABLE_AUTOUPDATER=1 | Fully works, but stuck on old version |
| Custom COMSPEC wrapper (details in #19012) | Fully works, requires compiling a C++ GUI-subsystem exe |
| Set CLAUDE_CODE_GIT_BASH_PATH to C:\Program Files\Git\bin\bash.exe | Works for some users |
| Use WSL instead of native Windows | Works but changes the whole workflow |
| Disable plugin hooks (claude-mem, etc.) | Reduces frequency but doesn't eliminate |

What a fix probably looks like

Based on community investigation, the fix needs to ensure windowsHide: true (or the Win32 CREATE_NO_WINDOW flag) is set on all child_process.spawn() and child_process.exec() calls — including the ones introduced by the shell snapshotting mechanism in v2.1.45 and the hook execution path changed in v2.1.47. The MCP SDK also has a bug where windowsHide is conditional on "type" in process which only returns true in Electron, so it's effectively always false in Node.js (#24708).

Environment

  • Windows 11 (also reported on Windows 10)
  • Claude Code v2.1.45+ (last working: v2.1.42)
  • Affects: CLI (VS Code extension and Claude Desktop also reported in some issues but unverified)
  • Terminals tested: Windows Terminal, VS Code integrated terminal, cmd.exe, PowerShell
ilude · 4 months ago

<img width="2286" height="1042" alt="cmd-exe-hydra.png — cut off one window, two more shall take its place" src="https://github.com/user-attachments/assets/fa5e4e9b-8c2b-4c9b-b5c8-5e0cfc5fd4aa" />

Tell me you don't use windows to develop claude code without saying you don't use windows!

Just try opening the start menu or typing while this is going on....

ilude · 4 months ago

Update: Narrowed down the hook-specific flashing on v2.1.59 (npm). Internal tool calls do not flash with hooks disabled — the regression appears to be specifically on the hook execution spawn path where windowsHide/CREATE_NO_WINDOW was lost in v2.1.45+.

Any hook command that spawns a separate Windows console-subsystem binary (like uv.exe or uvw.exe) triggers a visible conhost.exe window. Commands that run inside the existing bash process (echo, python) do not flash. This is consistent with v2.1.42 working — the hooks called uv run on both versions, but v2.1.42 suppressed the console allocation.

Workaround: use bare python instead of uv run in hook commands.

Full testing details: #28138 comment.

cruzlauroiii · 4 months ago

A fix is available as a Claude Code plugin: powershell-default

Install:

/plugin marketplace add cruzlauroiii/claude-code
/plugin install powershell-default@cruzlauroiii-plugins

Adds a native Pwsh tool (shows as Pwsh(...) in the UI). Commands use PowerShell syntax directly. When enabled, Bash tool is blocked. Works on any OS with PowerShell 7+.

PR: https://github.com/anthropics/claude-code/pull/35761

kamiletar · 3 months ago

Additional data: Procmon analysis reveals burst spawns on session start

Environment: Windows 11 Enterprise 10.0.26200, Claude Code 2.1.78, Claude Desktop

Finding: The problem is not just the 10s polling — it's burst spawns

Using Process Monitor (Sysinternals), I captured all Process Create events from Claude.exe. Two distinct patterns:

1. Background polling (always present, minor annoyance)

Claude.exe (PID 29504) runs git status --porcelain every 10 seconds. Each spawns git.execonhost.exe (-ForceV1) → git.exe (mingw64). This is 3 processes × 6/min = ~18 console windows per minute.

2. Session/dialog start burst (the real problem — ~20 windows at once)

When a new session or conversation starts, Claude fires a burst of 10-15 processes within ~500ms:

0:08:37,019  git status --porcelain
0:08:37,034  git --version
0:08:37,058  git rev-parse --verify HEAD
0:08:37,182  gh auth status --hostname github.com
0:08:37,293  git rev-parse --verify origin/main
0:08:37,372  git merge-base origin/main HEAD
0:08:37,446  git rev-list --left-right --count origin/main...HEAD
0:08:37,516  git diff --numstat -M <commit>
0:08:37,524  git diff --no-ext-diff -M --no-color <commit>
0:08:37,532  git diff --name-status -M <commit>

Then seconds later:

0:08:58,336  claude.exe plugin marketplace list --json
0:08:58,463  git status --porcelain
0:08:58,512  gh auth status --hostname github.com
0:08:59,452  claude.exe plugin marketplace update claude-plugins-official

And from a child Claude.exe (PID 40412):

0:09:25,440  cmd.exe /c "python --version"
0:09:25,557  cmd.exe /c "python --version"
0:09:25,605  cmd.exe /c "python --version"
0:09:25,664  cmd.exe /c "python --version"
0:09:25,703  cmd.exe /c "python --version"

python --version checks in 260ms!

Summary

| Pattern | Frequency | Processes per burst | Visual impact |
|---------|-----------|-------------------|---------------|
| git status polling | Every 10s | 3 (git→conhost→git) | 1 flash |
| Session start | On new dialog | ~15-20 | ~20 simultaneous flashes |
| Plugin checks | On session start | 5-7 | 5-7 flashes |
| Python version probe | On session start | 5 | 5 flashes |

Important: disabling all hooks does NOT fix this

I disabled all project hooks (SessionStart, PreToolUse, PostToolUse) and all plugin hooks (hookify, context-mode, security-guidance). The flashing persists — it's caused by Claude Code's own internal subprocess spawns, not by user hooks.

Suggested priorities

  1. All internal spawn()/execFile() calls for git, gh, python, and claude.exe subprocesses need windowsHide: true (or CREATE_NO_WINDOW)
  2. The python --version probe running 5 times is likely a bug — should be cached after first check
  3. Consider batching the session-start git queries or running them sequentially to reduce the simultaneous window count
Elie-Simard · 3 months ago

Still experiencing this on v2.1.87 (Windows 11, Git Bash shell).

Impact: Every hook execution (PreToolUse, PostToolUse, Stop, SessionStart) spawns node.exe via child_process without windowsHide: true, causing a visible terminal flash. MCP stdio servers using npx also flash at session start.

What we've done to mitigate (but can't fully fix):

  • Consolidated 7 hooks into 2 unified scripts (~60% fewer spawns per tool call)
  • Removed Read from PreToolUse matcher (~50% fewer hook invocations)
  • Merged 3 Stop hooks into 1 (sound + dream + kanban in one script)
  • Pre-installed MCP packages globally to reduce npx download time
  • Removed unused MCP servers

What's still flashing: Every remaining hook spawn (2 per Edit/Write/Bash, 1 per Stop, 1 per SessionStart) and MCP stdio server connections at boot.

The fix we need: windowsHide: true on all child_process.spawn() calls for hooks and MCP stdio servers on Windows. This is a one-line fix per spawn call.

dorian-simes · 3 months ago

Reproducing this on Windows 11 Pro (10.0.26200) with Claude Code in VS Code. Git Bash windows flash on every tool call (Bash, Grep, Glob, etc.). Using the VS Code extension, not standalone CLI. Very disruptive during normal use.

Captnwalker1 · 3 months ago

This is extremely frustrating, makes using claude so much more time consuming. More often than not the console windows close themselves, but if you have a custom statusline configured this one will stay open usually, and sometimes seems to prevent commands from finishing.

pauljones0 · 3 months ago

Hey want to crash my laptop? Why don't you introduce a bug that creates 150+ terminal windows? Great.
Is Anthropic going to fix it? No.
Can I use a non-claude application? No because the twerps running this gong show are worried about overuse.
They're going to keep vibe coding their lil dumb application. I hope this bubble pops.

Captnwalker1 · 3 months ago

This ended up being a issue with using git-bash.exe being used for SHELL, changed in ~/.claude/settings.json and now no issue

{
  "env": {
    "SHELL": "C:\\Users\\YOURUSER\\AppData\\Local\\Programs\\Git\\usr\\bin\\bash.exe",
    "CLAUDE_CODE_GIT_BASH_PATH": "C:\\Users\\YOURUSER\\AppData\\Local\\Programs\\Git\\usr\\bin\\bash.exe"
  },
Niizuki · 2 months ago

Seeing a more severe variant of this on Claude Code 2.1.68 / Windows 11
Enterprise 10.0.26200 with Git for Windows bash ($SHELL=/bin/bash.exe).

The Git Bash (MINGW64) window does not just flash — it opens and
stays open with an empty interactive prompt, and Claude Code is blocked
from continuing until I manually close the window. It happens intermittently
during normal Bash tool calls; no specific command reliably triggers it.

No user-configured hooks in settings.json. Confirmed these do not fix it:

  • git config --global core.pager cat
  • git config --global credential.helper manager

Hypothesis: on Windows the Bash tool is occasionally spawning
git-bash.exe / mintty.exe with a visible console attached instead of
hidden. Spawning child processes with CREATE_NO_WINDOW (or equivalent
detached mode) should prevent any visible terminal from ever surfacing.

Lonli-Lokli · 2 months ago

If I understand correctly, we have to wait until somebody from Anthropic vibe coding team started to use windows

towerbrother · 2 months ago

Still seeing the flash after setting SHELL and CLAUDE_CODE_GIT_BASH_PATH in ~/.claude/settings.json. Running Git Bash (mintty) on Windows 11, Claude Code v2.1.x.

marcodelpin · 1 month ago

Architectural framing + open-source workaround (5-month flash-source cascade analysis)

Confirming this is still active on 2.1.145 (Windows 11 26200). I've spent ~3 months reverse-engineering the spawn topology and shipping a complete workaround stack. Sharing the architecture in case it helps prioritize the upstream fix.

Root cause is broader than windowsHide:true

The hook dispatch pipeline wraps EVERY hook command in bash -c "..." even when the target IS an .exe. Example from settings.json:

"command": "$HOME/.claude/hooks/bin/my-hook.exe --arg"

This gets executed as bash.exe -c "$HOME/.claude/hooks/bin/my-hook.exe --arg"bash.exe is CUI subsystem → conhost.exe flash, even if my-hook.exe is itself GUI subsystem. The bash wrapper is the visible window source for hook commands, NOT the hook executable.

Proposed fix (architectural, not windowsHide: flag tweak):

When the hook command's argv[0] resolves to an .exe directly (no shell metachars in argv), invoke it via child_process.spawn(<exe>, [<args>], { windowsHide: true, ... }) directly, bypassing the bash wrapper. This eliminates the bash.exe → conhost.exe flash entirely for native-binary hooks.

For Bash tool calls themselves (genuine shell scripts), windowsHide:true on the bash spawn AND on all child spawns (taskkill cleanup, ps inspection) would address the residual flashes — see related closed dups #43844, #59040, and #19012.

Open-source workaround stack we deployed

Working solution shipping CUI-flash from ~155/min to ~33/min:

  1. GUI-subsystem bash.exe trampoline — wraps bash.exe invocations. Detects single-token shell-metachar-free commands and bypasses bash entirely via exec.Command(target_exe, args...). Falls back to ConPTY for legitimate shell commands. Critical fix: HOME="" (empty string set by claude.exe in 163/164 invocations observed) requires fallback to USERPROFILE — otherwise ~/<path> tokens don't expand and bypass silently fails.
  1. GUI-subsystem launcher pattern for any locally-deployed CUI binary called from hooks: a small Go (or equivalent) shim sets syscall.SysProcAttr{HideWindow: true} on the exec.CommandSTARTF_USESHOWWINDOW + SW_HIDE ensures conhost.exe is allocated but never shown. Output flows normally via inherited stdin/stdout/stderr handles.
  1. Custom hook client replacing direct hook commands in settings.json. ConPTY-based with autospawn-grace + dial-with-retry. Eliminates ~all hook-event conhost flashes.
  1. PATH shim layer at ~/.claude/shims/: GUI-subsystem trampolines for git.exe, cmd.exe etc., prepended to PATH for sub-processes spawned by hook handlers. Catches the cascading flash from sub-tools that internally invoke other CUI binaries.

Result on a 6-repo VS Code workspace + active hook dispatch: 0 visible conhost windows observed under sustained Bash tool load + statusline polling.

Cofactors NOT addressed by user-side workarounds

Two claude.exe (node) internal spawn patterns bypass any user-side trampoline because they invoke cmd.exe via absolute C:\WINDOWS\system32\cmd.exe path:

  • cmd.exe /d /s /c "taskkill /pid <X> /T /F" — 14 flash/min (Bash tool subprocess cleanup)
  • cmd.exe /d /s /c "ps -axo user,pid,stat,command" — 5.6 flash/min (process inspection, UNIX command on cmd.exe = always fails but flash happens first)

Combined ~20 flash/min purely from claude.exe internal subprocess inspection/cleanup that no user-side shim can intercept. These would benefit from:

  • taskkill: replace with native Win32 TerminateJobObject (no cmd.exe)
  • ps -axo: replace with NtQuerySystemInformation or Node process APIs (no cmd.exe needed; the cmd.exe call ALWAYS fails because ps is UNIX-only — so the data isn't even being collected)

Asks

  • Could Anthropic team comment on whether this is on the roadmap? 5 months silence is the main pain — even a "tracked internally, won't fix" answer would let community deprioritize workaround maintenance.
  • The .exe direct-invoke architectural change has higher ROI than windowsHide because it eliminates the wrapper bash process entirely (lower latency too: ~10ms/hook saved per skipped bash -c startup × hooks-per-turn = noticeable on long sessions).
JustinCMR · 1 month ago

New reproduction path: clicking "New Session" in Claude Desktop triggers a ~50-spawn cascade with ~30 visible conhosts

Adding evidence for a different trigger than the statusline/hook scenarios already documented: the "New Session" button itself.

Repro

  1. Have Claude Desktop open with at least one git project
  2. Click New Session in the live Claude Code window (don't even send a message)
  3. Watch the screen: ~30 brief console-window flashes over ~75 seconds

What's happening (process snipe, 60ms WMI polling)

Captured the full cascade from a single click. ~50 subprocesses spawn, parent = Claude Desktop main (Electron) process. Timeline of key events after click:

| Δt from click | Subprocess | conhost |
|---|---|---|
| t+0s | git fetch --prune origin | VISIBLE |
| t+0s | git credential-manager get + store | inherited |
| t+5s | git index-pack --stdin --fix-thin | inherited |
| t+16s | git maintenance run --auto (auto-triggered by fetch) | inherited |
| t+17–27s | git repack -d -l --geometric=2 --write-midx, git pack-objects, git multi-pack-index writemulti-second console ops | inherited |
| t+18s | gh pr view <branch>, gh pr checks <num>, gh pr view <num> (PR context lookup) | VISIBLE ×3 |
| t+30s | git update-ref refs/heads/main (fast-forward local main) | VISIBLE |
| t+32s | git worktree add --no-checkout -b claude/<auto-name> <user-path>\.claude\worktrees\<auto-name> | VISIBLE |
| t+32s | git checkout HEAD -- . :(exclude).claude, git config extensions.worktreeConfig true | VISIBLE ×2 |
| t+36s | Same gh pr view <branch> as t+18s (redundant query) | VISIBLE |
| t+40s | New claude.exe (claude-code child) spawns for the session | VISIBLE |
| t+41s | Session init: git --no-optional-locks status --short, log --oneline -n 5, config user.name, config user.email | VISIBLE ×4 |
| t+41s | cmd.exe /d /s /c "git config --get user.email" (raw cmd.exe wrapper) | VISIBLE |
| t+41s | cmd.exe /d /s /c "tasklist \| findstr /I \"Code.exe Cursor.exe Windsurf.exe idea64.exe pycharm64.exe ...\"" — IDE detection | VISIBLE |
| t+41s | powershell.exe -NoProfile -Command "(Get-CimInstance Win32_Process -Filter ...).CreationDate.Ticks" | VISIBLE |

Smoking gun: the spawn code knows how to do --headless, just doesn't use it consistently

Over the same 90-second window, the SAME parent (Claude Desktop main process) spawned ~30 subprocesses with auto-allocated console (no --headless flag — Windows wrote conhost.exe 0x4) and exactly 1 with proper conhost.exe --headless --width 80 --height 24 --signal 0xNNNN --server 0xNNNN.

So the bug isn't "Electron can't hide console windows on Windows" — it's that the spawn path for git/gh/cmd/powershell tool subprocesses is missing windowsHide: true (or CREATE_NO_WINDOW), while the spawn path for some Electron-internal utility processes correctly sets it.

Compounding factors observed in the same investigation

  1. Session restore after auto-update: same cascade fires for each claude-code session being restored. Captured 1.9255.0.0 → 1.9255.2.0 update auto-restoring 2 sessions → 2 visible-conhost spawns + downstream chain.
  1. git maintenance run --auto is the worst offendergit repack + git pack-objects are seconds-long console processes. A typical click-spawn flash lasts ~50ms; these last seconds.
  1. Redundant PR queries: gh pr view <branch> runs twice during a single new-session init (visible at t+18s and t+36s in the table). Halving these would halve the gh-related flashes.
  1. Compounds with #62659: in the same investigation, found 6 orphan bash.exe processes (one alive 13 hours) that survived the originating claude-code session's death — generating ~8 gh.exe spawns/sec via a model-generated until ... do true; done busy-wait loop. Each spawn flashed because of this issue (#14828). Without the visible-conhost bug, the orphan loop would silently waste CPU; with it, the loop becomes a focus-stealing keystroke killer.

Environment

  • Claude Desktop: 1.9255.2.0 (Microsoft Store install)
  • claude-code: 2.1.149
  • Windows 11
  • Git for Windows (standard install)
  • GitHub CLI installed
theotillotson · 1 month ago

Independent confirmation on Claude Code 2.1.142 / Windows 11 (build 26200).

@JustinCMR's diagnosis matches what I see — the tool-subprocess spawn path is missing windowsHide: true / CREATE_NO_WINDOW, and the windowless path already exists in the codebase: a live process snapshot shows conhost.exe --headless --width 80 --height 24 --server 0x... being used for some child processes but not the shell/tool ones. So this is a one-flag inconsistency, not a platform limitation.

One spawn path I haven't seen called out yet: MCP stdio servers. Each configured MCP server is launched as a child node.exe / python.exe at session start/restore, and those spawns also lack windowsHide — so they flash too. For anyone running several MCP servers, that's an extra burst of windows on every session start, on top of the per-tool-call flashes. Whatever fixes the tool-subprocess path should cover the MCP stdio launch path as well (same child_process.spawn options).

Mitigation for the portion that's user-owned (not the harness): if some of your flashes come from your own Windows automations (scheduled tasks, file watchers, helper scripts) rather than Claude Code itself, that part is fixable today:

  • Scheduled tasks: add -WindowStyle Hidden to a powershell.exe action, or switch a console python.exe action to pythonw.exe.
  • On-demand launches: wrap in a one-line wscript VBS shim — CreateObject("WScript.Shell").Run cmd, 0, False — which gives zero flash (window style 0), stronger than -WindowStyle Hidden (which can still flash briefly).

I verified this silences recurring scheduled automations completely. It does not touch the Claude Code tool/MCP flashes (those still need the windowsHide fix above), but it removed a meaningful chunk of the noise in my case.

+1 for prioritizing the one-flag fix — this is a daily, focus-stealing problem on Windows.

AgathoZorya · 28 days ago

Same root cause, confirming with an independent diagnostic method — also affects Windows PowerShell tool calls, not just Bash. Full write-up and a feature suggestion posted on #58606 (which has the closest match in scope), copying the key part here since this issue is older:

Environment: Windows 11 Home, build 10.0.26200, anthropic.claude-code v2.1.181-win32-x64, Git Bash + Windows PowerShell 5.1.

I confirmed the bash.exe/powershell.execonhost.exe (no CREATE_NO_WINDOW) pattern via Windows native Process Creation auditing (Event ID 4688 in the Security log) while debugging an unrelated, separate console-flash issue on the same machine. That gave a reliable way to attribute flashes specifically to Claude Code's tool execution versus anything else running on the box.

Suggestion: rather than only hiding the window, consider exposing it as a setting (hidden / visible / visible-signed with a distinguishing title) — some users may want the visibility as a "Claude is working" signal rather than have it fully suppressed. Details on #58606.

Geozstevenzz · 24 days ago

This very annoying

AgathoZorya · 24 days ago

claude code made an "visible-signed with a distinguishing title windows" for my powershell process -
so now there is no more flash on my computer - its very comfortable one ..

AgathoZorya · 24 days ago

Can confirm - traced this with Windows Process Creation auditing (Event ID 4688): every Bash/PowerShell tool call from Claude Code spawns bash.exe/powershell.exe -> conhost.exe without CREATE_NO_WINDOW. Seems to be the extension host launching child processes without the no-window flag, not something fixable from the user side (settings.json hooks etc. don't touch this path). Hoping for an exposed window-style option on the tool execution side.

AgathoZorya · 24 days ago

For anyone else dealing with console flashes from their own elevated PowerShell calls (separate from the tool-execution flash above) - a small trick that helped distinguish "my own elevated action" from "something else is flashing":

The problem

Start-Process ... -Verb RunAs opens a real console window for the elevated command. By default it opens and closes very fast (a flash) and gives no clue about who launched it.

The fix: title + visible banner + wait

Start-Process powershell -Verb RunAs -ArgumentList '-NoProfile -ExecutionPolicy Bypass -Command "$host.UI.RawUI.WindowTitle=''MYTOOL - diagnostic''; Write-Host ''=== MYTOOL - action in progress ==='' -ForegroundColor Cyan; & \"script.ps1\""' -Wait
  • $host.UI.RawUI.WindowTitle = '...' renames the title bar - visible on Alt+Tab / taskbar
  • Write-Host '=== ... ===' -ForegroundColor Cyan prints a colored banner right when the console opens, readable even on a quick screenshot
  • -Wait keeps the window open for the whole duration of the action instead of a few-millisecond round trip

Result: a flash with a UAC prompt + a clearly signed window is unambiguous (a deliberate elevated action), versus a flash without UAC and without a signature, which is worth investigating as coming from something else entirely (in my case, two unrelated background services that never trigger UAC turned out to be the real source of separate, unexplained flashes).

khaledfouad0 · 19 days ago

Still reproduces on v2.1.195 (Windows 11, Git Bash backend, VS Code integrated terminal).

Confirmed via process monitor — the flash is claude.exe spawning the hook/statusLine subprocess without a hidden-window flag, so Windows allocates a conhost.exe per spawn. Representative chain:

conhost.exe ← bash.exe ← claude.exe   (e.g. bash -c 'sh -c "exec sh .../statusline.sh"')

Two distinct triggers on this build:

  • statusLinebash → jq → bunx re-spawned on every render (continuous flicker even at idle). Same as the older #51867.
  • Hook subprocesses — any type:command hook is wrapped in an un-hidden bash -c, firing on every PreToolUse/PostToolUse/UserPromptSubmit. Plugin hooks that use bash/python3 (e.g. PostToolUse-on-every-tool-call) flash on each tool use.

windowsHide: true in hook config and CREATE_NO_WINDOW in the env block are both ignored — the flash is claude.exe's own outer wrapper, before the hook command runs, so neither has any effect (matches #27115).

Mitigations that actually reduce it (not eliminate): disabling hook-heavy plugins and clearing the custom statusLine. Only WSL gets it to zero. A CREATE_NO_WINDOW / STARTF_USESHOWWINDOW+SW_HIDE flag on the internal spawn is the real fix.

Eddie-Huang · 17 days ago

Install RTK (https://github.com/rtk-ai/rtk) has solved this annoying shit!! At least for Bash tool, Search still flash that cmd window

romemozu · 10 days ago

Same issue here, and it makes Claude Code very hard to use for non-stop daily work on Windows 11 (v2.1.197, PowerShell host).

Extra detail from monitoring process creation events (Win32_Process __InstanceCreationEvent) that may help pinpoint it. Visible conhost/console windows flash on EVERY turn from Claude Code's own internal spawns, not just user tool calls:

  • git.exe --no-optional-locks status --short and git log --oneline -n 5 (parent = claude.exe)
  • gh.exe pr view <branch> --json ... (parent = claude.exe)
  • cmd.exe /c tasklist | findstr /I "Code.exe Cursor.exe ..." (IDE detection, parent = claude.exe)
  • one visible bash.exe window per configured hook (SessionStart / PostToolUse / Stop)
  • MCP stdio servers (node.exe) launched with a visible console window

Workarounds we applied (consolidating hooks into one orchestrator per event, wrapping MCP servers in a pythonw launcher with STARTUPINFO+SW_HIDE and a kill-on-close Job Object, switching the default terminal from Windows Terminal to Console Host) reduce it a lot, but the internal git/gh/tasklist spawns cannot be hidden from user side at all.

Feature request: spawn internal child processes and hook/MCP commands with CREATE_NO_WINDOW (or a settings.json option like "hideChildConsoles": true) on Windows.

Captnwalker1 · 10 days ago
Same issue here, and it makes Claude Code very hard to use for non-stop daily work on Windows 11 (v2.1.197, PowerShell host). Extra detail from monitoring process creation events (Win32_Process __InstanceCreationEvent) that may help pinpoint it. Visible conhost/console windows flash on EVERY turn from Claude Code's own internal spawns, not just user tool calls: git.exe --no-optional-locks status --short and git log --oneline -n 5 (parent = claude.exe) gh.exe pr view <branch> --json ... (parent = claude.exe) cmd.exe /c tasklist | findstr /I "Code.exe Cursor.exe ..." (IDE detection, parent = claude.exe) one visible bash.exe window per configured hook (SessionStart / PostToolUse / Stop) * MCP stdio servers (node.exe) launched with a visible console window Workarounds we applied (consolidating hooks into one orchestrator per event, wrapping MCP servers in a pythonw launcher with STARTUPINFO+SW_HIDE and a kill-on-close Job Object, switching the default terminal from Windows Terminal to Console Host) reduce it a lot, but the internal git/gh/tasklist spawns cannot be hidden from user side at all. Feature request: spawn internal child processes and hook/MCP commands with CREATE_NO_WINDOW (or a settings.json option like "hideChildConsoles": true) on Windows.

curious if you tried my solution above? https://github.com/anthropics/claude-code/issues/14828#issuecomment-4253966091

feelgoodfarms · 5 days ago

Adding a data point + a diagnostic method, in case it helps others triage.

On a Windows box with a lot of automation, I had the same unbearable flashing — dozens of PowerShell/conhost/OCR windows per second stealing focus. When I actually traced what was spawning each window, most of my storm was not Claude Code's tool calls. The two dominant sources were:

  1. My own Scheduled Tasks registered with LogonType = Interactive ("Run only when user is logged on"). Those run in the visible desktop session (session 1), so every console child they spawn — PowerShell, cmd, and especially tesseract.exe / pdftoppm.exe in OCR pipelines (one window per page) — flashes. The task's "Hidden" checkbox and -WindowStyle Hidden are cosmetic and do not stop this.
  2. A third-party RGB/fan-control utility polling the GPU by launching an un-hidden PowerShell every few seconds.

Diagnostic: attribute each flash to its real source

Run in an elevated PowerShell — this shows console processes in your visible session and their parent, so you can see whether Claude Code, a Scheduled Task (svchost … Schedule), or some app is the spawner:

$s = (Get-Process -Id (Get-CimInstance Win32_Process -Filter "Name='explorer.exe'").ProcessId).SessionId
Get-CimInstance Win32_Process -Filter "Name='powershell.exe' OR Name='cmd.exe' OR Name='tesseract.exe' OR Name='pdftoppm.exe' OR Name='conhost.exe'" |
  Where-Object { (Get-Process -Id $_.ProcessId -EA SilentlyContinue).SessionId -eq $s } |
  ForEach-Object { $p=(Get-CimInstance Win32_Process -Filter "ProcessId=$($_.ParentProcessId)").Name; "$($_.Name) <- $p" } |
  Group-Object | Sort-Object Count -Descending

The fix for the non-Claude sources

The key realization: what decides visibility is the session, not the "Hidden" flag. Interactive logon = session 1 = visible; SYSTEM/ServiceAccount (or "Run whether user is logged on or not") = session 0 = invisible.

  • Back up first: Export-ScheduledTask every interactive task to XML so it's reversible.
  • Convert the offending tasks to run in session 0:

``powershell
$p = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType ServiceAccount -RunLevel Highest
Set-ScheduledTask -TaskName 'YOUR_TASK' -Principal $p
``

  • Caveat: tasks that read Credential Manager / DPAPI secrets or a browser profile must not go to SYSTEM (they'll run but fail auth) — keep those as your user via "Run whether user is logged on or not" (Password logon), which is also session 0. Note S4U cannot be set for a different user by SYSTEM (Access denied 0x80070005).
  • For Python pipelines shelling out to CLI tools, pass creationflags=subprocess.CREATE_NO_WINDOW on Windows (common with pytesseract/pdftoppm/ffmpeg).

Eliminating those two sources removed the overwhelming majority of my flashing. The remaining Claude-Code tool-spawn flashes are what this issue is about — this isn't a fix for that, just a way to rule out (and kill) the other contributors so you can see how much is actually the tool spawns.

magicexperience · 1 day ago

I fully agree. I hope this gets fixed soon because it's really disruptive when trying to work.