# NousResearch/hermes-agent · Config precedence and stale env override bugs

## Open now

- 3 issues, 4 PRs open on GitHub.
- #13582: Non-secret gateway settings in .env silently override config.yaml
- #13685: \[Bug\]: config.yaml settings override .env settings, despite doc says the opposite
- #25402: terminal.backend=local can still use Docker when stale Docker config keys remain
- PR #29239: fix(env): make config.yaml authoritative for terminal.backend (#29186)
- PR #29246: docs(skills): require duplicate search before filing GitHub issues
- PR #39641: fix(config): warn when env shadows gateway config (#13582)
- PR #89451: fix(discord): explicit DISCORD_FREE_RESPONSE_CHANNELS beats config.yaml

These issues and fixes address conflicts between config.yaml settings and .env values, where stale environment variables incorrectly override intended configuration. A related cluster covers Docker-specific JSON being parsed regardless of the active terminal backend, causing crashes on non-Docker setups.

## TL;DR

- 28 member(s): 3 open issue(s), 5 closed issue(s), 4 open PR(s), 4 merged PR(s), 12 PR(s) closed without merging.
- A fix was merged to main in PR #21240. Verify it addresses your case.
- **Recommended:** read PR #21240 (and any competing PRs below) before filing. Confirm the merged change covers your symptom.

## Maintainer resolution verdict

- Internal-tracker verdict over this cluster's issue members: `partially_resolved` · deciding PR(s): `pr-21240,pr-42733,pr-77180`. This is distinct from the fix status above. Weigh it yourself.

## How this cluster was grouped

- Link evidence (`STRUCTURAL_PARTIAL`): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text.
- Members outside that structural core may belong to a different underlying problem.
- Pairwise link density `0.06`: the share of member pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36. `1.00` means every pair is linked.

## Open related issues

- #13582: Non-secret gateway settings in .env silently override config.yaml
- #13685: \[Bug\]: config.yaml settings override .env settings, despite doc says the opposite
- #25402: terminal.backend=local can still use Docker when stale Docker config keys remain

## Closed / duplicate issues

- #9240: Bug: Discord free_response_channels from config.yaml can become operationally unreliable after restart; explicit .env fixes it
- #17534: \[Bug\]: setup wizard double-writes max_turns to both .env (HERMES_MAX_ITERATIONS) and config.yaml (agent.max_turns), causing silent state drift
- #19158: Gateway max_turns can be overridden by stale HERMES_MAX_ITERATIONS from .env
- #29186: TERMINAL_ENV in ~/.hermes/.env overrides terminal.backend in config.yaml
- #42725: \[Bug\]: TERMINAL_DOCKER_VOLUMES parsed eagerly with json.loads regardless of terminal.backend, crashes all subprocess tools

## Prior & competing PRs

- **#13732: fix(discord): honor documented env-wins-over-config precedence for require_mention/free_response_channels**. closed without merge · fix tier `suggested`
  - maintainer direction: category `uncategorized`; implication `needs_llm`
  - _suggested-tier fix detail withheld; re-request with `?tier=all` to include it._
- **#18764: fix(gateway): config.yaml wins over .env for agent/display/timezone settings**. merged to main · fix tier `suggested`
  - maintainer direction: category `merged`; implication `superseded`
  - _suggested-tier fix detail withheld; re-request with `?tier=all` to include it._
- **#21240: fix(gateway): preserve max_turns after env reload (salvage #19183)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `gateway/run.py`, `tests/gateway/test_runtime_env_reload_config_authority.py`
- **#29372: fix: always export TERMINAL_ENV from config.yaml to prevent stale .env override**. closed without merge · fix tier `suggested`
  - maintainer direction: category `superseded_by_pr`; implication `superseded`; refs `#29239`
- **#42733: fix(terminal): lazy-parse Docker env config**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `tests/tools/test_terminal_tool.py`, `tools/terminal_tool.py`
- **#77180: fix(env): config.yaml terminal.* keys win over stale .env on every reload (#29186)**. merged to main · fix tier `verified`
  - maintainer direction: category `merged`; implication `superseded`
  - files: `hermes_cli/env_loader.py`, `tests/gateway/test_runtime_env_reload_config_authority.py`, `tests/hermes_cli/test_dump_terminal_backend.py`, `tests/hermes_cli/test_env_loader.py`
- **#13629: fix(gateway-config): warn when non-secret settings conflict between config.yaml and .env (#13582)**. closed without merge
  - maintainer direction: category `stale_abandoned`; implication `active`
- **#17554: fix(setup): keep max turns in config**. closed without merge
  - maintainer direction: category `uncategorized`; implication `needs_llm`; refs `#17672`, `#17534`
- **#17672: fix(cli): drop max_turns env-var dual-write in setup wizard (#17534)**. closed without merge
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`; refs `#18413`, `#18413`
- **#19183: fix(gateway): preserve max turns after env reload**. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#18230`, `#17306`
- **#25881: fix(terminal): clear container config when backend is local**. closed without merge
  - maintainer direction: category `wontfix_bydesign`; implication `wontfix`; refs `#25402`, `#25412`, `#23321`
- **#26546: fix(gateway): ignore stale docker config for local terminal**. closed without merge
  - maintainer direction: category `uncategorized`; implication `needs_llm`; refs `29036155ceb9e29d07f7b49eb073e6ec23802bf8`, `#25402`
- **#29239: fix(env): make config.yaml authoritative for terminal.backend (#29186)**. open
  - maintainer direction: category `uncategorized`; implication `needs_llm`
  - files: `hermes_cli/env_loader.py`, `tests/hermes_cli/test_env_loader.py`
- **#29246: docs(skills): require duplicate search before filing GitHub issues**. open
  - maintainer direction: category `uncategorized`; implication `needs_llm`
  - files: `skills/github/github-issues/SKILL.md`
- **#39641: fix(config): warn when env shadows gateway config (#13582)**. open
  - maintainer direction: category `implemented_elsewhere`; implication `superseded`
  - files: `gateway/config.py`, `gateway/platform_registry.py`, `gateway/platforms/ADDING_A_PLATFORM.md`, `gateway/run.py`, `gateway/slash_commands.py`, `gateway/yaml_env.py`, `hermes_cli/gateway.py`, `hermes_cli/gateway_windows.py`, `hermes_cli/web_server.py`, `plugins/platforms/buzz/adapter.py`, `plugins/platforms/dingtalk/adapter.py`, `plugins/platforms/discord/adapter.py`, `plugins/platforms/feishu/adapter.py`, `plugins/platforms/matrix/adapter.py`, `plugins/platforms/mattermost/adapter.py`, `plugins/platforms/slack/adapter.py`, `plugins/platforms/telegram/adapter.py`, `plugins/platforms/whatsapp/adapter.py`, `tests/gateway/fixtures/issue-13582-telegram-self-restart.json`, `tests/gateway/test_config.py` (+8 more)
- **#42736: fix(terminal): ignore malformed docker JSON outside docker backend**. closed without merge
  - maintainer direction: category `superseded_by_pr`; implication `superseded`; refs `#42733`, `#42725`
- **#42791: fix(terminal): use safe JSON parser for docker env vars (#42725)**. closed without merge
  - maintainer direction: category `superseded_by_pr`; implication `superseded`; refs `#42733`, `#42725`, `#42733`
- **#42910: fix(terminal): ignore docker config JSON on local backend**. closed without merge
  - maintainer direction: category `superseded_by_pr`; implication `superseded`; refs `#42733`
- **#42911: fix(terminal): guard Docker env var parsing against non-Docker backends**. closed without merge
  - maintainer direction: category `duplicate_of`; implication `duplicate`; refs `#42733`
- **#89451: fix(discord): explicit DISCORD_FREE_RESPONSE_CHANNELS beats config.yaml**. open
  - maintainer direction: category `uncategorized`; implication `needs_llm`
  - files: `contributors/emails/[redacted:email]`, `plugins/platforms/discord/adapter.py`, `tests/gateway/test_discord_free_response.py`

## Fix status

- Merged to main in PR #21240 (cited above). No release data is tracked. Verify downstream.
- Fix last verified (merged) `2026-08-03`.
- Subsystem: `environments`
