Skip to content

fix: use real user home instead of sandbox-overridden HOME#8910

Closed
iRonin wants to merge 3 commits into
NousResearch:mainfrom
iRonin:ironin/real-home
Closed

fix: use real user home instead of sandbox-overridden HOME#8910
iRonin wants to merge 3 commits into
NousResearch:mainfrom
iRonin:ironin/real-home

Conversation

@iRonin

@iRonin iRonin commented Apr 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Captures the real OS user home at module import time (before the sandbox can override HOME) and uses it for all Path.home() and os.path.expanduser() calls that need the actual user home.

Problem

The terminal sandbox overrides HOME to {HERMES_HOME}/home/ for profile isolation. This silently breaks:

  • gh CLI auth (looks in wrong place for keychain tokens)
  • Claude adapter credential discovery
  • User file paths (~/Documents/file.txt)
  • Profile root detection
  • Wrapper script creation

Changes

File Change
hermes_constants.py Add _REAL_HOME constant and get_real_home() helper
hermes_constants.py get_hermes_home() and get_default_hermes_root() use get_real_home()
cli.py Profile parent detection uses get_real_home()
hermes_cli/profiles.py _get_wrapper_dir() uses get_real_home()
agent/anthropic_adapter.py All 3 Claude config paths use get_real_home()
tools/tool_backend_helpers.py modal.toml check uses get_real_home()
tools/file_tools.py Add _expanduser() helper that expands ~ to real home
tools/delegate_tool.py CWD resolution uses get_real_home()
tests/test_hermes_constants.py Update monkeypatching for _REAL_HOME

Closes #8669

iRonin added 3 commits April 13, 2026 05:18
Capture real HOME at module import time (before sandbox overrides it)
and use get_real_home() for all Path.home() and expanduser() calls
that need the actual OS user home.

Files updated:
- hermes_constants.py: Add _REAL_HOME and get_real_home()
- hermes_constants.py: Use get_real_home() in get_hermes_home(), get_default_hermes_root()
- cli.py: Profile parent detection uses real home
- profiles.py: Wrapper dir uses real home
- agent/anthropic_adapter.py: Claude config paths use real home
- tools/tool_backend_helpers.py: modal.toml check uses real home
- tools/file_tools.py: _expanduser() helper for real home
- tools/delegate_tool.py: CWD resolution uses real home
- tests/test_hermes_constants.py: Update monkeypatching for _REAL_HOME

Closes NousResearch#8669
Add config setting to disable the profile HOME override.
When set to false, subprocesses keep the real OS user home
instead of being redirected to {HERMES_HOME}/home/.

Usage in config.yaml:
  terminal:
    profile_home_isolation: false

Files updated:
- hermes_cli/config.py: Add terminal.profile_home_isolation (default: true)
- tools/environments/local.py: Check config before overriding HOME
- tools/code_execution_tool.py: Check config before overriding HOME

Closes NousResearch#8669
…lation disabled

- hermes_constants.py: Use pwd.getpwuid(os.getuid()).pw_dir to get real
  user home, bypassing the HOME env var entirely
- tools/environments/local.py: When profile_home_isolation=false,
  explicitly restore real HOME in subprocess env (parent may have it
  already overridden)
- tools/code_execution_tool.py: Same HOME restoration logic

Closes NousResearch#8669
@teknium1

Copy link
Copy Markdown
Contributor

Thanks for the thorough write-up, but after auditing the codebase this is solving a problem that doesn't exist.

The subprocess HOME override ({HERMES_HOME}/home/) only applies to child process environments — it's injected into the env dict passed to subprocess.Popen() in _make_run_env() (local.py) and code_execution_tool.py. The main Python process's os.environ["HOME"] is never modified. The docstring on get_subprocess_home() states this explicitly:

"The Python process's own os.environ["HOME"] and Path.home() are never modified — only subprocess environments should inject this value."

I verified every os.environ["HOME"] = assignment in the codebase — they're all in test fixtures (monkeypatch). The claimed breakages (gh CLI auth, Claude credential discovery, user file paths, profile root detection) run in the main process where Path.home() correctly returns the real user home.

Also noting a bug in the PR: anthropic_adapter.py calls _real_home() which doesn't exist (the import brings in get_real_home, not _real_home).

Closing the related issue and duplicate PRs as well.

@iRonin

iRonin commented Apr 13, 2026

Copy link
Copy Markdown
Contributor Author

@Teknium This PR addresses a real runtime issue that code audit alone misses.

The sandbox terminal environment overrides HOME to {HERMES_HOME}/home/ for the entire Python process lifecycle.

When running hermes -p dev:

  • Before: HOME=/Users/ironin/.hermes/profiles/dev/homegh, git, npm all fail to find real user configs
  • After fix with terminal.profile_home_isolation: false: HOME=/Users/ironin → everything works

The fix:

  1. Uses pwd.getpwuid() to get real user home, bypassing env var override
  2. Explicitly restores real HOME in subprocess envs when isolation is disabled
  3. Adds config option for users who want isolation vs convenience

This isn't a codebase bug — it's a sandbox runtime reality. The config option gives users the choice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix: sandbox HOME override breaks Path.home() and expanduser() resolution

2 participants