Windows: child processes spawn visible conhost.exe windows
Summary
On Windows, claude.exe is a console subsystem binary. When it spawns child processes (Bash tool calls, MCP servers), those children inherit the console subsystem type but have no console to attach to — particularly in headless (-p) mode or when the parent is spawned with windowsHide: true. Windows responds by creating a new conhost.exe instance (a visible command prompt window) for each child process.
Steps to reproduce
- On Windows 11, run
claude -pfrom a Node.js script:
``js``
const { spawn } = require('child_process');
const child = spawn('claude', ['-p', 'list files in the current directory'], {
windowsHide: true
});
- Observe a
conhost.exewindow appearing when the Bash tool call executes. - Run a prompt that starts MCP servers — each server spawns 1–2 persistent visible windows.
Expected behavior
Child processes spawned by claude.exe should not create visible console windows. The fix is to pass CREATE_NO_WINDOW (0x08000000) via dwCreationFlags — or equivalently, set windowsHide: true in Node.js child_process.spawn() options — when spawning:
- Bash tool shell processes (
bash.exe,cmd.exe) - MCP server processes (
cmd.exe,node.exe,npx,uvx)
Actual behavior
Every child process creates its own conhost.exe, resulting in visible command prompt windows on the desktop.
Impact
| Scenario | Visible windows created |
|---|---|
| Single Bash tool call | 1 window flash per call |
| run_in_background: true Bash call | 1 persistent window that never closes |
| 1 MCP server | 1–2 persistent windows per session |
| 5 MCP servers across 3 sessions | 30+ command windows on the desktop |
This makes claude -p (programmatic mode) unusable for background automation on Windows. Users running Claude Code from scripts, schedulers, or GUI wrappers see a flood of command prompt windows.
Why this happens
claude.exeis compiled as a console subsystem binary (PE header subsystem =IMAGE_SUBSYSTEM_WINDOWS_CONSOLE).- When a console app spawns a child process without explicit creation flags, Windows gives the child a console. If the parent's console is hidden or absent, Windows creates a new
conhost.exefor the child. - Setting
windowsHide: trueon the outerclaude.exespawn only hidesclaude.exe's own console allocation — it does not propagate to internally spawned children.
Suggested fix
In the Node.js code that spawns child processes (Bash tool execution and MCP server startup), add windowsHide: true to the spawn/execFile options:
spawn(command, args, {
// existing options...
windowsHide: true // sets CREATE_NO_WINDOW on Windows, no-op on other platforms
});
This is a one-line change per spawn site and has no effect on macOS/Linux.
Workaround
Users can wrap the initial claude.exe invocation with a GUI-subsystem launcher (e.g., a .NET exe compiled with /target:winexe, or a VBScript with WScript.CreateObject("WScript.Shell").Run). This prevents claude.exe's own console but does not fix the internal child process windows.
Environment
- OS: Windows 11 (10.0.26200)
- Claude Code: CLI (
claude.exe) - Shell: Git Bash / PowerShell
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗