fix(install): keep venv Scripts dir off the user PATH (#83797) - #83830
fix(install): keep venv Scripts dir off the user PATH (#83797)#83830zuowen7 wants to merge 3 commits into
Conversation
…3797) Pre-2026-08 installers prepended <install>\venv\Scripts to the persisted User PATH so `hermes` would be globally available. That dir also hosts python.exe/pip.exe, so every new shell resolved `python` to the Hermes runtime instead of the user's own interpreter. - install.ps1: Set-PathVariable now ships hermes/hermes-acp as .cmd forwarding shims in $LOCALAPPDATA\hermes\bin (a Hermes-owned dir that holds only Hermes-specific commands) and runs Update-UserPathForHermes, which migrates existing installs by dropping the stale venv\Scripts entry while preserving all other entries. - update_cmd.py: _ensure_acp_launcher's Windows branch (previously a no-op relying on venv\Scripts being on PATH) now (re)creates the acp shim, since `hermes update` does not re-run install.ps1. - Tests: behavior test for Update-UserPathForHermes (AST-lifted, same harness as test_install_ps1_path_migration.ps1) plus Windows shim unit tests for the acp launcher. Verified on a real Windows host: after migration, where.exe python resolves to the user's own interpreter and hermes/hermes-acp still resolve via the bin shims.
The new install.ps1 (NousResearch#83797) prepends %LOCALAPPDATA%\hermes\bin (not venv\Scripts) to the User PATH. _hermes_path_markers was missing this entry, so the uninstaller left it behind. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Update-UserPathForHermes: TrimEnd backslash on ShimDir so registry-style trailing slashes cannot defeat membership detection (mirrors the legacy entry handling). - New-HermesShims: Set-Content -NoNewline so shim bytes exactly match the intended content (Set-Content appends a newline otherwise, breaking the idempotence check). - _ensure_windows_acp_shim: document the silent degradation for custom install dirs. - Behavior test now also covers New-HermesShims (create, idempotence, missing-target skip, empty args) and the trailing-backslash case (24 assertions total).
|
@teknium1 — thanks for #84452, the One part of this PR that one doesn't cover: uninstall cleanup ( Happy to trim it down to just the uninstall piece if that keeps the diff cleaner. |
|
Correction on my earlier comment — I re-checked, and this PR has no independent value left: |
What does this PR do?
On Windows, installs made by the pre-2026-08
install.ps1prepend the venv Scripts dir (<install>\venv\Scripts) to the persisted User PATH sohermesis globally available. That dir also containspython.exe/pip.exe, so every new shell resolvespythonto the Hermes runtime instead of the user's own interpreter (reproduced on a real Windows 11 host:where.exe pythonreturned...\hermes-agent\venv\Scripts\python.exeahead of the user's own Anaconda / Python 3.14).This PR keeps the command surface global without hijacking
python:install.ps1Set-PathVariableno longer putsvenv\Scriptson the user PATH. It shipshermes/hermes-acpas.cmdforwarding shims in%LOCALAPPDATA%\hermes\bin(a Hermes-owned dir holding only Hermes-specific commands likeuv) and runs a newUpdate-UserPathForHermesmigration that drops the stalevenv\Scriptsentry from the User PATH, preserving every other entry (order, empty segments, case-insensitive).hermes_cli/update_cmd.py_ensure_acp_launcher's Windows branch (previously a no-op relying onvenv\Scriptsbeing on PATH) now (re)creates the acp shim, sincehermes updatedoes not re-runinstall.ps1.hermes_cli/uninstall.py_hermes_path_markersnow also matches%LOCALAPPDATA%\hermes\binso uninstall sweeps the shim dir.Note on the 0.19.0
.hermes-runtime\python\...entry mentioned in the issue: the current codebase has never written.hermes-runtimeto the user PATH (it is an internal runtime dir); that entry lives under thehermes-agentprefix and is already swept by the uninstaller'shermes-agentmarker. This PR targets the current-installer layout (venv\Scripts).Related Issue
Fixes #83797
Type of Change
Changes Made
scripts/install.ps1—Set-PathVariablerewritten; newNew-HermesShims+Update-UserPathForHermes(migration); backslash normalization +-NoNewlinehardeninghermes_cli/update_cmd.py— new_ensure_windows_acp_shim(); Windows branch of_ensure_acp_launcherno longer a no-op; silent degradation for custom install dirs documentedhermes_cli/uninstall.py—_hermes_path_markersnow also matches%LOCALAPPDATA%\hermes\binscripts/ci/test_install_ps1_hermes_shim_path.ps1— new behavior test (AST-lifted, same harness astest_install_ps1_path_migration.ps1; 24 assertions incl.New-HermesShimscoverage)tests/hermes_cli/test_ensure_acp_launcher.py— 4 new Windows-shim unit testsHow to Test
pwsh -NoProfile -File scripts/ci/test_install_ps1_path_migration.ps1— passes (no regression)pwsh -NoProfile -File scripts/ci/test_install_ps1_hermes_shim_path.ps1— 24 assertions passpytest tests/hermes_cli/test_ensure_acp_launcher.py— 4 new tests pass; the 2 pre-existing failures are environment-only on Windows (symlink perms /os.geteuid), identical failures on unmodifiedmain(verified via git stash comparison)Update-UserPathForHermes+New-HermesShimsagainst the live registry (backed up first). After:where.exe python→D:\env\anaconda\python.exe(user's own);hermes --version→ v0.20.0 via...\hermes\bin\hermes.cmd;hermes-acpshim present.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/ -qand all tests pass — targeted files only; full suite not run locally, pre-existing Windows environment failures documented aboveDocumentation & Housekeeping
docs/, docstrings) — or N/Acli-config.yaml.exampleif I added/changed config keys — or N/ACONTRIBUTING.mdorAGENTS.mdif I changed architecture or workflows — or N/AScreenshots / Logs
Real-host verification (fresh-shell PATH reconstructed from registry):