From 1ddf8c26f50d49719a502fd0cf9b47d30a136a46 Mon Sep 17 00:00:00 2001 From: teknium1 Date: Sat, 28 Feb 2026 10:35:49 -0800 Subject: [PATCH] refactor(cli): update max turns configuration precedence and enhance documentation --- README.md | 13 +++++++++++++ cli.py | 6 +++--- gateway/run.py | 4 ++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3cb1d6598..4b407c267 100644 --- a/README.md +++ b/README.md @@ -161,6 +161,19 @@ hermes config set terminal.backend docker hermes config set OPENROUTER_API_KEY sk-or-... # Saves to .env ``` +### Configuration Precedence + +Settings are resolved in this order (highest priority first): + +1. **CLI arguments** — `hermes chat --max-turns 100` (per-invocation override) +2. **`~/.hermes/config.yaml`** — the primary config file for all non-secret settings +3. **`~/.hermes/.env`** — fallback for env vars; **required** for secrets (API keys, tokens, passwords) +4. **Built-in defaults** — hardcoded safe defaults when nothing else is set + +**Rule of thumb:** Secrets (API keys, bot tokens, passwords) go in `.env`. Everything else (model, terminal backend, compression settings, memory limits, toolsets) goes in `config.yaml`. When both are set, `config.yaml` wins for non-secret settings. + +The `hermes config set` command automatically routes values to the right file — API keys are saved to `.env`, everything else to `config.yaml`. + ### Optional API Keys | Feature | Provider | Env Variable | diff --git a/cli.py b/cli.py index ea9c3e630..89aa463d9 100755 --- a/cli.py +++ b/cli.py @@ -822,15 +822,15 @@ class HermesCLI: ) self._nous_key_expires_at: Optional[str] = None self._nous_key_source: Optional[str] = None - # Max turns priority: CLI arg > env var > config file (agent.max_turns or root max_turns) > default + # Max turns priority: CLI arg > config file > env var > default if max_turns is not None: self.max_turns = max_turns - elif os.getenv("HERMES_MAX_ITERATIONS"): - self.max_turns = int(os.getenv("HERMES_MAX_ITERATIONS")) elif CLI_CONFIG["agent"].get("max_turns"): self.max_turns = CLI_CONFIG["agent"]["max_turns"] elif CLI_CONFIG.get("max_turns"): # Backwards compat: root-level max_turns self.max_turns = CLI_CONFIG["max_turns"] + elif os.getenv("HERMES_MAX_ITERATIONS"): + self.max_turns = int(os.getenv("HERMES_MAX_ITERATIONS")) else: self.max_turns = 60 diff --git a/gateway/run.py b/gateway/run.py index 4f4a81bad..c5d283a19 100644 --- a/gateway/run.py +++ b/gateway/run.py @@ -88,6 +88,10 @@ if _config_path.exists(): for _cfg_key, _env_var in _compression_env_map.items(): if _cfg_key in _compression_cfg: os.environ[_env_var] = str(_compression_cfg[_cfg_key]) + _agent_cfg = _cfg.get("agent", {}) + if _agent_cfg and isinstance(_agent_cfg, dict): + if "max_turns" in _agent_cfg: + os.environ["HERMES_MAX_ITERATIONS"] = str(_agent_cfg["max_turns"]) except Exception: pass # Non-fatal; gateway can still run with .env values