Windows: background Agent worker spawns a console window that steals foreground keyboard focus
Title: Windows: background Agent (bg worker) spawns a console window that steals foreground keyboard focus
Environment: Windows 11 Pro (10.0.26200), Claude Code CLI (C:\Users\coach\.local\bin\claude.exe), daemon version 2.1.211 (per daemon.log), running interactively in Windows Terminal.
Repro:
- Have an active Claude Code session in the foreground (typing in Windows Terminal).
- From that session, dispatch a background subagent via the
Agenttool (anysubagent_type, notfork). - Watch the desktop: a new
claude.exeprocess spawns paired with a newconhost.exeprocess (confirmed viaGet-Process— both created within ~1 second of the dispatch). - The new console window takes foreground focus and keyboard input away from whatever the user was actively typing into, for several seconds, before returning control.
Impact: Every background agent dispatch interrupts active typing in the foreground terminal. In a session that fires several background agents in sequence (a common pattern — parallel research/execution subagents), this happens repeatedly, each time stealing the keyboard mid-sentence.
Likely cause: The daemon's background-worker mechanism (bg spawned <id> in daemon.log) appears to launch each worker as a new top-level console process (via ConPTY/conhost) rather than a hidden/no-window process. Windows grants a freshly-spawned child process permission to call SetForegroundWindow if its parent is the current foreground app, which is why the new window jumps to the front.
Requested fix: Spawn background-worker console hosts without creating a visible/foreground-stealing window — e.g. via the CREATE_NO_WINDOW process creation flag, or explicitly minimized + non-activating (SW_SHOWMINNOACTIVE) at creation, the same way well-behaved Windows background services avoid grabbing focus.
Workaround in place (user-side, not a real fix): a small always-on script that watches for new conhost.exe/claude.exe processes and force-minimizes them within ~150ms of creation via ShowWindowAsync(..., SW_SHOWMINNOACTIVE). Confirms the window is real and stealable; doesn't confirm whether the fix should be at spawn time (preferred) vs. post-creation suppression.