# NousResearch/hermes-agent · Installer marker files dirtying Git checkouts

## Open now

- Nothing open on GitHub.

These issues and PRs address installer- and bootstrap-created marker files (.install_method, .hermes-bootstrap-complete) that unintentionally dirty Git working directories, causing repeated autostash loops during updates. Fixes involve gitignoring the files and/or stopping their creation inside Git checkouts.

## TL;DR

- 9 member(s): 0 open issue(s), 2 closed issue(s), 0 open PR(s), 2 merged PR(s), 5 PR(s) closed without merging.
- A fix was merged to main in PR #39707. Verify it addresses your case.
- **Recommended:** read PR #39707 (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: `resolved` · deciding PR(s): `pr-39707,pr-67364`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_PARTIAL`): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text.
- Members outside that structural core may belong to a different underlying problem.
- Pairwise link density `0.20`: 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

- #38529: hermes update repeatedly autostashes Desktop bootstrap marker .hermes-bootstrap-complete
- #66189: \[Bug\]: Installer-created .install_method dirties Git checkouts

## Prior & competing PRs

- **#39707: fix(cli): gitignore Desktop bootstrap marker so hermes update stops autostashing it**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `.gitignore`, `scripts/release.py`, `tests/hermes_cli/test_update_autostash.py`
  - fix hunks:
  - `.gitignore`

    ```diff
    @@ -108,6 +108,12 @@ docs/superpowers/*
     # logs, and per-session caches are never artifacts of the codebase.
     .hermes/
     
    +# Desktop/bootstrap install marker written into the managed checkout root by the
    +# bootstrap installer. It is Hermes-managed runtime state, never a code change —
    +# ignore it so `hermes update`'s `git stash push --include-untracked` does not
    +# treat it as a local edit and autostash it on every run (#38529).
    +.hermes-bootstrap-complete
    +
     # Tool Search live-test harness output — non-deterministic model transcripts,
     # regenerated by scripts/tool_search_livetest.py. Never an artifact of the repo.
     scripts/out/
    ```
  - `scripts/release.py`

    ```diff
    @@ -45,6 +45,7 @@
     
     # Auto-extracted from noreply emails + manual overrides
     AUTHOR_MAP = {
    +    "[redacted:email]": "harjothkhara",
         "[redacted:email]": "HeLLGURD",
         "[redacted:email]": "dirtyren",
         "[redacted:email]": "zhaoleibd",
    ```
  - `tests/hermes_cli/test_update_autostash.py`

    ```diff
    @@ -819,3 +819,50 @@ def test_cmd_update_skips_stash_restore_when_reset_fails(monkeypatch, tmp_path,
     
         out = capsys.readouterr().out
         assert "preserved in stash" in out
    +
    +
    +def test_bootstrap_marker_not_autostashed_by_update(tmp_path):
    +    """#38529: the Desktop bootstrap marker must be git-ignored so that
    +    ``hermes update``'s ``git stash push --include-untracked`` does not sweep it
    +    into an autostash on every run.
    +
    +    Behavioral + hermetic: build a throwaway repo that adopts the project's real
    +    ``.gitignore`` (the contract under test), drop the marker, and confirm the
    +    same stash invocation the updater uses leaves it untouched.
    +    """
    +    import shutil
    +    import subprocess
    +
    +    if shutil.which("git") is None:
    +        pytest.skip("git not available")
    +
    +    repo_gitignore = Path(hermes_main.__file__).resolve().parents[1] / ".gitignore"
    +
    +    def git(*args):
    +        return subprocess.run(
    +            ["git", *args], cwd=tmp_path, capture_output=True, text=True, check=True
    +        )
    +
    +    git("init", "-q")
    +    git("config", "user.email", "[redacted:email]")
    +    git("config", "user.name", "t")
    +    (tmp_path / ".gitignore").write_text(repo_gitignore.read_text())
    +    (tmp_path / "tracked.txt").write_text("x\n")
    +    git("add", "-A")
    +    git("commit", "-qm", "init")
    +
    +    marker = tmp_path / ".hermes-bootstrap-complete"
    +    marker.write_text("")
    +
    +    # Exact flags used by hermes update (hermes_cli/main.py).
    +    git("stash", "push", "--include-untracked", "-m", "hermes-update-autostash")
    +
    +    assert marker.exists(), (
    +        ".hermes-bootstrap-complete was swept into the update autostash — it must "
    +        "be listed in .gitignore so `git stash -u` skips it (#38529)."
    +    )
    +    # It must not even register as a dirty/untracked change.
    +    status = subprocess.run(
    +        ["git", "status", "--porcelain"], cwd=tmp_path, capture_output=True, text=True
    +    ).stdout
    +    assert ".hermes-bootstrap-complete" not in status
    ```
- **#67364: chore(gitignore): ignore installer .install_method stamp (salvage of #54855)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `.gitignore`, `tests/hermes_cli/test_update_autostash.py`
- **#38550: fix(cli): gitignore Desktop bootstrap marker so hermes update stops autostashing it**. closed without merge
  - maintainer direction: category `silent_close`; implication `active`
- **#38555: fix(cli): ignore Desktop bootstrap marker to fix update stash loops**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `#38550`, `#38529`, `#38542`, `#38529`
- **#66216: fix: ignore installer-created .install_method runtime stamp (#66189)**. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#54855`, `#54855`
- **#66322: fix(cli): stop creating .install_method in Git checkout (#66189)**. closed without merge
  - maintainer direction: category `partial_fix`; implication `needs_llm`; refs `211edd5e08d5`, `48d8483250f5`, `#66189`, `#66322`, `#67364`, `#67364`, `#67364`, `#54855`, `#67364`, `#66216`, `#54855`, `#66322`, `#67364`, `#66723`, `#54855`, `#67364`, `#54855`, `#66189`, `#54855`, `#66216`, `#66322`, `#66723`, `#67364`, `#66322`, `#67364`, `#66216`, `#66723`, `#54855`, `#67364`, `#54855`, `#66322`, `#67364`, `#67364`, `#66216`, `#66723`, `#66216`, `#66723`, `#54855`, `#67364`, `#374151`, `#66189`, `#54855`, `#66216`, `#66322`, `#66723`, `#67364`
- **#66723: chore(gitignore): ignore .install_method installer marker (#66189)**. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`

## Fix status

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