# NousResearch/hermes-agent · Windows console flash and encoding fixes for git probes

## Open now

- Nothing open on GitHub.

These items address two related Windows-specific bugs: subprocess calls spawning visible console windows during git/shell operations, and a cp950 encoding crash on non-ASCII paths in the dashboard's git probe logic.

## TL;DR

- 3 member(s): 0 open issue(s), 1 closed issue(s), 0 open PR(s), 1 merged PR(s), 1 PR(s) closed without merging.
- A fix was merged to main in PR #54236. Verify it addresses your case.
- **Recommended:** read PR #54236 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `unresolved`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_SPANNING`): every member is connected by structural evidence: shared changed files, or a closing/superseded reference.
- Pairwise link density `0.67`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Closed / duplicate issues

- #53178: \[Windows\] dashboard Projects-tree git probe (tui_gateway/git_probe.py run_git) flashes a console window per repo + crashes on non-ASCII paths (missing CREATE_NO_WINDOW + encoding)

## Prior & competing PRs

- **#54236: fix(windows): hide console-window flash on backend git/gh/wmic/bash subprocess spawns**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`
  - files: `agent/coding_context.py`, `agent/context_references.py`, `agent/shell_hooks.py`, `agent/skill_preprocessing.py`, `gateway/status.py`, `hermes_cli/copilot_auth.py`, `hermes_cli/gateway.py`, `hermes_cli/main.py`, `tests/gateway/test_status.py`, `tests/test_windows_subprocess_no_window_flags.py`, `tui_gateway/git_probe.py`, `tui_gateway/server.py`
  - fix hunks:
  - `agent/coding_context.py`

    ```diff
    @@ -60,6 +60,8 @@
     from pathlib import Path
     from typing import Any, Optional
     
    +from hermes_cli._subprocess_compat import IS_WINDOWS, windows_hide_flags
    +
     logger = logging.getLogger("hermes.coding_context")
     
     CODING_TOOLSET = "coding"
    ```

    ```diff
    @@ -647,12 +649,14 @@ def _enabled_mcp_servers(config: Optional[dict[str, Any]]) -> list[str]:
     
     
     def _git(cwd: Path, *args: str) -> str:
    +    _popen_kwargs = {"creationflags": windows_hide_flags()} if IS_WINDOWS else {}
         try:
             out = subprocess.run(
                 ["git", "-C", str(cwd), *args],
                 capture_output=True,
                 text=True,
                 timeout=_GIT_TIMEOUT,
    +            **_popen_kwargs,
             )
         except (OSError, subprocess.SubprocessError):
             return ""
    ```
  - `agent/context_references.py`

    ```diff
    @@ -12,6 +12,7 @@
     from typing import Awaitable, Callable
     
     from agent.model_metadata import estimate_tokens_rough
    +from hermes_cli._subprocess_compat import IS_WINDOWS, windows_hide_flags
     
     _QUOTED_REFERENCE_VALUE = r'(?:`[^`\n]+`|"[^"\n]+"|\'[^\'\n]+\')'
     REFERENCE_PATTERN = re.compile(
    ```

    ```diff
    @@ -290,6 +291,7 @@ def _expand_git_reference(
         args: list[str],
         label: str,
     ) -> tuple[str | None, str | None]:
    +    _popen_kwargs = {"creationflags": windows_hide_flags()} if IS_WINDOWS else {}
         try:
             result = subprocess.run(
                 ["git", *args],
    ```

    ```diff
    @@ -298,6 +300,7 @@ def _expand_git_reference(
                 text=True,
                 timeout=30,
                 stdin=subprocess.DEVNULL,
    +            **_popen_kwargs,
             )
         except subprocess.TimeoutExpired:
             return f"{ref.raw}: git command timed out (30s)", None
    ```

    ```diff
    @@ -483,6 +486,7 @@ def _iter_visible_entries(path: Path, cwd: Path, limit: int) -> list[Path]:
     
     
     def _rg_files(path: Path, cwd: Path, limit: int) -> list[Path] | None:
    +    _popen_kwargs = {"creationflags": windows_hide_flags()} if IS_WINDOWS else {}
         try:
             result = subprocess.run(
                 ["rg", "--files", str(path.relative_to(cwd))],
    ```

    ```diff
    @@ -491,6 +495,7 @@ def _rg_files(path: Path, cwd: Path, limit: int) -> list[Path] | None:
                 text=True,
                 timeout=10,
                 stdin=subprocess.DEVNULL,
    +            **_popen_kwargs,
             )
         except (FileNotFoundError, OSError, subprocess.TimeoutExpired):
             return None
    ```
  - `agent/shell_hooks.py`

    ```diff
    @@ -122,6 +122,8 @@
     from pathlib import Path
     from typing import Any, Callable, Dict, Iterator, List, Optional, Set, Tuple
     
    +from hermes_cli._subprocess_compat import IS_WINDOWS, windows_hide_flags
    +
     try:
         import fcntl  # POSIX only; Windows falls back to best-effort without flock.
     except ImportError:  # pragma: no cover
    ```

    ```diff
    @@ -441,6 +443,7 @@ def _spawn(spec: ShellHookSpec, stdin_json: str) -> Dict[str, Any]:
             return result
     
         t0 = time.monotonic()
    +    _popen_kwargs = {"creationflags": windows_hide_flags()} if IS_WINDOWS else {}
         try:
             proc = subprocess.run(
                 argv,
    ```

    ```diff
    @@ -449,6 +452,7 @@ def _spawn(spec: ShellHookSpec, stdin_json: str) -> Dict[str, Any]:
                 timeout=spec.timeout,
                 text=True,
                 shell=False,
    +            **_popen_kwargs,
             )
         except subprocess.TimeoutExpired:
             result["timed_out"] = True
    ```
  - `agent/skill_preprocessing.py`

    ```diff
    @@ -5,6 +5,8 @@
     import subprocess
     from pathlib import Path
     
    +from hermes_cli._subprocess_compat import IS_WINDOWS, windows_hide_flags
    +
     logger = logging.getLogger(__name__)
     
     # Matches ${HERMES_SKILL_DIR} / ${HERMES_SESSION_ID} tokens in SKILL.md.
    ```

    ```diff
    @@ -66,6 +68,7 @@ def run_inline_shell(command: str, cwd: Path | None, timeout: int) -> str:
         Failures return a short ``[inline-shell error: ...]`` marker instead of
         raising, so one bad snippet can't wreck the whole skill message.
         """
    +    _popen_kwargs = {"creationflags": windows_hide_flags()} if IS_WINDOWS else {}
         try:
             completed = subprocess.run(
                 ["bash", "-c", command],
    ```

    ```diff
    @@ -75,6 +78,7 @@ def run_inline_shell(command: str, cwd: Path | None, timeout: int) -> str:
                 timeout=max(1, int(timeout)),
                 check=False,
                 stdin=subprocess.DEVNULL,
    +            **_popen_kwargs,
             )
         except subprocess.TimeoutExpired:
             return f"[inline-shell timeout after {timeout}s: {command}]"
    ```
  - `gateway/status.py`

    ```diff
    @@ -81,12 +81,18 @@ def terminate_pid(pid: int, *, force: bool = False) -> None:
         because os.kill(..., SIGTERM) is not equivalent to a tree-killing hard stop.
         """
         if force and _IS_WINDOWS:
    +        # CREATE_NO_WINDOW: terminate_pid runs from the windowless pythonw.exe
    +        # gateway/desktop backend, so a bare taskkill spawn would flash a
    +        # conhost window on every force-kill.
    +        from hermes_cli._subprocess_compat import windows_hide_flags
    +
             try:
                 result = subprocess.run(
                     ["taskkill", "/PID", str(pid), "/T", "/F"],
                     capture_output=True,
                     text=True,
                     timeout=10,
    +                creationflags=windows_hide_flags(),
                 )
             except FileNotFoundError:
                 os.kill(pid, signal.SIGTERM)
    ```
  - `hermes_cli/copilot_auth.py`

    ```diff
    @@ -27,6 +27,8 @@
     from pathlib import Path
     from typing import Optional
     
    +from hermes_cli._subprocess_compat import IS_WINDOWS, windows_hide_flags
    +
     logger = logging.getLogger(__name__)
     
     # OAuth device code flow constants (same client ID as opencode/Copilot CLI)
    ```

    ```diff
    @@ -130,6 +132,7 @@ def _try_gh_cli_token() -> Optional[str]:
         clean_env = {k: v for k, v in os.environ.items()
                      if k not in {"GITHUB_TOKEN", "GH_TOKEN"}}
     
    +    _popen_kwargs = {"creationflags": windows_hide_flags()} if IS_WINDOWS else {}
         for gh_path in _gh_cli_candidates():
             cmd = [gh_path, "auth", "token"]
             if hostname:
    ```

    ```diff
    @@ -141,6 +144,7 @@ def _try_gh_cli_token() -> Optional[str]:
                     text=True,
                     timeout=5,
                     env=clean_env,
    +                **_popen_kwargs,
                 )
             except (FileNotFoundError, subprocess.TimeoutExpired) as exc:
                 logger.debug("gh CLI token lookup failed (%s): %s", gh_path, exc)
    ```
  - `hermes_cli/gateway.py`

    ```diff
    @@ -384,6 +384,12 @@ def _matches_gateway_runtime(command: str) -> bool:
                 # removed as part of the WMIC deprecation — fall back to
                 # PowerShell's Get-CimInstance.  Any OSError here (FileNotFoundError
                 # on missing wmic) trips the fallback.
    +            # Hide the console window: this scan runs inside the windowless
    +            # pythonw.exe gateway/desktop backend, so a bare wmic/powershell
    +            # spawn would flash a conhost window on every watchdog probe.
    +            from hermes_cli._subprocess_compat import windows_hide_flags
    +
    +            _no_window = {"creationflags": windows_hide_flags()}
                 wmic_path = shutil.which("wmic")
                 used_fallback = False
                 result = None
    ```

    ```diff
    @@ -402,6 +408,7 @@ def _matches_gateway_runtime(command: str) -> bool:
                             encoding="utf-8",
                             errors="ignore",
                             timeout=10,
    +                        **_no_window,
                         )
                     except (OSError, subprocess.TimeoutExpired):
                         result = None
    ```

    ```diff
    @@ -427,6 +434,7 @@ def _matches_gateway_runtime(command: str) -> bool:
                             encoding="utf-8",
                             errors="ignore",
                             timeout=15,
    +                        **_no_window,
                         )
                     except (OSError, subprocess.TimeoutExpired):
                         return []
    ```
  - `hermes_cli/main.py`

    ```diff
    @@ -5825,6 +5825,11 @@ def _find_stale_dashboard_pids(
                 # here is errors="ignore": it prevents a reader-thread
                 # UnicodeDecodeError from leaving result.stdout=None and turning
                 # the later .split() into an AttributeError (#17049).
    +            # CREATE_NO_WINDOW hides the conhost flash: this scan can run from
    +            # the windowless pythonw.exe desktop/gateway backend during an
    +            # update, where a bare wmic spawn would pop a console window.
    +            from hermes_cli._subprocess_compat import windows_hide_flags
    +
                 result = subprocess.run(
                     ["wmic", "process", "get", "ProcessId,CommandLine", "/FORMAT:LIST"],
                     capture_output=True,
    ```

    ```diff
    @@ -5832,6 +5837,7 @@ def _find_stale_dashboard_pids(
                     timeout=10,
                     encoding="utf-8",
                     errors="ignore",
    +                creationflags=windows_hide_flags(),
                 )
                 if result.returncode != 0 or result.stdout is None:
                     return []
    ```
  - `tests/gateway/test_status.py`

    ```diff
    @@ -621,16 +621,22 @@ def test_force_uses_taskkill_on_windows(self, monkeypatch):
             calls = []
             monkeypatch.setattr(status, "_IS_WINDOWS", True)
     
    -        def fake_run(cmd, capture_output=False, text=False, timeout=None):
    -            calls.append((cmd, capture_output, text, timeout))
    +        def fake_run(cmd, capture_output=False, text=False, timeout=None, creationflags=0):
    +            calls.append((cmd, capture_output, text, timeout, creationflags))
                 return SimpleNamespace(returncode=0, stdout="", stderr="")
     
             monkeypatch.setattr(status.subprocess, "run", fake_run)
     
             status.terminate_pid(123, force=True)
     
    +        # taskkill is spawned with the no-window flag so the windowless
    +        # pythonw.exe backend doesn't flash a conhost window on force-kill.
    +        # windows_hide_flags() is 0 on the POSIX test host (a valid no-op
    +        # creationflags value); on real Windows it is CREATE_NO_WINDOW.
    +        from hermes_cli._subprocess_compat import windows_hide_flags
    +
             assert calls == [
    -            (["taskkill", "/PID", "123", "/T", "/F"], True, True, 10)
    +            (["taskkill", "/PID", "123", "/T", "/F"], True, True, 10, windows_hide_flags())
             ]
     
         def test_force_falls_back_to_sigterm_when_taskkill_missing(self, monkeypatch):
    ```
  - `tests/test_windows_subprocess_no_window_flags.py`

    ```diff
    @@ -0,0 +1,263 @@
    +from __future__ import annotations
    +
    +import subprocess
    +from pathlib import Path
    +from types import SimpleNamespace
    +
    +
    +_CREATE_NO_WINDOW = 0x08000000
    +
    +
    +class _Completed:
    +    def __init__(self, stdout: str | bytes = "ok\n", returncode: int = 0):
    +        self.stdout = stdout
    +        self.stderr = ""
    +        self.returncode = returncode
    +
    +
    +def test_tui_gateway_git_probe_hides_git_windows(monkeypatch):
    +    from tui_gateway import git_probe
    +
    +    captured = []
    +
    +    def fake_run(cmd, **kwargs):
    +        captured.append((cmd, kwargs))
    +        return _Completed(stdout="main\n")
    +
    +    monkeypatch.setattr(git_probe, "IS_WINDOWS", True)
    +    monkeypatch.setattr(git_probe, "windows_hide_flags", lambda: _CREATE_NO_WINDOW)
    +    monkeypatch.setattr(git_probe.subprocess, "run", fake_run)
    +
    +    assert git_probe.run_git("C:/repo", "branch", "--show-current") == "main"
    +
    +    assert captured == [
    +        (
    +            ["git", "-C", "C:/repo", "branch", "--show-current"],
    +            {
    +                "capture_output": True,
    +                "text": True,
    +                "encoding": "utf-8",
    +                "errors": "replace",
    +                "timeout": git_probe._GIT_TIMEOUT,
    +                "check": False,
    +                "stdin": subprocess.DEVNULL,
    +                "creationflags": _CREATE_NO_WINDOW,
    +            },
    +        )
    +    ]
    +
    +
    +def test_tui_gateway_fuzzy_file_listing_hides_git_windows(monkeypatch):
    +    from hermes_cli import _subprocess_compat
    +    from tui_gateway import server
    +
    +    captured = []
    +
    +    def fake_run(cmd, **kwargs):
    +        captured.append((cmd, kwargs))
    +        if cmd[-1] == "--show-toplevel":
    +            return _Completed(stdout=b"C:/repo\n")
    +        return _Completed(stdout=b"src/main.py\0README.md\0")
    +
    +    monkeypatch.setattr(_subprocess_compat, "IS_WINDOWS", True)
    +    monkeypatch.setattr(_subprocess_compat, "windows_hide_flags", lambda: _CREATE_NO_WINDOW)
    +    monkeypatch.setattr(server.subprocess, "run", fake_run)
    +    server._fuzzy_cache.clear()
    +
    +    assert server._list_repo_files("C:/repo") == ["src/main.py", "README.md"]
    +
    +    assert [kwargs["creationflags"] for _, kwargs in captured] == [
    +        _CREATE_NO_WINDOW,
    +        _CREATE_NO_WINDOW,
    +    ]
    +
    +
    +def test_coding_context_git_hides_git_windows(monkeypatch):
    +    from agent import coding_context
    +
    +    captured = []
    +
    +    def fake_run(cmd, **kwargs):
    +        captured.append((cmd, kwargs))
    +        return _Completed(stdout="clean\n")
    +
    +    monkeypatch.setattr(coding_context, "IS_WINDOWS", True)
    +    monkeypatch.setattr(coding_context, "windows_hide_flags", lambda: _CREATE_NO_WINDOW)
    +    monkeypatch.setattr(coding_context.subprocess, "run", fake_run)
    +
    +    assert coding_context._git(Path("C:/repo"), "status", "--short") == "clean"
    +    assert captured[0][1]["creationflags"] == _CREATE_NO_WINDOW
    +
    +
    +def test_context_reference_git_and_rg_hide_windows(monkeypatch):
    +    from agent import context_references
    +
    +    captured = []
    +
    +    def fake_run(cmd, **kwargs):
    +        captured.append((cmd, kwargs))
    +        if cmd[0] == "rg":
    +            return _Completed(stdout="src/main.py\n")
    +        return _Completed(stdout="diff --git a/src/main.py b/src/main.py\n")
    +
    +    monkeypatch.setattr(context_references, "IS_WINDOWS", True)
    +    monkeypatch.setattr(context_references, "windows_hide_flags", lambda: _CREATE_NO_WINDOW)
    +    monkeypatch.setattr(context_references.subprocess, "run", fake_run)
    +
    +    ref = context_references.ContextReference(
    +        raw="@diff",
    +        kind="diff",
    +        target="",
    +        start=0,
    +        end=5,
    +    )
    +    warning, block = context_references._expand_git_reference(
    +        ref,
    +        Path("C:/repo"),
    +        ["diff"],
    +        "git diff",
    +    )
    +    assert warning is None
    +    assert block is not None
    +    assert "git diff" in block
    +    assert context_references._rg_files(Path("C:/repo/src"), Path("C:/repo"), 10) == [
    +        Path("src/main.py")
    +    ]
    +
    +    assert [kwargs["creationflags"] for _, kwargs in captured] == [
    +        _CREATE_NO_WINDOW,
    +        _CREATE_NO_WINDOW,
    +    ]
    +
    +
    +def test_copilot_gh_cli_probe_hides_gh_windows(monkeypatch):
    +    from hermes_cli import copilot_auth
    +
    +    captured = []
    +
    +    def fake_run(cmd, **kwargs):
    +        captured.append((cmd, kwargs))
    +        return _Completed(stdout="gho_from_cli\n")
    +
    +    monkeypatch.setattr(copilot_auth, "IS_WINDOWS", True)
    +    monkeypatch.setattr(copilot_auth, "windows_hide_flags", lambda: _CREATE_NO_WINDOW)
    +    monkeypatch.setattr(copilot_auth, "_gh_cli_candidates", lambda: ["gh"])
    +    monkeypatch.setattr(copilot_auth.subprocess, "run", fake_run)
    +
    +    assert copilot_auth._try_gh_cli_token() == "gho_from_cli"
    +    assert captured[0][0] == ["gh", "auth", "token"]
    +    assert captured[0][1]["creationflags"] == _CREATE_NO_WINDOW
    +
    +
    +def test_gateway_pid_scan_hides_wmic_and_powershell_windows(monkeypatch):
    +    from hermes_cli import gateway
    +    from hermes_cli import _subprocess_compat
    +
    +    captured = []
    +
    +    def fake_run(cmd, **kwargs):
    +        captured.append((cmd, kwargs))
    +        if cmd[0] == "wmic":
    +            return _Completed(stdout="", returncode=1)
    +        return _Completed(stdout="CommandLine=hermes gateway\nProcessId=123\n")
    +
    +    monkeypatch.setattr(gateway, "is_windows", lambda: True)
    +    monkeypatch.setattr(gateway.shutil, "which", lambda name: name)
    +    monkeypatch.setattr(_subprocess_compat, "IS_WINDOWS", True)
    +    monkeypatch.setattr(_subprocess_compat, "windows_hide_flags", lambda: _CREATE_NO_WINDOW)
    +    monkeypatch.setattr(gateway.subprocess, "run", fake_run)
    +
    +    assert gateway._scan_gateway_pids(set()) == [123]
    +    assert [kwargs["creationflags"] for _, kwargs in captured] == [
    +        _CREATE_NO_WINDOW,
    +        _CREATE_NO_WINDOW,
    +    ]
    +
    +
    +def test_stale_dashboard_windows_scan_hides_wmic(monkeypatch):
    +    from hermes_cli import main
    +    from hermes_cli import _subprocess_compat
    +
    +    captured = []
    +
    +    def fake_run(cmd, **kwargs):
    +        captured.append((cmd, kwargs))
    +        return _Completed(stdout="CommandLine=hermes dashboard\nProcessId=123\n")
    +
    +    monkeypatch.setattr(main.sys, "platform", "win32")
    +    monkeypatch.setattr(_subprocess_compat, "IS_WINDOWS", True)
    +    monkeypatch.setattr(_subprocess_compat, "windows_hide_flags", lambda: _CREATE_NO_WINDOW)
    +    monkeypatch.setattr(main.subprocess, "run", fake_run)
    +
    +    assert main._find_stale_dashboard_pids() == [123]
    +    assert captured[0][1]["creationflags"] == _CREATE_NO_WINDOW
    +
    +
    +def test_gateway_force_kill_hides_taskkill_window(monkeypatch):
    +    from gateway import status
    +    from hermes_cli import _subprocess_compat
    +
    +    captured = []
    +
    +    def fake_run(cmd, **kwargs):
    +        captured.append((cmd, kwargs))
    +        return _Completed(stdout="")
    +
    +    monkeypatch.setattr(status, "_IS_WINDOWS", True)
    +    monkeypatch.setattr(_subprocess_compat, "IS_WINDOWS", True)
    +    monkeypatch.setattr(_subprocess_compat, "windows_hide_flags", lambda: _CREATE_NO_WINDOW)
    +    monkeypatch.setattr(status.subprocess, "run", fake_run)
    +
    +    status.terminate_pid(123, force=True)
    +
    +    assert captured == [
    +        (
    +            ["taskkill", "/PID", "123", "/T", "/F"],
    +            {
    +                "capture_output": True,
    +                "text": True,
    +                "timeout": 10,
    +                "creationflags": _CREATE_NO_WINDOW,
    +            },
    +        )
    +    ]
    +
    +
    +def test_shell_hooks_hide_hook_command_windows(monkeypatch):
    +    from agent import shell_hooks
    +
    +    captured = []
    +
    +    def fake_run(cmd, **kwargs):
    +        captured.append((cmd, kwargs))
    +        return SimpleNamespace(returncode=0, stdout="{}", stderr="")
    +
    +    monkeypatch.setattr(shell_hooks, "IS_WINDOWS", True)
    +    monkeypatch.setattr(shell_hooks, "windows_hide_flags", lambda: _CREATE_NO_WINDOW)
    +    monkeypatch.setattr(shell_hooks.subprocess, "run", fake_run)
    +
    +    result = shell_hooks._spawn(
    +        shell_hooks.ShellHookSpec(event="post_tool_call", command="hook-bin --flag"),
    +        "{}",
    +    )
    +
    +    assert result["returncode"] == 0
    +    assert captured[0][1]["creationflags"] == _CREATE_NO_WINDOW
    +
    +
    +def test_inline_skill_shell_hides_bash_window(monkeypatch):
    +    from agent import skill_preprocessing
    +
    +    captured = []
    +
    +    def fake_run(cmd, **kwargs):
    +        captured.append((cmd, kwargs))
    +        return SimpleNamespace(returncode=0, stdout="ok\n", stderr="")
    +
    +    monkeypatch.setattr(skill_preprocessing, "IS_WINDOWS", True)
    +    monkeypatch.setattr(skill_preprocessing, "windows_hide_flags", lambda: _CREATE_NO_WINDOW)
    +    monkeypatch.setattr(skill_preprocessing.subprocess, "run", fake_run)
    +
    +    assert skill_preprocessing.run_inline_shell("echo ok", cwd=None, timeout=5) == "ok"
    +    assert captured[0][0] == ["bash", "-c", "echo ok"]
    +    assert captured[0][1]["creationflags"] == _CREATE_NO_WINDOW
    ```
  - `tui_gateway/git_probe.py`

    ```diff
    @@ -31,6 +31,8 @@
     from collections.abc import Iterable
     from concurrent.futures import ThreadPoolExecutor
     
    +from hermes_cli._subprocess_compat import IS_WINDOWS, windows_hide_flags
    +
     _GIT_TIMEOUT = 1.5
     _WARM_WORKERS = 8
     
    ```

    ```diff
    @@ -45,14 +47,18 @@ def run_git(cwd: str, *args: str) -> str:
         """``git -C <cwd> <args>`` → stripped stdout, or ``""`` on any failure."""
         if not cwd:
             return ""
    +    _popen_kwargs = {"creationflags": windows_hide_flags()} if IS_WINDOWS else {}
         try:
             result = subprocess.run(
                 ["git", "-C", cwd, *args],
                 capture_output=True,
                 text=True,
    +            encoding="utf-8",
    +            errors="replace",
                 timeout=_GIT_TIMEOUT,
                 check=False,
                 stdin=subprocess.DEVNULL,
    +            **_popen_kwargs,
             )
             return result.stdout.strip() if result.returncode == 0 else ""
         except Exception:
    ```
  - `tui_gateway/server.py`

    ```diff
    @@ -11668,6 +11668,9 @@ def _list_repo_files(root: str) -> list[str]:
                 return cached[1]
     
         files: list[str] = []
    +    from hermes_cli._subprocess_compat import windows_hide_flags
    +
    +    _creationflags = windows_hide_flags()
         try:
             top_result = subprocess.run(
                 ["git", "-C", root, "rev-parse", "--show-toplevel"],
    ```

    ```diff
    @@ -11675,6 +11678,7 @@ def _list_repo_files(root: str) -> list[str]:
                 timeout=2.0,
                 check=False,
                 stdin=subprocess.DEVNULL,
    +            creationflags=_creationflags,
             )
             if top_result.returncode == 0:
                 top = top_result.stdout.decode("utf-8", "replace").strip()
    ```

    ```diff
    @@ -11693,6 +11697,7 @@ def _list_repo_files(root: str) -> list[str]:
                     timeout=2.0,
                     check=False,
                     stdin=subprocess.DEVNULL,
    +                creationflags=_creationflags,
                 )
                 if list_result.returncode == 0:
                     for p in list_result.stdout.decode("utf-8", "replace").split("\0"):
    ```
- **#53184: fix(windows): suppress git-probe console flash + cp950 crash in dashboard**. closed without merge
  - maintainer direction: category `superseded_by_pr`; implication `superseded`; refs `#54220`, `#54236`, `#53892`, `#54417`

## Fix status

- Merged to main in PR #54236 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-06-28`.
- Subsystem: `dashboard`
