Bug Description
In hermes_constants.py, the get_hermes_home() function silently falls back to Path.home() / ".hermes" when the HERMES_HOME environment variable is unset (line 17-18):
def get_hermes_home() -> Path:
val = os.environ.get("HERMES_HOME", "").strip()
return Path(val) if val else Path.home() / ".hermes"
This is correct for classic (non-profile) mode, but dangerous in profile mode (HERMES_HOME=<root>/profiles/<name>). When HERMES_HOME is unset or empty, the function returns ~/.hermes — which is the default profile, not the active profile. Any code path that relies on get_hermes_home() for data storage will silently read/write to the wrong profile.
Steps to Reproduce
- Run a cron job, skill, or sub-agent without
HERMES_HOME set in the environment
- The agent calls
get_hermes_home() for data paths (memory, state.db, etc.)
- Instead of failing or using the intended profile, it resolves to
~/.hermes (default profile)
- Result: data from Profile A is silently stored in Profile B's database
Real incident (May 1 2026): A holographic-memory-reflect cron job (running under a named profile) executed SQL queries with hardcoded ~/.hermes/memory_store.db paths from skill text. Because HERMES_HOME was not inherited by the sub-process, get_hermes_home() fell back to the default profile — contaminating the profile's memory with data that belonged to a user's personal data outside of the profile.
Expected Behavior
When HERMES_HOME is unset in profile mode, get_hermes_home() should raise an error (e.g., ValueError("HERMES_HOME not set — profile mode requires this env var")) rather than silently returning ~/.hermes.
Actual Behavior
Silently returns ~/.hermes as a fallback, causing silent cross-profile data corruption.
Affected Component
Agent Core (conversation loop, context compression, memory)
Messaging Platform (if gateway-related)
No response
Debug Report
Operating System
OpenSUSE Leap 16
Python Version
3.11.15
Hermes Version
0.12.0
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
In profile mode, HERMES_HOME is set by the CLI launcher to <root>/profiles/<name> before spawning sub-processes (cron jobs, skills, sub-agents). However, these sub-processes do not inherit the parent process's environment variables — they start with a clean or minimal environment. When get_hermes_home() is called without HERMES_HOME in the subprocess's own environment, it cannot distinguish between:
- Classic mode where
~/.hermes is the correct default
- Profile mode where
HERMES_HOME should have been set and ~/.hermes is almost certainly wrong
Because there is no in-process signal indicating which mode is active, the function defaults to the classic-mode fallback. This makes the bug invisible — the code runs without errors while silently writing to the wrong profile's data directory.
Proposed Fix (optional)
def get_hermes_home() -> Path:
val = os.environ.get("HERMES_HOME", "").strip()
if not val:
# In profile mode, ~/.hermes is almost never the right answer.
# Raise to force the caller or operator to be explicit.
raise ValueError(
"HERMES_HOME is not set. "
"In profile mode this should be set to the profile directory "
"(e.g. ~/.hermes/profiles/<name>). "
"Classic mode can set HERMES_HOME to ~/.hermes explicitly."
)
return Path(val)
Alternatively, if backward compatibility is needed, add a require_env=False kwarg that defaults to raising in profile-mode-detected contexts.
Are you willing to submit a PR for this?
Bug Description
In hermes_constants.py, the
get_hermes_home()function silently falls back toPath.home() / ".hermes"when theHERMES_HOMEenvironment variable is unset (line 17-18):def get_hermes_home() -> Path:
val = os.environ.get("HERMES_HOME", "").strip()
return Path(val) if val else Path.home() / ".hermes"
This is correct for classic (non-profile) mode, but dangerous in profile mode (
HERMES_HOME=<root>/profiles/<name>). WhenHERMES_HOMEis unset or empty, the function returns~/.hermes— which is the default profile, not the active profile. Any code path that relies onget_hermes_home()for data storage will silently read/write to the wrong profile.Steps to Reproduce
HERMES_HOMEset in the environmentget_hermes_home()for data paths (memory, state.db, etc.)~/.hermes(default profile)Real incident (May 1 2026): A holographic-memory-reflect cron job (running under a named profile) executed SQL queries with hardcoded
~/.hermes/memory_store.dbpaths from skill text. BecauseHERMES_HOMEwas not inherited by the sub-process,get_hermes_home()fell back to the default profile — contaminating the profile's memory with data that belonged to a user's personal data outside of the profile.Expected Behavior
When
HERMES_HOMEis unset in profile mode,get_hermes_home()should raise an error (e.g.,ValueError("HERMES_HOME not set — profile mode requires this env var")) rather than silently returning~/.hermes.Actual Behavior
Silently returns
~/.hermesas a fallback, causing silent cross-profile data corruption.Affected Component
Agent Core (conversation loop, context compression, memory)
Messaging Platform (if gateway-related)
No response
Debug Report
Operating System
OpenSUSE Leap 16
Python Version
3.11.15
Hermes Version
0.12.0
Additional Logs / Traceback (optional)
Root Cause Analysis (optional)
In profile mode,
HERMES_HOMEis set by the CLI launcher to<root>/profiles/<name>before spawning sub-processes (cron jobs, skills, sub-agents). However, these sub-processes do not inherit the parent process's environment variables — they start with a clean or minimal environment. Whenget_hermes_home()is called withoutHERMES_HOMEin the subprocess's own environment, it cannot distinguish between:~/.hermesis the correct defaultHERMES_HOMEshould have been set and~/.hermesis almost certainly wrongBecause there is no in-process signal indicating which mode is active, the function defaults to the classic-mode fallback. This makes the bug invisible — the code runs without errors while silently writing to the wrong profile's data directory.
Proposed Fix (optional)
Alternatively, if backward compatibility is needed, add a
require_env=Falsekwarg that defaults to raising in profile-mode-detected contexts.Are you willing to submit a PR for this?