mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
feat(cli): add --ignore-user-config and --ignore-rules flags
Port from openai/codex#18646. Adds two flags to 'hermes chat' that fully isolate a run from user-level configuration and rules: * --ignore-user-config: skip ~/.hermes/config.yaml and fall back to built-in defaults. Credentials in .env are still loaded so the agent can actually call a provider. * --ignore-rules: skip auto-injection of AGENTS.md, SOUL.md, .cursorrules, and persistent memory (maps to AIAgent(skip_context_files=True, skip_memory=True)). Primary use cases: - Reproducible CI runs that should not pick up developer-local config - Third-party integrations (e.g. Chronicle in Codex) that bring their own config and don't want user preferences leaking in - Bug-report reproduction without the reporter's personal overrides - Debugging: bisect 'was it my config?' vs 'real bug' in one command Both flags are registered on the parent parser AND the 'chat' subparser (with argparse.SUPPRESS on the subparser to avoid overwriting the parent value when the flag is placed before the subcommand, matching the existing --yolo/--worktree/--pass-session-id pattern). Env vars HERMES_IGNORE_USER_CONFIG=1 and HERMES_IGNORE_RULES=1 are set by cmd_chat BEFORE 'from cli import main' runs, which is critical because cli.py evaluates CLI_CONFIG = load_cli_config() at module import time. The cli.py / hermes_cli.config.load_cli_config() function checks the env var and skips ~/.hermes/config.yaml when set. Tests: 11 new tests in tests/hermes_cli/test_ignore_user_config_flags.py covering the env gate, constructor wiring, cmd_chat simulation, and argparse flag registration. All pass; existing hermes_cli + cli suites unaffected (3005 pass, 2 pre-existing unrelated failures).
This commit is contained in:
parent
520b8d9002
commit
a2a8092e90
4 changed files with 312 additions and 1 deletions
23
cli.py
23
cli.py
|
|
@ -305,13 +305,23 @@ def load_cli_config() -> Dict[str, Any]:
|
|||
|
||||
Environment variables take precedence over config file values.
|
||||
Returns default values if no config file exists.
|
||||
|
||||
If HERMES_IGNORE_USER_CONFIG=1 is set (via ``hermes chat --ignore-user-config``),
|
||||
the user config at ``~/.hermes/config.yaml`` is skipped entirely and only the
|
||||
built-in defaults plus the project-level ``cli-config.yaml`` (if any) are used.
|
||||
Credentials in ``.env`` are still loaded — this flag only suppresses
|
||||
behavioral/config settings.
|
||||
"""
|
||||
# Check user config first ({HERMES_HOME}/config.yaml)
|
||||
user_config_path = _hermes_home / 'config.yaml'
|
||||
project_config_path = Path(__file__).parent / 'cli-config.yaml'
|
||||
|
||||
# --ignore-user-config: force-skip the user config.yaml (still honor project
|
||||
# config as a fallback so defaults stay sensible).
|
||||
ignore_user_config = os.environ.get("HERMES_IGNORE_USER_CONFIG") == "1"
|
||||
|
||||
# Use user config if it exists, otherwise project config
|
||||
if user_config_path.exists():
|
||||
if user_config_path.exists() and not ignore_user_config:
|
||||
config_path = user_config_path
|
||||
else:
|
||||
config_path = project_config_path
|
||||
|
|
@ -1802,6 +1812,7 @@ class HermesCLI:
|
|||
resume: str = None,
|
||||
checkpoints: bool = False,
|
||||
pass_session_id: bool = False,
|
||||
ignore_rules: bool = False,
|
||||
):
|
||||
"""
|
||||
Initialize the Hermes CLI.
|
||||
|
|
@ -1955,6 +1966,11 @@ class HermesCLI:
|
|||
self.checkpoints_enabled = checkpoints or cp_cfg.get("enabled", False)
|
||||
self.checkpoint_max_snapshots = cp_cfg.get("max_snapshots", 50)
|
||||
self.pass_session_id = pass_session_id
|
||||
# --ignore-rules: honor either the constructor flag or the env var set
|
||||
# by `hermes chat --ignore-rules` in hermes_cli/main.py. When true we
|
||||
# pass skip_context_files=True and skip_memory=True to AIAgent so
|
||||
# AGENTS.md/SOUL.md/.cursorrules and persistent memory are not loaded.
|
||||
self.ignore_rules = ignore_rules or os.environ.get("HERMES_IGNORE_RULES") == "1"
|
||||
|
||||
# Ephemeral system prompt: env var takes precedence, then config
|
||||
self.system_prompt = (
|
||||
|
|
@ -3312,6 +3328,8 @@ class HermesCLI:
|
|||
checkpoints_enabled=self.checkpoints_enabled,
|
||||
checkpoint_max_snapshots=self.checkpoint_max_snapshots,
|
||||
pass_session_id=self.pass_session_id,
|
||||
skip_context_files=self.ignore_rules,
|
||||
skip_memory=self.ignore_rules,
|
||||
tool_progress_callback=self._on_tool_progress,
|
||||
tool_start_callback=self._on_tool_start if self._inline_diffs_enabled else None,
|
||||
tool_complete_callback=self._on_tool_complete if self._inline_diffs_enabled else None,
|
||||
|
|
@ -10816,6 +10834,8 @@ def main(
|
|||
w: bool = False,
|
||||
checkpoints: bool = False,
|
||||
pass_session_id: bool = False,
|
||||
ignore_user_config: bool = False,
|
||||
ignore_rules: bool = False,
|
||||
):
|
||||
"""
|
||||
Hermes Agent CLI - Interactive AI Assistant
|
||||
|
|
@ -10925,6 +10945,7 @@ def main(
|
|||
resume=resume,
|
||||
checkpoints=checkpoints,
|
||||
pass_session_id=pass_session_id,
|
||||
ignore_rules=ignore_rules,
|
||||
)
|
||||
|
||||
if parsed_skills:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue