# NousResearch/hermes-agent · MSYS path conversion breaking Windows terminal commands

## Open now

- Nothing open on GitHub.

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.

## TL;DR

- 6 member(s): 0 open issue(s), 2 closed issue(s), 0 open PR(s), 1 merged PR(s), 3 PR(s) closed without merging.
- A fix was merged to main in PR #57006. Verify it addresses your case.
- **Recommended:** read PR #57006 (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: `partially_resolved` · deciding PR(s): `pr-57006`. 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.36`: 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

- #56147: \[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)
- #56700: Windows terminal: MSYS path mangling breaks native commands (tasklist, schtasks, wmic)

## Prior & competing PRs

- **#56783: fix(terminal): keep cmd /c from being rewritten by MSYS on Windows (#56147)**. closed without merge · fix tier `suggested`
  - maintainer direction: category `uncategorized`; implication `needs_llm`; refs `#56228`, `#56147`
- **#57006: fix(terminal): disable MSYS argv path conversion for Windows bash subprocesses**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `tests/tools/test_local_env_windows_msys.py`, `tools/environments/local.py`
  - fix hunks:
  - `tests/tools/test_local_env_windows_msys.py`

    ```diff
    @@ -24,9 +24,12 @@
     from tools.environments import local as local_mod
     from tools.environments.local import (
         LocalEnvironment,
    +    _make_run_env,
         _msys_to_windows_path,
         _resolve_safe_cwd,
    +    _sanitize_subprocess_env,
         _windows_to_msys_path,
    +    hermes_subprocess_env,
     )
     
     
    ```

    ```diff
    @@ -228,6 +231,53 @@ def test_valid_msys_marker_normalized_to_native(self, monkeypatch, tmp_path):
             assert env.cwd == str(new_dir)
     
     
    +# ---------------------------------------------------------------------------
    +# MSYS_NO_PATHCONV — native Windows command flags (#56700)
    +# ---------------------------------------------------------------------------
    +
    +class TestWindowsMsysPathconvDefaults:
    +    def test_make_run_env_sets_msys_no_pathconv_on_windows(self, monkeypatch):
    +        monkeypatch.setattr(local_mod, "_IS_WINDOWS", True)
    +        run_env = _make_run_env({})
    +        assert run_env.get("MSYS_NO_PATHCONV") == "1"
    +
    +    def test_sanitize_subprocess_env_sets_msys_no_pathconv_on_windows(self, monkeypatch):
    +        monkeypatch.setattr(local_mod, "_IS_WINDOWS", True)
    +        env = _sanitize_subprocess_env({})
    +        assert env.get("MSYS_NO_PATHCONV") == "1"
    +
    +    def test_hermes_subprocess_env_sets_msys_no_pathconv_on_windows(self, monkeypatch):
    +        monkeypatch.setattr(local_mod, "_IS_WINDOWS", True)
    +        env = hermes_subprocess_env()
    +        assert env.get("MSYS_NO_PATHCONV") == "1"
    +
    +    def test_no_pathconv_not_set_on_posix(self, monkeypatch):
    +        monkeypatch.setattr(local_mod, "_IS_WINDOWS", False)
    +        assert "MSYS_NO_PATHCONV" not in _make_run_env({})
    +
    +    def test_respects_user_override(self, monkeypatch):
    +        monkeypatch.setattr(local_mod, "_IS_WINDOWS", True)
    +        run_env = _make_run_env({"MSYS_NO_PATHCONV": "0"})
    +        assert run_env.get("MSYS_NO_PATHCONV") == "0"
    +
    +    def test_msys2_arg_conv_excl_set_on_windows(self, monkeypatch):
    +        # MSYS2-proper / Cygwin bash ignore MSYS_NO_PATHCONV; they honor
    +        # MSYS2_ARG_CONV_EXCL. Both must be set on every env builder.
    +        monkeypatch.setattr(local_mod, "_IS_WINDOWS", True)
    +        assert _make_run_env({}).get("MSYS2_ARG_CONV_EXCL") == "*"
    +        assert _sanitize_subprocess_env({}).get("MSYS2_ARG_CONV_EXCL") == "*"
    +        assert hermes_subprocess_env().get("MSYS2_ARG_CONV_EXCL") == "*"
    +
    +    def test_msys2_arg_conv_excl_not_set_on_posix(self, monkeypatch):
    +        monkeypatch.setattr(local_mod, "_IS_WINDOWS", False)
    +        assert "MSYS2_ARG_CONV_EXCL" not in _make_run_env({})
    +
    +    def test_msys2_arg_conv_excl_respects_user_override(self, monkeypatch):
    +        monkeypatch.setattr(local_mod, "_IS_WINDOWS", True)
    +        run_env = _make_run_env({"MSYS2_ARG_CONV_EXCL": "/custom"})
    +        assert run_env.get("MSYS2_ARG_CONV_EXCL") == "/custom"
    +
    +
     # ---------------------------------------------------------------------------
     # Command wrapping — native Windows cwd must be Git Bash-friendly for cd
     # ---------------------------------------------------------------------------
    ```
  - `tools/environments/local.py`

    ```diff
    @@ -383,6 +383,8 @@ def _sanitize_subprocess_env(base_env: dict | None, extra_env: dict | None = Non
         for _marker in _ACTIVE_VENV_MARKER_VARS:
             sanitized.pop(_marker, None)
     
    +    _apply_windows_msys_bash_env_defaults(sanitized)
    +
         return sanitized
     
     
    ```

    ```diff
    @@ -493,6 +495,8 @@ def hermes_subprocess_env(*, inherit_credentials: bool = False) -> dict[str, str
         for _marker in _ACTIVE_VENV_MARKER_VARS:
             env.pop(_marker, None)
     
    +    _apply_windows_msys_bash_env_defaults(env)
    +
         # Cross-session leak guard, same as the terminal spawn paths: this helper
         # copies os.environ, whose HERMES_SESSION_* mirror is a last-writer-wins
         # global under a concurrent multi-session host. A caller that re-binds the
    ```

    ```diff
    @@ -746,6 +750,29 @@ def _append_missing_sane_path_entries(existing_path: str) -> str:
         return ":".join(ordered_entries)
     
     
    +def _apply_windows_msys_bash_env_defaults(env: dict) -> None:
    +    """Disable MSYS argument path conversion for Git Bash subprocesses.
    +
    +    Git Bash rewrites arguments that look like Unix paths (``/FO``, ``/TN``,
    +    ``/Create``) into ``C:/.../git/FO``-style paths, which breaks native
    +    Windows commands such as ``tasklist``, ``schtasks``, and ``wmic``.  Hermes
    +    runs terminal commands through bash on Windows, so set the standard MSYS
    +    opt-out by default.  Users who need conversion can override in their env.
    +    Refs #56700.
    +
    +    ``MSYS_NO_PATHCONV`` is honored by Git for Windows bash only.  MSYS2-proper
    +    and Cygwin bash (which ``_find_bash`` can still return via the final
    +    ``shutil.which`` fallback) ignore it and honor ``MSYS2_ARG_CONV_EXCL``
    +    instead, so set both.  ``*`` disables all argv conversion — the semantic
    +    equivalent of ``MSYS_NO_PATHCONV=1``.  Also fixes ``cmd /c`` mangling
    +    (#56147).
    +    """
    +    if not _IS_WINDOWS:
    +        return
    +    env.setdefault("MSYS_NO_PATHCONV", "1")
    +    env.setdefault("MSYS2_ARG_CONV_EXCL", "*")
    +
    +
     def _path_env_key(run_env: dict) -> str | None:
         """Return the PATH env key to update without altering Windows casing.
     
    ```

    ```diff
    @@ -804,6 +831,8 @@ def _make_run_env(env: dict) -> dict:
         for _marker in _ACTIVE_VENV_MARKER_VARS:
             run_env.pop(_marker, None)
     
    +    _apply_windows_msys_bash_env_defaults(run_env)
    +
         return run_env
     
     
    ```
- **#56228: fix(env): inject MSYS2_ARG_CONV_EXCL=/c on Windows to prevent cmd /c silent failure**. closed without merge
  - maintainer direction: category `superseded_by_pr`; implication `superseded`; refs `a2d49de80`, `#57006`, `#56147`
- **#56734: fix(terminal): disable MSYS path conversion on Windows**. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#56705`, `#56700`, `#56705`

## Fix status

- Merged to main in PR #57006 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-07-02`.
- Subsystem: `environments`
