Skip to content

fix(windows): hide console-window flash on gateway-runtime subprocess spawns#44105

Open
AIalliAI wants to merge 6 commits into
NousResearch:mainfrom
AIalliAI:windows-terminal-no-window
Open

fix(windows): hide console-window flash on gateway-runtime subprocess spawns#44105
AIalliAI wants to merge 6 commits into
NousResearch:mainfrom
AIalliAI:windows-terminal-no-window

Conversation

@AIalliAI

@AIalliAI AIalliAI commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

On Windows, when the gateway runs without a console (Desktop app / background service), every console child process it spawns opens a visible conhost window that flickers and steals focus — the behavior reported in #43848.

The main terminal-tool execution path already hides its window via windows_hide_flags() (tools/environments/local.py), and the same convention exists in tools/process_registry.py and cron/scheduler.py — but a number of spawn sites reachable during a normal agent turn were missed. The most user-visible ones run on every message (git workspace probes during prompt building) or on every file edit (checkpoint git calls), which is what makes the flicker so noticeable.

Change

Pass creationflags=windows_hide_flags() (CREATE_NO_WINDOW; returns 0 on POSIX, so non-Windows behavior is unchanged) at the gateway-runtime spawn sites:

Per agent turn

  • agent/coding_context.py — git workspace probes during prompt building (several per message)
  • agent/context_references.py@git/@diff reference git calls and rg --files listing
  • tools/checkpoint_manager.py — shadow-store git calls on every checkpointed file edit
  • agent/shell_hooks.py — user-configured hook commands
  • agent/skill_preprocessing.py — SKILL.md inline-shell snippets

Terminal tool probes (first commit)

  • tools/terminal_tool.pysudo -n true probe (Windows 11 ships a sudo), docker version / apptainer --version backend probes

Process cleanup (taskkill tree-kills, Windows-only branches)

  • gateway/status.py::terminate_pid, tools/tts_tool.py, tools/transcription_tools.py

Runtime installs / probes

  • tools/lazy_deps.pyuv pip / pip / ensurepip runtime dependency installs (these otherwise show a console window for the whole install)
  • tools/env_probe.py — interpreter/binary version probes

Container/remote backends

  • tools/environments/base.py_popen_bash now defaults creationflags to windows_hide_flags() (via setdefault, so callers can still override), covering the shared docker exec / ssh per-command spawn path
  • tools/environments/docker.py — container lifecycle and probe spawns (docker ps/rm/inspect/run/start/stop/info/create)
  • tools/environments/ssh.py — control-master setup, scp/tar sync, and remote command spawns

Sites intentionally left alone: macOS-only spawns (security, scutil), interactive flows that must keep the console (claude setup-token), and the interactive CLI (a console already exists there, so nothing flashes).

Testing

  • New regression tests in tests/tools/test_windows_native_support.py (TestGatewayRuntimeSpawnsHideConsole) simulate Windows by flipping IS_WINDOWS in _subprocess_compat and assert the CREATE_NO_WINDOW bit reaches subprocess.run for the per-turn probes, taskkill paths, and inline-shell helper. Verified they fail against unpatched modules.
  • Existing suites for all touched modules pass: 348 tests across test_coding_context, test_context_references, test_shell_hooks, test_checkpoint_manager, test_env_probe, test_lazy_deps, test_windows_native_support, test_status, plus the terminal-tool suites (220 more).

Fixes #43848

🤖 Generated with Claude Code

… probes

The terminal tool's synchronous probe spawns (sudo NOPASSWD check, docker
and apptainer/singularity availability checks) called subprocess.run
without creationflags, so on Windows each one briefly pops a console
window that also steals focus. The main command-execution path already
passes windows_hide_flags() (tools/environments/local.py), but these
probe sites were missed.

Pass creationflags=windows_hide_flags() at each site. The helper returns
0 on non-Windows, so POSIX behavior is unchanged (creationflags=0 is the
subprocess default).

Fixes NousResearch#43848

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
When the gateway runs without a console on Windows (Desktop app, service),
every console child process (git probes, rg, hooks, pip, taskkill, backend
version probes) opens a visible conhost window that flickers and steals
focus on each agent call.

Pass creationflags=windows_hide_flags() (CREATE_NO_WINDOW; 0 on POSIX) to
the subprocess spawn sites reachable during an agent turn, following the
existing convention in tools/environments/local.py, tools/process_registry.py
and cron/scheduler.py.

Fixes NousResearch#43848

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AIalliAI AIalliAI changed the title fix(terminal): hide Windows console flash on terminal-tool subprocess probes fix(windows): hide console-window flash on gateway-runtime subprocess spawns Jun 11, 2026
@AIalliAI

Copy link
Copy Markdown
Contributor Author

Pushed a second commit expanding this beyond the terminal-tool probes: the dominant flicker sources on the default local backend turn out to be the spawns that run on every agent message — the git workspace probes in agent/coding_context.py (prompt building), the checkpoint git calls in tools/checkpoint_manager.py (every file edit), and @git/@diff context references — plus the taskkill tree-kills and runtime pip/uv installs. All now pass creationflags=windows_hide_flags() following the existing convention. Added regression tests (TestGatewayRuntimeSpawnsHideConsole) that simulate Windows and assert the CREATE_NO_WINDOW bit reaches subprocess.run. PR description updated with the full site list.

@alt-glitch alt-glitch added type/bug Something isn't working P2 Medium — degraded but workaround exists comp/agent Core agent loop, run_agent.py, prompt builder comp/tools Tool registry, model_tools, toolsets tool/terminal Terminal execution and process management tool/tts Text-to-speech and transcription labels Jun 11, 2026
Adalsteinn Helgason and others added 4 commits June 12, 2026 08:19
gateway/status.py now passes creationflags=windows_hide_flags() to the
taskkill subprocess.run; the narrow fake_run signature rejected the new
kwarg.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
_ensure_docker_available now passes creationflags=windows_hide_flags()
(0 on POSIX) so the exact-kwargs assertion in
test_ensure_docker_available_uses_resolved_executable must include it,
mirroring the earlier TestTerminatePid taskkill stub fix.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
check-attribution flagged the email introduced by this branch's
2026-06-12 follow-up commit.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts:
#	scripts/release.py
@AIalliAI

Copy link
Copy Markdown
Contributor Author

Requesting maintainer review — this is ready to land from my side. Just merge-synced with current main (the only conflict was a trivial AUTHOR_MAP keep-both in scripts/release.py); the PR's touched test files pass locally on the merged head. Standalone fork CI is pending first-run approval here; the rollup branch in #44061 carrying this session's batch is fully green on upstream CI.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder comp/tools Tool registry, model_tools, toolsets P2 Medium — degraded but workaround exists tool/terminal Terminal execution and process management tool/tts Text-to-speech and transcription type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Set the "CREATE_NO_WINDOW" flag for Window terminal process

2 participants