Windows install.ps1 script bugs and fixes

NousResearch/hermes-agent · cluster 27397 · hermes cli

Data as of

Nothing open on GitHub. Fix merged in #28169. Check it covers your case.

The short answer

0open issues
0open PRs
8items grouped
Known?
Yes. 8 related items grouped here, 4 issues already closed.
Fix event
A fix was merged to main in PR #28169. Check it covers your case. No release data is tracked.
Tracker
The maintainers' tracker marks this unresolved. That is separate from the fix event.
Still open
Nothing open on GitHub.

Multiple bugs and fixes related to the Windows PowerShell installer script, including a malformed param() block, UTF-8 BOM characters, and syntax errors that break the one-line installation command. Several fixes address the same or closely related root causes.

Open issues0

No open issues.

Open PRs0

No open pull requests.

Fixes on record

Merged to main. A stamp counts the issues a fix is linked to.

  • #28169 feat(install.ps1): strip BOM, add -Commit/-Tag pin params, harden git ops

    merged to main

    files: scripts/install.ps1

    Show the diff
    • scripts/install.ps1
      @@ -1,4 +1,4 @@
      -# ============================================================================
      +# ============================================================================
       # Hermes Agent Installer for Windows
       # ============================================================================
       # Installation script for Windows (PowerShell).
      @@ -16,6 +16,13 @@ param(
           [switch]$NoVenv,
           [switch]$SkipSetup,
           [string]$Branch = "main",
      +    # -Commit and -Tag are higher-precedence variants of -Branch for users
      +    # who need reproducible installs (desktop installer pinning, CI, release
      +    # bundles).  When set, the repository stage clones $Branch (faster than
      +    # cloning the full default-branch history) and then `git checkout`s the
      +    # exact ref.  Precedence: Commit > Tag > Branch.
      +    [string]$Commit = "",
      +    [string]$Tag = "",
           [string]$HermesHome = "$env:LOCALAPPDATA\hermes",
           [string]$InstallDir = "$env:LOCALAPPDATA\hermes\hermes-agent",
       
      @@ -955,14 +962,36 @@ function Install-Repository {
               if ($repoValid) {
                   Write-Info "Existing installation found, updating..."
                   Push-Location $InstallDir
      +            # Wrap the entire fetch+checkout block in EAP=Continue so git's
      +            # routine stderr output (e.g. 'From <url>' info lines emitted by
      +            # `git fetch`) doesn't terminate the script under the global
      +            # EAP=Stop.  We rely on $LASTEXITCODE for actual failures.
      +            $prevEAP = $ErrorActionPreference
      +            $ErrorActionPreference = "Continue"
                   try {
                       git -c windows.appendAtomically=false fetch origin
                       if ($LASTEXITCODE -ne 0) { throw "git fetch failed (exit $LASTEXITCODE)" }
      -                git -c windows.appendAtomically=false checkout $Branch
      -                if ($LASTEXITCODE -ne 0) { throw "git checkout $Branch failed (exit $LASTEXITCODE)" }
      -                git -c windows.appendAtomically=false pull origin $Branch
      -                if ($LASTEXITCODE -ne 0) { throw "git pull failed (exit $LASTEXITCODE)" }
      +                # Precedence: Commit > Tag > Branch.  Commit and Tag check
      +                # out as detached HEAD intentionally -- they're meant to be
      +                # reproducible pins, not branches the user pulls into.
      +                if ($Commit) {
      +                    # Make sure we have the commit locally (a tag-less commit
      +                    # SHA isn't always reachable from any one branch fetch).
      +                    git -c windows.appendAtomically=false fetch origin $Commit
      +                    git -c windows.appendAtomically=false checkout --detach $Commit
      +                    if ($LASTEXITCODE -ne 0) { throw "git checkout $Commit failed (exit $LASTEXITCODE)" }
      +                } elseif ($Tag) {
      +                    git -c windows.appendAtomically=false fetch origin "refs/tags/${Tag}:refs/tags/${Tag}"
      +                    git -c windows.appendAtomically=false checkout --detach "refs/tags/$Tag"
      +                    if ($LASTEXITCODE -ne 0) { throw "git checkout tag $Tag failed (exit $LASTEXITCODE)" }
      +                } else {
      +                    git -c windows.appendAtomically=false checkout $Branch
      +                    if ($LASTEXITCODE -ne 0) { throw "git checkout $Branch failed (exit $LASTEXITCODE)" }
      +                    git -c windows.appendAtomically=false pull origin $Branch
      +                    if ($LASTEXITCODE -ne 0) { throw "git pull failed (exit $LASTEXITCODE)" }
      +                }
                   } finally {
      +                $ErrorActionPreference = $prevEAP
                       Pop-Location
                   }
                   $didUpdate = $true
      @@ -1020,8 +1049,20 @@ function Install-Repository {
                   if (Test-Path $InstallDir) { Remove-Item -Recurse -Force $InstallDir -ErrorAction SilentlyContinue }
                   Write-Warn "Git clone failed -- downloading ZIP archive instead..."
                   try {
      -                $zipUrl = "https://github.com/NousResearch/hermes-agent/archive/refs/heads/$Branch.zip"
      -                $zipPath = "$env:TEMP\hermes-agent-$Branch.zip"
      +                # Pick the ZIP URL for the most-specific ref the caller asked
      +                # for.  GitHub supports archive URLs for commits, tags, and
      +                # branches; we honour Commit > Tag > Branch.
      +                if ($Commit) {
      +                    $zipUrl = "https://github.com/NousResearch/hermes-agent/archive/$Commit.zip"
      +                    $zipLabel = $Commit
      +                } elseif ($Tag) {
      +                    $zipUrl = "https://github.com/NousResearch/hermes-agent/archive/refs/tags/$Tag.zip"
      +                    $zipLabel = $Tag
      +                } else {
      +                    $zipUrl = "https://github.com/NousResearch/hermes-agent/archive/refs/heads/$Branch.zip"
      +                    $zipLabel = $Branch
      +                }
      +                $zipPath = "$env:TEMP\hermes-agent-$zipLabel.zip"
                       $extractPath = "$env:TEMP\hermes-agent-extract"
       
                       Invoke-WebRequest -Uri $zipUrl -OutFile $zipPath -UseBasicParsing
      @@ -1063,6 +1104,37 @@ function Install-Repository {
           Push-Location $InstallDir
           git -c windows.appendAtomically=false config windows.appendAtomically false 2>$null
       
      +    # Post-clone pin: when a clone (or ZIP-fallback init) just landed us on
      +    # $Branch's tip, honour the higher-precedence $Commit / $Tag by checking
      +    # the exact ref out as a detached HEAD.  Skipped for the in-place update
      +    # path (above) since that already routed via the same precedence.
      +    if (-not $didUpdate) {
      +        # Same EAP=Continue wrap as the update path -- git fetch's 'From <url>'
      +        # info line goes to stderr and would terminate the script under the
      +        # global EAP=Stop otherwise.  We check $LASTEXITCODE for real errors.
      +        $prevEAP = $ErrorActionPreference
      +        $ErrorActionPreference = "Continue"
      +        try {
      +            if ($Commit) {
      +                Write-Info "Pinning to commit $Commit..."
      +                git -c windows.appendAtomically=false fetch origin $Commit
      +                git -c windows.appendAtomically=false checkout --detach $Commit
      +                if ($LASTEXITCODE -ne 0) {
      +                    throw "git checkout $Commit failed (exit $LASTEXITCODE)"
      +                }
      +            } elseif ($Tag) {
      +                Write-Info "Pinning to tag $Tag..."
      +                git -c windows.appendAtomically=false fetch origin "refs/tags/${Tag}:refs/tags/${Tag}"
      +                git -c windows.appendAtomically=false checkout --detach "refs/tags/$Tag"
      +                if ($LASTEXITCODE -ne 0) {
      +                    throw "git checkout tag $Tag failed (exit $LASTEXITCODE)"
      +                }
      +            }
      +        } finally {
      +            $ErrorActionPreference = $prevEAP
      +        }
      +    }
      +
           # Ensure submodules are initialized and updated
           Write-Info "Initializing submodules..."
           git -c windows.appendAtomically=false submodule update --init --recursive 2>$null

3 PRs closed without merging

From the close comments: done elsewhere 1 · superseded by another PR 1 · other 1

  • #27419 fix(install.ps1): drop UTF-8 BOM that breaks the irm | iex one-liner (#27397) · superseded by another PR → #28169
  • #28732 fix(install.ps1): remove UTF-8 BOM that breaks irm | iex path · other → #28169
  • #29206 fix(install): correct param() block placement in install.ps1 (#28141) · done elsewhere → a53e8ca, #28141, #27397
Closed issues · 4
  • Closed#27397[Bug]: One Line Install not working
  • Closed#27622[Bug]: Windows Install Isn't Working
  • Closed#28071Fix critical syntax error in install.ps1 that breaks Windows installation
  • Closed#28141install.ps1: malformed param() block breaks Windows one-line installer
How this cluster was grouped
  • Link evidence (partly structural links): 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.26: the share of item 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.

Pick up a Lab task

Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.

Open the Lab

At a glance

Subsystem
hermes cli
Merged PRs
#28169
Closed issues
4
Attempts
3 PRs closed without merging
Fix link checked
19 May 2026

For your agent

The same facts, typed.