{"repo":"NousResearch/hermes-agent","public_id":"56147","display_label":"MSYS path conversion breaking Windows terminal commands","summary":"These issues and pull requests address MSYS/Git Bash argv path conversion mangling arguments like '/c' before they reach native Windows commands such as cmd.exe. Proposed fixes involve disabling or excluding MSYS path conversion for affected subprocesses on Windows.","subsystem":"environments","counts":{"members":6,"open_issues":0,"open_issues_distinct":0,"open_prs":0,"closed_issues":2,"merged_prs":1,"attempt_prs":3},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":57006},"resolution":{"state":"partially_resolved","by":"pr-57006"},"freshness":{"state":"verified","last_verified_at":"2026-07-02T18:48:04+00:00","is_stale":false},"grouping":{"backbone":"STRUCTURAL_SPANNING","link_density":0.35733333333333334},"fix_edges":[{"issue_number":56147,"pr_number":57006,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false},{"issue_number":56700,"pr_number":57006,"tier":"verified","basis":"closing_ref","confidence":0.95,"recoverable_from_timeline":true}],"members":[{"kind":"issue","number":56147,"title":"[Bug]: GUI launch commands on Windows say exit_code: 0 but never actually open anything (Git Bash/MSYS rewriting /c before cmd.exe gets it)","url":null,"state":"closed"},{"kind":"issue","number":56700,"title":"Windows terminal: MSYS path mangling breaks native commands (tasklist, schtasks, wmic)","url":null,"state":"closed"},{"kind":"pr","number":56228,"title":"fix(env): inject MSYS2_ARG_CONV_EXCL=/c on Windows to prevent cmd /c silent failure","url":null,"state":"closed","close_reason":{"refs":[{"kind":"commit","value":"a2d49de80","number":0},{"kind":"pr","value":"#57006","number":57006},{"kind":"pr","value":"#56147","number":56147}],"category":"superseded_by_pr","implication":"superseded"},"merged":false},{"kind":"pr","number":56734,"title":"fix(terminal): disable MSYS path conversion on Windows","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#56705","number":56705},{"kind":"pr","value":"#56700","number":56700},{"kind":"pr","value":"#56705","number":56705}],"category":"duplicate_of","implication":"duplicate"},"merged":false},{"kind":"pr","number":56783,"title":"fix(terminal): keep cmd /c from being rewritten by MSYS on Windows (#56147)","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#56228","number":56228},{"kind":"pr","value":"#56147","number":56147}],"category":"uncategorized","implication":"needs_llm"},"merged":false,"is_fix_pr":true,"fix_tier":"suggested","fix_detail_withheld":true},{"kind":"pr","number":57006,"title":"fix(terminal): disable MSYS argv path conversion for Windows bash subprocesses","url":null,"state":"merged","close_reason":{"category":"merged","implication":"superseded"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["tests/tools/test_local_env_windows_msys.py","tools/environments/local.py"],"fix_hunks":[{"file":"tests/tools/test_local_env_windows_msys.py","hunks":["@@ -24,9 +24,12 @@\n from tools.environments import local as local_mod\n from tools.environments.local import (\n     LocalEnvironment,\n+    _make_run_env,\n     _msys_to_windows_path,\n     _resolve_safe_cwd,\n+    _sanitize_subprocess_env,\n     _windows_to_msys_path,\n+    hermes_subprocess_env,\n )\n \n ","@@ -228,6 +231,53 @@ def test_valid_msys_marker_normalized_to_native(self, monkeypatch, tmp_path):\n         assert env.cwd == str(new_dir)\n \n \n+# ---------------------------------------------------------------------------\n+# MSYS_NO_PATHCONV — native Windows command flags (#56700)\n+# ---------------------------------------------------------------------------\n+\n+class TestWindowsMsysPathconvDefaults:\n+    def test_make_run_env_sets_msys_no_pathconv_on_windows(self, monkeypatch):\n+        monkeypatch.setattr(local_mod, \"_IS_WINDOWS\", True)\n+        run_env = _make_run_env({})\n+        assert run_env.get(\"MSYS_NO_PATHCONV\") == \"1\"\n+\n+    def test_sanitize_subprocess_env_sets_msys_no_pathconv_on_windows(self, monkeypatch):\n+        monkeypatch.setattr(local_mod, \"_IS_WINDOWS\", True)\n+        env = _sanitize_subprocess_env({})\n+        assert env.get(\"MSYS_NO_PATHCONV\") == \"1\"\n+\n+    def test_hermes_subprocess_env_sets_msys_no_pathconv_on_windows(self, monkeypatch):\n+        monkeypatch.setattr(local_mod, \"_IS_WINDOWS\", True)\n+        env = hermes_subprocess_env()\n+        assert env.get(\"MSYS_NO_PATHCONV\") == \"1\"\n+\n+    def test_no_pathconv_not_set_on_posix(self, monkeypatch):\n+        monkeypatch.setattr(local_mod, \"_IS_WINDOWS\", False)\n+        assert \"MSYS_NO_PATHCONV\" not in _make_run_env({})\n+\n+    def test_respects_user_override(self, monkeypatch):\n+        monkeypatch.setattr(local_mod, \"_IS_WINDOWS\", True)\n+        run_env = _make_run_env({\"MSYS_NO_PATHCONV\": \"0\"})\n+        assert run_env.get(\"MSYS_NO_PATHCONV\") == \"0\"\n+\n+    def test_msys2_arg_conv_excl_set_on_windows(self, monkeypatch):\n+        # MSYS2-proper / Cygwin bash ignore MSYS_NO_PATHCONV; they honor\n+        # MSYS2_ARG_CONV_EXCL. Both must be set on every env builder.\n+        monkeypatch.setattr(local_mod, \"_IS_WINDOWS\", True)\n+        assert _make_run_env({}).get(\"MSYS2_ARG_CONV_EXCL\") == \"*\"\n+        assert _sanitize_subprocess_env({}).get(\"MSYS2_ARG_CONV_EXCL\") == \"*\"\n+        assert hermes_subprocess_env().get(\"MSYS2_ARG_CONV_EXCL\") == \"*\"\n+\n+    def test_msys2_arg_conv_excl_not_set_on_posix(self, monkeypatch):\n+        monkeypatch.setattr(local_mod, \"_IS_WINDOWS\", False)\n+        assert \"MSYS2_ARG_CONV_EXCL\" not in _make_run_env({})\n+\n+    def test_msys2_arg_conv_excl_respects_user_override(self, monkeypatch):\n+        monkeypatch.setattr(local_mod, \"_IS_WINDOWS\", True)\n+        run_env = _make_run_env({\"MSYS2_ARG_CONV_EXCL\": \"/custom\"})\n+        assert run_env.get(\"MSYS2_ARG_CONV_EXCL\") == \"/custom\"\n+\n+\n # ---------------------------------------------------------------------------\n # Command wrapping — native Windows cwd must be Git Bash-friendly for cd\n # ---------------------------------------------------------------------------"]},{"file":"tools/environments/local.py","hunks":["@@ -383,6 +383,8 @@ def _sanitize_subprocess_env(base_env: dict | None, extra_env: dict | None = Non\n     for _marker in _ACTIVE_VENV_MARKER_VARS:\n         sanitized.pop(_marker, None)\n \n+    _apply_windows_msys_bash_env_defaults(sanitized)\n+\n     return sanitized\n \n ","@@ -493,6 +495,8 @@ def hermes_subprocess_env(*, inherit_credentials: bool = False) -> dict[str, str\n     for _marker in _ACTIVE_VENV_MARKER_VARS:\n         env.pop(_marker, None)\n \n+    _apply_windows_msys_bash_env_defaults(env)\n+\n     # Cross-session leak guard, same as the terminal spawn paths: this helper\n     # copies os.environ, whose HERMES_SESSION_* mirror is a last-writer-wins\n     # global under a concurrent multi-session host. A caller that re-binds the","@@ -746,6 +750,29 @@ def _append_missing_sane_path_entries(existing_path: str) -> str:\n     return \":\".join(ordered_entries)\n \n \n+def _apply_windows_msys_bash_env_defaults(env: dict) -> None:\n+    \"\"\"Disable MSYS argument path conversion for Git Bash subprocesses.\n+\n+    Git Bash rewrites arguments that look like Unix paths (``/FO``, ``/TN``,\n+    ``/Create``) into ``C:/.../git/FO``-style paths, which breaks native\n+    Windows commands such as ``tasklist``, ``schtasks``, and ``wmic``.  Hermes\n+    runs terminal commands through bash on Windows, so set the standard MSYS\n+    opt-out by default.  Users who need conversion can override in their env.\n+    Refs #56700.\n+\n+    ``MSYS_NO_PATHCONV`` is honored by Git for Windows bash only.  MSYS2-proper\n+    and Cygwin bash (which ``_find_bash`` can still return via the final\n+    ``shutil.which`` fallback) ignore it and honor ``MSYS2_ARG_CONV_EXCL``\n+    instead, so set both.  ``*`` disables all argv conversion — the semantic\n+    equivalent of ``MSYS_NO_PATHCONV=1``.  Also fixes ``cmd /c`` mangling\n+    (#56147).\n+    \"\"\"\n+    if not _IS_WINDOWS:\n+        return\n+    env.setdefault(\"MSYS_NO_PATHCONV\", \"1\")\n+    env.setdefault(\"MSYS2_ARG_CONV_EXCL\", \"*\")\n+\n+\n def _path_env_key(run_env: dict) -> str | None:\n     \"\"\"Return the PATH env key to update without altering Windows casing.\n ","@@ -804,6 +831,8 @@ def _make_run_env(env: dict) -> dict:\n     for _marker in _ACTIVE_VENV_MARKER_VARS:\n         run_env.pop(_marker, None)\n \n+    _apply_windows_msys_bash_env_defaults(run_env)\n+\n     return run_env\n \n \n"]}]}],"trust":{"default_tier":"verified","includes_suggested":false}}