Skip to content

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

Closed
AIalliAI wants to merge 4 commits into
NousResearch:mainfrom
AIalliAI:windows-terminal-no-window
Closed

fix(windows): hide console-window flash on gateway-runtime subprocess spawns#44105
AIalliAI wants to merge 4 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

@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 runtime: loop, agent_init, prompt builder, context-compression, responses endpoint 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
@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.

AIalliAI added 4 commits June 18, 2026 18:41
… 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
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
gateway/status.py now passes creationflags=windows_hide_flags() to the
taskkill subprocess.run; the narrow fake_run signature rejected the new
kwarg.
_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.
@AIalliAI

AIalliAI commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Superseded: the CREATE_NO_WINDOW/DETACHED_PROCESS fix reached main via hermes_cli._subprocess_compat module. Different implementation, same outcome.

@AIalliAI AIalliAI closed this Jul 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent runtime: loop, agent_init, prompt builder, context-compression, responses endpoint 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