fix(windows): hide conhost window spawned with core sidecar#731
Conversation
The core binary is a console-subsystem .exe so `openhuman core run` works correctly in a terminal. When the GUI shell (which is built with `windows_subsystem = "windows"`) spawns it as a child without the `CREATE_NO_WINDOW` creation flag, Windows allocates a fresh conhost window that pops up on top of the app. Apply `CREATE_NO_WINDOW` (0x08000000) at every site where the GUI launches a core subprocess: - `core_process.rs`: both sidecar spawn paths (`CoreRunMode::InProcess` fallback and `CoreRunMode::ChildProcess`). - `lib.rs`: the short-lived `run_core_cli` used by `service_*_direct` commands. Non-Windows builds get a no-op helper, so the cross-platform call sites stay identical. Stdout/stderr piping for log forwarding is unaffected.
📝 WalkthroughWalkthroughThe changes suppress console windows for Tauri core sidecar processes spawned on Windows by adding platform-specific command configuration. Two separate code paths are updated to set the Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
app/src-tauri/src/lib.rs (1)
225-230: DeduplicateCREATE_NO_WINDOWconfiguration across spawn paths.This block duplicates the Windows flag logic already introduced in
app/src-tauri/src/core_process.rs(apply_core_no_window). Centralizing this behavior would reduce drift risk between service-direct CLI execution and core sidecar spawning.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@app/src-tauri/src/lib.rs` around lines 225 - 230, The Windows-specific CREATE_NO_WINDOW setup in the lib.rs spawn path is a duplicate of the logic in apply_core_no_window (core_process.rs); remove the inline #[cfg(windows)] block that defines CREATE_NO_WINDOW and calls cmd.creation_flags(...) and instead factor that behavior into a shared helper (or directly call apply_core_no_window) so both the service-direct CLI spawn and the core sidecar spawn use the same function; ensure the helper accepts the Command (or mutable reference used as cmd) and applies creation_flags(CREATE_NO_WINDOW) on Windows to keep behavior centralized.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@app/src-tauri/src/lib.rs`:
- Around line 225-230: The Windows-specific CREATE_NO_WINDOW setup in the lib.rs
spawn path is a duplicate of the logic in apply_core_no_window
(core_process.rs); remove the inline #[cfg(windows)] block that defines
CREATE_NO_WINDOW and calls cmd.creation_flags(...) and instead factor that
behavior into a shared helper (or directly call apply_core_no_window) so both
the service-direct CLI spawn and the core sidecar spawn use the same function;
ensure the helper accepts the Command (or mutable reference used as cmd) and
applies creation_flags(CREATE_NO_WINDOW) on Windows to keep behavior
centralized.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 8d7bcf9a-24ad-4dca-9eb8-f0558956ea44
📒 Files selected for processing (2)
app/src-tauri/src/core_process.rsapp/src-tauri/src/lib.rs
/tinyhumansai#1338 follow-up) On Windows, `CreateProcess` allocates a conhost for every child unless `CREATE_NO_WINDOW` (creation flag `0x0800_0000`) is set. The shell-side spawns were fixed in tinyhumansai#731 (core sidecar) and tinyhumansai#1338 (netstat/taskkill). The core-side spawns were not — so any frontend-polled RPC that fans out into a native command (e.g. `local_ai_device_profile` -> `nvidia-smi`) flashes a console window on every poll. On a fresh Windows install with no Ollama, the combined effect was a continuous terminal-flash storm before the auth screen had even rendered. Sites covered: - `local_ai/install.rs`: PowerShell wrapper that runs OllamaSetup.exe - `local_ai/service/ollama_admin.rs`: `ollama --version`, `ollama serve`, candidate probe in `command_works`, `taskkill /F /IM ollama.exe` - `local_ai/device.rs`: `nvidia-smi --query-gpu` — re-probed by `handle_local_ai_device_profile` on every poll - `doctor/core.rs`: PowerShell `Get-PSDrive` for disk space, and `<cmd> --version` for `git` / `curl` / etc. - `node_runtime/resolver.rs`: `<bin> --version` in `probe_subcommand_version` - `service/common.rs` helpers (`run_checked`, `run_capture`, `run_best_effort`, `run_check_silent`) — silences every Windows `schtasks` call at the helper boundary (covers `status`, `start`, `stop`, `install`, `uninstall`, `is_task_exists_windows`). Linux `systemctl` and macOS `launchctl` callers go through the same helpers; `no_window` is a `cfg(not(windows))` no-op for them. New helper `local_ai/process_util::apply_no_window` keeps the `cfg(windows)` + `creation_flags` detail out of call sites. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nsai#731) The core binary is a console-subsystem .exe so `openhuman core run` works correctly in a terminal. When the GUI shell (which is built with `windows_subsystem = "windows"`) spawns it as a child without the `CREATE_NO_WINDOW` creation flag, Windows allocates a fresh conhost window that pops up on top of the app. Apply `CREATE_NO_WINDOW` (0x08000000) at every site where the GUI launches a core subprocess: - `core_process.rs`: both sidecar spawn paths (`CoreRunMode::InProcess` fallback and `CoreRunMode::ChildProcess`). - `lib.rs`: the short-lived `run_core_cli` used by `service_*_direct` commands. Non-Windows builds get a no-op helper, so the cross-platform call sites stay identical. Stdout/stderr piping for log forwarding is unaffected.
…nsai#731/tinyhumansai#1338 follow-up) (tinyhumansai#1498) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
On Windows, launching the installed
OpenHuman.exepops a stray conhost (terminal) window on top of the app. The GUI shell is built withwindows_subsystem = "windows"(no console), but theopenhuman-coresidecar is a console-subsystem executable — kept that way intentionally so thatopenhuman core runworks as a normal CLI in a terminal. When the GUI shell spawns the console sidecar as a child withoutCREATE_NO_WINDOW, Windows allocates a fresh console window for it.Fix: pass
CREATE_NO_WINDOW(0x08000000) at every site where the GUI launches a core subprocess. Non-Windows platforms get a no-op helper so the call sites stay identical.Changes
app/src-tauri/src/core_process.rsapply_core_no_window(&mut Command)helper — setsCREATE_NO_WINDOWon Windows, no-op elsewhere.CoreRunMode::InProcessfallback andCoreRunMode::ChildProcess).app/src-tauri/src/lib.rsrun_core_clisubprocess used byservice_install_direct/service_start_direct/service_stop_direct/service_status_direct.Stdout/stderr piping (used for our log forwarding) is unaffected —
CREATE_NO_WINDOWonly suppresses the window, not the handles.Why the core binary stays console-subsystem
The core binary at
src/main.rsis intentionally not markedwindows_subsystem = "windows"so that running it directly from a terminal (openhuman core run, service CLI, etc.) behaves like a normal CLI tool with visible stdout/stderr. Flipping the subsystem would break that UX. Suppressing the window at the spawner is the right layer.Test plan
openhuman core rundirectly from a Windows terminal — CLI output still visible (unchanged).service_install_directetc.) — no window flash; command still returns expected output.yarn tauri devstill starts the sidecar and RPC becomes ready as before.Summary by CodeRabbit