fix(terminal): strip VIRTUAL_ENV from agent subprocess envs#23474
Open
TheoLong wants to merge 1 commit into
Open
fix(terminal): strip VIRTUAL_ENV from agent subprocess envs#23474TheoLong wants to merge 1 commit into
TheoLong wants to merge 1 commit into
Conversation
The gateway systemd unit sets VIRTUAL_ENV=<hermes-venv> so the gateway process can find its own .venv. That variable then leaks into every terminal subprocess Hermes spawns. If the agent runs 'uv sync', 'uv pip install', 'poetry install', or 'pip install' in any OTHER project directory, those tools see VIRTUAL_ENV pointing at Hermes' own venv and treat it as the active install target — they rebuild it against the user's pyproject.toml, blow away every Hermes runtime dependency, and the gateway fails to start on the next restart. Reproduced in the wild: 'cd ~/code/some-project && uv sync' wiped ~/.hermes/hermes-agent/venv (Python 3.11 → 3.12, every dep gone) mid-conversation. Gateway crashed on restart with ImportError. Fix: add VIRTUAL_ENV and the related package-manager activation markers (VIRTUAL_ENV_PROMPT, UV_PROJECT_ENVIRONMENT, POETRY_ACTIVE, PIPENV_ACTIVE, CONDA_PREFIX, CONDA_DEFAULT_ENV) to the subprocess env blocklist in tools/environments/local.py. The gateway still gets its own VIRTUAL_ENV from the unit file; it just stops there. Opt-out: users who genuinely want their tools to run inside Hermes' venv can add VIRTUAL_ENV to tools.env_passthrough in config.yaml. Adds regression tests covering the blocklist membership and _sanitize_subprocess_env behavior.
This was referenced May 11, 2026
Closed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #23473.
Problem
The gateway systemd unit sets
VIRTUAL_ENV=<hermes-venv>so the gateway process can find its own.venv. That variable then leaks into every terminal subprocess Hermes spawns.If the agent runs
uv sync,uv pip install,poetry install, orpip installin any project directory other than Hermes' own, those tools seeVIRTUAL_ENVpointing at Hermes' venv and treat it as the active install target. They rebuild it against the user'spyproject.toml, wipe every Hermes runtime dependency, and the gateway fails on the next restart.Reproduced in the wild:
cd ~/code/some-project && uv syncwiped~/.hermes/hermes-agent/venv(Python 3.11 → 3.12, every dep gone) mid-conversation. Full repro and root-cause analysis in #23473.Fix
Scrub at the subprocess-env boundary in
tools/environments/local.py. AddVIRTUAL_ENVand the related package-manager activation markers to_HERMES_PROVIDER_ENV_BLOCKLIST:VIRTUAL_ENVVIRTUAL_ENV_PROMPTUV_PROJECT_ENVIRONMENTPOETRY_ACTIVEPIPENV_ACTIVECONDA_PREFIXCONDA_DEFAULT_ENVThe gateway still receives
VIRTUAL_ENVfrom its unit file — it just stops there.Why not
UnsetEnvironment=in the systemd unit?That removes
VIRTUAL_ENVfrom the gateway's own environment, which the unit specifically sets for the gateway process. We need it set for the gateway and unset for children of the gateway. The subprocess-env scrub is the right layer.Opt-out
Users who genuinely want their terminal tools to run inside Hermes' venv can add
VIRTUAL_ENVtotools.env_passthroughinconfig.yaml. The existing passthrough mechanism intools/env_passthrough.pyalready handles this — no new plumbing needed.Tests
Added a
TestVirtualEnvIsBlockedclass intests/tools/test_local_env_blocklist.py:test_virtual_env_is_blocked— membership in the blocklisttest_related_venv_markers_are_blocked— covers the full set of package-manager markerstest_sanitize_strips_virtual_env— end-to-end:_sanitize_subprocess_envstrips the varAll 38 tests in
tests/tools/test_local_env_blocklist.py+tests/tools/test_env_passthrough.pypass locally.Out of scope (deferred)
sys.prefix/VIRTUAL_ENVself-check in the gateway — would catch leftover broken venvs from earlier clobbering. Belongs on thehermes doctorwork in feat: hermes doctor — automated diagnostics and migration runner #8946.hermes_cli/gateway.py— not needed once the subprocess scrub is in place.