feat(tui): expand light-terminal auto-detection (HERMES_TUI_THEME, background hex)#17113
Conversation
There was a problem hiding this comment.
Pull request overview
Expands TUI light/dark theme auto-detection so it works on modern terminals that don’t set COLORFGBG, by adding explicit env overrides and a background-color luminance hint with a clearly ordered precedence chain.
Changes:
- Add
HERMES_TUI_THEME=light|darkas a symmetric explicit override for theme mode selection. - Add
HERMES_TUI_BACKGROUNDhex parsing + Rec.709 luma thresholding to infer light vs dark whenCOLORFGBGis missing. - Tighten/clarify detection precedence so
COLORFGBGremains authoritative when present, with a reservedTERM_PROGRAMallow-list fallback.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| ui-tui/src/theme.ts | Implements ordered detection signals for light mode, including new theme/background env vars and luminance parsing. |
| ui-tui/src/tests/theme.test.ts | Adds tests covering the new env var overrides, background hex luminance behavior, and COLORFGBG precedence. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
7370a9a to
34a0249
Compare
There was a problem hiding this comment.
Pull request overview
Expands the TUI’s light-vs-dark auto-detection so it works on modern terminals that don’t set COLORFGBG, while keeping a clear, ordered precedence of env-based signals.
Changes:
- Adds
HERMES_TUI_THEME=light|darkandHERMES_TUI_BACKGROUND(hex → luminance) as higher-priority signals thanCOLORFGBG. - Makes
COLORFGBG“authoritative” when present (non-light 0–15 values block later fallbacks). - Adds new unit tests covering
HERMES_TUI_THEMEandHERMES_TUI_BACKGROUNDbehavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| ui-tui/src/theme.ts | Implements ordered detection signals, adds hex→luma parsing, and preserves COLORFGBG precedence when present. |
| ui-tui/src/tests/theme.test.ts | Adds tests for new env signals and precedence expectations. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
34a0249 to
89a2c67
Compare
There was a problem hiding this comment.
Pull request overview
Expands the TUI’s light/dark theme auto-detection to work in modern terminals that don’t reliably set COLORFGBG, by adding additional env-based signals with a clear precedence chain.
Changes:
- Add
HERMES_TUI_THEME=light|darkas an explicit symmetric override. - Add
HERMES_TUI_BACKGROUND(3/6-digit hex) luminance-based detection with strict validation. - Make
COLORFGBGauthoritative when present and introduce a (currently empty)TERM_PROGRAMallow-list as a last-resort hook.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| ui-tui/src/theme.ts | Implements ordered light/dark detection via new env signals and luminance parsing. |
| ui-tui/src/tests/theme.test.ts | Adds tests covering HERMES_TUI_THEME, background hex luminance, and invalid hex rejection. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… hex)
Modern terminals (Ghostty, Warp, iTerm2) don't set COLORFGBG, so the
auto-light path was effectively COLORFGBG-only and silently broken for
many users. Two pragmatic additions, both opt-in, plus a clearer
priority chain:
1. **`HERMES_TUI_THEME=light|dark`** as a symmetric explicit override.
The existing `HERMES_TUI_LIGHT` is fine but reads as boolean noise;
a named theme env var matches `display.skin` muscle memory.
2. **`HERMES_TUI_BACKGROUND` hex/rgb hint.** Lets advanced users
(or a future OSC11 query helper that caches the answer) state a
ground-truth background colour. Decoded to Rec. 709 luma; ≥ 0.6
counts as light.
Priority order is now fully ordered and explainable:
1. `HERMES_TUI_LIGHT` (1/0/true/false/on/off).
2. `HERMES_TUI_THEME=light|dark`.
3. `HERMES_TUI_BACKGROUND` luminance.
4. `COLORFGBG` last field — light slots 7/15 → light, 0–15 → dark
(authoritative when set, so the new TERM_PROGRAM path can never
stomp on a terminal that already volunteered a dark answer).
5. `TERM_PROGRAM` allow-list — empty by default. The slot is left
in place because folks asked for it but populating it risks
wrongly flipping users on Apple_Terminal / iTerm2 dark profiles
to light. Easy to add per terminal once we have signal.
Tests: 5 new cases in `theme.test.ts` covering theme env, background
hex (3- and 6-char), invalid hex falling through, and COLORFGBG taking
precedence over the future allow-list.
Validation: `npm run type-check` clean, `npm test --run` 392/392.
…rovable Copilot review on PR #17113: `LIGHT_DEFAULT_TERM_PROGRAMS` is empty in production, so the prior assertion would have passed even if `detectLightMode` ignored `COLORFGBG` entirely. That defeats the test's purpose. `detectLightMode` now takes the allow-list as an optional second argument (defaults to the production set). The test injects a set containing `Apple_Terminal`, asserts the allow-list alone WOULD return light, then asserts `COLORFGBG: '15;0'` overrides it — the precedence rule is now exercised, not assumed.
89a2c67 to
c4a2645
Compare
There was a problem hiding this comment.
Pull request overview
This PR improves the TUI’s light-vs-dark theme auto-detection by adding additional, explicitly ordered environment signals beyond COLORFGBG, making theme selection more reliable in modern terminals that don’t populate COLORFGBG.
Changes:
- Extends
detectLightMode()to honorHERMES_TUI_THEME=light|darkandHERMES_TUI_BACKGROUND(3/6-digit hex → Rec.709 luma threshold). - Refactors the precedence chain so overrides are ordered and explainable, with
COLORFGBGtreated as authoritative when present. - Adds Vitest coverage for the new env signals, strict hex validation, and TERM_PROGRAM precedence behavior (via injectable allow-list).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| ui-tui/src/theme.ts | Adds new env-based light/dark detection signals and codifies the precedence chain. |
| ui-tui/src/tests/theme.test.ts | Adds tests for HERMES_TUI_THEME, HERMES_TUI_BACKGROUND, strict hex rejection, and TERM_PROGRAM allow-list precedence. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…LT_THEME tests Round 2 Copilot review on PR #17113: 1. `Number(colorfgbg.split(';').at(-1))` returns 0 for an empty trailing field (e.g. `COLORFGBG='15;'` → bg===0), which would have looked like an authoritative dark slot and incorrectly blocked the TERM_PROGRAM allow-list. Added a `/^\d+$/` guard before coercion; non-numeric trailing fields now fall through. 2. Fixed the misleading '0–6 / 8–15 ranges are dark' comment — the block returns true for bg===15, so the range is actually 0–6 / 8–14. 3. `DEFAULT_THEME` is computed from `process.env` at module-load. A developer shell with `HERMES_TUI_THEME=light` (or a bright `HERMES_TUI_BACKGROUND`) would flip it and break local tests. The DEFAULT_THEME describe blocks now sterilize the relevant env vars + dynamically import theme.ts (vi.resetModules pattern from platform.test.ts). fromSkin tests compare against DARK_THEME directly to decouple them from ambient env.
There was a problem hiding this comment.
Pull request overview
Expands the TUI’s light-vs-dark theme auto-detection so it works on modern terminals that don’t set COLORFGBG, by adding additional ordered env-based signals and strengthening test coverage around precedence and parsing.
Changes:
- Adds
HERMES_TUI_THEME=light|darkandHERMES_TUI_BACKGROUND(3-/6-digit hex) as new, ordered inputs todetectLightMode(). - Makes
COLORFGBGparsing stricter (numeric trailing token) and treatsCOLORFGBGas authoritative within the 0–15 range. - Updates theme tests to avoid
DEFAULT_THEMEflakiness by importing with a cleaned environment and adds new precedence/parsing tests.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
ui-tui/src/theme.ts |
Implements ordered, explainable light/dark detection with new env signals and stricter parsing. |
ui-tui/src/__tests__/theme.test.ts |
Adds tests for new signals and attempts to de-flake DEFAULT_THEME assertions via env stubbing + dynamic import. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Round 3 Copilot review on PR #17113: the static top-level imports of `fromSkin`, `DARK_THEME`, `LIGHT_THEME` evaluated theme.ts before `importThemeWithCleanEnv` had a chance to clean the env. Because `fromSkin` closes over `DEFAULT_THEME`, an ambient `HERMES_TUI_THEME=light` or bright `HERMES_TUI_BACKGROUND` would still flip the base palette and cause local-only failures. Removed the static import entirely. Every test now obtains its theme symbols via `importThemeWithCleanEnv`, including `detectLightMode` (for consistency, even though it takes env as a parameter). `fromSkin` tests assert against the cleaned `DEFAULT_THEME` from the same dynamic import — preserves the actual contract (skins extend the ambient base palette) without coupling the test to dev-shell state. Verified by running with HERMES_TUI_THEME=light + HERMES_TUI_BACKGROUND=#ffffff: all 20 theme tests still pass. Self-review (avoid round 4): - Audited other test files importing DEFAULT_THEME (syntax.test.ts, streamingMarkdown.test.ts, constants.test.ts) — all just pass it as a parameter or assert palette property existence (works on both light + dark), so no env coupling there.
There was a problem hiding this comment.
Pull request overview
This PR improves the TUI’s light/dark theme auto-detection so it works on modern terminals that don’t set COLORFGBG, while keeping the decision order explicit and testable.
Changes:
- Expands
detectLightMode()to supportHERMES_TUI_THEME=light|darkandHERMES_TUI_BACKGROUND(3/6-digit hex → Rec.709 luma). - Makes
COLORFGBGhandling stricter (numeric validation + “authoritative” behavior for ANSI 0–15 slots). - Updates/extends tests to be env-immune by sanitizing relevant
process.envvars and dynamically importing the theme module.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| ui-tui/src/theme.ts | Adds ordered, explainable light/dark detection with new env signals and stricter parsing/precedence rules. |
| ui-tui/src/tests/theme.test.ts | Adds coverage for new signals and precedence; hardens tests against ambient developer env via env stubbing + dynamic imports. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…ers (#17727) Covers ~60 merged PRs from Apr 15–29 that shipped user-visible behavior without docs coverage. No functional code changes; docs + static manifest regeneration only. Highlights: Stale / incorrect: - configuration.md: auxiliary auto-routing line was wrong since #11900; now correctly states auto routes to the main model, with a note on the cost trade-off and per-task override pattern. - integrations/providers.md + configuration.md compression intro: removed stale 'Gemini Flash via OpenRouter' claim. - website/static/api/model-catalog.json: rebuilt from hermes_cli/models.py so the live manifest picks up tencent/hy3-preview (and remains in sync for future model-catalog PRs). Platform messaging (#17417 #16997 #16193 #14315 #13151 #11794 #10610 #10283 #10246 #11564 #13178): - Signal: native formatting (bodyRanges), reply quotes, reactions. - Telegram: table rendering (bullets + code-block fallback), disable_link_previews, group_allowed_chats. - Slack: strict_mention config. - Discord: slash_commands disable, send_animation GIF, send_message native media attachments. - DingTalk: require_mention + allowed_users. CLI (#16052 #16539 #16566 #15841 #14798 #10043): - New 'hermes fallback' interactive manager. - New 'hermes update --check', '--backup' flag, and pre-update pairing snapshot behavior. - 'hermes gateway start/restart --all' multi-profile flag. - cron.md: 'hermes tools' as a platform, per-job enabled_toolsets, wakeAgent gate, context_from chaining. Config keys / env vars (#17305 #17026 #17000 #15077 #14557 #14227 #14166 #14730 #17008): - terminal.docker_run_as_host_user, display.runtime_metadata_footer, compression.hygiene_hard_message_limit, HINDSIGHT_TIMEOUT, skills.guard_agent_created, TAVILY_BASE_URL, security.allow_private_urls, agent.api_max_retries, gateway hot-reload of compression/context_length config edits. TUI / CLI UX (#17130 #17113 #17175 #17150 #16707 #12312 #12305 #12934 #14810 #14045 #17286 #17126): - HERMES_TUI_RESUME, HERMES_TUI_THEME, LaTeX rendering, busy-indicator styles, ctrl-x queued-message delete, git branch in status bar, per- prompt elapsed stopwatch, external-editor keybind, markdown stripping, TUI voice-mode parity, /agents overlay, /reload + /mouse. Gateway features (#16506 #15027 #13428 #12116): - Native multimodal image routing based on vision capability. - /usage account-limits section. - /steer slash command (added to reference + explanation in CLI). Plugins / hooks (#12929 #12972 #10763 #16364): - transform_tool_result, transform_terminal_output plugin hooks. - PluginContext.dispatch_tool() documented with slash-command example. - google_meet bundled plugin entry under built-in-plugins.md. Other (#16576 #16572 #16383 #15878 #15608 #15606 #14809 #14767 #14231 #14232 #14307 #13683 #12373 #11891 #11291 #10066): - hermes backup exclusions (WAL/SHM/journal + checkpoints/). - security.md hardline blocklist (floor below --yolo). - FHS install layout for root installs. - openssh-client + docker-cli baked into the Docker image. - MEDIA: tag supported extensions table (docs/office/archives/pdf). - Remote-to-host file sync on SSH/Modal/Daytona teardown. - 'hermes model' -> Configure Auxiliary Models interactive picker. - Podman support via HERMES_DOCKER_BINARY. Providers / STT / one-shot (#15045 #14473 #15704): - alibaba-coding-plan first-class provider entry. - xAI Grok STT as a 6th transcription option. - 'hermes -z' scripted one-shot mode + HERMES_INFERENCE_MODEL. Build: 'docusaurus build' succeeds. No new broken links/anchors; pre-existing warnings unchanged.
…ckground hex) (NousResearch#17113) * feat(tui): expand light-terminal auto-detection (HERMES_TUI_THEME, BG hex) Modern terminals (Ghostty, Warp, iTerm2) don't set COLORFGBG, so the auto-light path was effectively COLORFGBG-only and silently broken for many users. Two pragmatic additions, both opt-in, plus a clearer priority chain: 1. **`HERMES_TUI_THEME=light|dark`** as a symmetric explicit override. The existing `HERMES_TUI_LIGHT` is fine but reads as boolean noise; a named theme env var matches `display.skin` muscle memory. 2. **`HERMES_TUI_BACKGROUND` hex/rgb hint.** Lets advanced users (or a future OSC11 query helper that caches the answer) state a ground-truth background colour. Decoded to Rec. 709 luma; ≥ 0.6 counts as light. Priority order is now fully ordered and explainable: 1. `HERMES_TUI_LIGHT` (1/0/true/false/on/off). 2. `HERMES_TUI_THEME=light|dark`. 3. `HERMES_TUI_BACKGROUND` luminance. 4. `COLORFGBG` last field — light slots 7/15 → light, 0–15 → dark (authoritative when set, so the new TERM_PROGRAM path can never stomp on a terminal that already volunteered a dark answer). 5. `TERM_PROGRAM` allow-list — empty by default. The slot is left in place because folks asked for it but populating it risks wrongly flipping users on Apple_Terminal / iTerm2 dark profiles to light. Easy to add per terminal once we have signal. Tests: 5 new cases in `theme.test.ts` covering theme env, background hex (3- and 6-char), invalid hex falling through, and COLORFGBG taking precedence over the future allow-list. Validation: `npm run type-check` clean, `npm test --run` 392/392. * review(copilot): tighten theme detection comments + drop unnecessary cast * review(copilot): strict hex regex so partial garbage doesn't slip into luminance * test(tui): make TERM_PROGRAM allow-list injectable so precedence is provable Copilot review on PR NousResearch#17113: `LIGHT_DEFAULT_TERM_PROGRAMS` is empty in production, so the prior assertion would have passed even if `detectLightMode` ignored `COLORFGBG` entirely. That defeats the test's purpose. `detectLightMode` now takes the allow-list as an optional second argument (defaults to the production set). The test injects a set containing `Apple_Terminal`, asserts the allow-list alone WOULD return light, then asserts `COLORFGBG: '15;0'` overrides it — the precedence rule is now exercised, not assumed. * fix(tui): COLORFGBG empty-trailing-field falls through; isolate DEFAULT_THEME tests Round 2 Copilot review on PR NousResearch#17113: 1. `Number(colorfgbg.split(';').at(-1))` returns 0 for an empty trailing field (e.g. `COLORFGBG='15;'` → bg===0), which would have looked like an authoritative dark slot and incorrectly blocked the TERM_PROGRAM allow-list. Added a `/^\d+$/` guard before coercion; non-numeric trailing fields now fall through. 2. Fixed the misleading '0–6 / 8–15 ranges are dark' comment — the block returns true for bg===15, so the range is actually 0–6 / 8–14. 3. `DEFAULT_THEME` is computed from `process.env` at module-load. A developer shell with `HERMES_TUI_THEME=light` (or a bright `HERMES_TUI_BACKGROUND`) would flip it and break local tests. The DEFAULT_THEME describe blocks now sterilize the relevant env vars + dynamically import theme.ts (vi.resetModules pattern from platform.test.ts). fromSkin tests compare against DARK_THEME directly to decouple them from ambient env. * test(tui): isolate ALL env-coupled theme symbols, not just DEFAULT_THEME Round 3 Copilot review on PR NousResearch#17113: the static top-level imports of `fromSkin`, `DARK_THEME`, `LIGHT_THEME` evaluated theme.ts before `importThemeWithCleanEnv` had a chance to clean the env. Because `fromSkin` closes over `DEFAULT_THEME`, an ambient `HERMES_TUI_THEME=light` or bright `HERMES_TUI_BACKGROUND` would still flip the base palette and cause local-only failures. Removed the static import entirely. Every test now obtains its theme symbols via `importThemeWithCleanEnv`, including `detectLightMode` (for consistency, even though it takes env as a parameter). `fromSkin` tests assert against the cleaned `DEFAULT_THEME` from the same dynamic import — preserves the actual contract (skins extend the ambient base palette) without coupling the test to dev-shell state. Verified by running with HERMES_TUI_THEME=light + HERMES_TUI_BACKGROUND=#ffffff: all 20 theme tests still pass. Self-review (avoid round 4): - Audited other test files importing DEFAULT_THEME (syntax.test.ts, streamingMarkdown.test.ts, constants.test.ts) — all just pass it as a parameter or assert palette property existence (works on both light + dark), so no env coupling there.
…ckground hex) (NousResearch#17113) * feat(tui): expand light-terminal auto-detection (HERMES_TUI_THEME, BG hex) Modern terminals (Ghostty, Warp, iTerm2) don't set COLORFGBG, so the auto-light path was effectively COLORFGBG-only and silently broken for many users. Two pragmatic additions, both opt-in, plus a clearer priority chain: 1. **`HERMES_TUI_THEME=light|dark`** as a symmetric explicit override. The existing `HERMES_TUI_LIGHT` is fine but reads as boolean noise; a named theme env var matches `display.skin` muscle memory. 2. **`HERMES_TUI_BACKGROUND` hex/rgb hint.** Lets advanced users (or a future OSC11 query helper that caches the answer) state a ground-truth background colour. Decoded to Rec. 709 luma; ≥ 0.6 counts as light. Priority order is now fully ordered and explainable: 1. `HERMES_TUI_LIGHT` (1/0/true/false/on/off). 2. `HERMES_TUI_THEME=light|dark`. 3. `HERMES_TUI_BACKGROUND` luminance. 4. `COLORFGBG` last field — light slots 7/15 → light, 0–15 → dark (authoritative when set, so the new TERM_PROGRAM path can never stomp on a terminal that already volunteered a dark answer). 5. `TERM_PROGRAM` allow-list — empty by default. The slot is left in place because folks asked for it but populating it risks wrongly flipping users on Apple_Terminal / iTerm2 dark profiles to light. Easy to add per terminal once we have signal. Tests: 5 new cases in `theme.test.ts` covering theme env, background hex (3- and 6-char), invalid hex falling through, and COLORFGBG taking precedence over the future allow-list. Validation: `npm run type-check` clean, `npm test --run` 392/392. * review(copilot): tighten theme detection comments + drop unnecessary cast * review(copilot): strict hex regex so partial garbage doesn't slip into luminance * test(tui): make TERM_PROGRAM allow-list injectable so precedence is provable Copilot review on PR NousResearch#17113: `LIGHT_DEFAULT_TERM_PROGRAMS` is empty in production, so the prior assertion would have passed even if `detectLightMode` ignored `COLORFGBG` entirely. That defeats the test's purpose. `detectLightMode` now takes the allow-list as an optional second argument (defaults to the production set). The test injects a set containing `Apple_Terminal`, asserts the allow-list alone WOULD return light, then asserts `COLORFGBG: '15;0'` overrides it — the precedence rule is now exercised, not assumed. * fix(tui): COLORFGBG empty-trailing-field falls through; isolate DEFAULT_THEME tests Round 2 Copilot review on PR NousResearch#17113: 1. `Number(colorfgbg.split(';').at(-1))` returns 0 for an empty trailing field (e.g. `COLORFGBG='15;'` → bg===0), which would have looked like an authoritative dark slot and incorrectly blocked the TERM_PROGRAM allow-list. Added a `/^\d+$/` guard before coercion; non-numeric trailing fields now fall through. 2. Fixed the misleading '0–6 / 8–15 ranges are dark' comment — the block returns true for bg===15, so the range is actually 0–6 / 8–14. 3. `DEFAULT_THEME` is computed from `process.env` at module-load. A developer shell with `HERMES_TUI_THEME=light` (or a bright `HERMES_TUI_BACKGROUND`) would flip it and break local tests. The DEFAULT_THEME describe blocks now sterilize the relevant env vars + dynamically import theme.ts (vi.resetModules pattern from platform.test.ts). fromSkin tests compare against DARK_THEME directly to decouple them from ambient env. * test(tui): isolate ALL env-coupled theme symbols, not just DEFAULT_THEME Round 3 Copilot review on PR NousResearch#17113: the static top-level imports of `fromSkin`, `DARK_THEME`, `LIGHT_THEME` evaluated theme.ts before `importThemeWithCleanEnv` had a chance to clean the env. Because `fromSkin` closes over `DEFAULT_THEME`, an ambient `HERMES_TUI_THEME=light` or bright `HERMES_TUI_BACKGROUND` would still flip the base palette and cause local-only failures. Removed the static import entirely. Every test now obtains its theme symbols via `importThemeWithCleanEnv`, including `detectLightMode` (for consistency, even though it takes env as a parameter). `fromSkin` tests assert against the cleaned `DEFAULT_THEME` from the same dynamic import — preserves the actual contract (skins extend the ambient base palette) without coupling the test to dev-shell state. Verified by running with HERMES_TUI_THEME=light + HERMES_TUI_BACKGROUND=#ffffff: all 20 theme tests still pass. Self-review (avoid round 4): - Audited other test files importing DEFAULT_THEME (syntax.test.ts, streamingMarkdown.test.ts, constants.test.ts) — all just pass it as a parameter or assert palette property existence (works on both light + dark), so no env coupling there.
…ers (NousResearch#17727) Covers ~60 merged PRs from Apr 15–29 that shipped user-visible behavior without docs coverage. No functional code changes; docs + static manifest regeneration only. Highlights: Stale / incorrect: - configuration.md: auxiliary auto-routing line was wrong since NousResearch#11900; now correctly states auto routes to the main model, with a note on the cost trade-off and per-task override pattern. - integrations/providers.md + configuration.md compression intro: removed stale 'Gemini Flash via OpenRouter' claim. - website/static/api/model-catalog.json: rebuilt from hermes_cli/models.py so the live manifest picks up tencent/hy3-preview (and remains in sync for future model-catalog PRs). Platform messaging (NousResearch#17417 NousResearch#16997 NousResearch#16193 NousResearch#14315 NousResearch#13151 NousResearch#11794 NousResearch#10610 NousResearch#10283 NousResearch#10246 NousResearch#11564 NousResearch#13178): - Signal: native formatting (bodyRanges), reply quotes, reactions. - Telegram: table rendering (bullets + code-block fallback), disable_link_previews, group_allowed_chats. - Slack: strict_mention config. - Discord: slash_commands disable, send_animation GIF, send_message native media attachments. - DingTalk: require_mention + allowed_users. CLI (NousResearch#16052 NousResearch#16539 NousResearch#16566 NousResearch#15841 NousResearch#14798 NousResearch#10043): - New 'hermes fallback' interactive manager. - New 'hermes update --check', '--backup' flag, and pre-update pairing snapshot behavior. - 'hermes gateway start/restart --all' multi-profile flag. - cron.md: 'hermes tools' as a platform, per-job enabled_toolsets, wakeAgent gate, context_from chaining. Config keys / env vars (NousResearch#17305 NousResearch#17026 NousResearch#17000 NousResearch#15077 NousResearch#14557 NousResearch#14227 NousResearch#14166 NousResearch#14730 NousResearch#17008): - terminal.docker_run_as_host_user, display.runtime_metadata_footer, compression.hygiene_hard_message_limit, HINDSIGHT_TIMEOUT, skills.guard_agent_created, TAVILY_BASE_URL, security.allow_private_urls, agent.api_max_retries, gateway hot-reload of compression/context_length config edits. TUI / CLI UX (NousResearch#17130 NousResearch#17113 NousResearch#17175 NousResearch#17150 NousResearch#16707 NousResearch#12312 NousResearch#12305 NousResearch#12934 NousResearch#14810 NousResearch#14045 NousResearch#17286 NousResearch#17126): - HERMES_TUI_RESUME, HERMES_TUI_THEME, LaTeX rendering, busy-indicator styles, ctrl-x queued-message delete, git branch in status bar, per- prompt elapsed stopwatch, external-editor keybind, markdown stripping, TUI voice-mode parity, /agents overlay, /reload + /mouse. Gateway features (NousResearch#16506 NousResearch#15027 NousResearch#13428 NousResearch#12116): - Native multimodal image routing based on vision capability. - /usage account-limits section. - /steer slash command (added to reference + explanation in CLI). Plugins / hooks (NousResearch#12929 NousResearch#12972 NousResearch#10763 NousResearch#16364): - transform_tool_result, transform_terminal_output plugin hooks. - PluginContext.dispatch_tool() documented with slash-command example. - google_meet bundled plugin entry under built-in-plugins.md. Other (NousResearch#16576 NousResearch#16572 NousResearch#16383 NousResearch#15878 NousResearch#15608 NousResearch#15606 NousResearch#14809 NousResearch#14767 NousResearch#14231 NousResearch#14232 NousResearch#14307 NousResearch#13683 NousResearch#12373 NousResearch#11891 NousResearch#11291 NousResearch#10066): - hermes backup exclusions (WAL/SHM/journal + checkpoints/). - security.md hardline blocklist (floor below --yolo). - FHS install layout for root installs. - openssh-client + docker-cli baked into the Docker image. - MEDIA: tag supported extensions table (docs/office/archives/pdf). - Remote-to-host file sync on SSH/Modal/Daytona teardown. - 'hermes model' -> Configure Auxiliary Models interactive picker. - Podman support via HERMES_DOCKER_BINARY. Providers / STT / one-shot (NousResearch#15045 NousResearch#14473 NousResearch#15704): - alibaba-coding-plan first-class provider entry. - xAI Grok STT as a 6th transcription option. - 'hermes -z' scripted one-shot mode + HERMES_INFERENCE_MODEL. Build: 'docusaurus build' succeeds. No new broken links/anchors; pre-existing warnings unchanged.
…ckground hex) (NousResearch#17113) * feat(tui): expand light-terminal auto-detection (HERMES_TUI_THEME, BG hex) Modern terminals (Ghostty, Warp, iTerm2) don't set COLORFGBG, so the auto-light path was effectively COLORFGBG-only and silently broken for many users. Two pragmatic additions, both opt-in, plus a clearer priority chain: 1. **`HERMES_TUI_THEME=light|dark`** as a symmetric explicit override. The existing `HERMES_TUI_LIGHT` is fine but reads as boolean noise; a named theme env var matches `display.skin` muscle memory. 2. **`HERMES_TUI_BACKGROUND` hex/rgb hint.** Lets advanced users (or a future OSC11 query helper that caches the answer) state a ground-truth background colour. Decoded to Rec. 709 luma; ≥ 0.6 counts as light. Priority order is now fully ordered and explainable: 1. `HERMES_TUI_LIGHT` (1/0/true/false/on/off). 2. `HERMES_TUI_THEME=light|dark`. 3. `HERMES_TUI_BACKGROUND` luminance. 4. `COLORFGBG` last field — light slots 7/15 → light, 0–15 → dark (authoritative when set, so the new TERM_PROGRAM path can never stomp on a terminal that already volunteered a dark answer). 5. `TERM_PROGRAM` allow-list — empty by default. The slot is left in place because folks asked for it but populating it risks wrongly flipping users on Apple_Terminal / iTerm2 dark profiles to light. Easy to add per terminal once we have signal. Tests: 5 new cases in `theme.test.ts` covering theme env, background hex (3- and 6-char), invalid hex falling through, and COLORFGBG taking precedence over the future allow-list. Validation: `npm run type-check` clean, `npm test --run` 392/392. * review(copilot): tighten theme detection comments + drop unnecessary cast * review(copilot): strict hex regex so partial garbage doesn't slip into luminance * test(tui): make TERM_PROGRAM allow-list injectable so precedence is provable Copilot review on PR NousResearch#17113: `LIGHT_DEFAULT_TERM_PROGRAMS` is empty in production, so the prior assertion would have passed even if `detectLightMode` ignored `COLORFGBG` entirely. That defeats the test's purpose. `detectLightMode` now takes the allow-list as an optional second argument (defaults to the production set). The test injects a set containing `Apple_Terminal`, asserts the allow-list alone WOULD return light, then asserts `COLORFGBG: '15;0'` overrides it — the precedence rule is now exercised, not assumed. * fix(tui): COLORFGBG empty-trailing-field falls through; isolate DEFAULT_THEME tests Round 2 Copilot review on PR NousResearch#17113: 1. `Number(colorfgbg.split(';').at(-1))` returns 0 for an empty trailing field (e.g. `COLORFGBG='15;'` → bg===0), which would have looked like an authoritative dark slot and incorrectly blocked the TERM_PROGRAM allow-list. Added a `/^\d+$/` guard before coercion; non-numeric trailing fields now fall through. 2. Fixed the misleading '0–6 / 8–15 ranges are dark' comment — the block returns true for bg===15, so the range is actually 0–6 / 8–14. 3. `DEFAULT_THEME` is computed from `process.env` at module-load. A developer shell with `HERMES_TUI_THEME=light` (or a bright `HERMES_TUI_BACKGROUND`) would flip it and break local tests. The DEFAULT_THEME describe blocks now sterilize the relevant env vars + dynamically import theme.ts (vi.resetModules pattern from platform.test.ts). fromSkin tests compare against DARK_THEME directly to decouple them from ambient env. * test(tui): isolate ALL env-coupled theme symbols, not just DEFAULT_THEME Round 3 Copilot review on PR NousResearch#17113: the static top-level imports of `fromSkin`, `DARK_THEME`, `LIGHT_THEME` evaluated theme.ts before `importThemeWithCleanEnv` had a chance to clean the env. Because `fromSkin` closes over `DEFAULT_THEME`, an ambient `HERMES_TUI_THEME=light` or bright `HERMES_TUI_BACKGROUND` would still flip the base palette and cause local-only failures. Removed the static import entirely. Every test now obtains its theme symbols via `importThemeWithCleanEnv`, including `detectLightMode` (for consistency, even though it takes env as a parameter). `fromSkin` tests assert against the cleaned `DEFAULT_THEME` from the same dynamic import — preserves the actual contract (skins extend the ambient base palette) without coupling the test to dev-shell state. Verified by running with HERMES_TUI_THEME=light + HERMES_TUI_BACKGROUND=#ffffff: all 20 theme tests still pass. Self-review (avoid round 4): - Audited other test files importing DEFAULT_THEME (syntax.test.ts, streamingMarkdown.test.ts, constants.test.ts) — all just pass it as a parameter or assert palette property existence (works on both light + dark), so no env coupling there.
…ers (NousResearch#17727) Covers ~60 merged PRs from Apr 15–29 that shipped user-visible behavior without docs coverage. No functional code changes; docs + static manifest regeneration only. Highlights: Stale / incorrect: - configuration.md: auxiliary auto-routing line was wrong since NousResearch#11900; now correctly states auto routes to the main model, with a note on the cost trade-off and per-task override pattern. - integrations/providers.md + configuration.md compression intro: removed stale 'Gemini Flash via OpenRouter' claim. - website/static/api/model-catalog.json: rebuilt from hermes_cli/models.py so the live manifest picks up tencent/hy3-preview (and remains in sync for future model-catalog PRs). Platform messaging (NousResearch#17417 NousResearch#16997 NousResearch#16193 NousResearch#14315 NousResearch#13151 NousResearch#11794 NousResearch#10610 NousResearch#10283 NousResearch#10246 NousResearch#11564 NousResearch#13178): - Signal: native formatting (bodyRanges), reply quotes, reactions. - Telegram: table rendering (bullets + code-block fallback), disable_link_previews, group_allowed_chats. - Slack: strict_mention config. - Discord: slash_commands disable, send_animation GIF, send_message native media attachments. - DingTalk: require_mention + allowed_users. CLI (NousResearch#16052 NousResearch#16539 NousResearch#16566 NousResearch#15841 NousResearch#14798 NousResearch#10043): - New 'hermes fallback' interactive manager. - New 'hermes update --check', '--backup' flag, and pre-update pairing snapshot behavior. - 'hermes gateway start/restart --all' multi-profile flag. - cron.md: 'hermes tools' as a platform, per-job enabled_toolsets, wakeAgent gate, context_from chaining. Config keys / env vars (NousResearch#17305 NousResearch#17026 NousResearch#17000 NousResearch#15077 NousResearch#14557 NousResearch#14227 NousResearch#14166 NousResearch#14730 NousResearch#17008): - terminal.docker_run_as_host_user, display.runtime_metadata_footer, compression.hygiene_hard_message_limit, HINDSIGHT_TIMEOUT, skills.guard_agent_created, TAVILY_BASE_URL, security.allow_private_urls, agent.api_max_retries, gateway hot-reload of compression/context_length config edits. TUI / CLI UX (NousResearch#17130 NousResearch#17113 NousResearch#17175 NousResearch#17150 NousResearch#16707 NousResearch#12312 NousResearch#12305 NousResearch#12934 NousResearch#14810 NousResearch#14045 NousResearch#17286 NousResearch#17126): - HERMES_TUI_RESUME, HERMES_TUI_THEME, LaTeX rendering, busy-indicator styles, ctrl-x queued-message delete, git branch in status bar, per- prompt elapsed stopwatch, external-editor keybind, markdown stripping, TUI voice-mode parity, /agents overlay, /reload + /mouse. Gateway features (NousResearch#16506 NousResearch#15027 NousResearch#13428 NousResearch#12116): - Native multimodal image routing based on vision capability. - /usage account-limits section. - /steer slash command (added to reference + explanation in CLI). Plugins / hooks (NousResearch#12929 NousResearch#12972 NousResearch#10763 NousResearch#16364): - transform_tool_result, transform_terminal_output plugin hooks. - PluginContext.dispatch_tool() documented with slash-command example. - google_meet bundled plugin entry under built-in-plugins.md. Other (NousResearch#16576 NousResearch#16572 NousResearch#16383 NousResearch#15878 NousResearch#15608 NousResearch#15606 NousResearch#14809 NousResearch#14767 NousResearch#14231 NousResearch#14232 NousResearch#14307 NousResearch#13683 NousResearch#12373 NousResearch#11891 NousResearch#11291 NousResearch#10066): - hermes backup exclusions (WAL/SHM/journal + checkpoints/). - security.md hardline blocklist (floor below --yolo). - FHS install layout for root installs. - openssh-client + docker-cli baked into the Docker image. - MEDIA: tag supported extensions table (docs/office/archives/pdf). - Remote-to-host file sync on SSH/Modal/Daytona teardown. - 'hermes model' -> Configure Auxiliary Models interactive picker. - Podman support via HERMES_DOCKER_BINARY. Providers / STT / one-shot (NousResearch#15045 NousResearch#14473 NousResearch#15704): - alibaba-coding-plan first-class provider entry. - xAI Grok STT as a 6th transcription option. - 'hermes -z' scripted one-shot mode + HERMES_INFERENCE_MODEL. Build: 'docusaurus build' succeeds. No new broken links/anchors; pre-existing warnings unchanged.
…ers (NousResearch#17727) Covers ~60 merged PRs from Apr 15–29 that shipped user-visible behavior without docs coverage. No functional code changes; docs + static manifest regeneration only. Highlights: Stale / incorrect: - configuration.md: auxiliary auto-routing line was wrong since NousResearch#11900; now correctly states auto routes to the main model, with a note on the cost trade-off and per-task override pattern. - integrations/providers.md + configuration.md compression intro: removed stale 'Gemini Flash via OpenRouter' claim. - website/static/api/model-catalog.json: rebuilt from hermes_cli/models.py so the live manifest picks up tencent/hy3-preview (and remains in sync for future model-catalog PRs). Platform messaging (NousResearch#17417 NousResearch#16997 NousResearch#16193 NousResearch#14315 NousResearch#13151 NousResearch#11794 NousResearch#10610 NousResearch#10283 NousResearch#10246 NousResearch#11564 NousResearch#13178): - Signal: native formatting (bodyRanges), reply quotes, reactions. - Telegram: table rendering (bullets + code-block fallback), disable_link_previews, group_allowed_chats. - Slack: strict_mention config. - Discord: slash_commands disable, send_animation GIF, send_message native media attachments. - DingTalk: require_mention + allowed_users. CLI (NousResearch#16052 NousResearch#16539 NousResearch#16566 NousResearch#15841 NousResearch#14798 NousResearch#10043): - New 'hermes fallback' interactive manager. - New 'hermes update --check', '--backup' flag, and pre-update pairing snapshot behavior. - 'hermes gateway start/restart --all' multi-profile flag. - cron.md: 'hermes tools' as a platform, per-job enabled_toolsets, wakeAgent gate, context_from chaining. Config keys / env vars (NousResearch#17305 NousResearch#17026 NousResearch#17000 NousResearch#15077 NousResearch#14557 NousResearch#14227 NousResearch#14166 NousResearch#14730 NousResearch#17008): - terminal.docker_run_as_host_user, display.runtime_metadata_footer, compression.hygiene_hard_message_limit, HINDSIGHT_TIMEOUT, skills.guard_agent_created, TAVILY_BASE_URL, security.allow_private_urls, agent.api_max_retries, gateway hot-reload of compression/context_length config edits. TUI / CLI UX (NousResearch#17130 NousResearch#17113 NousResearch#17175 NousResearch#17150 NousResearch#16707 NousResearch#12312 NousResearch#12305 NousResearch#12934 NousResearch#14810 NousResearch#14045 NousResearch#17286 NousResearch#17126): - HERMES_TUI_RESUME, HERMES_TUI_THEME, LaTeX rendering, busy-indicator styles, ctrl-x queued-message delete, git branch in status bar, per- prompt elapsed stopwatch, external-editor keybind, markdown stripping, TUI voice-mode parity, /agents overlay, /reload + /mouse. Gateway features (NousResearch#16506 NousResearch#15027 NousResearch#13428 NousResearch#12116): - Native multimodal image routing based on vision capability. - /usage account-limits section. - /steer slash command (added to reference + explanation in CLI). Plugins / hooks (NousResearch#12929 NousResearch#12972 NousResearch#10763 NousResearch#16364): - transform_tool_result, transform_terminal_output plugin hooks. - PluginContext.dispatch_tool() documented with slash-command example. - google_meet bundled plugin entry under built-in-plugins.md. Other (NousResearch#16576 NousResearch#16572 NousResearch#16383 NousResearch#15878 NousResearch#15608 NousResearch#15606 NousResearch#14809 NousResearch#14767 NousResearch#14231 NousResearch#14232 NousResearch#14307 NousResearch#13683 NousResearch#12373 NousResearch#11891 NousResearch#11291 NousResearch#10066): - hermes backup exclusions (WAL/SHM/journal + checkpoints/). - security.md hardline blocklist (floor below --yolo). - FHS install layout for root installs. - openssh-client + docker-cli baked into the Docker image. - MEDIA: tag supported extensions table (docs/office/archives/pdf). - Remote-to-host file sync on SSH/Modal/Daytona teardown. - 'hermes model' -> Configure Auxiliary Models interactive picker. - Podman support via HERMES_DOCKER_BINARY. Providers / STT / one-shot (NousResearch#15045 NousResearch#14473 NousResearch#15704): - alibaba-coding-plan first-class provider entry. - xAI Grok STT as a 6th transcription option. - 'hermes -z' scripted one-shot mode + HERMES_INFERENCE_MODEL. Build: 'docusaurus build' succeeds. No new broken links/anchors; pre-existing warnings unchanged.
…ckground hex) (NousResearch#17113) * feat(tui): expand light-terminal auto-detection (HERMES_TUI_THEME, BG hex) Modern terminals (Ghostty, Warp, iTerm2) don't set COLORFGBG, so the auto-light path was effectively COLORFGBG-only and silently broken for many users. Two pragmatic additions, both opt-in, plus a clearer priority chain: 1. **`HERMES_TUI_THEME=light|dark`** as a symmetric explicit override. The existing `HERMES_TUI_LIGHT` is fine but reads as boolean noise; a named theme env var matches `display.skin` muscle memory. 2. **`HERMES_TUI_BACKGROUND` hex/rgb hint.** Lets advanced users (or a future OSC11 query helper that caches the answer) state a ground-truth background colour. Decoded to Rec. 709 luma; ≥ 0.6 counts as light. Priority order is now fully ordered and explainable: 1. `HERMES_TUI_LIGHT` (1/0/true/false/on/off). 2. `HERMES_TUI_THEME=light|dark`. 3. `HERMES_TUI_BACKGROUND` luminance. 4. `COLORFGBG` last field — light slots 7/15 → light, 0–15 → dark (authoritative when set, so the new TERM_PROGRAM path can never stomp on a terminal that already volunteered a dark answer). 5. `TERM_PROGRAM` allow-list — empty by default. The slot is left in place because folks asked for it but populating it risks wrongly flipping users on Apple_Terminal / iTerm2 dark profiles to light. Easy to add per terminal once we have signal. Tests: 5 new cases in `theme.test.ts` covering theme env, background hex (3- and 6-char), invalid hex falling through, and COLORFGBG taking precedence over the future allow-list. Validation: `npm run type-check` clean, `npm test --run` 392/392. * review(copilot): tighten theme detection comments + drop unnecessary cast * review(copilot): strict hex regex so partial garbage doesn't slip into luminance * test(tui): make TERM_PROGRAM allow-list injectable so precedence is provable Copilot review on PR NousResearch#17113: `LIGHT_DEFAULT_TERM_PROGRAMS` is empty in production, so the prior assertion would have passed even if `detectLightMode` ignored `COLORFGBG` entirely. That defeats the test's purpose. `detectLightMode` now takes the allow-list as an optional second argument (defaults to the production set). The test injects a set containing `Apple_Terminal`, asserts the allow-list alone WOULD return light, then asserts `COLORFGBG: '15;0'` overrides it — the precedence rule is now exercised, not assumed. * fix(tui): COLORFGBG empty-trailing-field falls through; isolate DEFAULT_THEME tests Round 2 Copilot review on PR NousResearch#17113: 1. `Number(colorfgbg.split(';').at(-1))` returns 0 for an empty trailing field (e.g. `COLORFGBG='15;'` → bg===0), which would have looked like an authoritative dark slot and incorrectly blocked the TERM_PROGRAM allow-list. Added a `/^\d+$/` guard before coercion; non-numeric trailing fields now fall through. 2. Fixed the misleading '0–6 / 8–15 ranges are dark' comment — the block returns true for bg===15, so the range is actually 0–6 / 8–14. 3. `DEFAULT_THEME` is computed from `process.env` at module-load. A developer shell with `HERMES_TUI_THEME=light` (or a bright `HERMES_TUI_BACKGROUND`) would flip it and break local tests. The DEFAULT_THEME describe blocks now sterilize the relevant env vars + dynamically import theme.ts (vi.resetModules pattern from platform.test.ts). fromSkin tests compare against DARK_THEME directly to decouple them from ambient env. * test(tui): isolate ALL env-coupled theme symbols, not just DEFAULT_THEME Round 3 Copilot review on PR NousResearch#17113: the static top-level imports of `fromSkin`, `DARK_THEME`, `LIGHT_THEME` evaluated theme.ts before `importThemeWithCleanEnv` had a chance to clean the env. Because `fromSkin` closes over `DEFAULT_THEME`, an ambient `HERMES_TUI_THEME=light` or bright `HERMES_TUI_BACKGROUND` would still flip the base palette and cause local-only failures. Removed the static import entirely. Every test now obtains its theme symbols via `importThemeWithCleanEnv`, including `detectLightMode` (for consistency, even though it takes env as a parameter). `fromSkin` tests assert against the cleaned `DEFAULT_THEME` from the same dynamic import — preserves the actual contract (skins extend the ambient base palette) without coupling the test to dev-shell state. Verified by running with HERMES_TUI_THEME=light + HERMES_TUI_BACKGROUND=#ffffff: all 20 theme tests still pass. Self-review (avoid round 4): - Audited other test files importing DEFAULT_THEME (syntax.test.ts, streamingMarkdown.test.ts, constants.test.ts) — all just pass it as a parameter or assert palette property existence (works on both light + dark), so no env coupling there.
…ers (NousResearch#17727) Covers ~60 merged PRs from Apr 15–29 that shipped user-visible behavior without docs coverage. No functional code changes; docs + static manifest regeneration only. Highlights: Stale / incorrect: - configuration.md: auxiliary auto-routing line was wrong since NousResearch#11900; now correctly states auto routes to the main model, with a note on the cost trade-off and per-task override pattern. - integrations/providers.md + configuration.md compression intro: removed stale 'Gemini Flash via OpenRouter' claim. - website/static/api/model-catalog.json: rebuilt from hermes_cli/models.py so the live manifest picks up tencent/hy3-preview (and remains in sync for future model-catalog PRs). Platform messaging (NousResearch#17417 NousResearch#16997 NousResearch#16193 NousResearch#14315 NousResearch#13151 NousResearch#11794 NousResearch#10610 NousResearch#10283 NousResearch#10246 NousResearch#11564 NousResearch#13178): - Signal: native formatting (bodyRanges), reply quotes, reactions. - Telegram: table rendering (bullets + code-block fallback), disable_link_previews, group_allowed_chats. - Slack: strict_mention config. - Discord: slash_commands disable, send_animation GIF, send_message native media attachments. - DingTalk: require_mention + allowed_users. CLI (NousResearch#16052 NousResearch#16539 NousResearch#16566 NousResearch#15841 NousResearch#14798 NousResearch#10043): - New 'hermes fallback' interactive manager. - New 'hermes update --check', '--backup' flag, and pre-update pairing snapshot behavior. - 'hermes gateway start/restart --all' multi-profile flag. - cron.md: 'hermes tools' as a platform, per-job enabled_toolsets, wakeAgent gate, context_from chaining. Config keys / env vars (NousResearch#17305 NousResearch#17026 NousResearch#17000 NousResearch#15077 NousResearch#14557 NousResearch#14227 NousResearch#14166 NousResearch#14730 NousResearch#17008): - terminal.docker_run_as_host_user, display.runtime_metadata_footer, compression.hygiene_hard_message_limit, HINDSIGHT_TIMEOUT, skills.guard_agent_created, TAVILY_BASE_URL, security.allow_private_urls, agent.api_max_retries, gateway hot-reload of compression/context_length config edits. TUI / CLI UX (NousResearch#17130 NousResearch#17113 NousResearch#17175 NousResearch#17150 NousResearch#16707 NousResearch#12312 NousResearch#12305 NousResearch#12934 NousResearch#14810 NousResearch#14045 NousResearch#17286 NousResearch#17126): - HERMES_TUI_RESUME, HERMES_TUI_THEME, LaTeX rendering, busy-indicator styles, ctrl-x queued-message delete, git branch in status bar, per- prompt elapsed stopwatch, external-editor keybind, markdown stripping, TUI voice-mode parity, /agents overlay, /reload + /mouse. Gateway features (NousResearch#16506 NousResearch#15027 NousResearch#13428 NousResearch#12116): - Native multimodal image routing based on vision capability. - /usage account-limits section. - /steer slash command (added to reference + explanation in CLI). Plugins / hooks (NousResearch#12929 NousResearch#12972 NousResearch#10763 NousResearch#16364): - transform_tool_result, transform_terminal_output plugin hooks. - PluginContext.dispatch_tool() documented with slash-command example. - google_meet bundled plugin entry under built-in-plugins.md. Other (NousResearch#16576 NousResearch#16572 NousResearch#16383 NousResearch#15878 NousResearch#15608 NousResearch#15606 NousResearch#14809 NousResearch#14767 NousResearch#14231 NousResearch#14232 NousResearch#14307 NousResearch#13683 NousResearch#12373 NousResearch#11891 NousResearch#11291 NousResearch#10066): - hermes backup exclusions (WAL/SHM/journal + checkpoints/). - security.md hardline blocklist (floor below --yolo). - FHS install layout for root installs. - openssh-client + docker-cli baked into the Docker image. - MEDIA: tag supported extensions table (docs/office/archives/pdf). - Remote-to-host file sync on SSH/Modal/Daytona teardown. - 'hermes model' -> Configure Auxiliary Models interactive picker. - Podman support via HERMES_DOCKER_BINARY. Providers / STT / one-shot (NousResearch#15045 NousResearch#14473 NousResearch#15704): - alibaba-coding-plan first-class provider entry. - xAI Grok STT as a 6th transcription option. - 'hermes -z' scripted one-shot mode + HERMES_INFERENCE_MODEL. Build: 'docusaurus build' succeeds. No new broken links/anchors; pre-existing warnings unchanged.
…ckground hex) (NousResearch#17113) * feat(tui): expand light-terminal auto-detection (HERMES_TUI_THEME, BG hex) Modern terminals (Ghostty, Warp, iTerm2) don't set COLORFGBG, so the auto-light path was effectively COLORFGBG-only and silently broken for many users. Two pragmatic additions, both opt-in, plus a clearer priority chain: 1. **`HERMES_TUI_THEME=light|dark`** as a symmetric explicit override. The existing `HERMES_TUI_LIGHT` is fine but reads as boolean noise; a named theme env var matches `display.skin` muscle memory. 2. **`HERMES_TUI_BACKGROUND` hex/rgb hint.** Lets advanced users (or a future OSC11 query helper that caches the answer) state a ground-truth background colour. Decoded to Rec. 709 luma; ≥ 0.6 counts as light. Priority order is now fully ordered and explainable: 1. `HERMES_TUI_LIGHT` (1/0/true/false/on/off). 2. `HERMES_TUI_THEME=light|dark`. 3. `HERMES_TUI_BACKGROUND` luminance. 4. `COLORFGBG` last field — light slots 7/15 → light, 0–15 → dark (authoritative when set, so the new TERM_PROGRAM path can never stomp on a terminal that already volunteered a dark answer). 5. `TERM_PROGRAM` allow-list — empty by default. The slot is left in place because folks asked for it but populating it risks wrongly flipping users on Apple_Terminal / iTerm2 dark profiles to light. Easy to add per terminal once we have signal. Tests: 5 new cases in `theme.test.ts` covering theme env, background hex (3- and 6-char), invalid hex falling through, and COLORFGBG taking precedence over the future allow-list. Validation: `npm run type-check` clean, `npm test --run` 392/392. * review(copilot): tighten theme detection comments + drop unnecessary cast * review(copilot): strict hex regex so partial garbage doesn't slip into luminance * test(tui): make TERM_PROGRAM allow-list injectable so precedence is provable Copilot review on PR NousResearch#17113: `LIGHT_DEFAULT_TERM_PROGRAMS` is empty in production, so the prior assertion would have passed even if `detectLightMode` ignored `COLORFGBG` entirely. That defeats the test's purpose. `detectLightMode` now takes the allow-list as an optional second argument (defaults to the production set). The test injects a set containing `Apple_Terminal`, asserts the allow-list alone WOULD return light, then asserts `COLORFGBG: '15;0'` overrides it — the precedence rule is now exercised, not assumed. * fix(tui): COLORFGBG empty-trailing-field falls through; isolate DEFAULT_THEME tests Round 2 Copilot review on PR NousResearch#17113: 1. `Number(colorfgbg.split(';').at(-1))` returns 0 for an empty trailing field (e.g. `COLORFGBG='15;'` → bg===0), which would have looked like an authoritative dark slot and incorrectly blocked the TERM_PROGRAM allow-list. Added a `/^\d+$/` guard before coercion; non-numeric trailing fields now fall through. 2. Fixed the misleading '0–6 / 8–15 ranges are dark' comment — the block returns true for bg===15, so the range is actually 0–6 / 8–14. 3. `DEFAULT_THEME` is computed from `process.env` at module-load. A developer shell with `HERMES_TUI_THEME=light` (or a bright `HERMES_TUI_BACKGROUND`) would flip it and break local tests. The DEFAULT_THEME describe blocks now sterilize the relevant env vars + dynamically import theme.ts (vi.resetModules pattern from platform.test.ts). fromSkin tests compare against DARK_THEME directly to decouple them from ambient env. * test(tui): isolate ALL env-coupled theme symbols, not just DEFAULT_THEME Round 3 Copilot review on PR NousResearch#17113: the static top-level imports of `fromSkin`, `DARK_THEME`, `LIGHT_THEME` evaluated theme.ts before `importThemeWithCleanEnv` had a chance to clean the env. Because `fromSkin` closes over `DEFAULT_THEME`, an ambient `HERMES_TUI_THEME=light` or bright `HERMES_TUI_BACKGROUND` would still flip the base palette and cause local-only failures. Removed the static import entirely. Every test now obtains its theme symbols via `importThemeWithCleanEnv`, including `detectLightMode` (for consistency, even though it takes env as a parameter). `fromSkin` tests assert against the cleaned `DEFAULT_THEME` from the same dynamic import — preserves the actual contract (skins extend the ambient base palette) without coupling the test to dev-shell state. Verified by running with HERMES_TUI_THEME=light + HERMES_TUI_BACKGROUND=#ffffff: all 20 theme tests still pass. Self-review (avoid round 4): - Audited other test files importing DEFAULT_THEME (syntax.test.ts, streamingMarkdown.test.ts, constants.test.ts) — all just pass it as a parameter or assert palette property existence (works on both light + dark), so no env coupling there.
…ers (NousResearch#17727) Covers ~60 merged PRs from Apr 15–29 that shipped user-visible behavior without docs coverage. No functional code changes; docs + static manifest regeneration only. Highlights: Stale / incorrect: - configuration.md: auxiliary auto-routing line was wrong since NousResearch#11900; now correctly states auto routes to the main model, with a note on the cost trade-off and per-task override pattern. - integrations/providers.md + configuration.md compression intro: removed stale 'Gemini Flash via OpenRouter' claim. - website/static/api/model-catalog.json: rebuilt from hermes_cli/models.py so the live manifest picks up tencent/hy3-preview (and remains in sync for future model-catalog PRs). Platform messaging (NousResearch#17417 NousResearch#16997 NousResearch#16193 NousResearch#14315 NousResearch#13151 NousResearch#11794 NousResearch#10610 NousResearch#10283 NousResearch#10246 NousResearch#11564 NousResearch#13178): - Signal: native formatting (bodyRanges), reply quotes, reactions. - Telegram: table rendering (bullets + code-block fallback), disable_link_previews, group_allowed_chats. - Slack: strict_mention config. - Discord: slash_commands disable, send_animation GIF, send_message native media attachments. - DingTalk: require_mention + allowed_users. CLI (NousResearch#16052 NousResearch#16539 NousResearch#16566 NousResearch#15841 NousResearch#14798 NousResearch#10043): - New 'hermes fallback' interactive manager. - New 'hermes update --check', '--backup' flag, and pre-update pairing snapshot behavior. - 'hermes gateway start/restart --all' multi-profile flag. - cron.md: 'hermes tools' as a platform, per-job enabled_toolsets, wakeAgent gate, context_from chaining. Config keys / env vars (NousResearch#17305 NousResearch#17026 NousResearch#17000 NousResearch#15077 NousResearch#14557 NousResearch#14227 NousResearch#14166 NousResearch#14730 NousResearch#17008): - terminal.docker_run_as_host_user, display.runtime_metadata_footer, compression.hygiene_hard_message_limit, HINDSIGHT_TIMEOUT, skills.guard_agent_created, TAVILY_BASE_URL, security.allow_private_urls, agent.api_max_retries, gateway hot-reload of compression/context_length config edits. TUI / CLI UX (NousResearch#17130 NousResearch#17113 NousResearch#17175 NousResearch#17150 NousResearch#16707 NousResearch#12312 NousResearch#12305 NousResearch#12934 NousResearch#14810 NousResearch#14045 NousResearch#17286 NousResearch#17126): - HERMES_TUI_RESUME, HERMES_TUI_THEME, LaTeX rendering, busy-indicator styles, ctrl-x queued-message delete, git branch in status bar, per- prompt elapsed stopwatch, external-editor keybind, markdown stripping, TUI voice-mode parity, /agents overlay, /reload + /mouse. Gateway features (NousResearch#16506 NousResearch#15027 NousResearch#13428 NousResearch#12116): - Native multimodal image routing based on vision capability. - /usage account-limits section. - /steer slash command (added to reference + explanation in CLI). Plugins / hooks (NousResearch#12929 NousResearch#12972 NousResearch#10763 NousResearch#16364): - transform_tool_result, transform_terminal_output plugin hooks. - PluginContext.dispatch_tool() documented with slash-command example. - google_meet bundled plugin entry under built-in-plugins.md. Other (NousResearch#16576 NousResearch#16572 NousResearch#16383 NousResearch#15878 NousResearch#15608 NousResearch#15606 NousResearch#14809 NousResearch#14767 NousResearch#14231 NousResearch#14232 NousResearch#14307 NousResearch#13683 NousResearch#12373 NousResearch#11891 NousResearch#11291 NousResearch#10066): - hermes backup exclusions (WAL/SHM/journal + checkpoints/). - security.md hardline blocklist (floor below --yolo). - FHS install layout for root installs. - openssh-client + docker-cli baked into the Docker image. - MEDIA: tag supported extensions table (docs/office/archives/pdf). - Remote-to-host file sync on SSH/Modal/Daytona teardown. - 'hermes model' -> Configure Auxiliary Models interactive picker. - Podman support via HERMES_DOCKER_BINARY. Providers / STT / one-shot (NousResearch#15045 NousResearch#14473 NousResearch#15704): - alibaba-coding-plan first-class provider entry. - xAI Grok STT as a 6th transcription option. - 'hermes -z' scripted one-shot mode + HERMES_INFERENCE_MODEL. Build: 'docusaurus build' succeeds. No new broken links/anchors; pre-existing warnings unchanged.
…ckground hex) (NousResearch#17113) * feat(tui): expand light-terminal auto-detection (HERMES_TUI_THEME, BG hex) Modern terminals (Ghostty, Warp, iTerm2) don't set COLORFGBG, so the auto-light path was effectively COLORFGBG-only and silently broken for many users. Two pragmatic additions, both opt-in, plus a clearer priority chain: 1. **`HERMES_TUI_THEME=light|dark`** as a symmetric explicit override. The existing `HERMES_TUI_LIGHT` is fine but reads as boolean noise; a named theme env var matches `display.skin` muscle memory. 2. **`HERMES_TUI_BACKGROUND` hex/rgb hint.** Lets advanced users (or a future OSC11 query helper that caches the answer) state a ground-truth background colour. Decoded to Rec. 709 luma; ≥ 0.6 counts as light. Priority order is now fully ordered and explainable: 1. `HERMES_TUI_LIGHT` (1/0/true/false/on/off). 2. `HERMES_TUI_THEME=light|dark`. 3. `HERMES_TUI_BACKGROUND` luminance. 4. `COLORFGBG` last field — light slots 7/15 → light, 0–15 → dark (authoritative when set, so the new TERM_PROGRAM path can never stomp on a terminal that already volunteered a dark answer). 5. `TERM_PROGRAM` allow-list — empty by default. The slot is left in place because folks asked for it but populating it risks wrongly flipping users on Apple_Terminal / iTerm2 dark profiles to light. Easy to add per terminal once we have signal. Tests: 5 new cases in `theme.test.ts` covering theme env, background hex (3- and 6-char), invalid hex falling through, and COLORFGBG taking precedence over the future allow-list. Validation: `npm run type-check` clean, `npm test --run` 392/392. * review(copilot): tighten theme detection comments + drop unnecessary cast * review(copilot): strict hex regex so partial garbage doesn't slip into luminance * test(tui): make TERM_PROGRAM allow-list injectable so precedence is provable Copilot review on PR NousResearch#17113: `LIGHT_DEFAULT_TERM_PROGRAMS` is empty in production, so the prior assertion would have passed even if `detectLightMode` ignored `COLORFGBG` entirely. That defeats the test's purpose. `detectLightMode` now takes the allow-list as an optional second argument (defaults to the production set). The test injects a set containing `Apple_Terminal`, asserts the allow-list alone WOULD return light, then asserts `COLORFGBG: '15;0'` overrides it — the precedence rule is now exercised, not assumed. * fix(tui): COLORFGBG empty-trailing-field falls through; isolate DEFAULT_THEME tests Round 2 Copilot review on PR NousResearch#17113: 1. `Number(colorfgbg.split(';').at(-1))` returns 0 for an empty trailing field (e.g. `COLORFGBG='15;'` → bg===0), which would have looked like an authoritative dark slot and incorrectly blocked the TERM_PROGRAM allow-list. Added a `/^\d+$/` guard before coercion; non-numeric trailing fields now fall through. 2. Fixed the misleading '0–6 / 8–15 ranges are dark' comment — the block returns true for bg===15, so the range is actually 0–6 / 8–14. 3. `DEFAULT_THEME` is computed from `process.env` at module-load. A developer shell with `HERMES_TUI_THEME=light` (or a bright `HERMES_TUI_BACKGROUND`) would flip it and break local tests. The DEFAULT_THEME describe blocks now sterilize the relevant env vars + dynamically import theme.ts (vi.resetModules pattern from platform.test.ts). fromSkin tests compare against DARK_THEME directly to decouple them from ambient env. * test(tui): isolate ALL env-coupled theme symbols, not just DEFAULT_THEME Round 3 Copilot review on PR NousResearch#17113: the static top-level imports of `fromSkin`, `DARK_THEME`, `LIGHT_THEME` evaluated theme.ts before `importThemeWithCleanEnv` had a chance to clean the env. Because `fromSkin` closes over `DEFAULT_THEME`, an ambient `HERMES_TUI_THEME=light` or bright `HERMES_TUI_BACKGROUND` would still flip the base palette and cause local-only failures. Removed the static import entirely. Every test now obtains its theme symbols via `importThemeWithCleanEnv`, including `detectLightMode` (for consistency, even though it takes env as a parameter). `fromSkin` tests assert against the cleaned `DEFAULT_THEME` from the same dynamic import — preserves the actual contract (skins extend the ambient base palette) without coupling the test to dev-shell state. Verified by running with HERMES_TUI_THEME=light + HERMES_TUI_BACKGROUND=#ffffff: all 20 theme tests still pass. Self-review (avoid round 4): - Audited other test files importing DEFAULT_THEME (syntax.test.ts, streamingMarkdown.test.ts, constants.test.ts) — all just pass it as a parameter or assert palette property existence (works on both light + dark), so no env coupling there.
…ers (NousResearch#17727) Covers ~60 merged PRs from Apr 15–29 that shipped user-visible behavior without docs coverage. No functional code changes; docs + static manifest regeneration only. Highlights: Stale / incorrect: - configuration.md: auxiliary auto-routing line was wrong since NousResearch#11900; now correctly states auto routes to the main model, with a note on the cost trade-off and per-task override pattern. - integrations/providers.md + configuration.md compression intro: removed stale 'Gemini Flash via OpenRouter' claim. - website/static/api/model-catalog.json: rebuilt from hermes_cli/models.py so the live manifest picks up tencent/hy3-preview (and remains in sync for future model-catalog PRs). Platform messaging (NousResearch#17417 NousResearch#16997 NousResearch#16193 NousResearch#14315 NousResearch#13151 NousResearch#11794 NousResearch#10610 NousResearch#10283 NousResearch#10246 NousResearch#11564 NousResearch#13178): - Signal: native formatting (bodyRanges), reply quotes, reactions. - Telegram: table rendering (bullets + code-block fallback), disable_link_previews, group_allowed_chats. - Slack: strict_mention config. - Discord: slash_commands disable, send_animation GIF, send_message native media attachments. - DingTalk: require_mention + allowed_users. CLI (NousResearch#16052 NousResearch#16539 NousResearch#16566 NousResearch#15841 NousResearch#14798 NousResearch#10043): - New 'hermes fallback' interactive manager. - New 'hermes update --check', '--backup' flag, and pre-update pairing snapshot behavior. - 'hermes gateway start/restart --all' multi-profile flag. - cron.md: 'hermes tools' as a platform, per-job enabled_toolsets, wakeAgent gate, context_from chaining. Config keys / env vars (NousResearch#17305 NousResearch#17026 NousResearch#17000 NousResearch#15077 NousResearch#14557 NousResearch#14227 NousResearch#14166 NousResearch#14730 NousResearch#17008): - terminal.docker_run_as_host_user, display.runtime_metadata_footer, compression.hygiene_hard_message_limit, HINDSIGHT_TIMEOUT, skills.guard_agent_created, TAVILY_BASE_URL, security.allow_private_urls, agent.api_max_retries, gateway hot-reload of compression/context_length config edits. TUI / CLI UX (NousResearch#17130 NousResearch#17113 NousResearch#17175 NousResearch#17150 NousResearch#16707 NousResearch#12312 NousResearch#12305 NousResearch#12934 NousResearch#14810 NousResearch#14045 NousResearch#17286 NousResearch#17126): - HERMES_TUI_RESUME, HERMES_TUI_THEME, LaTeX rendering, busy-indicator styles, ctrl-x queued-message delete, git branch in status bar, per- prompt elapsed stopwatch, external-editor keybind, markdown stripping, TUI voice-mode parity, /agents overlay, /reload + /mouse. Gateway features (NousResearch#16506 NousResearch#15027 NousResearch#13428 NousResearch#12116): - Native multimodal image routing based on vision capability. - /usage account-limits section. - /steer slash command (added to reference + explanation in CLI). Plugins / hooks (NousResearch#12929 NousResearch#12972 NousResearch#10763 NousResearch#16364): - transform_tool_result, transform_terminal_output plugin hooks. - PluginContext.dispatch_tool() documented with slash-command example. - google_meet bundled plugin entry under built-in-plugins.md. Other (NousResearch#16576 NousResearch#16572 NousResearch#16383 NousResearch#15878 NousResearch#15608 NousResearch#15606 NousResearch#14809 NousResearch#14767 NousResearch#14231 NousResearch#14232 NousResearch#14307 NousResearch#13683 NousResearch#12373 NousResearch#11891 NousResearch#11291 NousResearch#10066): - hermes backup exclusions (WAL/SHM/journal + checkpoints/). - security.md hardline blocklist (floor below --yolo). - FHS install layout for root installs. - openssh-client + docker-cli baked into the Docker image. - MEDIA: tag supported extensions table (docs/office/archives/pdf). - Remote-to-host file sync on SSH/Modal/Daytona teardown. - 'hermes model' -> Configure Auxiliary Models interactive picker. - Podman support via HERMES_DOCKER_BINARY. Providers / STT / one-shot (NousResearch#15045 NousResearch#14473 NousResearch#15704): - alibaba-coding-plan first-class provider entry. - xAI Grok STT as a 6th transcription option. - 'hermes -z' scripted one-shot mode + HERMES_INFERENCE_MODEL. Build: 'docusaurus build' succeeds. No new broken links/anchors; pre-existing warnings unchanged.
Summary
Modern terminals (Ghostty, Warp, iTerm2) don't set `COLORFGBG`, so `detectLightMode()` was effectively COLORFGBG-only and silently broken for many users — light themes only worked when the user already set `HERMES_TUI_LIGHT=1`.
This adds two opt-in signals and tightens the priority chain so the answer is fully ordered and explainable.
New signals
Priority order
Test plan
Refs
Audit comment (asheriif): "Light theme auto-detection depends on unreliable COLORFGBG".