[Skip to content](https://github.com/nousresearch/hermes-agent#start-of-content)

You signed in with another tab or window. [Reload](https://github.com/nousresearch/hermes-agent) to refresh your session.You signed out in another tab or window. [Reload](https://github.com/nousresearch/hermes-agent) to refresh your session.You switched accounts on another tab or window. [Reload](https://github.com/nousresearch/hermes-agent) to refresh your session.Dismiss alert

{{ message }}

### Uh oh!

There was an error while loading. [Please reload this page](https://github.com/nousresearch/hermes-agent).

[NousResearch](https://github.com/NousResearch)/ **[hermes-agent](https://github.com/NousResearch/hermes-agent)** Public

- [Notifications](https://github.com/login?return_to=%2FNousResearch%2Fhermes-agent) You must be signed in to change notification settings
- [Fork\\
43.5k](https://github.com/login?return_to=%2FNousResearch%2Fhermes-agent)
- [Star\\
225k](https://github.com/login?return_to=%2FNousResearch%2Fhermes-agent)


main

[**1396** Branches](https://github.com/NousResearch/hermes-agent/branches) [**29** Tags](https://github.com/NousResearch/hermes-agent/tags)

[Go to Branches page](https://github.com/NousResearch/hermes-agent/branches)[Go to Tags page](https://github.com/NousResearch/hermes-agent/tags)

Go to file

Code

Open more actions menu

## Folders and files

| Name | Name | Last commit message | Last commit date |
| --- | --- | --- | --- |
| ## Latest commit<br>![PRATHAMESH75](https://avatars.githubusercontent.com/u/118293218?v=4&size=40)![kshitijk4poor](https://avatars.githubusercontent.com/u/82637225?v=4&size=40)<br>[PRATHAMESH75](https://github.com/NousResearch/hermes-agent/commits?author=PRATHAMESH75)<br>and<br>[kshitijk4poor](https://github.com/NousResearch/hermes-agent/commits?author=kshitijk4poor)<br>[fix(stt): thread confidence thresholds into faster-whisper's own gate (](https://github.com/NousResearch/hermes-agent/commit/fe6330de035c27f64c356a819a2218ee1cb05e93) […](https://github.com/NousResearch/hermes-agent/issues/74178)<br>Open commit detailspending<br>6 minutes agoAug 3, 2026<br>[fe6330d](https://github.com/NousResearch/hermes-agent/commit/fe6330de035c27f64c356a819a2218ee1cb05e93) · 6 minutes agoAug 3, 2026<br>## History<br>[20,418 Commits](https://github.com/NousResearch/hermes-agent/commits/main/) <br>Open commit details<br>[View commit history for this file.](https://github.com/NousResearch/hermes-agent/commits/main/) 20,418 Commits |
| [.github](https://github.com/NousResearch/hermes-agent/tree/main/.github ".github") | [.github](https://github.com/NousResearch/hermes-agent/tree/main/.github ".github") | [feat(ci): auto-fixable contributor attribution — audit\_pr\_attribution…](https://github.com/NousResearch/hermes-agent/commit/1c39f1c9f984705e7b5be66f826ebecb9d381629 "feat(ci): auto-fixable contributor attribution — audit_pr_attribution.py + gate points at it  The check-attribution CI gate kept bouncing salvage PRs because mapping contributor emails was a manual, easy-to-forget step (bare <login>@users.noreply.github.com emails don't auto-resolve like the <id>+<login> form).  - scripts/audit_pr_attribution.py: mirrors the CI gate's logic exactly   (merge-base scan, same skip rules). Report mode for pre-push checks;   --fix auto-resolves via the bare-noreply local part (verified against   the GitHub users API) or GitHub email search, then writes   contributors/emails/<email> files via add_contributor.py. Prints a   confirm-the-human warning on bare-noreply resolution since the local   part is user-controlled (the bryan->hydraxman case). - contributor-check.yml: failure output + review_status how_to_fix now   lead with the one-command fix instead of hand-editing instructions   (also drops the stale 'edit AUTHOR_MAP' guidance — AUTHOR_MAP is   frozen).") | 10 hours agoAug 2, 2026 |
| [.plans](https://github.com/NousResearch/hermes-agent/tree/main/.plans ".plans") | [.plans](https://github.com/NousResearch/hermes-agent/tree/main/.plans ".plans") | [feat(gateway): iMessage-style message reactions — storage, RPC, agent…](https://github.com/NousResearch/hermes-agent/commit/7d92056c49a43658e02422ffc006a734b0220719 "feat(gateway): iMessage-style message reactions — storage, RPC, agent tool, model context  Reactions live in the existing messages.display_metadata JSON column (no new table), with iOS Tapback semantics enforced DB-side: one reaction per author per message, re-tap retracts, different emoji replaces. The desktop catches up to the reaction contract five platform adapters already ship.  - SessionDB: set/get_message_reaction, latest_message_row_id (role + offset +   require_text so invisible tool-call-only rows are never targeted),   take_unseen_reactions (announce-exactly-once), get_message_role - message.react RPC: accepts row_id or newest_role for live messages that   haven't learned their durable id yet - react_to_message tool: desktop-gated (check_fn), defaults to the user's   latest visible message, messages_back for retroactive reactions - Model context rides run_message only (beside the speech-interrupted note):   the persisted prompt stays clean, so no [The user reacted …] scaffolding in   transcripts, and no cached prefix ever changes - Resume projection forwards row_id + reactions; _row_id is stripped from   outgoing API copies next to display_metadata") | 4 days agoJul 30, 2026 |
| [acp\_adapter](https://github.com/NousResearch/hermes-agent/tree/main/acp_adapter "acp_adapter") | [acp\_adapter](https://github.com/NousResearch/hermes-agent/tree/main/acp_adapter "acp_adapter") | [fix(approval): classify CLI/TUI approval timeouts separately from exp…](https://github.com/NousResearch/hermes-agent/commit/aac74be2f11f0fc80a1988bcaacabf40b28a1295 "fix(approval): classify CLI/TUI approval timeouts separately from explicit denials  When an approval prompt expired without a response, every CLI-side path collapsed the timeout into the same 'deny' choice as an explicit user refusal, so the agent was told the user denied the action when the user simply never answered. The gateway wait already distinguished the two ('timed out without user response... Silence is not consent.'); this brings the CLI/TUI/ACP surfaces to parity.  - prompt_dangerous_approval(): input()-path expiry now returns a distinct   'timeout' choice (still fail-closed). - cli.py _approval_callback + hermes_cli/callbacks.py approval_callback:   deadline expiry returns 'timeout' instead of 'deny'. - check_all_command_guards / _run_approval_gate CLI tails: 'timeout' maps   to outcome='timeout' with a 'timed out without user response... Silence   is not consent.' BLOCKED message (matching the gateway wording);   explicit deny keeps outcome='denied' and gains user_consent=False for   shape parity. - computer_use: 'timeout' verdict threads through the CLI adapter and   yields a 'prompt timed out — the user did not respond' error instead of   'denied by user'. - ACP permissions bridge: FutureTimeout returns 'timeout' (other failures   still 'deny'); elicitation maps 'timeout' to 'cancel' like the gateway's   unresolved outcome; codex wire mapping documents deny/timeout→decline. - write_approval already treats unknown choices as 'stage, not drop', so   a timeout now stages the memory write instead of silently refusing it.  Every timeout path remains fail-closed — the action never runs; only the classification reported to the agent changes.") | 5 hours agoAug 2, 2026 |
| [agent](https://github.com/NousResearch/hermes-agent/tree/main/agent "agent") | [agent](https://github.com/NousResearch/hermes-agent/tree/main/agent "agent") | [fix: exclude DeepSeek from OpenCode caching path to prevent HTTP 400](https://github.com/NousResearch/hermes-agent/commit/5b5a29f96e72482e8958ea80c836e87a25baa406 "fix: exclude DeepSeek from OpenCode caching path to prevent HTTP 400  OpenCode Zen's relay rejects the Anthropic-style content block format that cache markers produce (content becomes a block array instead of a plain string), causing HTTP 400 with \"content must be string, not block array\" for DeepSeek models.  Reverts the DeepSeek addition from commit 6b6435a874 while preserving the Qwen/Alibaba caching path which continues to work.  Fixes #77217") | 16 minutes agoAug 3, 2026 |
| [apps](https://github.com/NousResearch/hermes-agent/tree/main/apps "apps") | [apps](https://github.com/NousResearch/hermes-agent/tree/main/apps "apps") | [test: expect omit\_messages in the tile-delegate resume call shape](https://github.com/NousResearch/hermes-agent/commit/dd08277104ab03da588620e9f4aa6afefa01d11a "test: expect omit_messages in the tile-delegate resume call shape  Two more call-shape-pinning tests (cold tile resume, default-profile resume) assert session.resume's exact params; the delegate passes omit_messages: true like every other Desktop resume call site. Swept all 5 desktop test files that reference session.resume/activate: 380 of 381 files green (the one failure is a pre-existing locale- dependent number-grouping test that fails identically on clean main).") | 51 minutes agoAug 3, 2026 |
| [assets](https://github.com/NousResearch/hermes-agent/tree/main/assets "assets") | [assets](https://github.com/NousResearch/hermes-agent/tree/main/assets "assets") | [Update banner image to new version](https://github.com/NousResearch/hermes-agent/commit/3e311a009278895df422e4ce58d53d6c0a46a0f8 "Update banner image to new version") | 6 months agoFeb 25, 2026 |
| [contributors](https://github.com/NousResearch/hermes-agent/tree/main/contributors "contributors") | [contributors](https://github.com/NousResearch/hermes-agent/tree/main/contributors "contributors") | [Merge pull request](https://github.com/NousResearch/hermes-agent/commit/636d4e6435e4c9e63e1430318a61387cff737826 "Merge pull request #77515 from kshitijk4poor/chore-baau-email  chore: add contributor email mapping for baau") [#77515](https://github.com/NousResearch/hermes-agent/pull/77515) [from kshitijk4poor/chore-baau-email](https://github.com/NousResearch/hermes-agent/commit/636d4e6435e4c9e63e1430318a61387cff737826 "Merge pull request #77515 from kshitijk4poor/chore-baau-email  chore: add contributor email mapping for baau") | 15 minutes agoAug 3, 2026 |
| [cron](https://github.com/NousResearch/hermes-agent/tree/main/cron "cron") | [cron](https://github.com/NousResearch/hermes-agent/tree/main/cron "cron") | [fix(cron): retain completed one-shot jobs instead of deleting them on…](https://github.com/NousResearch/hermes-agent/commit/d1afa16053a3777849c2b5465d59a0147b2172f9 "fix(cron): retain completed one-shot jobs instead of deleting them on completion  mark_job_run popped a finite one-shot from jobs.json the moment its repeat limit was reached and returned early — discarding the last_status / last_error / last_delivery_error it had just written. Every finished one-shot vanished from `cronjob action=list` with no inspectable record, and a delivery failure (agent succeeded, platform send failed) was silently thrown away with it.  Changes: - mark_job_run now retires a limit-reached one-shot as a terminal   record (state=\"completed\", enabled=False, next_run_at=None) —   mirroring the existing next_run_at-is-None terminal branch — so the   final status and any delivery error persist and surface in the   cronjob tool's list output (which already emits last_delivery_error   and defaults to include_disabled=True). - claim_dispatch's stale-job cleanup marks already-ran jobs completed   instead of popping them; genuinely wedged claims (last_run_at never   written) are still removed with the operator-visible diagnostic. - Retention sweep in the due scan prunes completed one-shot records   older than cron.completed_retention_days (default 7; non-positive   disables) so jobs.json cannot grow unboundedly. Recurring jobs and   non-terminal one-shots are never candidates.  Tests: completion retains record + delivery error, list surfaces it, completed jobs never re-dispatch, sweep prunes old / keeps recent / ignores recurring / honors the disable knob; recurring lifecycle unchanged.") | 2 hours agoAug 3, 2026 |
| [datagen-config-examples](https://github.com/NousResearch/hermes-agent/tree/main/datagen-config-examples "datagen-config-examples") | [datagen-config-examples](https://github.com/NousResearch/hermes-agent/tree/main/datagen-config-examples "datagen-config-examples") | [feat: add WebResearchEnv RL environment for multi-step web research](https://github.com/NousResearch/hermes-agent/commit/15561ec425a74f26bd2051f562d60ec43f78a050 "feat: add WebResearchEnv RL environment for multi-step web research") | 5 months agoMar 5, 2026 |
| [docker](https://github.com/NousResearch/hermes-agent/tree/main/docker "docker") | [docker](https://github.com/NousResearch/hermes-agent/tree/main/docker "docker") | [fix(docker): gate the remaining every-boot chown walks (cron, pairing)](https://github.com/NousResearch/hermes-agent/commit/4983c576b1ed118d56ddf98feed468f4b3a7042c "fix(docker): gate the remaining every-boot chown walks (cron, pairing)  Whole-bug-class follow-up to the profiles/ gate: cron/, platforms/ pairing, and legacy pairing/ ran chown_hermes_tree unconditionally on every boot with the identical warm-boot cost profile. Same tree_has_non_hermes_owner gate; find evaluates the top directory first and -quits on the first mismatch, so a mis-owned tree short-circuits in O(1) while a clean tree pays one read-only walk instead of a full chown -R inode rewrite.") | 16 hours agoAug 2, 2026 |
| [docs](https://github.com/NousResearch/hermes-agent/tree/main/docs "docs") | [docs](https://github.com/NousResearch/hermes-agent/tree/main/docs "docs") | [fix(kanban): deliver notifications from non-dispatch gateways](https://github.com/NousResearch/hermes-agent/commit/991f5f1e9e192ee8039ad5245401798a925fb380 "fix(kanban): deliver notifications from non-dispatch gateways") | 2 days agoAug 1, 2026 |
| [gateway](https://github.com/NousResearch/hermes-agent/tree/main/gateway "gateway") | [gateway](https://github.com/NousResearch/hermes-agent/tree/main/gateway "gateway") | [test: raise blocking-probe timeouts for loaded CI runners](https://github.com/NousResearch/hermes-agent/commit/5b36d64583bf9ed8c30b127d24b671f229f8abcb "test: raise blocking-probe timeouts for loaded CI runners  CI slices failed the offload tests with 0.5s witness timeouts: on a loaded shared runner the event loop thread can take >0.5s to get scheduled even when NOT blocked, making the probe report a false positive. A genuinely blocked loop can never set the progress event at any timeout (the witness coroutine can't run at all), so 5s only absorbs scheduler flake without weakening the invariant. Mutation re-verified: reverting the offload still fails all 4 tests.") | 3 hours agoAug 3, 2026 |
| [hermes\_cli](https://github.com/NousResearch/hermes-agent/tree/main/hermes_cli "hermes_cli") | [hermes\_cli](https://github.com/NousResearch/hermes-agent/tree/main/hermes_cli "hermes_cli") | [perf(models): cache GitHub Copilot model catalog for 5 minutes](https://github.com/NousResearch/hermes-agent/commit/bd56440f4cc1b83de300800484bb2fc9b8f2399f "perf(models): cache GitHub Copilot model catalog for 5 minutes  The picker path fetches the Copilot /models catalog multiple times per process (list_authenticated_providers -> provider_model_ids -> _fetch_github_models, plus get_copilot_model_context / normalize helpers). Cache the filtered catalog at module level with a short TTL so repeated picker opens do not pay a TLS handshake each time.  Fold-fixes on top of the original patch: - key the cache by api_key so a mid-process credential swap never   serves the previous account's catalog - use time.monotonic() so wall-clock adjustments cannot extend the TTL - deep-copy on store/serve so callers cannot mutate cached entries - tests updated to patch _urlopen_model_catalog_request (main routes   catalog fetches through open_credentialed_url now), plus TTL-expiry   and credential-change coverage  Extracted from #40276.") | 49 minutes agoAug 3, 2026 |
| [locales](https://github.com/NousResearch/hermes-agent/tree/main/locales "locales") | [locales](https://github.com/NousResearch/hermes-agent/tree/main/locales "locales") | [feat(diff): cross-surface /diff with staged/all/session modes](https://github.com/NousResearch/hermes-agent/commit/0fa5e41c86f022bba147797849f0b44865721476 "feat(diff): cross-surface /diff with staged/all/session modes  Widen the cherry-picked /diff base (#4839 by @SHL0MS) into one cross-surface implementation, folding in the review feedback and the best ideas from the two sibling PRs (#22703, #53527):  - tools/working_diff.py: shared git collection layer — unstaged   (default), staged, and all (vs HEAD) modes; untracked files folded in   via `git diff --no-index` so new files appear as additions (Codex   /diff parity); shlex-split arguments preserve quoted paths. - CLI: handler moved to hermes_cli/cli_commands_mixin.py per the   current god-file decomposition (dispatch stays in cli.py), renders   through the rich console with a 400-line terminal-flood guard. - Gateway: _handle_diff_command in gateway/slash_commands.py + dispatch   in gateway/run.py; fenced ```diff output truncated to 60 lines /   3000 chars before the platform senders apply their own per-platform   message clamps (tool-progress-style layered truncation). Localized   strings in all 17 locale catalogs. - /diff session (from #53527): cumulative checkpoint-baseline diff of   everything Hermes changed, via new CheckpointManager.session_diff();   docstring records the retained-baseline approximation caveat from   review. Works on both surfaces; degrades with an actionable message   when checkpoints are off. - Slack: /diff routed via /hermes diff (50-slash cap; keeps   telegram-parity test green and /version native). - Registry: cross-surface CommandDef with staged|all|session   subcommands; docs: slash-commands reference (CLI + gateway tables +   both-surfaces list) and hermes-agent skill reference. - Tests: tests/tools/test_working_diff.py (real git repos),   tests/hermes_cli/test_diff_command.py (real git + stubbed checkpoint   manager), tests/gateway/test_diff_command.py (end-to-end handler,   real checkpoint store), TestSessionDiff in   tests/tools/test_checkpoint_manager.py.  Salvaged from the /diff PR cluster #4839 + #22703 + #53527.  Co-authored-by: Ninso112 <ninso112@proton.me> Co-authored-by: Harshkamdar67 <harshkamdar67@gmail.com>") | last weekJul 26, 2026 |
| [mcp-research-data](https://github.com/NousResearch/hermes-agent/tree/main/mcp-research-data "mcp-research-data") | [mcp-research-data](https://github.com/NousResearch/hermes-agent/tree/main/mcp-research-data "mcp-research-data") | [bench: discovery-bound suite — paraphrase/absence/survey tasks isolat…](https://github.com/NousResearch/hermes-agent/commit/2643ea17fbbeb3f9f74ab06907cfbb3153f54b0d "bench: discovery-bound suite — paraphrase/absence/survey tasks isolate the listing's structural advantage  Bridge vs listing only (Opus 4.8, 830 real UE schemas, 3 reps/cell). Excluding one both-modes mock artifact: listing 24/24 vs bridge 20/24, searches/task 0.2 vs 4.0. Bridge failures: core-tool substitution at frontier tier (ran the host test suite via terminal instead of discovering RunTests, 2/3 reps), up to 8 searches to prove a negative, and search-vocabulary misses on paraphrase. Listing asserts absence in zero searches and answers a 5-way capability survey in 1 API call.") | last weekJul 26, 2026 |
| [native/fts5\_cjk](https://github.com/NousResearch/hermes-agent/tree/main/native/fts5_cjk "This path skips through empty directories") | [native/fts5\_cjk](https://github.com/NousResearch/hermes-agent/tree/main/native/fts5_cjk "This path skips through empty directories") | [feat(state): messages\_fts\_cjk — CJK-bigram index on the v23 external-…](https://github.com/NousResearch/hermes-agent/commit/f13f845116941ac5616e8df3294f3379a3efeb20 "feat(state): messages_fts_cjk — CJK-bigram index on the v23 external-content layout  Integration layer for the cjk_unicode61 tokenizer, rebuilt on the v23 schema (the contributed integration in PR #65544 predated it):  - messages_fts_cjk: external-content FTS5 over a tool-row-excluding view   (same v23 storage discipline as the trigram index it supersedes — zero   inline text copies). Serves EVERY CJK query shape the legacy routing   split between trigram (>=3 chars/token) and LIKE full scans (1-2 char   tokens). Lone 1-char CJK runs and role_filter=['tool'] queries keep   their legacy routes. - Dedicated marker pair (fts_cjk_rebuild_high_water/progress) gates the   id-scoped triggers, so a cjk-only backfill never gates the complete   messages_fts/trigram triggers. - Transitions ride  (the existing   throttled/resumable chunk engine): fresh DBs are born with the index;   legacy v22 DBs land on v23+cjk in one run; already-optimized v23 DBs   gaining the tokenizer get a marker-gated backfill; live writes are   indexed immediately in every case. - Tokenizer-loss self-heal: a process that can't load the extension drops   the cjk triggers (writes keep working), leaves a stale breadcrumb, and   the index is rebuilt from scratch on the next optimize run — triggers   are never reinstalled over a gap (external-content 'delete' on an   unindexed rowid is the FTS5 corruption hazard the marker gating exists   to prevent). - Capability classification: 'no such tokenizer: cjk_unicode61' joins the   degraded-runtime error class everywhere (read probe, write probe,   repair) so tokenizer absence is never misclassified as corruption. - Config: sessions.cjk_fts (default on, inert without the .so) and   sessions.search_slow_ms in config.yaml, bridged to env by CLI + gateway   (startup + per-turn reload). build.sh falls back to vendored SQLite   headers so no libsqlite3-dev is needed.  Slow-query log path attribution updated: fts_cjk / fts5 / trigram / like_scan. Tests: 14 lifecycle tests (fresh/legacy/stale/backfill paths, tokenizer-loss round-trip) + 5 config-bridge tests + slow-log suite.") | 2 weeks agoJul 22, 2026 |
| [nix](https://github.com/NousResearch/hermes-agent/tree/main/nix "nix") | [nix](https://github.com/NousResearch/hermes-agent/tree/main/nix "nix") | [feat(runtime)!: require Node 26 across all installers, heal, and upgr…](https://github.com/NousResearch/hermes-agent/commit/713a983e4aa8824ce9efbceb3b32c1cd962e0a7d "feat(runtime)!: require Node 26 across all installers, heal, and upgrade paths  Hermes now pins its toolchain to Node 26 everywhere. Every path that installs, accepts, heals, or upgrades a Node runtime moves from the old 22-default / `^20.19 || >=22.12` floor to a single rule: Node >=26.  Installers: - scripts/install.sh — NODE_VERSION=26; node_satisfies_build() collapses   the two-branch Vite floor to `major >= 26`; user-facing messages updated. - scripts/install.ps1 — $NodeVersion=26; Test-NodeVersionOk likewise;   winget fallback switches OpenJS.NodeJS.LTS -> OpenJS.NodeJS (26 is   Current, not LTS — the LTS manifest would reinstall a too-old Node). - Dockerfile — node_source stage node:22-bookworm-slim -> node:26 (digest   pinned, amd64 sha256:9e6f...bf73). - nix/ was already on nodejs_26 (lib.nix, npm-12-0-2.nix); the checks.nix   wrapper check ratchets from `>= 20` to `>= 26`.  Heal/upgrade paths: - scripts/lib/node-bootstrap.sh — HERMES_NODE_TARGET_MAJOR default 22->26   and HERMES_NODE_MIN_VERSION default 20->26, so heal_managed_node,   _nb_install_bundled_node, and the fnm/proto/nvm/brew rungs all target 26   and stop accepting an on-PATH Node below it. Both remain env-overridable. - hermes_constants.py — _HERMES_NODE_TARGET_MAJOR fallback 22->26, which   drives the Windows heal path's latest-v26.x download.  Version gates: - package.json engines.node >=20 -> >=26; apps/desktop engines   `^20.19.0 || >=22.12.0` -> `>=26.0.0`. - CI setup-node: all five workflows 22 -> 26. - Docs describing Hermes's own toolchain updated (windows-native, docker,   acp, nix-setup, contributing). Skill docs describing third-party tools'   own requirements are untouched.  Termux still installs via `pkg install nodejs` best-effort (nodejs.org ships no Android tarballs); that path was never version-gated.  Verified: bash -n on both shell scripts, PowerShell AST parse of install.ps1, latest-v26.x index resolves (node-v26.5.1), and the install test suite — 18 tests across the 5 install/runtime test files — passes.") | yesterdayAug 1, 2026 |
| [optional-mcps](https://github.com/NousResearch/hermes-agent/tree/main/optional-mcps "optional-mcps") | [optional-mcps](https://github.com/NousResearch/hermes-agent/tree/main/optional-mcps "optional-mcps") | [fix(mcp): curate comfy-cloud default tool set + drop legacy packaging…](https://github.com/NousResearch/hermes-agent/commit/d9101bef0aa357a7922319d0d631f85a43ccdca1 "fix(mcp): curate comfy-cloud default tool set + drop legacy packaging line  - tools.default_enabled: 20-tool curated subset (discovery, generation,   job lifecycle, billing). The server exposes ~37 tools; all-enabled adds   ~16-22k tokens of schema to every API call — larger than the entire   Hermes core toolset (~12.7k). Curated default lands at ~9-12k. Batch,   saved/shared workflow, and App Mode tools remain opt-in via   'hermes mcp configure comfy-cloud'. - report_session_summary excluded from defaults per telemetry policy   (no outbound telemetry without explicit user opt-in). - description trimmed to catalog guideline length. - revert pyproject data-files line: the per-entry packaging enforcement   was removed (no-pip policy); blender/unreal-engine entries have no   data-files lines either.") | 4 days agoJul 29, 2026 |
| [optional-skills](https://github.com/NousResearch/hermes-agent/tree/main/optional-skills "optional-skills") | [optional-skills](https://github.com/NousResearch/hermes-agent/tree/main/optional-skills "optional-skills") | [fix(cli): swallow fsync errors in the openclaw EXDEV fallback](https://github.com/NousResearch/hermes-agent/commit/0a62610f10cc34d696b2239b2c69fa1ba0f1ca63 "fix(cli): swallow fsync errors in the openclaw EXDEV fallback  Exact parity with utils.atomic_replace: its target fsync is wrapped in try/except OSError. A failed fsync after a successful copy must not surface the already-completed write as an error (Windows can raise on fsync of a read-only handle).") | yesterdayAug 2, 2026 |
| [plugins](https://github.com/NousResearch/hermes-agent/tree/main/plugins "plugins") | [plugins](https://github.com/NousResearch/hermes-agent/tree/main/plugins "plugins") | [fix(discord): suppress link embeds in tool preview markdown links](https://github.com/NousResearch/hermes-agent/commit/dd600d1ace727fc9f10c9f8763f21b564e25b06f "fix(discord): suppress link embeds in tool preview markdown links  Wrap the masked-link destination in angle brackets so Discord does not unfurl an OG-preview embed under every tool progress bubble. quote() percent-encodes any <> inside the URL itself, so the wrapper cannot be broken out of.") | 4 hours agoAug 3, 2026 |
| [providers](https://github.com/NousResearch/hermes-agent/tree/main/providers "providers") | [providers](https://github.com/NousResearch/hermes-agent/tree/main/providers "providers") | [feat(providers): Support DeepInfra as an LLM provider](https://github.com/NousResearch/hermes-agent/commit/fe002eb124d9f9e23769afdfc437f716255983b1 "feat(providers): Support DeepInfra as an LLM provider") | 3 weeks agoJul 13, 2026 |
| [scripts](https://github.com/NousResearch/hermes-agent/tree/main/scripts "scripts") | [scripts](https://github.com/NousResearch/hermes-agent/tree/main/scripts "scripts") | [fix(whatsapp): guard bridge reconnect against hangs and unhandled rej…](https://github.com/NousResearch/hermes-agent/commit/947fdeab3bdef53bb3ff856a4bce0e6e6235122a "fix(whatsapp): guard bridge reconnect against hangs and unhandled rejections  startSocket() awaits useMultiFileAuthState() and fetchLatestBaileysVersion() before it creates a socket or registers event handlers, and the close handler re-entered it via a bare setTimeout(startSocket, ...). That leaves two unrecoverable failure modes on a reconnect:  - a rejection is an unhandled promise rejection (fatal on modern Node) - a hang leaves the bridge permanently disconnected with nothing left to   retry, while its HTTP server keeps answering 503 to the gateway  The second mode was observed in the field: fetchLatestBaileysVersion() is a plain fetch to raw.githubusercontent.com with no AbortSignal, and after a stream:error 503 disconnect the bridge logged 'Reconnecting in 3s...' once and then sat silent and disconnected for 27+ hours until manually restarted.  Fix, as two pure helpers in bridge_helpers.js (keeping bridge.js side-effect free to test):  - createReconnectScheduler(): every (re)connect entry point now catches a   failed startSocket() and reschedules it instead of dying or going silent - createVersionResolver(): bounds the version fetch with a 15s timeout and   falls back to the last known-good version (or the Baileys default before   first success) instead of pending forever") | 4 hours agoAug 3, 2026 |
| [skills](https://github.com/NousResearch/hermes-agent/tree/main/skills "skills") | [skills](https://github.com/NousResearch/hermes-agent/tree/main/skills "skills") | [fix(skills): match evidence quotes through markdown markup](https://github.com/NousResearch/hermes-agent/commit/a6defd4f1549da3fe1d08d6f746fc645c64543f0 "fix(skills): match evidence quotes through markdown markup  Live-run findings from a real fact-checking task (ankylosing spondylitis genetics, 7 authoritative sources) against the new mode:  - Verbatim check rejected a legitimate quote because web_extract returns   markdown: the MedlinePlus sentence is \"including _[ERAP1](https://...)_,   _[IL1A](...)_\" on the wire but plain prose to a reader. The agent was   forced onto a weaker evidence fragment — the opposite of the point.   Matching now canonicalizes inline links to their label and drops   emphasis/code markers and backslash escapes on both sides, so quoting   the sentence a reader sees works. Paraphrases are still rejected. - Escaped asterisks (HLA-B\*27) no longer have to be reproduced in the   quote, so extractor artifacts stop leaking into rendered evidence. - New `render --replace-in <draft>`: rewrites a draft's Sources block in   place, idempotently. Previously the only path was hand-slicing the   file, which also tripped over the emitted heading being `## Sources`   while the prose said \"Sources:\". - verify stats: report the provenance total that the percentage is   actually computed from (cited + [unverified], counted once), and print   the line as `info:` instead of `warn:` when nothing is wrong. The old   line printed 17 cited / 2 unverified next to 72%, which does not   reconcile — a sentence can be both. - SKILL.md documents the emitted heading, --replace-in, and exactly what   counts as a prose sentence for --min-coverage.  7 new tests (47 total) using the real MedlinePlus/Frontiers markup; 6 sabotage runs, all red.") | 9 hours agoAug 2, 2026 |
| [tests-js](https://github.com/NousResearch/hermes-agent/tree/main/tests-js "tests-js") | [tests-js](https://github.com/NousResearch/hermes-agent/tree/main/tests-js "tests-js") | [fix(js): hoist eslint shared devDeps to workspace root](https://github.com/NousResearch/hermes-agent/commit/fabc2d7d331e067607a55429d9bfd635743950a7 "fix(js): hoist eslint shared devDeps to workspace root") | 3 days agoJul 31, 2026 |
| [tests](https://github.com/NousResearch/hermes-agent/tree/main/tests "tests") | [tests](https://github.com/NousResearch/hermes-agent/tree/main/tests "tests") | [fix(stt): thread confidence thresholds into faster-whisper's own gate (](https://github.com/NousResearch/hermes-agent/commit/fe6330de035c27f64c356a819a2218ee1cb05e93 "fix(stt): thread confidence thresholds into faster-whisper's own gate (#74178)  build_local_transcribe_kwargs read stt.local.no_speech_prob_threshold / stt.local.logprob_threshold only for Hermes' post-filter (_is_hallucinated_segment). faster-whisper's model.transcribe() never received them, so its internal defaults (no_speech_threshold=0.6, log_prob_threshold=-1.0) always applied and silently dropped low-confidence segments before they reached the post-filter — making those config knobs dead for the first gate.  Non-English speech decodes at a lower avg_logprob, so the English-tuned defaults discard whole utterances (empty transcript despite correct capture and language detection). Map the same config values through to model.transcribe() so both gates stay in sync and the knobs work. Defaults are unchanged, so behavior is identical unless a user tunes them.  Fixes #74178") […](https://github.com/NousResearch/hermes-agent/issues/74178) | 6 minutes agoAug 3, 2026 |
| [tools](https://github.com/NousResearch/hermes-agent/tree/main/tools "tools") | [tools](https://github.com/NousResearch/hermes-agent/tree/main/tools "tools") | [fix(stt): thread confidence thresholds into faster-whisper's own gate (](https://github.com/NousResearch/hermes-agent/commit/fe6330de035c27f64c356a819a2218ee1cb05e93 "fix(stt): thread confidence thresholds into faster-whisper's own gate (#74178)  build_local_transcribe_kwargs read stt.local.no_speech_prob_threshold / stt.local.logprob_threshold only for Hermes' post-filter (_is_hallucinated_segment). faster-whisper's model.transcribe() never received them, so its internal defaults (no_speech_threshold=0.6, log_prob_threshold=-1.0) always applied and silently dropped low-confidence segments before they reached the post-filter — making those config knobs dead for the first gate.  Non-English speech decodes at a lower avg_logprob, so the English-tuned defaults discard whole utterances (empty transcript despite correct capture and language detection). Map the same config values through to model.transcribe() so both gates stay in sync and the knobs work. Defaults are unchanged, so behavior is identical unless a user tunes them.  Fixes #74178") […](https://github.com/NousResearch/hermes-agent/issues/74178) | 6 minutes agoAug 3, 2026 |
| [tui\_gateway](https://github.com/NousResearch/hermes-agent/tree/main/tui_gateway "tui_gateway") | [tui\_gateway](https://github.com/NousResearch/hermes-agent/tree/main/tui_gateway "tui_gateway") | [fix(gateway): let Desktop omit duplicate transcripts on session resume](https://github.com/NousResearch/hermes-agent/commit/cd41454dfc42c66a17e9bacb2409c56d549f8258 "fix(gateway): let Desktop omit duplicate transcripts on session resume  Salvage of #69926: omit_messages support ported from the PR's tui_gateway/server.py base onto the post-split methods_session.py layout. When a Desktop client passes omit_messages=true on session.resume / session.activate, the RPC returns messages: [] with messages_omitted: true and an accurate message_count, skipping the potentially multi-megabyte compression-lineage serialization over the WebSocket; Desktop hydrates the transcript via the authenticated REST route in parallel.  The PR's bundled cron-outputs endpoint and codex quiet-timeout bump were dropped from this salvage as unrelated (invited back separately).") | 51 minutes agoAug 3, 2026 |
| [ui-tui](https://github.com/NousResearch/hermes-agent/tree/main/ui-tui "ui-tui") | [ui-tui](https://github.com/NousResearch/hermes-agent/tree/main/ui-tui "ui-tui") | [refactor(ui-tui): single source for the floating-panel kind set](https://github.com/NousResearch/hermes-agent/commit/e8c1882766d257145f6f20ca1b3d37289680bf34 "refactor(ui-tui): single source for the floating-panel kind set  Review follow-up: $isStatusRuleOccluded and FloatingOverlays each enumerated the same six overlay kinds — adding a 7th floating panel required updating both or the timer gate silently missed it. Extracted hasFloatingPanel as the shared predicate (completions stays local to FloatingOverlays; it deliberately never occludes the status rule). Full ui-tui suite green (1487 tests).") | 4 hours agoAug 3, 2026 |
| [web](https://github.com/NousResearch/hermes-agent/tree/main/web "web") | [web](https://github.com/NousResearch/hermes-agent/tree/main/web "web") | [fix: fix @nousresearch/ui version, update to npm 12](https://github.com/NousResearch/hermes-agent/commit/f88ed6c71768cdc7ea3bfa8cf62d16654792fd2a "fix: fix @nousresearch/ui version, update to npm 12") | 2 days agoAug 1, 2026 |
| [website](https://github.com/NousResearch/hermes-agent/tree/main/website "website") | [website](https://github.com/NousResearch/hermes-agent/tree/main/website "website") | [perf(tools): compact delegate\_task description by deduping against pa…](https://github.com/NousResearch/hermes-agent/commit/4be0d5602334c72e76f972e8b04400cf8c51be59 "perf(tools): compact delegate_task description by deduping against param schema  The top-level delegate_task description repeated content the model already receives through parameter descriptions: the concurrency limit (tasks param), the full nesting clause (role param), context-passing guidance (goal/context params), and background semantics (background param). Every API call paid for the duplication (~4,000 chars).  The description now carries only what exists nowhere else in the schema: use/don't-use routing (execute_code, cronjob), the no-poll rule, the non-durability warning, the self-report verification contract with concrete verbs, the language-passing example, the leaf blocked-tool list, and model inheritance. 3,963 -> 1,704 chars (~570 tokens saved per API call), and the top-level text is now static (dynamic limits flow only through the two param descriptions, which are already rebuilt per get_definitions() call).  A/B benchmark across 4 models (gpt-4o, gpt-4o-mini, claude-haiku-4.5, llama-3.3-70b) showed the naive compaction in PR #72813 regressed weaker models on exactly the passages it cut (side-effect verification 8/8->0/8 on gpt-4o-mini; language passing 3/3->0/3 on haiku-4.5). This version keeps those benchmark-sensitive hooks verbatim.  Tests pin the contracts at keyword level (not prose-literal) plus a size ceiling, and verify dynamic limits still reach the model via the tasks/role param descriptions.  Refs #72737, supersedes the delegate_task half of PR #72813.") | 3 hours agoAug 3, 2026 |
| [.dockerignore](https://github.com/NousResearch/hermes-agent/blob/main/.dockerignore ".dockerignore") | [.dockerignore](https://github.com/NousResearch/hermes-agent/blob/main/.dockerignore ".dockerignore") | [rip out brew + pip/PyPI wheel support (](https://github.com/NousResearch/hermes-agent/commit/d84e11af4d9927c41ad0a3b4db72042cca250c64 "rip out brew + pip/PyPI wheel support (#68217)  Removes Homebrew and PyPI wheel/sdist as Hermes distribution paths while preserving the supported source, Docker, and Nix workflows.  Changes: - Removes the Homebrew formula, PyPI publish workflow, sdist manifest   (MANIFEST.in), and wheel/sdist release-attachment logic from scripts/release.py. - Keeps setuptools metadata and entry points required by editable installs   and Docker/Nix builds, but adds a setup.py guard that rejects wheel/sdist   builds outside a sealed Nix derivation (HERMES_NIX_BUILD=1). - Removes pip/Homebrew install detection, PyPI update checks, the pip   self-update path, the deprecation-banner state, the postinstall subcommand,   wheel data-directory fallbacks in agent/i18n.py and hermes_constants.py,   and the ACP Registry manifest/version-lockstep release logic. - Adds /nix/store/ path detection so `nix run` / `nix profile install`   installs (which don't set HERMES_MANAGED) are correctly identified as   \"nix\" rather than falling through to \"git\"/\"unknown\". - Retired install-method values (\"pip\", \"homebrew\") in existing   .install_method stamps (both code-scoped and home-scoped) are ignored by   the allowlist reader and fall through to \"unknown\" instead of resurrecting   a retired enum value. - Updates Nix packaging to ship bare runtime data (locales, optional-mcps)   through store symlinks and wrapper env vars instead of wheel data-files. - Removes the ACP Registry manifest/icon and their version-lockstep tests. - Deletes or rewrites packaging, pip-update, Homebrew, and ACP Registry   tests; adds parametrized coverage for the packaging build guard covering   BOTH sdist and wheel paths (the guards live in separate cmdclass entries   — a passing sdist test proves nothing about the wheel path). - Updates installation/platform documentation and related user-facing copy. - Adjusts the supply-chain scan so deleted install-hook files do not trigger   a finding, while additions or modifications still require the existing   ci-reviewed label gate.  Supported installation paths (unchanged): - git installer (install.sh) - Docker - Nix/NixOS - editable development installs (uv sync, uv pip install -e ., pip install -e .)") [#68217](https://github.com/NousResearch/hermes-agent/pull/68217) [)](https://github.com/NousResearch/hermes-agent/commit/d84e11af4d9927c41ad0a3b4db72042cca250c64 "rip out brew + pip/PyPI wheel support (#68217)  Removes Homebrew and PyPI wheel/sdist as Hermes distribution paths while preserving the supported source, Docker, and Nix workflows.  Changes: - Removes the Homebrew formula, PyPI publish workflow, sdist manifest   (MANIFEST.in), and wheel/sdist release-attachment logic from scripts/release.py. - Keeps setuptools metadata and entry points required by editable installs   and Docker/Nix builds, but adds a setup.py guard that rejects wheel/sdist   builds outside a sealed Nix derivation (HERMES_NIX_BUILD=1). - Removes pip/Homebrew install detection, PyPI update checks, the pip   self-update path, the deprecation-banner state, the postinstall subcommand,   wheel data-directory fallbacks in agent/i18n.py and hermes_constants.py,   and the ACP Registry manifest/version-lockstep release logic. - Adds /nix/store/ path detection so `nix run` / `nix profile install`   installs (which don't set HERMES_MANAGED) are correctly identified as   \"nix\" rather than falling through to \"git\"/\"unknown\". - Retired install-method values (\"pip\", \"homebrew\") in existing   .install_method stamps (both code-scoped and home-scoped) are ignored by   the allowlist reader and fall through to \"unknown\" instead of resurrecting   a retired enum value. - Updates Nix packaging to ship bare runtime data (locales, optional-mcps)   through store symlinks and wrapper env vars instead of wheel data-files. - Removes the ACP Registry manifest/icon and their version-lockstep tests. - Deletes or rewrites packaging, pip-update, Homebrew, and ACP Registry   tests; adds parametrized coverage for the packaging build guard covering   BOTH sdist and wheel paths (the guards live in separate cmdclass entries   — a passing sdist test proves nothing about the wheel path). - Updates installation/platform documentation and related user-facing copy. - Adjusts the supply-chain scan so deleted install-hook files do not trigger   a finding, while additions or modifications still require the existing   ci-reviewed label gate.  Supported installation paths (unchanged): - git installer (install.sh) - Docker - Nix/NixOS - editable development installs (uv sync, uv pip install -e ., pip install -e .)") | 2 weeks agoJul 22, 2026 |
| [.env.example](https://github.com/NousResearch/hermes-agent/blob/main/.env.example ".env.example") | [.env.example](https://github.com/NousResearch/hermes-agent/blob/main/.env.example ".env.example") | [feat(agent): add Upstage Solar as a model provider](https://github.com/NousResearch/hermes-agent/commit/20502b407c8d80e14808442d58ebbe90cb8b543b "feat(agent): add Upstage Solar as a model provider  Adds Upstage Solar as a bundled model-provider plugin. Solar exposes an OpenAI-compatible chat-completions endpoint at https://api.upstage.ai/v1, so the generic chat_completions transport handles request/response/streaming/tool calls — the profile is the core integration.  Provider registration (Upstage isn't in models.dev, so each registry that does not auto-wire from the plugin layer needs an explicit entry — same pattern as nvidia/gmi): - plugins/model-providers/upstage/: UpstageProfile + plugin.yaml. Picker default   and offline catalog list only the agentic Solar Pro models, led by `solar-pro`   (rolling alias for the latest Pro). default_aux_model empty so aux tasks use   the main model. `solar` alias. UPSTAGE_BASE_URL overrides the host. - hermes_cli/providers.py: HERMES_OVERLAYS + label + `solar` alias, so   resolve_provider_full('upstage') resolves (without this, an explicit   `provider: upstage` in config was dropped and fell through to auto-detect). - hermes_cli/auth.py: PROVIDER_REGISTRY entry + `solar` alias, so `hermes   doctor` / resolve_provider recognise upstage (the static-registry path the   lazy profile-extension doesn't reliably cover at validation time). - hermes_cli/models.py: CANONICAL_PROVIDERS entry places Upstage Solar in the   curated picker order (above the auto-appended `custom`). - agent/model_metadata.py: context-window fallbacks (/v1/models omits   context_length); `solar-pro` carries the 128K Pro context as the catch-all.  Reasoning: UpstageProfile.build_api_kwargs_extras wires Solar's top-level `reasoning_effort` (low|medium|high; xhigh/max→high). Reasoning-capable families are solar-pro* and solar-open*; solar-mini/syn-pro never receive it. Defaults ON at medium when unset (matches the /reasoning \"medium (default)\" label); `/reasoning none` disables; explicit/saved settings are honored. No reasoning_content echo handling needed (unlike DeepSeek/Kimi).  Web dashboard: - web/src/pages/EnvPage.tsx: add an \"Upstage Solar\" provider group so   UPSTAGE_API_KEY / UPSTAGE_BASE_URL appear under LLM Providers (not \"Other\").  Docs/tests: - .env.example: documents UPSTAGE_API_KEY / UPSTAGE_BASE_URL. - tests: profile wiring, reasoning_effort mapping (pro/open/mini, efforts,   disabled, default-on), provider-resolver regression (resolve_provider_full /   get_provider / solar alias / overlay), `solar-pro` default.  Testing: pytest tests/providers tests/plugins/model_providers tests/hermes_cli/test_upstage_provider.py tests/run_agent/test_provider_parity.py tests/hermes_cli/test_api_key_providers.py; ruff clean. Verified end-to-end: `hermes doctor` shows \"Upstage Solar\", and live chat works via both `--provider upstage` and `--provider solar`. Reasoning wire format per https://console.upstage.ai/api/docs/for-agents/raw. Platforms tested: macOS.  Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>") | 3 weeks agoJul 14, 2026 |
| [.envrc](https://github.com/NousResearch/hermes-agent/blob/main/.envrc ".envrc") | [.envrc](https://github.com/NousResearch/hermes-agent/blob/main/.envrc ".envrc") | [feat(install): warn pip/Homebrew installs are unsupported (CLI, TUI, …](https://github.com/NousResearch/hermes-agent/commit/4d7f8ade3e586d83003d61be76e909f364040fba "feat(install): warn pip/Homebrew installs are unsupported (CLI, TUI, desktop) (#57225)  * feat(install): warn pip/Homebrew installs are unsupported (CLI, TUI, desktop)  pip and Homebrew are now Unsupported install methods per website/docs/getting-started/platform-support.md. Surface a warn-don't-block deprecation notice everywhere the install method is already shown, pointing at the platform-support docs and noting these installs will not receive further updates. NixOS (Tier 2) is untouched.  - hermes_cli/config.py: shared is_unsupported_install_method() /   format_unsupported_install_warning() helpers so the wording and docs   link stay consistent across every surface. - hermes_cli/banner.py: generalize the existing pip-only banner   warning to also cover Homebrew. - hermes_cli/main.py: hermes update and hermes update --check print   the warning before proceeding (still update; warn, don't block). - tui_gateway/server.py: session.info gains install_warning. - ui-tui: SessionPanel renders install_warning alongside the existing   'N commits behind' notice. - apps/desktop: SessionRuntimeInfo/GatewayEventPayload gain   install_warning; applyRuntimeInfo + the live session.info event fire   a snoozable warning toast via a new reportInstallMethodWarning(),   mirroring the existing backend-contract-skew toast pattern. i18n   strings added for en/zh/zh-hant/ja. - Tests: updated pip banner assertions for the new wording, added a   Homebrew banner test, and two tui_gateway session_info tests   (install_warning present for pip, absent for git).  * fix(nix): make `hermes` in developement environment actually work  install modules as editable overlay with uv  * feat: print install method when running --version  * fix: correct detect install method when running from a subtree") | last monthJul 8, 2026 |
| [.gitattributes](https://github.com/NousResearch/hermes-agent/blob/main/.gitattributes ".gitattributes") | [.gitattributes](https://github.com/NousResearch/hermes-agent/blob/main/.gitattributes ".gitattributes") | [chore: enforce LF line endings for container entrypoints (](https://github.com/NousResearch/hermes-agent/commit/6ad015255d0f75ede2d9b35b2dd9d1cde0a73343 "chore: enforce LF line endings for container entrypoints (#12181)  Windows contributors checking out on NTFS with git's default core.autocrlf will end up with CRLF in docker/entrypoint.sh. When COPY'd into the image and invoked as ENTRYPOINT, the kernel interprets the trailing \r as part of the interpreter path, producing a confusing 'no such file or directory' despite the file being present and executable.  Lock LF for the usual suspects (*.sh, Dockerfile, *.dockerfile, and the specific docker/entrypoint.sh). The existing tree is already LF; this is preventive against future Windows regressions only.") [#12181](https://github.com/NousResearch/hermes-agent/pull/12181) [)](https://github.com/NousResearch/hermes-agent/commit/6ad015255d0f75ede2d9b35b2dd9d1cde0a73343 "chore: enforce LF line endings for container entrypoints (#12181)  Windows contributors checking out on NTFS with git's default core.autocrlf will end up with CRLF in docker/entrypoint.sh. When COPY'd into the image and invoked as ENTRYPOINT, the kernel interprets the trailing \r as part of the interpreter path, producing a confusing 'no such file or directory' despite the file being present and executable.  Lock LF for the usual suspects (*.sh, Dockerfile, *.dockerfile, and the specific docker/entrypoint.sh). The existing tree is already LF; this is preventive against future Windows regressions only.") | 2 months agoJun 4, 2026 |
| [.gitignore](https://github.com/NousResearch/hermes-agent/blob/main/.gitignore ".gitignore") | [.gitignore](https://github.com/NousResearch/hermes-agent/blob/main/.gitignore ".gitignore") | [chore: gitignore the .lazy-refresh-incomplete runtime marker](https://github.com/NousResearch/hermes-agent/commit/0fe6a36e6e34fdaf42292f2cf6cdffe7e0098fcc "chore: gitignore the .lazy-refresh-incomplete runtime marker  Companion to the #72002 salvage: the marker was accidentally committed once (3a69e34702) and the guard now prevents test runs from writing it; ignoring it prevents any future accidental re-commit.") | 4 days agoJul 30, 2026 |
| [.hadolint.yaml](https://github.com/NousResearch/hermes-agent/blob/main/.hadolint.yaml ".hadolint.yaml") | [.hadolint.yaml](https://github.com/NousResearch/hermes-agent/blob/main/.hadolint.yaml ".hadolint.yaml") | [feat(docker): remove gosu from bundled image; s6-setuidgid handles pr…](https://github.com/NousResearch/hermes-agent/commit/4b4c36cb61dd21be469195c0775f6fcd9611dbd2 "feat(docker): remove gosu from bundled image; s6-setuidgid handles privilege drop  The s6-overlay migration replaced every runtime use of gosu with s6-setuidgid (in stage2-hook.sh, main-wrapper.sh, per-service run scripts, and cont-init.d hooks), but the gosu binary itself was still being copied into the image from tianon/gosu, and several comments across the repo still pointed to it.  Image changes: - Drop the FROM tianon/gosu:1.19-trixie AS gosu_source stage - Drop the COPY --from=gosu_source /gosu /usr/local/bin/ layer - Net: one fewer base-image pull, ~12-15 MB layer eliminated  Documentation/comment refresh (no behavior change): - Dockerfile: update root-user rationale comment + cont-init.d comment - docker/main-wrapper.sh: drop \"pre-s6 contract (gosu drop)\" reference - docker-compose.yml: update UID/GID remap comment - .hadolint.yaml: update DL3002 ignore rationale - website/docs/user-guide/docker.md: privilege-drop helper is s6-setuidgid now - hermes_cli/config.py: docker_run_as_host_user docstring  tools/environments/docker.py runs *arbitrary user images* via the terminal backend, not the bundled Hermes image. It still needs SETUID/ SETGID caps so user images that use gosu/su/s6-setuidgid all work. Renamed the cap-list constant _GOSU_CAP_ARGS → _PRIVDROP_CAP_ARGS and updated comments to list s6-setuidgid alongside the others as examples. The matching test (test_security_args_include_setuid_setgid_for_gosu_drop → test_security_args_include_setuid_setgid_for_privdrop) was renamed and its docstring updated; behavior is unchanged.  Verification: - hadolint clean against .hadolint.yaml - shellcheck clean against all docker/ shell scripts - Image rebuilt successfully (sha 1a090924ccea) - Docker harness: 19 passed in 41.87s (every Phase 0 test + Phase 4   per-profile-gateway lifecycle + container-restart reconciliation) - tests/tools/test_docker_environment.py: 23 passed (rename did not   break test discovery; pre-existing unrelated mock warning)  The plan document (docs/plans/2026-05-07-s6-overlay-dynamic-subagent-gateways.md) intentionally retains its historical references to gosu — it describes the pre-s6 entrypoint as background for understanding the migration.") | 3 months agoMay 24, 2026 |
| [.mailmap](https://github.com/NousResearch/hermes-agent/blob/main/.mailmap ".mailmap") | [.mailmap](https://github.com/NousResearch/hermes-agent/blob/main/.mailmap ".mailmap") | [chore: add MestreY0d4-Uninter to AUTHOR\_MAP and .mailmap](https://github.com/NousResearch/hermes-agent/commit/902f1e6ede20dd618d64aa6dccced966675f8316 "chore: add MestreY0d4-Uninter to AUTHOR_MAP and .mailmap") | 4 months agoApr 15, 2026 |
| [.npmrc](https://github.com/NousResearch/hermes-agent/blob/main/.npmrc ".npmrc") | [.npmrc](https://github.com/NousResearch/hermes-agent/blob/main/.npmrc ".npmrc") | [fix: fix @nousresearch/ui version, update to npm 12](https://github.com/NousResearch/hermes-agent/commit/f88ed6c71768cdc7ea3bfa8cf62d16654792fd2a "fix: fix @nousresearch/ui version, update to npm 12") | 2 days agoAug 1, 2026 |
| [.nvmrc](https://github.com/NousResearch/hermes-agent/blob/main/.nvmrc ".nvmrc") | [.nvmrc](https://github.com/NousResearch/hermes-agent/blob/main/.nvmrc ".nvmrc") | [feat: add .nvmrc w/ node 26](https://github.com/NousResearch/hermes-agent/commit/aa4ce7a507f0135623dcc02bc1b536c327348a5f "feat: add .nvmrc w/ node 26") | yesterdayAug 1, 2026 |
| [.prettierignore](https://github.com/NousResearch/hermes-agent/blob/main/.prettierignore ".prettierignore") | [.prettierignore](https://github.com/NousResearch/hermes-agent/blob/main/.prettierignore ".prettierignore") | [fix(ci): js-autofix pushes via PR instead of direct push to main (](https://github.com/NousResearch/hermes-agent/commit/64389a2ce26a9ecd5fb745343f6247582def0eb8 "fix(ci): js-autofix pushes via PR instead of direct push to main (#65186)  * fix(js): never format package-lock.json  prettier and eslint should never touch package-lock.json. main has a repo rule requiring team approval when lockfiles change, so an autofix PR touching it would hang waiting for review.  - Add .prettierignore at repo root - Add '**/package-lock.json' to eslint shared config ignores  * fix(ci): js-autofix pushes via PR instead of direct push to main  Main now has repository rules requiring pull requests + required status checks (\"All required checks pass\"), so the workflow's direct push to main is rejected with GH013 every time eslint --fix produces changes.  Switch apply-patch to push to a dedicated bot/js-autofix branch, create or update a PR, and enable auto-merge (squash). The PR auto-merges once CI passes. If CI fails or main moves, the PR is auto-closed and the branch deleted — the next run re-applies on the current state.  The two-job security split is preserved: - generate-patch stays unprivileged (contents: read only) — it runs npm   on an ephemeral runner with zero push permissions. - apply-patch (contents: write + pull-requests: write) still never runs   npm, never installs anything, never executes repo code — it applies   the trusted patch artifact and delivers it via PR.") [#65186](https://github.com/NousResearch/hermes-agent/pull/65186) | 3 weeks agoJul 15, 2026 |
| [.prettierrc](https://github.com/NousResearch/hermes-agent/blob/main/.prettierrc ".prettierrc") | [.prettierrc](https://github.com/NousResearch/hermes-agent/blob/main/.prettierrc ".prettierrc") | [refactor(lint): hoist shared eslint + prettier config to root](https://github.com/NousResearch/hermes-agent/commit/214cbf77f065aba4747b018d7aeb08ebcedb4576 "refactor(lint): hoist shared eslint + prettier config to root") | 3 weeks agoJul 15, 2026 |
| [.python-version](https://github.com/NousResearch/hermes-agent/blob/main/.python-version ".python-version") | [.python-version](https://github.com/NousResearch/hermes-agent/blob/main/.python-version ".python-version") | [fix: pin uv python to 3.11](https://github.com/NousResearch/hermes-agent/commit/f5130f02328079a8f1958f803e5c90a32213ec5d "fix: pin uv python to 3.11") | yesterdayAug 1, 2026 |
| [AGENTS.md](https://github.com/NousResearch/hermes-agent/blob/main/AGENTS.md "AGENTS.md") | [AGENTS.md](https://github.com/NousResearch/hermes-agent/blob/main/AGENTS.md "AGENTS.md") | [docs: purge stale xdist/\_enforce\_test\_timeout test-runner references …](https://github.com/NousResearch/hermes-agent/commit/8e1debd5ed6cb0fe5737c59682fb0036d79c29f5 "docs: purge stale xdist/_enforce_test_timeout test-runner references repo-wide  The test runner moved to per-file subprocess isolation via scripts/run_tests_parallel.py (hermetic `env -i`, worker count auto-scaled from CPU count, FLAKY-retry policy) — no pytest-xdist, no SIGALRM per-test timeout fixture. Docs still described the old runner in many places:  - AGENTS.md: \"-n auto xdist workers, in-tree subprocess-isolation plugin\"   clause replaced with the current per-file-subprocess description; the   `::test_x` single-test example now shows file + -k (runner is   file-granular). - CONTRIBUTING.md: \"hermetic env, 4 xdist workers\" comment corrected;   `tests/conftest.py::_enforce_test_timeout` reference redirected to the   win32 timeout-method shim in `tests/conftest.py::pytest_configure`. - skills/autonomous-ai-agents/hermes-agent/references/contributor-guide.md   and windows-quirks.md: same corrections (the bundled skill mirrors the   contributor docs); Windows workaround no longer installs pytest-xdist   or passes -n 0. - website/docs + zh-Hans i18n mirrors: same fixes in adding-providers.md   and the bundled-skill doc pages. - skills/software-development/python-debugpy/SKILL.md (+ zh-Hans mirror):   \"-p no:xdist\"/\"-n 0\" pdb advice rewritten for the captured per-file   subprocess runner. - skills/creative/comfyui/tests/README.md: parent-repo \"-n auto by   default\" rationale updated to past tense.  Combined salvage of PR #38295 (konsisumer), PR #51354 (TutkuEroglu, redirected to the current conftest truth and the relocated references/contributor-guide.md), and PR #54956 (waroffchange).  Co-authored-by: TutkuEroglu <rrandqua@gmail.com> Co-authored-by: waroffchange <116298975+waroffchange@users.noreply.github.com>") | 4 days agoJul 30, 2026 |
| [CONTRIBUTING.es.md](https://github.com/NousResearch/hermes-agent/blob/main/CONTRIBUTING.es.md "CONTRIBUTING.es.md") | [CONTRIBUTING.es.md](https://github.com/NousResearch/hermes-agent/blob/main/CONTRIBUTING.es.md "CONTRIBUTING.es.md") | [docs(i18n): align translated CONTRIBUTING files with pyproject Python…](https://github.com/NousResearch/hermes-agent/commit/ee0b54e16cbbd1ca96d4a1facdcef683c1608696 "docs(i18n): align translated CONTRIBUTING files with pyproject Python range (3.11-3.13)") | last monthJul 8, 2026 |
| [CONTRIBUTING.md](https://github.com/NousResearch/hermes-agent/blob/main/CONTRIBUTING.md "CONTRIBUTING.md") | [CONTRIBUTING.md](https://github.com/NousResearch/hermes-agent/blob/main/CONTRIBUTING.md "CONTRIBUTING.md") | [docs: purge stale xdist/\_enforce\_test\_timeout test-runner references …](https://github.com/NousResearch/hermes-agent/commit/8e1debd5ed6cb0fe5737c59682fb0036d79c29f5 "docs: purge stale xdist/_enforce_test_timeout test-runner references repo-wide  The test runner moved to per-file subprocess isolation via scripts/run_tests_parallel.py (hermetic `env -i`, worker count auto-scaled from CPU count, FLAKY-retry policy) — no pytest-xdist, no SIGALRM per-test timeout fixture. Docs still described the old runner in many places:  - AGENTS.md: \"-n auto xdist workers, in-tree subprocess-isolation plugin\"   clause replaced with the current per-file-subprocess description; the   `::test_x` single-test example now shows file + -k (runner is   file-granular). - CONTRIBUTING.md: \"hermetic env, 4 xdist workers\" comment corrected;   `tests/conftest.py::_enforce_test_timeout` reference redirected to the   win32 timeout-method shim in `tests/conftest.py::pytest_configure`. - skills/autonomous-ai-agents/hermes-agent/references/contributor-guide.md   and windows-quirks.md: same corrections (the bundled skill mirrors the   contributor docs); Windows workaround no longer installs pytest-xdist   or passes -n 0. - website/docs + zh-Hans i18n mirrors: same fixes in adding-providers.md   and the bundled-skill doc pages. - skills/software-development/python-debugpy/SKILL.md (+ zh-Hans mirror):   \"-p no:xdist\"/\"-n 0\" pdb advice rewritten for the captured per-file   subprocess runner. - skills/creative/comfyui/tests/README.md: parent-repo \"-n auto by   default\" rationale updated to past tense.  Combined salvage of PR #38295 (konsisumer), PR #51354 (TutkuEroglu, redirected to the current conftest truth and the relocated references/contributor-guide.md), and PR #54956 (waroffchange).  Co-authored-by: TutkuEroglu <rrandqua@gmail.com> Co-authored-by: waroffchange <116298975+waroffchange@users.noreply.github.com>") | 4 days agoJul 30, 2026 |
| [Dockerfile](https://github.com/NousResearch/hermes-agent/blob/main/Dockerfile "Dockerfile") | [Dockerfile](https://github.com/NousResearch/hermes-agent/blob/main/Dockerfile "Dockerfile") | [fix(docker): drop corepack and add libatomic1 for the Node 26 bump](https://github.com/NousResearch/hermes-agent/commit/2ad0ea4d3f2320473676092e7d660f4eb5cdb99a "fix(docker): drop corepack and add libatomic1 for the Node 26 bump  Two breaks from moving node_source to node:26, both proven against the real image rather than inferred:  1. `COPY .../node_modules/corepack` failed with \"not found\". Node    unbundled corepack upstream, so node:26 ships only `npm` in    /usr/local/lib/node_modules (verified: `ls` in the pinned image lists    `npm` alone). Nothing in this repo needs it — no package.json declares    a `packageManager` and no build step shells out to yarn or pnpm — so    the COPY and its symlink are removed rather than replaced.  2. Hidden behind that failure: node 26's binary links against    `libatomic.so.1`, which node 22's did not, and bare debian:13.4    doesn't ship it. Without it every `node` invocation in the image dies    with \"error while loading shared libraries: libatomic.so.1\". Added    `libatomic1` to the existing apt layer, which runs well before the    node COPY so layer ordering and caching are unchanged.  Verified with a minimal probe image (debian:13.4 + the same two COPY lines): node v26.5.1, npm 11.17.0, npx 11.17.0, uv 0.11.6 all execute.") | yesterdayAug 1, 2026 |
| [LICENSE](https://github.com/NousResearch/hermes-agent/blob/main/LICENSE "LICENSE") | [LICENSE](https://github.com/NousResearch/hermes-agent/blob/main/LICENSE "LICENSE") | [fix: restore missing MIT license file](https://github.com/NousResearch/hermes-agent/commit/9ba5d399e58fa353d7132b0e2e9533d281ff64d1 "fix: restore missing MIT license file") | 5 months agoMar 7, 2026 |
| [README.es.md](https://github.com/NousResearch/hermes-agent/blob/main/README.es.md "README.es.md") | [README.es.md](https://github.com/NousResearch/hermes-agent/blob/main/README.es.md "README.es.md") | [feat(i18n): add complete Spanish translation](https://github.com/NousResearch/hermes-agent/commit/2609bcccca305046ea90da1f44c20d0b607635c6 "feat(i18n): add complete Spanish translation  - Complete README.es.md (full Spanish translation of README) - Add CONTRIBUTING.es.md (Spanish contributing guide) - Add SECURITY.es.md (Spanish security policy) - Fix remaining English strings in locales/es.yaml (resume Matrix section) - Add Spanish badge to README.md  All 47 i18n tests pass, including catalog key parity and placeholder parity.  Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>") | 2 months agoJun 21, 2026 |
| [README.md](https://github.com/NousResearch/hermes-agent/blob/main/README.md "README.md") | [README.md](https://github.com/NousResearch/hermes-agent/blob/main/README.md "README.md") | [Revert "remove Vercel AI Gateway and Vercel Sandbox (](https://github.com/NousResearch/hermes-agent/commit/ad12df6ba488129c07c2b58d9ad30dcaba440ab4 "Revert \"remove Vercel AI Gateway and Vercel Sandbox (#33067)\"  This reverts commit febc4cfec0a79b175a430304765473c97e10622f.") [#33067](https://github.com/NousResearch/hermes-agent/pull/33067) [)"](https://github.com/NousResearch/hermes-agent/commit/ad12df6ba488129c07c2b58d9ad30dcaba440ab4 "Revert \"remove Vercel AI Gateway and Vercel Sandbox (#33067)\"  This reverts commit febc4cfec0a79b175a430304765473c97e10622f.") | 4 days agoJul 29, 2026 |
| [README.ur-pk.md](https://github.com/NousResearch/hermes-agent/blob/main/README.ur-pk.md "README.ur-pk.md") | [README.ur-pk.md](https://github.com/NousResearch/hermes-agent/blob/main/README.ur-pk.md "README.ur-pk.md") | [docs: add Urdu translation of README (](https://github.com/NousResearch/hermes-agent/commit/2b119baac137b9348a0cf812b03c96ed8cee8296 "docs: add Urdu translation of README (#40578)  Co-authored-by: AMIK-coorporations <info@amik.co>") [#40578](https://github.com/NousResearch/hermes-agent/pull/40578) [)](https://github.com/NousResearch/hermes-agent/commit/2b119baac137b9348a0cf812b03c96ed8cee8296 "docs: add Urdu translation of README (#40578)  Co-authored-by: AMIK-coorporations <info@amik.co>") | 2 months agoJun 7, 2026 |
| [README.zh-CN.md](https://github.com/NousResearch/hermes-agent/blob/main/README.zh-CN.md "README.zh-CN.md") | [README.zh-CN.md](https://github.com/NousResearch/hermes-agent/blob/main/README.zh-CN.md "README.zh-CN.md") | [docs(README.zh-CN): update Windows install from 'not supported' to na…](https://github.com/NousResearch/hermes-agent/commit/2b08a4295a650d27fc354573ef2dde87dd211103 "docs(README.zh-CN): update Windows install from 'not supported' to native PowerShell  The Chinese README still told Windows users to install WSL2 and run the Linux installer. Hermes now ships a native PowerShell install script, so replace the outdated WSL2-only note with the direct PowerShell one-liner.  Fixes: documentation accuracy / Windows onboarding") | 2 months agoJun 20, 2026 |
| [SECURITY.es.md](https://github.com/NousResearch/hermes-agent/blob/main/SECURITY.es.md "SECURITY.es.md") | [SECURITY.es.md](https://github.com/NousResearch/hermes-agent/blob/main/SECURITY.es.md "SECURITY.es.md") | [docs: sync overnight sweep with registry, gateway, curator, cron](https://github.com/NousResearch/hermes-agent/commit/782d0219a0a3c475882b2dae0dca7d8d80eecf0a "docs: sync overnight sweep with registry, gateway, curator, cron  Salvaged from #72422 by @virtuadex (conflicts resolved against current main; superseded slash-command hunks dropped):  - SECURITY.md + SECURITY.es.md: gateway adapters live under   plugins/platforms/<name>/, registry in gateway/platform_registry.py - gateway-internals.md (EN + zh-Hans): key-files table rows for   platform_registry.py and plugins/platforms/, deferred-loading section - slash-commands.md: /reasoning full level list (max/ultra) + --global;   CLI-only notes list gains /prompt, /pet, /hatch, /timestamps - cron.md + cron-script-only.md: script runner accuracy — bash resolved   from PATH with /bin/bash fallback, script paths confined to   ~/.hermes/scripts/, provider credentials stripped via   _sanitize_subprocess_env - curator.md: cron-referenced skills protected from auto-archive,   never-used grace floor") | 5 days agoJul 29, 2026 |
| [SECURITY.md](https://github.com/NousResearch/hermes-agent/blob/main/SECURITY.md "SECURITY.md") | [SECURITY.md](https://github.com/NousResearch/hermes-agent/blob/main/SECURITY.md "SECURITY.md") | [docs: sync overnight sweep with registry, gateway, curator, cron](https://github.com/NousResearch/hermes-agent/commit/782d0219a0a3c475882b2dae0dca7d8d80eecf0a "docs: sync overnight sweep with registry, gateway, curator, cron  Salvaged from #72422 by @virtuadex (conflicts resolved against current main; superseded slash-command hunks dropped):  - SECURITY.md + SECURITY.es.md: gateway adapters live under   plugins/platforms/<name>/, registry in gateway/platform_registry.py - gateway-internals.md (EN + zh-Hans): key-files table rows for   platform_registry.py and plugins/platforms/, deferred-loading section - slash-commands.md: /reasoning full level list (max/ultra) + --global;   CLI-only notes list gains /prompt, /pet, /hatch, /timestamps - cron.md + cron-script-only.md: script runner accuracy — bash resolved   from PATH with /bin/bash fallback, script paths confined to   ~/.hermes/scripts/, provider credentials stripped via   _sanitize_subprocess_env - curator.md: cron-referenced skills protected from auto-archive,   never-used grace floor") | 5 days agoJul 29, 2026 |
| [batch\_runner.py](https://github.com/NousResearch/hermes-agent/blob/main/batch_runner.py "batch_runner.py") | [batch\_runner.py](https://github.com/NousResearch/hermes-agent/blob/main/batch_runner.py "batch_runner.py") | [fix: context-length fallback logging, batch trajectory durability, po…](https://github.com/NousResearch/hermes-agent/commit/a1ff62a139aca2c5dd13a2c312731371475a583b "fix: context-length fallback logging, batch trajectory durability, pool cleanup  Salvage of #6629 by aaronlab (kshitijk4poor reworked against current main).  Three concerns from the original PR, reworked to address review feedback:  1. Context-length fallback diagnostic (agent/model_metadata.py):    get_model_context_length() silently returned 256K when all 9 detection    methods failed. Users with small-context models (8K, 32K) would get 256K    silently, causing hard-to-debug API context-length errors. Added a    warning log at the step 9 fallback with model name, base_url, and the    correct config override hint (model.context_length, not context_length).    The token-estimation ceiling-division fix from the original PR already    landed on main (5c2ecdec) with CJK handling — not duplicated here.  2. Fsync for batch trajectory writes (batch_runner.py):    Trajectory entries were written without flush/fsync, but the checkpoint    immediately marked them as completed. A crash between write and disk    sync would leave the checkpoint claiming completion with no trajectory    data on disk. Added flush() + os.fsync() before checkpoint update.  3. Pool cleanup on interruption (batch_runner.py):    Ctrl+C during pool.imap_unordered() relied on context manager cleanup    which can hang. Added explicit pool.terminate() + pool.join() for both    KeyboardInterrupt and Exception paths. The original PR used    pool.join(timeout=10) which is invalid — CPython's Pool.join() takes    no timeout parameter. Fixed to use pool.join() without arguments.  Tests:   - test_warning_emitted_on_fallback: verifies warning fires at step 9   - test_no_warning_when_cached: verifies no false warning when cache hits   - test_trajectory_entry_is_synced_to_disk: verifies os.fsync is called   - test_pool_terminate_called_on_exception: verifies cleanup on RuntimeError   - test_pool_terminate_called_on_keyboard_interrupt: verifies cleanup on Ctrl+C   - test_pool_join_called_without_timeout: verifies no timeout arg to join()   - test_real_pool_join_accepts_no_timeout: integration check on CPython API  Co-authored-by: Aaron Lab <aaronlab@users.noreply.github.com>") | 2 days agoAug 1, 2026 |
| [cli-config.yaml.example](https://github.com/NousResearch/hermes-agent/blob/main/cli-config.yaml.example "cli-config.yaml.example") | [cli-config.yaml.example](https://github.com/NousResearch/hermes-agent/blob/main/cli-config.yaml.example "cli-config.yaml.example") | [docs: document agent.session\_stall\_timeout + compression timeout keys…](https://github.com/NousResearch/hermes-agent/commit/b2963f8034bcd2e5f6b6c32cef2a11ced187242d "docs: document agent.session_stall_timeout + compression timeout keys (re-review #7)  - website/docs/user-guide/configuration.md (en) and the zh-Hans   translation gain a 'Session Stall Watchdog' section: default 300,   0=disabled, notify-only semantics (never kills the turn — contrast   gateway_timeout), one notification per stall episode, and the exact   stall message text so it is greppable. - cli-config.yaml.example: the two in-agent compression timeout keys   (compression.context_timeout_seconds /   compression.context_total_ceiling_seconds) are shown as commented   lines next to session_stall_timeout's example for discoverability.") | 9 hours agoAug 2, 2026 |
| [cli.py](https://github.com/NousResearch/hermes-agent/blob/main/cli.py "cli.py") | [cli.py](https://github.com/NousResearch/hermes-agent/blob/main/cli.py "cli.py") | [fix(cli): persist YOLO mode across --resume](https://github.com/NousResearch/hermes-agent/commit/ef9f6effaffc5c454598a072c7ffba12048783f6 "fix(cli): persist YOLO mode across --resume  A session's YOLO bypass lived only in the in-memory tools.approval._session_yolo set (or the process-frozen --yolo env var), so resuming a session in a fresh process silently reverted the user's /yolo ON — dangerous commands started prompting again.  Persist a yolo_mode flag in the session row's model_config JSON and restore it on every CLI resume path:  - SessionDB.set_session_yolo() merges the flag into model_config   (same lineage-preserving merge as update_session_runtime_lock);   SessionDB.session_yolo_enabled() reads it back, false on any parse   failure. - /yolo toggle persists ON and OFF through the new helper; the   compression/branch session-id rotation carries the flag onto the   continuation row. - --yolo launches record the flag at session creation (agent_init),   and a /yolo toggled before the lazily-created row exists is carried   into the creation-time model_config (_ensure_db_session). - HermesCLI._restore_session_yolo() re-enables the bypass on startup   --resume/-c, the deferred init path, and mid-chat /resume, with a   visible '⚡ YOLO mode restored from session' notice. No-op under a   frozen process-wide --yolo and never enables on absent/garbage flags.") | 5 hours agoAug 2, 2026 |
| [constraints-termux.txt](https://github.com/NousResearch/hermes-agent/blob/main/constraints-termux.txt "constraints-termux.txt") | [constraints-termux.txt](https://github.com/NousResearch/hermes-agent/blob/main/constraints-termux.txt "constraints-termux.txt") | [feat: add tested Termux install path and EOF-aware gh auth](https://github.com/NousResearch/hermes-agent/commit/e79cc8898517cf4b06b0490b828e79a1ee1ede59 "feat: add tested Termux install path and EOF-aware gh auth") | 4 months agoApr 9, 2026 |
| [docker-compose.windows.yml](https://github.com/NousResearch/hermes-agent/blob/main/docker-compose.windows.yml "docker-compose.windows.yml") | [docker-compose.windows.yml](https://github.com/NousResearch/hermes-agent/blob/main/docker-compose.windows.yml "docker-compose.windows.yml") | [feat(docker): add Windows Docker Desktop compatible compose file](https://github.com/NousResearch/hermes-agent/commit/f8695ed6a7e64f9a62ed73fd559bf6887d69d079 "feat(docker): add Windows Docker Desktop compatible compose file") | 3 months agoMay 23, 2026 |
| [docker-compose.yml](https://github.com/NousResearch/hermes-agent/blob/main/docker-compose.yml "docker-compose.yml") | [docker-compose.yml](https://github.com/NousResearch/hermes-agent/blob/main/docker-compose.yml "docker-compose.yml") | [docs(compose): update entrypoint comment for s6-overlay](https://github.com/NousResearch/hermes-agent/commit/143a189def3201bf8f79a7036b1e5e8c9aff87a8 "docs(compose): update entrypoint comment for s6-overlay  PR #30136 review caught: docker-compose.yml still said \"If you override entrypoint, keep /opt/hermes/docker/entrypoint.sh in the command chain.\" That was true under tini; under s6-overlay the entrypoint is /init plus main-wrapper.sh, and entrypoint.sh is now only a backward-compat shim.  Replace with an accurate description: /init must remain first in the chain because it's PID 1 and runs the cont-init.d scripts (chown, profile reconcile, dashboard toggle) before any service starts.") | 3 months agoMay 24, 2026 |
| [eslint.config.shared.mjs](https://github.com/NousResearch/hermes-agent/blob/main/eslint.config.shared.mjs "eslint.config.shared.mjs") | [eslint.config.shared.mjs](https://github.com/NousResearch/hermes-agent/blob/main/eslint.config.shared.mjs "eslint.config.shared.mjs") | [fix(js): hoist eslint shared devDeps to workspace root](https://github.com/NousResearch/hermes-agent/commit/fabc2d7d331e067607a55429d9bfd635743950a7 "fix(js): hoist eslint shared devDeps to workspace root") | 3 days agoJul 31, 2026 |
| [flake.lock](https://github.com/NousResearch/hermes-agent/blob/main/flake.lock "flake.lock") | [flake.lock](https://github.com/NousResearch/hermes-agent/blob/main/flake.lock "flake.lock") | [nix: update nixpkgs, update nodejs to 26](https://github.com/NousResearch/hermes-agent/commit/f976284245fb54ca8c85ee82818540c5a4287178 "nix: update nixpkgs, update nodejs to 26  brings npm 12 :)") | 3 days agoJul 31, 2026 |
| [flake.nix](https://github.com/NousResearch/hermes-agent/blob/main/flake.nix "flake.nix") | [flake.nix](https://github.com/NousResearch/hermes-agent/blob/main/flake.nix "flake.nix") | [fix(nix): follow root pyproject inputs](https://github.com/NousResearch/hermes-agent/commit/5a5e7e2a465e7570f6c1fd9bb16d8dec1814e731 "fix(nix): follow root pyproject inputs") | last monthJul 5, 2026 |
| [hermes](https://github.com/NousResearch/hermes-agent/blob/main/hermes "hermes") | [hermes](https://github.com/NousResearch/hermes-agent/blob/main/hermes "hermes") | [fix: use argparse entrypoint in top-level launcher (](https://github.com/NousResearch/hermes-agent/commit/fd29933a6d44fdb1168fed5a50df07aba84c8387 "fix: use argparse entrypoint in top-level launcher (#3874)  The ./hermes convenience script still used the legacy Fire-based cli.main wrapper, which doesn't support subcommands (gateway, cron, doctor, etc.). The installed 'hermes' command already uses hermes_cli.main:main (argparse) — this aligns the launcher.  Salvaged from PR #2009 by gito369.") [#3874](https://github.com/NousResearch/hermes-agent/pull/3874) [)](https://github.com/NousResearch/hermes-agent/commit/fd29933a6d44fdb1168fed5a50df07aba84c8387 "fix: use argparse entrypoint in top-level launcher (#3874)  The ./hermes convenience script still used the legacy Fire-based cli.main wrapper, which doesn't support subcommands (gateway, cron, doctor, etc.). The installed 'hermes' command already uses hermes_cli.main:main (argparse) — this aligns the launcher.  Salvaged from PR #2009 by gito369.") | 5 months agoMar 30, 2026 |
| [hermes-already-has-routines.md](https://github.com/NousResearch/hermes-agent/blob/main/hermes-already-has-routines.md "hermes-already-has-routines.md") | [hermes-already-has-routines.md](https://github.com/NousResearch/hermes-agent/blob/main/hermes-already-has-routines.md "hermes-already-has-routines.md") | [docs: stop recommending pip install; curl installer is the only suppo…](https://github.com/NousResearch/hermes-agent/commit/a911bcda18cf83273d0aabd3e67adb2206436e60 "docs: stop recommending pip install; curl installer is the only supported path (#51743)  * docs: stop recommending pip install hermes-agent; point to install script  The install script is the only supported install path (it provisions a managed, isolated uv environment). Replace bare `pip install hermes-agent` primary-install recommendations with the curl install script, and rewrite optional-extra snippets (`pip install \"hermes-agent[X]\"`) to the managed-env form `cd ~/.hermes/hermes-agent && uv pip install -e \".[X]\"` that matches the installer and the English quickstart.  Covers English docs + zh-Hans mirrors, the achievements plugin README, and realigns the zh-Hans quickstart to the English Desktop-installer-first layout (dropping its stale \"Method A — pip (simplest)\" section).  * docs: drop pip as a supported install/update method  Removes the 'pip installs' supported-method sections from updating.md and cli-commands.md (EN + zh-Hans): the curl install script is the only supported way to install/update the Hermes CLI. The _cmd_update_pip pip/pipx branches remain in code as an undocumented safety net for users who already have such an install, but the docs no longer advertise pip as a path.  Also normalizes a bare `pip install -e '.[acp]'` to the managed-env form.  Leaves python-library.md untouched: importing AIAgent as a library dependency into your own project is a distinct use case where pip is correct.") | 2 months agoJun 24, 2026 |
| [hermes\_bootstrap.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_bootstrap.py "hermes_bootstrap.py") | [hermes\_bootstrap.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_bootstrap.py "hermes_bootstrap.py") | [fix(windows): platform.\_syscmd\_ver stub in bootstrap + PYTHONUTF8 in …](https://github.com/NousResearch/hermes-agent/commit/0fb0ba475dee759999fe665a7c59eedba7932be3 "fix(windows): platform._syscmd_ver stub in bootstrap + PYTHONUTF8 in desktop backend env  Two gaps found auditing the decode-crash cluster:  1. suppress_platform_ver_console() only ran in hermes_cli.main processes;    slash workers, tui_gateway/entry, run_agent, batch_runner, and cli.py    import only hermes_bootstrap and were exposed to both the console    flash and (on Python 3.11.0/3.11.1, which lack CPython's    encoding='locale' fix) a UnicodeDecodeError inside platform.win32_ver()    under PEP 540 — the crash #69413 reported. Move the stub into    hermes_bootstrap so every entry point gets it; the _subprocess_compat    copy stays for non-bootstrap callers.  2. The desktop Electron spawn built the backend env without PYTHONUTF8,    so anything the Python child emitted before hermes_bootstrap ran    (interpreter startup errors, pre-bootstrap tracebacks) decoded with    the locale default. Re-port of PR #56499's env half (echoriver89) to    backend-env.ts (original targeted the deleted backend-env.cjs);    explicit user setting wins.") | last weekJul 24, 2026 |
| [hermes\_constants.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_constants.py "hermes_constants.py") | [hermes\_constants.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_constants.py "hermes_constants.py") | [fix(install): restore installs — engines floor no shipping toolchain …](https://github.com/NousResearch/hermes-agent/commit/8e08a4a16e24144949c066521afddde12d5d31dd "fix(install): restore installs — engines floor no shipping toolchain can meet  Fresh installs and `hermes update` both fail at the first `npm ci`:      npm error code EBADENGINE     npm error notsup Required: {\"node\":\">=26.0.0\",\"npm\":\">=12.0.0\"}     npm error notsup Actual:   {\"node\":\"v24.15.0\",\"npm\":\"11.12.1\"}  `.npmrc` sets engine-strict=true, so `engines` is a hard gate on every install. The floor was raised to npm >=12 — but no Node release bundles npm 12: Node 26 ships 11.17.0, 24 ships 11.16.0, 22 ships 10.9.8. The requirement is unsatisfiable by any stock toolchain, so the installer provisions a Node and is immediately unable to install with it.  engines.npm becomes `<11.10.0 || >=11.17.0`. That still excludes the band the strictness was actually for: npm 11.10-11.16 honor `min-release-age` but ignore `min-release-age-exclude`, both set in .npmrc, so they apply the 14-day gate to packages we exempted. Verified rather than assumed — npm 11.12.1 fails `ETARGET ... vite@8.2.0 with a date before 7/18/2026` while 11.17.0 installs it.  engines.node returns to >=20.0.0 and the toolchain floor to Node 22. Nothing in the tree needs 26: Vite 8.2.0 declares `^20.19.0 || >=22.12.0` and Electron 40 declares `>=12.20.55`. Requiring 26 force-migrated every working install for no dependency reason. apps/desktop drops to Vite's own floor for the same reason; the desktop bundle builds clean on Node 22.  install.sh gained a second gate: a system Node was accepted on version alone, so a machine with Node 24 + its bundled npm 11.16.0 (the bad band) passed the check and then failed `npm ci`. npm_supports_npmrc() now rejects that band and installs the managed Node instead.  CI, Docker and nix are hermetic and keep pinning Node 26 / npm 12 — they provision their own toolchain, and both satisfy the relaxed range.  tests/test_engines_satisfiable.py encodes the invariants that would have caught this: the npm floor must be met by an npm some shipping Node bundles, the node floor by the runtime install.sh provisions, the desktop floor by its own build toolchain, and the lockfile mirror must match. Restoring the broken values fails 5 of them with the reason stated.  Verified end-to-end (real downloads, temp HERMES_HOME): - fresh install: managed node v22.23.2 / npm 10.9.8 -> npm ci, 209 packages - existing managed tree (v22.22.3 / npm 10.9.8) -> npm ci, 209 packages - node 26.5.1 + bundled npm 11.17.0 -> npm ci, 208 packages - system npm 11.12.1 (the reported case) -> EBADENGINE, recovery provisions   a managed tree and retries green - apps/desktop `npm run build` on Node 22 -> dist built, assert passes") | yesterdayAug 1, 2026 |
| [hermes\_logging.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_logging.py "hermes_logging.py") | [hermes\_logging.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_logging.py "hermes_logging.py") | [perf(config): one raw config.yaml parse per process instead of 3-4](https://github.com/NousResearch/hermes-agent/commit/fedd689d37f18cc67e01a062303349032ea16d7b "perf(config): one raw config.yaml parse per process instead of 3-4  Counted with an open()/read_text audit hook on a real 'hermes --version' run: config.yaml was parsed 3x before load_config() even ran — once by env_loader._load_secrets_config, once by main.py's early redact/ipv4 bridge (bespoke yaml.load), once by hermes_logging._read_logging_config. Each raw parse is 1-3 ms with libyaml plus an open/stat — pure duplication since all three want the same raw dict.  All three now route through read_raw_config()'s existing (mtime_ns, size)-keyed shared cache:  - env_loader._load_secrets_config: uses the shared reader when reading   the process HERMES_HOME (the cache key's home); other homes (profile   seeding) keep the isolated direct parse. Parse-error isolation is   preserved — the shared reader also swallows errors and returns {}. - main.py early bridge: drops the bespoke yaml.load for read_raw_config   (managed-scope overlay unchanged). - hermes_logging._read_logging_config: prefers the shared reader,   falls back to the direct fast_safe_load parse when hermes_cli.config   isn't importable.  Measured: config.yaml opens per 'hermes --version' 3 -> 1. 348 targeted tests green (env_loader + secret sources + applied-homes + bitwarden + hermes_logging + config).") | 5 days agoJul 29, 2026 |
| [hermes\_state.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_state.py "hermes_state.py") | [hermes\_state.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_state.py "hermes_state.py") | [fix(cli): persist YOLO mode across --resume](https://github.com/NousResearch/hermes-agent/commit/ef9f6effaffc5c454598a072c7ffba12048783f6 "fix(cli): persist YOLO mode across --resume  A session's YOLO bypass lived only in the in-memory tools.approval._session_yolo set (or the process-frozen --yolo env var), so resuming a session in a fresh process silently reverted the user's /yolo ON — dangerous commands started prompting again.  Persist a yolo_mode flag in the session row's model_config JSON and restore it on every CLI resume path:  - SessionDB.set_session_yolo() merges the flag into model_config   (same lineage-preserving merge as update_session_runtime_lock);   SessionDB.session_yolo_enabled() reads it back, false on any parse   failure. - /yolo toggle persists ON and OFF through the new helper; the   compression/branch session-id rotation carries the flag onto the   continuation row. - --yolo launches record the flag at session creation (agent_init),   and a /yolo toggled before the lazily-created row exists is carried   into the creation-time model_config (_ensure_db_session). - HermesCLI._restore_session_yolo() re-enables the bypass on startup   --resume/-c, the deferred init path, and mid-chat /resume, with a   visible '⚡ YOLO mode restored from session' notice. No-op under a   frozen process-wide --yolo and never enables on absent/garbage flags.") | 5 hours agoAug 2, 2026 |
| [hermes\_state\_common.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_state_common.py "hermes_state_common.py") | [hermes\_state\_common.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_state_common.py "hermes_state_common.py") | [chore(state): bump SCHEMA\_VERSION to 24 for activity-tracking columns…](https://github.com/NousResearch/hermes-agent/commit/53a5983af07a7507a5b7f6cbc0bb7ef1cd160eac "chore(state): bump SCHEMA_VERSION to 24 for activity-tracking columns (re-review #3)  The last_activity_at/description/provenance columns already live in SCHEMA_SQL and the column reconciler; existing DBs heal via the reconciler, but the version stamp must advance so downgrade/upgrade tooling sees the new layout. No version-literal test assertions exist (tests compare against the imported constant).") | 9 hours agoAug 2, 2026 |
| [hermes\_state\_portability.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_state_portability.py "hermes_state_portability.py") | [hermes\_state\_portability.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_state_portability.py "hermes_state_portability.py") | [docs(gateway): precise watchdog scope, explicit import-resets-activit…](https://github.com/NousResearch/hermes-agent/commit/038c1ad8724614ea2a76d72c1792ce7b172a708d "docs(gateway): precise watchdog scope, explicit import-resets-activity contract (review S4)  - Config docs now describe session_stall_timeout precisely: a RECOVERY   notifier for an in-process AIAgent with an adapter-queued follow-up —   not a general gateway/session stall detector — with a per-AIAgent scan   cadence (not globally coordinated per durable session). - import_sessions documents the deliberate export-includes /   import-resets asymmetry for the activity fields (no resurrected   'working' labels on machines where no agent runs), with a regression   pinning both halves. - Strip trailing whitespace in contributors/emails/fangliquan@qq.com   (git diff --check housekeeping).  PR #76354 review, scope/contract items + housekeeping.") | 9 hours agoAug 2, 2026 |
| [hermes\_state\_schema.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_state_schema.py "hermes_state_schema.py") | [hermes\_state\_schema.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_state_schema.py "hermes_state_schema.py") | [fix(state): do not stamp empty FTS after interrupted optimize-storage…](https://github.com/NousResearch/hermes-agent/commit/b2d5995fc6fa1f8ee11b895f3adf4995f8f23bbf "fix(state): do not stamp empty FTS after interrupted optimize-storage demote  Demote wrote the empty v23 schema via executescript inside BEGIN IMMEDIATE, which commits early and can leave trash + empty indexes without rebuild markers. Re-run then tore down trash and stamped fts_storage_version with docsize=0, permanently losing historical session search.  Stage markers with the demote, create schema only after they are durable, heal empty-index bookkeeping on resume, and refuse settle until the base index is populated. Settle refusal returns ok=False instead of raising, and resume fails fast if the base v23 table cannot be re-created.  Orphan-marker repair only resets a missing fts_rebuild_progress to 0 once the index is known empty: the chunk worker replays its whole selected id range without an anti-join, so a partially indexed DB that lost only its progress key is first reset to a known-empty surface, then rebuilt.  Ported onto the SessionDB mixin split (hermes_state_search.py / hermes_state_schema.py).") | 17 hours agoAug 2, 2026 |
| [hermes\_state\_search.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_state_search.py "hermes_state_search.py") | [hermes\_state\_search.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_state_search.py "hermes_state_search.py") | [perf(state): truncate FTS index with 'delete-all' instead of plain DE…](https://github.com/NousResearch/hermes-agent/commit/1e2e69db989066047e5fce2cc0a0c24b24633c9f "perf(state): truncate FTS index with 'delete-all' instead of plain DELETE  _reset_fts_index_to_empty used a no-WHERE DELETE, whose docstring claimed FTS5 treats it as an efficient drop-all. That's true only for ordinary rowid tables — on external-content FTS5 each deleted row's tokens are regenerated from the content table, making it O(rows) (measured ~12us/row: 0.22s @100K, 5.2s @400K, ~25s projected @2M) while holding the write lock. It also corrupts the index when indexed rows have diverged from messages — exactly the broken-bookkeeping shape this repair path handles. The FTS5 'delete-all' special command is the documented O(1) truncate for external-content tables (measured 1.6ms @100K) and truncates unconditionally regardless of divergence.") | 17 hours agoAug 2, 2026 |
| [hermes\_time.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_time.py "hermes_time.py") | [hermes\_time.py](https://github.com/NousResearch/hermes-agent/blob/main/hermes_time.py "hermes_time.py") | [perf(cli): TTFT round 2 — live reasoning by default, partial-line str…](https://github.com/NousResearch/hermes-agent/commit/0800af0b8ae01fd808e54be53d2cf12eca1d0638 "perf(cli): TTFT round 2 — live reasoning by default, partial-line streaming, prompt-build cache, stale budget-warning docs (#59389)  Follow-up to #59332 targeting the remaining PERCEIVED first-token latency (the wire streaming was already per-token; these fix what the user sees):  1. display.show_reasoning default ON. On thinking models the reasoning    phase streams for tens of seconds; with the display off users stare    at a spinner the whole time and read it as a stall. Flipped in    DEFAULT_CONFIG, load_cli_config defaults, tui_gateway raw-YAML    fallbacks, and the hermes setup status line (all four read sites kept    in sync). Gateway per-platform defaults intentionally stay off —    messaging chats shouldn't fill with thinking text. /reasoning hide    still turns it off and persists.  2. Response box force-flushes long partial lines. _emit_stream_text only    painted on newline, so a response opening with a long paragraph    stayed invisible until the first \n — seconds of blank box. Now    partial lines wrap at terminal width and paint as tokens arrive    (mirrors the reasoning box's 80-char force-flush that existed since    day one). Table blocks remain batch-aligned; no content loss at wrap    boundaries (regression tests added).  3. hermes_time timezone resolution uses read_raw_config (mtime-cached +    libyaml C loader) instead of a raw yaml.safe_load of config.yaml    (~110-140ms measured) inside the FIRST system prompt build. First    build drops 320ms -> ~155ms on a 200-skill install.  4. Stale docs: configuration.md (en+zh) still documented the 70%/90%    [BUDGET WARNING] tool-result injections. Those were removed in April    2026 (c8aff7463) precisely because they hurt task completion; current    behavior is exhaustion-message + one grace call, no mid-loop    injection, no cache impact. Docs now describe reality.  Verified: token-count compression decisions already use API-reported last_prompt_tokens (rough estimators are preflight-only and cost ~1.7ms even on 1.7MB histories — not worth touching).") | last monthJul 6, 2026 |
| [log.txt](https://github.com/NousResearch/hermes-agent/blob/main/log.txt "log.txt") | [log.txt](https://github.com/NousResearch/hermes-agent/blob/main/log.txt "log.txt") | [fix: fix @nousresearch/ui version, update to npm 12](https://github.com/NousResearch/hermes-agent/commit/f88ed6c71768cdc7ea3bfa8cf62d16654792fd2a "fix: fix @nousresearch/ui version, update to npm 12") | 2 days agoAug 1, 2026 |
| [mcp\_serve.py](https://github.com/NousResearch/hermes-agent/blob/main/mcp_serve.py "mcp_serve.py") | [mcp\_serve.py](https://github.com/NousResearch/hermes-agent/blob/main/mcp_serve.py "mcp_serve.py") | [fix(mcp): avoid replaying historical events on startup (](https://github.com/NousResearch/hermes-agent/commit/d109138ef5bdad2231d6be311c1cb6ec117b2631 "fix(mcp): avoid replaying historical events on startup (#13414)  EventBridge initialized each session's last_seen timestamp to 0.0, so the first poll after 'hermes mcp serve' starts treated every saved user/assistant message in state.db as a fresh events_poll event.  The fix establishes a per-session timestamp baseline on startup via _establish_baseline(), recording the latest existing message timestamp without emitting events. Only messages written after the baseline are delivered on subsequent polls.  Also hoists _ts_float to module-level (needed by _establish_baseline) and adds ImportError fallbacks for hermes_constants imports so the bridge works in environments where the module isn't on the path.  Salvage of #13414 by @afurm, re-applied by @HeLLGURD in #41239.  Co-authored-by: afurm <afurm@users.noreply.github.com>") [#13414](https://github.com/NousResearch/hermes-agent/pull/13414) [)](https://github.com/NousResearch/hermes-agent/commit/d109138ef5bdad2231d6be311c1cb6ec117b2631 "fix(mcp): avoid replaying historical events on startup (#13414)  EventBridge initialized each session's last_seen timestamp to 0.0, so the first poll after 'hermes mcp serve' starts treated every saved user/assistant message in state.db as a fresh events_poll event.  The fix establishes a per-session timestamp baseline on startup via _establish_baseline(), recording the latest existing message timestamp without emitting events. Only messages written after the baseline are delivered on subsequent polls.  Also hoists _ts_float to module-level (needed by _establish_baseline) and adds ImportError fallbacks for hermes_constants imports so the bridge works in environments where the module isn't on the path.  Salvage of #13414 by @afurm, re-applied by @HeLLGURD in #41239.  Co-authored-by: afurm <afurm@users.noreply.github.com>") | 2 days agoAug 1, 2026 |
| [mini\_swe\_runner.py](https://github.com/NousResearch/hermes-agent/blob/main/mini_swe_runner.py "mini_swe_runner.py") | [mini\_swe\_runner.py](https://github.com/NousResearch/hermes-agent/blob/main/mini_swe_runner.py "mini_swe_runner.py") | [fix: use lazy logging with %s formatting in logger calls](https://github.com/NousResearch/hermes-agent/commit/9eb8e20c684730e0853b3fcabe63ce8d88dd04c3 "fix: use lazy logging with %s formatting in logger calls  Replace f-string interpolation in logger calls with lazy %-style formatting across 10 files (38 instances). This follows Python logging best practices — the message is only formatted if the log level is enabled, avoiding unnecessary string concatenation overhead.  Files changed: - trajectory_compressor.py (6) - mini_swe_runner.py (2) - agent/tool_executor.py (1) - agent/model_metadata.py (1) - agent/agent_runtime_helpers.py (3) - agent/chat_completion_helpers.py (3) - agent/conversation_loop.py (8) - tools/skills_hub.py (2) - tools/environments/docker.py (10) - gateway/kanban_watchers.py (2)") | 15 hours agoAug 2, 2026 |
| [model\_tools.py](https://github.com/NousResearch/hermes-agent/blob/main/model_tools.py "model_tools.py") | [model\_tools.py](https://github.com/NousResearch/hermes-agent/blob/main/model_tools.py "model_tools.py") | [fix(tools): isolate model tools by multiplex profile](https://github.com/NousResearch/hermes-agent/commit/76cf19fee1f470061c4364321fdca30184f212e5 "fix(tools): isolate model tools by multiplex profile") | yesterdayAug 2, 2026 |
| [package-lock.json](https://github.com/NousResearch/hermes-agent/blob/main/package-lock.json "package-lock.json") | [package-lock.json](https://github.com/NousResearch/hermes-agent/blob/main/package-lock.json "package-lock.json") | [fix(install): sync the lockfile engines mirrors with the manifests](https://github.com/NousResearch/hermes-agent/commit/63ff4b87b6d00176c63b34e1555fe370944e7ce3 "fix(install): sync the lockfile engines mirrors with the manifests  `hermes desktop` still failed with EBADENGINE demanding Node >=26 after #76562, on a machine whose `apps/desktop/package.json` already said `^20.19.0 || >=22.12.0`. #76562 fixed the manifest but not its mirror in `package-lock.json`, and `npm ci` reads engines from the lockfile:      package.json  apps/desktop -> {'node': '^20.19.0 || >=22.12.0'}     package-lock  apps/desktop -> {'node': '>=26.0.0'}      <- what gated  Chasing that exposed a second, pre-existing problem: the floor #76562 declared was too generous. Running the real `npm ci` against the whole workspace on Node 22.21.1 fails on a transitive dependency —      npm error notsup Not compatible with your version of node/npm:       react-router@8.3.0     npm error notsup Required: {\"node\":\">=22.22.0\"}  react-router 8.3.0 (a direct dependency of both `apps/desktop` and `web`) declares `>=22.22.0`, which is tighter than Vite's `^20.19 || >=22.12` and excludes all of Node 20. So `>=20.0.0` promised support the tree cannot deliver: an install on Node 20 or early 22 passed the installer's gate and then died inside `npm ci` on someone else's package.  All four engine declarations now state the floor the dependency tree actually has, `>=22.22.0`: root `package.json`, `apps/desktop/package.json`, and both of their `package-lock.json` mirrors. The installer gates move with them (`node_satisfies_build` in install.sh, `Test-NodeVersionOk` in install.ps1) so a too-old system Node is replaced with the managed one *before* npm runs, and the failure a user does see names hermes-agent rather than a transitive package. NODE_VERSION stays 22 — latest-v22.x is 22.23.2, comfortably above the floor.  The invariant test gains the case that would have caught the mirror drift on its own: the desktop assertion now pins the tightest floor a dependency actually declares, and the managed-runtime check compares majors, since install.sh fetches latest-v{major}.x rather than {major}.0.0.  Verified with real `npm ci --dry-run` over the full workspace: - node 22.23.2 (what install.sh provisions) -> 1258 packages - node 26.5.1                               -> 1189 packages - node 22.21.1 (below the floor)            -> EBADENGINE naming   hermes-agent, i.e. our own manifest, not react-router") | yesterdayAug 2, 2026 |
| [package.json](https://github.com/NousResearch/hermes-agent/blob/main/package.json "package.json") | [package.json](https://github.com/NousResearch/hermes-agent/blob/main/package.json "package.json") | [fix(install): sync the lockfile engines mirrors with the manifests](https://github.com/NousResearch/hermes-agent/commit/63ff4b87b6d00176c63b34e1555fe370944e7ce3 "fix(install): sync the lockfile engines mirrors with the manifests  `hermes desktop` still failed with EBADENGINE demanding Node >=26 after #76562, on a machine whose `apps/desktop/package.json` already said `^20.19.0 || >=22.12.0`. #76562 fixed the manifest but not its mirror in `package-lock.json`, and `npm ci` reads engines from the lockfile:      package.json  apps/desktop -> {'node': '^20.19.0 || >=22.12.0'}     package-lock  apps/desktop -> {'node': '>=26.0.0'}      <- what gated  Chasing that exposed a second, pre-existing problem: the floor #76562 declared was too generous. Running the real `npm ci` against the whole workspace on Node 22.21.1 fails on a transitive dependency —      npm error notsup Not compatible with your version of node/npm:       react-router@8.3.0     npm error notsup Required: {\"node\":\">=22.22.0\"}  react-router 8.3.0 (a direct dependency of both `apps/desktop` and `web`) declares `>=22.22.0`, which is tighter than Vite's `^20.19 || >=22.12` and excludes all of Node 20. So `>=20.0.0` promised support the tree cannot deliver: an install on Node 20 or early 22 passed the installer's gate and then died inside `npm ci` on someone else's package.  All four engine declarations now state the floor the dependency tree actually has, `>=22.22.0`: root `package.json`, `apps/desktop/package.json`, and both of their `package-lock.json` mirrors. The installer gates move with them (`node_satisfies_build` in install.sh, `Test-NodeVersionOk` in install.ps1) so a too-old system Node is replaced with the managed one *before* npm runs, and the failure a user does see names hermes-agent rather than a transitive package. NODE_VERSION stays 22 — latest-v22.x is 22.23.2, comfortably above the floor.  The invariant test gains the case that would have caught the mirror drift on its own: the desktop assertion now pins the tightest floor a dependency actually declares, and the managed-runtime check compares majors, since install.sh fetches latest-v{major}.x rather than {major}.0.0.  Verified with real `npm ci --dry-run` over the full workspace: - node 22.23.2 (what install.sh provisions) -> 1258 packages - node 26.5.1                               -> 1189 packages - node 22.21.1 (below the floor)            -> EBADENGINE naming   hermes-agent, i.e. our own manifest, not react-router") | yesterdayAug 2, 2026 |
| [pyproject.toml](https://github.com/NousResearch/hermes-agent/blob/main/pyproject.toml "pyproject.toml") | [pyproject.toml](https://github.com/NousResearch/hermes-agent/blob/main/pyproject.toml "pyproject.toml") | [fix(deps): repair Google transitive security floors (](https://github.com/NousResearch/hermes-agent/commit/64dd8659127df0e36817df6a7b4f2f182fd9cd80 "fix(deps): repair Google transitive security floors (#72108)  Google API and authentication packages permit vulnerable httplib2 and pyasn1 transitives, while the Workspace and Google Chat runtime installers previously treated any importable version as sufficient. Existing environments could therefore remain vulnerable after the project dependency pins were repaired.  Carry the fixed versions through the Google and Vertex extras, lazy feature requirements, lockfile, and both runtime installers. Route the documented Google Chat installation path through its maintained secure requirements instead of an unconstrained direct pip command.  Detect stale distributions, install only unsatisfied requirements, and verify the result before continuing. Behavioral tests cover those repair invariants without freezing manifests, lockfiles, or complete package sets.  Related #72108 Extracted from #72840 Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>") [#72108](https://github.com/NousResearch/hermes-agent/issues/72108) [)](https://github.com/NousResearch/hermes-agent/commit/64dd8659127df0e36817df6a7b4f2f182fd9cd80 "fix(deps): repair Google transitive security floors (#72108)  Google API and authentication packages permit vulnerable httplib2 and pyasn1 transitives, while the Workspace and Google Chat runtime installers previously treated any importable version as sufficient. Existing environments could therefore remain vulnerable after the project dependency pins were repaired.  Carry the fixed versions through the Google and Vertex extras, lazy feature requirements, lockfile, and both runtime installers. Route the documented Google Chat installation path through its maintained secure requirements instead of an unconstrained direct pip command.  Detect stale distributions, install only unsatisfied requirements, and verify the result before continuing. Behavioral tests cover those repair invariants without freezing manifests, lockfiles, or complete package sets.  Related #72108 Extracted from #72840 Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>") | 2 days agoAug 1, 2026 |
| [run\_agent.py](https://github.com/NousResearch/hermes-agent/blob/main/run_agent.py "run_agent.py") | [run\_agent.py](https://github.com/NousResearch/hermes-agent/blob/main/run_agent.py "run_agent.py") | [fix(cli): persist YOLO mode across --resume](https://github.com/NousResearch/hermes-agent/commit/ef9f6effaffc5c454598a072c7ffba12048783f6 "fix(cli): persist YOLO mode across --resume  A session's YOLO bypass lived only in the in-memory tools.approval._session_yolo set (or the process-frozen --yolo env var), so resuming a session in a fresh process silently reverted the user's /yolo ON — dangerous commands started prompting again.  Persist a yolo_mode flag in the session row's model_config JSON and restore it on every CLI resume path:  - SessionDB.set_session_yolo() merges the flag into model_config   (same lineage-preserving merge as update_session_runtime_lock);   SessionDB.session_yolo_enabled() reads it back, false on any parse   failure. - /yolo toggle persists ON and OFF through the new helper; the   compression/branch session-id rotation carries the flag onto the   continuation row. - --yolo launches record the flag at session creation (agent_init),   and a /yolo toggled before the lazily-created row exists is carried   into the creation-time model_config (_ensure_db_session). - HermesCLI._restore_session_yolo() re-enables the bypass on startup   --resume/-c, the deferred init path, and mid-chat /resume, with a   visible '⚡ YOLO mode restored from session' notice. No-op under a   frozen process-wide --yolo and never enables on absent/garbage flags.") | 5 hours agoAug 2, 2026 |
| [setup-hermes.sh](https://github.com/NousResearch/hermes-agent/blob/main/setup-hermes.sh "setup-hermes.sh") | [setup-hermes.sh](https://github.com/NousResearch/hermes-agent/blob/main/setup-hermes.sh "setup-hermes.sh") | [Revert "remove Vercel AI Gateway and Vercel Sandbox (](https://github.com/NousResearch/hermes-agent/commit/ad12df6ba488129c07c2b58d9ad30dcaba440ab4 "Revert \"remove Vercel AI Gateway and Vercel Sandbox (#33067)\"  This reverts commit febc4cfec0a79b175a430304765473c97e10622f.") [#33067](https://github.com/NousResearch/hermes-agent/pull/33067) [)"](https://github.com/NousResearch/hermes-agent/commit/ad12df6ba488129c07c2b58d9ad30dcaba440ab4 "Revert \"remove Vercel AI Gateway and Vercel Sandbox (#33067)\"  This reverts commit febc4cfec0a79b175a430304765473c97e10622f.") | 4 days agoJul 29, 2026 |
| [setup.py](https://github.com/NousResearch/hermes-agent/blob/main/setup.py "setup.py") | [setup.py](https://github.com/NousResearch/hermes-agent/blob/main/setup.py "setup.py") | [rip out brew + pip/PyPI wheel support (](https://github.com/NousResearch/hermes-agent/commit/d84e11af4d9927c41ad0a3b4db72042cca250c64 "rip out brew + pip/PyPI wheel support (#68217)  Removes Homebrew and PyPI wheel/sdist as Hermes distribution paths while preserving the supported source, Docker, and Nix workflows.  Changes: - Removes the Homebrew formula, PyPI publish workflow, sdist manifest   (MANIFEST.in), and wheel/sdist release-attachment logic from scripts/release.py. - Keeps setuptools metadata and entry points required by editable installs   and Docker/Nix builds, but adds a setup.py guard that rejects wheel/sdist   builds outside a sealed Nix derivation (HERMES_NIX_BUILD=1). - Removes pip/Homebrew install detection, PyPI update checks, the pip   self-update path, the deprecation-banner state, the postinstall subcommand,   wheel data-directory fallbacks in agent/i18n.py and hermes_constants.py,   and the ACP Registry manifest/version-lockstep release logic. - Adds /nix/store/ path detection so `nix run` / `nix profile install`   installs (which don't set HERMES_MANAGED) are correctly identified as   \"nix\" rather than falling through to \"git\"/\"unknown\". - Retired install-method values (\"pip\", \"homebrew\") in existing   .install_method stamps (both code-scoped and home-scoped) are ignored by   the allowlist reader and fall through to \"unknown\" instead of resurrecting   a retired enum value. - Updates Nix packaging to ship bare runtime data (locales, optional-mcps)   through store symlinks and wrapper env vars instead of wheel data-files. - Removes the ACP Registry manifest/icon and their version-lockstep tests. - Deletes or rewrites packaging, pip-update, Homebrew, and ACP Registry   tests; adds parametrized coverage for the packaging build guard covering   BOTH sdist and wheel paths (the guards live in separate cmdclass entries   — a passing sdist test proves nothing about the wheel path). - Updates installation/platform documentation and related user-facing copy. - Adjusts the supply-chain scan so deleted install-hook files do not trigger   a finding, while additions or modifications still require the existing   ci-reviewed label gate.  Supported installation paths (unchanged): - git installer (install.sh) - Docker - Nix/NixOS - editable development installs (uv sync, uv pip install -e ., pip install -e .)") [#68217](https://github.com/NousResearch/hermes-agent/pull/68217) [)](https://github.com/NousResearch/hermes-agent/commit/d84e11af4d9927c41ad0a3b4db72042cca250c64 "rip out brew + pip/PyPI wheel support (#68217)  Removes Homebrew and PyPI wheel/sdist as Hermes distribution paths while preserving the supported source, Docker, and Nix workflows.  Changes: - Removes the Homebrew formula, PyPI publish workflow, sdist manifest   (MANIFEST.in), and wheel/sdist release-attachment logic from scripts/release.py. - Keeps setuptools metadata and entry points required by editable installs   and Docker/Nix builds, but adds a setup.py guard that rejects wheel/sdist   builds outside a sealed Nix derivation (HERMES_NIX_BUILD=1). - Removes pip/Homebrew install detection, PyPI update checks, the pip   self-update path, the deprecation-banner state, the postinstall subcommand,   wheel data-directory fallbacks in agent/i18n.py and hermes_constants.py,   and the ACP Registry manifest/version-lockstep release logic. - Adds /nix/store/ path detection so `nix run` / `nix profile install`   installs (which don't set HERMES_MANAGED) are correctly identified as   \"nix\" rather than falling through to \"git\"/\"unknown\". - Retired install-method values (\"pip\", \"homebrew\") in existing   .install_method stamps (both code-scoped and home-scoped) are ignored by   the allowlist reader and fall through to \"unknown\" instead of resurrecting   a retired enum value. - Updates Nix packaging to ship bare runtime data (locales, optional-mcps)   through store symlinks and wrapper env vars instead of wheel data-files. - Removes the ACP Registry manifest/icon and their version-lockstep tests. - Deletes or rewrites packaging, pip-update, Homebrew, and ACP Registry   tests; adds parametrized coverage for the packaging build guard covering   BOTH sdist and wheel paths (the guards live in separate cmdclass entries   — a passing sdist test proves nothing about the wheel path). - Updates installation/platform documentation and related user-facing copy. - Adjusts the supply-chain scan so deleted install-hook files do not trigger   a finding, while additions or modifications still require the existing   ci-reviewed label gate.  Supported installation paths (unchanged): - git installer (install.sh) - Docker - Nix/NixOS - editable development installs (uv sync, uv pip install -e ., pip install -e .)") | 2 weeks agoJul 22, 2026 |
| [sqlite\_leak\_fix.png](https://github.com/NousResearch/hermes-agent/blob/main/sqlite_leak_fix.png "sqlite_leak_fix.png") | [sqlite\_leak\_fix.png](https://github.com/NousResearch/hermes-agent/blob/main/sqlite_leak_fix.png "sqlite_leak_fix.png") | [docs: add SQLite FD leak infographic and report updates for](https://github.com/NousResearch/hermes-agent/commit/12096b1e3d2eb59a4e77bf0222ff22514a919e10 "docs: add SQLite FD leak infographic and report updates for #69678") [#69678](https://github.com/NousResearch/hermes-agent/issues/69678) | 2 weeks agoJul 23, 2026 |
| [toolset\_distributions.py](https://github.com/NousResearch/hermes-agent/blob/main/toolset_distributions.py "toolset_distributions.py") | [toolset\_distributions.py](https://github.com/NousResearch/hermes-agent/blob/main/toolset_distributions.py "toolset_distributions.py") | [feat(moa): expose MoA presets as selectable virtual models (](https://github.com/NousResearch/hermes-agent/commit/c6575df92781a5b6859845b39ee59d7f07a8cf31 "feat(moa): expose MoA presets as selectable virtual models (#46081)  * feat(moa): expose MoA presets as selectable virtual models  Reconstructed onto current main (PR #46081's base had diverged with no common ancestor, marking the PR dirty so CI never dispatched). MoA is now a virtual provider: each named preset is a selectable model under provider 'moa', and the preset's aggregator is the acting model that answers and calls tools.  Reference models fan out in parallel via a bounded ThreadPoolExecutor (the same batch pattern delegate_task uses) — all references dispatched at once, collected when every one finishes, then handed to the aggregator. Output order is preserved, failures and the MoA-recursion guard stay isolated per reference.  - Removed the old mixture_of_agents model tool and moa toolset. - Added moa as a virtual provider in the provider/model inventory. - /moa is shortcut behavior over model selection (default preset / named preset   / one-shot prompt). - Dashboard + Desktop manage named presets; presets appear in model pickers. - Parallel reference fan-out in agent/moa_loop.py with regression test.  * fix(moa): thread moa_config through _run_agent to _run_agent_inner  The reconstructed gateway MoA wiring declared moa_config on _run_agent (the profile-scoping wrapper) and used it inside _run_agent_inner, but the wrapper never forwarded it — _run_agent_inner had no such parameter, so the runtime hit NameError: name 'moa_config' is not defined on the compression-failure session sync path. Add moa_config to _run_agent_inner's signature and forward it from both wrapper call sites (multiplex and non-multiplex). Caught by tests/gateway/test_compression_failure_session_sync.py on CI shard test(4).  * fix(moa): classify moa as a virtual provider in the catalog  The moa virtual provider has no PROVIDER_REGISTRY/ProviderProfile entry, so provider_catalog() fell through to the default auth_type=\"api_key\" with no env vars — tripping two catalog invariants:   - test_provider_catalog: api_key providers must expose a credential env var   - test_provider_parity: every hermes-model provider must be desktop-configurable  moa already declares auth_type=\"virtual\" in HERMES_OVERLAYS; consult that overlay as an auth_type fallback so the catalog reports moa as virtual (no real credential, no network endpoint). Exempt virtual providers from the desktop parity union check the same way 'custom' is exempt — derived from the catalog, not a hardcoded slug, so future virtual providers are covered too.") [#46081](https://github.com/NousResearch/hermes-agent/pull/46081) [)](https://github.com/NousResearch/hermes-agent/commit/c6575df92781a5b6859845b39ee59d7f07a8cf31 "feat(moa): expose MoA presets as selectable virtual models (#46081)  * feat(moa): expose MoA presets as selectable virtual models  Reconstructed onto current main (PR #46081's base had diverged with no common ancestor, marking the PR dirty so CI never dispatched). MoA is now a virtual provider: each named preset is a selectable model under provider 'moa', and the preset's aggregator is the acting model that answers and calls tools.  Reference models fan out in parallel via a bounded ThreadPoolExecutor (the same batch pattern delegate_task uses) — all references dispatched at once, collected when every one finishes, then handed to the aggregator. Output order is preserved, failures and the MoA-recursion guard stay isolated per reference.  - Removed the old mixture_of_agents model tool and moa toolset. - Added moa as a virtual provider in the provider/model inventory. - /moa is shortcut behavior over model selection (default preset / named preset   / one-shot prompt). - Dashboard + Desktop manage named presets; presets appear in model pickers. - Parallel reference fan-out in agent/moa_loop.py with regression test.  * fix(moa): thread moa_config through _run_agent to _run_agent_inner  The reconstructed gateway MoA wiring declared moa_config on _run_agent (the profile-scoping wrapper) and used it inside _run_agent_inner, but the wrapper never forwarded it — _run_agent_inner had no such parameter, so the runtime hit NameError: name 'moa_config' is not defined on the compression-failure session sync path. Add moa_config to _run_agent_inner's signature and forward it from both wrapper call sites (multiplex and non-multiplex). Caught by tests/gateway/test_compression_failure_session_sync.py on CI shard test(4).  * fix(moa): classify moa as a virtual provider in the catalog  The moa virtual provider has no PROVIDER_REGISTRY/ProviderProfile entry, so provider_catalog() fell through to the default auth_type=\"api_key\" with no env vars — tripping two catalog invariants:   - test_provider_catalog: api_key providers must expose a credential env var   - test_provider_parity: every hermes-model provider must be desktop-configurable  moa already declares auth_type=\"virtual\" in HERMES_OVERLAYS; consult that overlay as an auth_type fallback so the catalog reports moa as virtual (no real credential, no network endpoint). Exempt virtual providers from the desktop parity union check the same way 'custom' is exempt — derived from the catalog, not a hardcoded slug, so future virtual providers are covered too.") | 2 months agoJun 25, 2026 |
| [toolsets.py](https://github.com/NousResearch/hermes-agent/blob/main/toolsets.py "toolsets.py") | [toolsets.py](https://github.com/NousResearch/hermes-agent/blob/main/toolsets.py "toolsets.py") | [nous portal video gen (](https://github.com/NousResearch/hermes-agent/commit/07447bd5dbd291389438c19586780b7f7fe67c66 "nous portal video gen (#74963)") [#74963](https://github.com/NousResearch/hermes-agent/pull/74963) [)](https://github.com/NousResearch/hermes-agent/commit/07447bd5dbd291389438c19586780b7f7fe67c66 "nous portal video gen (#74963)") | 4 days agoJul 30, 2026 |
| [trajectory\_compressor.py](https://github.com/NousResearch/hermes-agent/blob/main/trajectory_compressor.py "trajectory_compressor.py") | [trajectory\_compressor.py](https://github.com/NousResearch/hermes-agent/blob/main/trajectory_compressor.py "trajectory_compressor.py") | [fix: use lazy logging with %s formatting in logger calls](https://github.com/NousResearch/hermes-agent/commit/9eb8e20c684730e0853b3fcabe63ce8d88dd04c3 "fix: use lazy logging with %s formatting in logger calls  Replace f-string interpolation in logger calls with lazy %-style formatting across 10 files (38 instances). This follows Python logging best practices — the message is only formatted if the log level is enabled, avoiding unnecessary string concatenation overhead.  Files changed: - trajectory_compressor.py (6) - mini_swe_runner.py (2) - agent/tool_executor.py (1) - agent/model_metadata.py (1) - agent/agent_runtime_helpers.py (3) - agent/chat_completion_helpers.py (3) - agent/conversation_loop.py (8) - tools/skills_hub.py (2) - tools/environments/docker.py (10) - gateway/kanban_watchers.py (2)") | 15 hours agoAug 2, 2026 |
| [utils.py](https://github.com/NousResearch/hermes-agent/blob/main/utils.py "utils.py") | [utils.py](https://github.com/NousResearch/hermes-agent/blob/main/utils.py "utils.py") | [refactor: extract atomic\_write\_text to utils.py; fix write-failure er…](https://github.com/NousResearch/hermes-agent/commit/22492f0c46a7ea7dd567fbeded58691b921170fc "refactor: extract atomic_write_text to utils.py; fix write-failure error handling  Deduplicates the mkstemp→fsync→atomic_replace pattern that existed in three places: agent_import.py (added by #72983), MemoryStore._write_file, and skill_manager_tool._atomic_write_text. All three now call a single utils.atomic_write_text helper.  Also wraps the atomic_write_text call in _merge_memory_entries with try/except OSError so a write failure records a per-item error instead of propagating uncaught and aborting the entire import with no record.  Follow-up to #72983.") | 5 days agoJul 29, 2026 |
| [uv.lock](https://github.com/NousResearch/hermes-agent/blob/main/uv.lock "uv.lock") | [uv.lock](https://github.com/NousResearch/hermes-agent/blob/main/uv.lock "uv.lock") | [fix(deps): repair Google transitive security floors (](https://github.com/NousResearch/hermes-agent/commit/64dd8659127df0e36817df6a7b4f2f182fd9cd80 "fix(deps): repair Google transitive security floors (#72108)  Google API and authentication packages permit vulnerable httplib2 and pyasn1 transitives, while the Workspace and Google Chat runtime installers previously treated any importable version as sufficient. Existing environments could therefore remain vulnerable after the project dependency pins were repaired.  Carry the fixed versions through the Google and Vertex extras, lazy feature requirements, lockfile, and both runtime installers. Route the documented Google Chat installation path through its maintained secure requirements instead of an unconstrained direct pip command.  Detect stale distributions, install only unsatisfied requirements, and verify the result before continuing. Behavioral tests cover those repair invariants without freezing manifests, lockfiles, or complete package sets.  Related #72108 Extracted from #72840 Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>") [#72108](https://github.com/NousResearch/hermes-agent/issues/72108) [)](https://github.com/NousResearch/hermes-agent/commit/64dd8659127df0e36817df6a7b4f2f182fd9cd80 "fix(deps): repair Google transitive security floors (#72108)  Google API and authentication packages permit vulnerable httplib2 and pyasn1 transitives, while the Workspace and Google Chat runtime installers previously treated any importable version as sufficient. Existing environments could therefore remain vulnerable after the project dependency pins were repaired.  Carry the fixed versions through the Google and Vertex extras, lazy feature requirements, lockfile, and both runtime installers. Route the documented Google Chat installation path through its maintained secure requirements instead of an unconstrained direct pip command.  Detect stale distributions, install only unsatisfied requirements, and verify the result before continuing. Behavioral tests cover those repair invariants without freezing manifests, lockfiles, or complete package sets.  Related #72108 Extracted from #72840 Co-authored-by: Teknium <127238744+teknium1@users.noreply.github.com>") | 2 days agoAug 1, 2026 |
| View all files |

## Repository files navigation

[![Hermes Agent](https://github.com/NousResearch/hermes-agent/raw/main/assets/banner.png)](https://github.com/NousResearch/hermes-agent/blob/main/assets/banner.png)

# Hermes Agent ☤

[Permalink: Hermes Agent ☤](https://github.com/nousresearch/hermes-agent#hermes-agent-)

[Hermes Agent](https://hermes-agent.nousresearch.com/) \| [Hermes Desktop](https://hermes-agent.nousresearch.com/)

[![Documentation](https://camo.githubusercontent.com/76d7a880842f286c4d4e07baf2db1046197c6cfaa564365e912938445fc54a32/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446f63732d6865726d65732d2d6167656e742e6e6f757372657365617263682e636f6d2d4646443730303f7374796c653d666f722d7468652d6261646765)](https://hermes-agent.nousresearch.com/docs/)[![Discord](https://camo.githubusercontent.com/8c0fca73564f21d7a6f235747eb4d739a2e4aaa348b8e074904127baeb944b9e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446973636f72642d3538363546323f7374796c653d666f722d7468652d6261646765266c6f676f3d646973636f7264266c6f676f436f6c6f723d7768697465)](https://discord.gg/NousResearch)[![License: MIT](https://camo.githubusercontent.com/153acf9dff19deb8abfc598c53bac50a4ceae0f5c83a552711060d3d78d2c057/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e3f7374796c653d666f722d7468652d6261646765)](https://github.com/NousResearch/hermes-agent/blob/main/LICENSE)[![Built by Nous Research](https://camo.githubusercontent.com/6195af06150f2173f79d16fa3462ccac43c7dbf78f06f3c7997dc4090d79b9ad/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4275696c7425323062792d4e6f757325323052657365617263682d626c756576696f6c65743f7374796c653d666f722d7468652d6261646765)](https://nousresearch.com/)[![中文](https://camo.githubusercontent.com/574634232e93a1f4f7399d7056282748bde9c89ff98c338cc9bec8101117832b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c616e672de4b8ade696872d7265643f7374796c653d666f722d7468652d6261646765)](https://github.com/NousResearch/hermes-agent/blob/main/README.zh-CN.md)[![اردو](https://camo.githubusercontent.com/157912df78b013a19a3d2daa5f43dc4e062052fc3cf8ef914835ec9fe65bc67e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c616e672dd8a7d8b1d8afd9882d677265656e3f7374796c653d666f722d7468652d6261646765)](https://github.com/NousResearch/hermes-agent/blob/main/README.ur-pk.md)[![Español](https://camo.githubusercontent.com/fd0847426473d023cc0540582c550991fd302ec4be0a6610cf7933980f46f120/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c616e672d45737061c3b16f6c2d6f72616e67653f7374796c653d666f722d7468652d6261646765)](https://github.com/NousResearch/hermes-agent/blob/main/README.es.md)

**The self-improving AI agent built by [Nous Research](https://nousresearch.com/).** It's the only agent with a built-in learning loop — it creates skills from experience, improves them during use, nudges itself to persist knowledge, searches its own past conversations, and builds a deepening model of who you are across sessions. Run it on a $5 VPS, a GPU cluster, or serverless infrastructure that costs nearly nothing when idle. It's not tied to your laptop — talk to it from Telegram while it works on a cloud VM.

Use any model you want — [Nous Portal](https://portal.nousresearch.com/), OpenRouter, OpenAI, your own endpoint, and [many others](https://hermes-agent.nousresearch.com/docs/integrations/providers). Switch with `hermes model` — no code changes, no lock-in.

|     |     |
| --- | --- |
| **A real terminal interface** | Full TUI with multiline editing, slash-command autocomplete, conversation history, interrupt-and-redirect, and streaming tool output. |
| **Lives where you do** | Telegram, Discord, Slack, WhatsApp, Signal, and CLI — all from a single gateway process. Voice memo transcription, cross-platform conversation continuity. |
| **A closed learning loop** | Agent-curated memory with periodic nudges. Autonomous skill creation after complex tasks. Skills self-improve during use. FTS5 session search with LLM summarization for cross-session recall. [Honcho](https://github.com/plastic-labs/honcho) dialectic user modeling. Compatible with the [agentskills.io](https://agentskills.io/) open standard. |
| **Scheduled automations** | Built-in cron scheduler with delivery to any platform. Daily reports, nightly backups, weekly audits — all in natural language, running unattended. |
| **Delegates and parallelizes** | Spawn isolated subagents for parallel workstreams. Write Python scripts that call tools via RPC, collapsing multi-step pipelines into zero-context-cost turns. |
| **Runs anywhere, not just your laptop** | Seven terminal backends — local, Docker, SSH, Singularity, Modal, Daytona, and Vercel Sandbox. Daytona and Modal offer serverless persistence — your agent's environment hibernates when idle and wakes on demand, costing nearly nothing between sessions. Run it on a $5 VPS or a GPU cluster. |
| **Research-ready** | Batch trajectory generation, trajectory compression for training the next generation of tool-calling models. |

* * *

## Quick Install

[Permalink: Quick Install](https://github.com/nousresearch/hermes-agent#quick-install)

### Linux, macOS, WSL2, Termux

[Permalink: Linux, macOS, WSL2, Termux](https://github.com/nousresearch/hermes-agent#linux-macos-wsl2-termux)

```
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
```

### Windows (native, PowerShell)

[Permalink: Windows (native, PowerShell)](https://github.com/nousresearch/hermes-agent#windows-native-powershell)

> **Heads up:** Native Windows runs Hermes without WSL — CLI, gateway, TUI, and tools all work natively. If you'd rather use WSL2, the Linux/macOS one-liner above works there too. Found a bug? Please [file issues](https://github.com/NousResearch/hermes-agent/issues).

Run this in PowerShell:

```
iex (irm https://hermes-agent.nousresearch.com/install.ps1)
```

The installer handles everything: uv, Python 3.11, Node.js, ripgrep, ffmpeg, **and a portable Git Bash** (MinGit, unpacked to `%LOCALAPPDATA%\hermes\git` — no admin required, completely isolated from any system Git install). Hermes uses this bundled Git Bash to run shell commands.

If you already have Git installed, the installer detects it and uses that instead. Otherwise a ~45MB MinGit download is all you need — it won't touch or interfere with any system Git.

> **Android / Termux:** The tested manual path is documented in the [Termux guide](https://hermes-agent.nousresearch.com/docs/getting-started/termux). On Termux, Hermes installs a curated `.[termux]` extra because the full `.[all]` extra currently pulls Android-incompatible voice dependencies.
>
> **Windows:** Native Windows is fully supported — the PowerShell one-liner above installs everything. If you'd rather use WSL2, the Linux command works there too. Native Windows install lives under `%LOCALAPPDATA%\hermes`; WSL2 installs under `~/.hermes` as on Linux.

After installation:

```
source ~/.bashrc    # reload shell (or: source ~/.zshrc)
hermes              # start chatting!
```

### Troubleshooting

[Permalink: Troubleshooting](https://github.com/nousresearch/hermes-agent#troubleshooting)

#### Windows Defender or antivirus flags `uv.exe` as malware

[Permalink: Windows Defender or antivirus flags uv.exe as malware](https://github.com/nousresearch/hermes-agent#windows-defender-or-antivirus-flags-uvexe-as-malware)

If your antivirus (Bitdefender, Windows Defender, etc.) quarantines `uv.exe` from the Hermes `bin` folder (`%LOCALAPPDATA%\hermes\bin\uv.exe`), this is a **false positive**. The file is Astral's `uv` — the Rust Python package manager Hermes bundles to manage its Python environment. ML-based antivirus engines commonly flag unsigned Rust binaries that download and install packages.

**To verify your copy is authentic:**

```
# Install GitHub CLI if needed
winget install --id GitHub.cli

# Login to GitHub
gh auth login

# Run verification
$uv = "$env:LOCALAPPDATA\hermes\bin\uv.exe"
$ver = (& $uv --version).Split(' ')[1]
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$zip = "$env:TEMP\uv.zip"
Invoke-WebRequest "https://github.com/astral-sh/uv/releases/download/$ver/uv-x86_64-pc-windows-msvc.zip" -OutFile $zip -UseBasicParsing
gh attestation verify $zip --repo astral-sh/uv
Expand-Archive $zip "$env:TEMP\uv_x" -Force
(Get-FileHash "$env:TEMP\uv_x\uv.exe").Hash -eq (Get-FileHash $uv).Hash
```

If attestation says "Verification succeeded" and the last line prints `True`, you're good.

**To whitelist Hermes:**

- **Windows Defender:** Run PowerShell as Admin → `Add-MpPreference -ExclusionPath "$env:LOCALAPPDATA\hermes\bin"`
- **Bitdefender:** Add an exception in the Bitdefender console (Protection > Antivirus > Settings > Manage Exceptions)
- Whitelist the **folder**, not the file hash — Hermes updates `uv` and the hash changes every version

For more context, see the upstream Astral reports: [astral-sh/uv#13553](https://github.com/astral-sh/uv/issues/13553), [astral-sh/uv#15011](https://github.com/astral-sh/uv/issues/15011), [astral-sh/uv#10079](https://github.com/astral-sh/uv/issues/10079).

* * *

## Getting Started

[Permalink: Getting Started](https://github.com/nousresearch/hermes-agent#getting-started)

```
hermes              # Interactive CLI — start a conversation
hermes model        # Choose your LLM provider and model
hermes tools        # Configure which tools are enabled
hermes config set   # Set individual config values
hermes config get   # Print individual config values
hermes gateway      # Start the messaging gateway (Telegram, Discord, etc.)
hermes setup        # Run the full setup wizard (configures everything at once)
hermes claw migrate # Migrate from OpenClaw (if coming from OpenClaw)
hermes update       # Update to the latest version
hermes doctor       # Diagnose any issues
```

📖 **[Full documentation →](https://hermes-agent.nousresearch.com/docs/)**

* * *

## Skip the API-key collection — Nous Portal

[Permalink: Skip the API-key collection — Nous Portal](https://github.com/nousresearch/hermes-agent#skip-the-api-key-collection--nous-portal)

Hermes works with whatever provider you want — that's not changing. But if you'd rather not collect five separate API keys for the model, web search, image generation, TTS, and a cloud browser, **[Nous Portal](https://portal.nousresearch.com/)** covers all of them under one subscription:

- **300+ models** — pick any of them with `/model <name>`
- **Tool Gateway** — web search (Firecrawl), image generation (FAL), text-to-speech (OpenAI), cloud browser (Browser Use), all routed through your sub. No extra accounts.

One command from a fresh install:

```
hermes setup --portal
```

That logs you in via OAuth, sets Nous as your provider, and turns on the Tool Gateway. Check what's wired up any time with `hermes portal info`. Full details on the [Tool Gateway docs page](https://hermes-agent.nousresearch.com/docs/user-guide/features/tool-gateway).

You can still bring your own keys per-tool whenever you want — the gateway is per-backend, not all-or-nothing.

* * *

## CLI vs Messaging Quick Reference

[Permalink: CLI vs Messaging Quick Reference](https://github.com/nousresearch/hermes-agent#cli-vs-messaging-quick-reference)

Hermes has two entry points: start the terminal UI with `hermes`, or run the gateway and talk to it from Telegram, Discord, Slack, WhatsApp, Signal, or Email. Once you're in a conversation, many slash commands are shared across both interfaces.

| Action | CLI | Messaging platforms |
| --- | --- | --- |
| Start chatting | `hermes` | Run `hermes gateway setup` \+ `hermes gateway start`, then send the bot a message |
| Start fresh conversation | `/new` or `/reset` | `/new` or `/reset` |
| Change model | `/model [provider:model]` | `/model [provider:model]` |
| Set a personality | `/personality [name]` | `/personality [name]` |
| Retry or undo the last turn | `/retry`, `/undo` | `/retry`, `/undo` |
| Compress context / check usage | `/compress`, `/usage`, `/insights [--days N]` | `/compress`, `/usage`, `/insights [days]` |
| Browse skills | `/skills` or `/<skill-name>` | `/<skill-name>` |
| Interrupt current work | `Ctrl+C` or send a new message | `/stop` or send a new message |
| Platform-specific status | `/platforms` | `/status`, `/sethome` |

For the full command lists, see the [CLI guide](https://hermes-agent.nousresearch.com/docs/user-guide/cli) and the [Messaging Gateway guide](https://hermes-agent.nousresearch.com/docs/user-guide/messaging).

* * *

## Documentation

[Permalink: Documentation](https://github.com/nousresearch/hermes-agent#documentation)

All documentation lives at **[hermes-agent.nousresearch.com/docs](https://hermes-agent.nousresearch.com/docs/)**:

| Section | What's Covered |
| --- | --- |
| [Quickstart](https://hermes-agent.nousresearch.com/docs/getting-started/quickstart) | Install → setup → first conversation in 2 minutes |
| [CLI Usage](https://hermes-agent.nousresearch.com/docs/user-guide/cli) | Commands, keybindings, personalities, sessions |
| [Configuration](https://hermes-agent.nousresearch.com/docs/user-guide/configuration) | Config file, providers, models, all options |
| [Messaging Gateway](https://hermes-agent.nousresearch.com/docs/user-guide/messaging) | Telegram, Discord, Slack, WhatsApp, Signal, Home Assistant |
| [Security](https://hermes-agent.nousresearch.com/docs/user-guide/security) | Command approval, DM pairing, container isolation |
| [Tools & Toolsets](https://hermes-agent.nousresearch.com/docs/user-guide/features/tools) | 40+ tools, toolset system, terminal backends |
| [Skills System](https://hermes-agent.nousresearch.com/docs/user-guide/features/skills) | Procedural memory, Skills Hub, creating skills |
| [Memory](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory) | Persistent memory, user profiles, best practices |
| [MCP Integration](https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp) | Connect any MCP server for extended capabilities |
| [Cron Scheduling](https://hermes-agent.nousresearch.com/docs/user-guide/features/cron) | Scheduled tasks with platform delivery |
| [Context Files](https://hermes-agent.nousresearch.com/docs/user-guide/features/context-files) | Project context that shapes every conversation |
| [Architecture](https://hermes-agent.nousresearch.com/docs/developer-guide/architecture) | Project structure, agent loop, key classes |
| [Contributing](https://hermes-agent.nousresearch.com/docs/developer-guide/contributing) | Development setup, PR process, code style |
| [CLI Reference](https://hermes-agent.nousresearch.com/docs/reference/cli-commands) | All commands and flags |
| [Environment Variables](https://hermes-agent.nousresearch.com/docs/reference/environment-variables) | Complete env var reference |

* * *

## Migrating from OpenClaw

[Permalink: Migrating from OpenClaw](https://github.com/nousresearch/hermes-agent#migrating-from-openclaw)

If you're coming from OpenClaw, Hermes can automatically import your settings, memories, skills, and API keys.

**During first-time setup:** The setup wizard (`hermes setup`) automatically detects `~/.openclaw` and offers to migrate before configuration begins.

**Anytime after install:**

```
hermes claw migrate              # Interactive migration (full preset)
hermes claw migrate --dry-run    # Preview what would be migrated
hermes claw migrate --preset user-data   # Migrate without secrets
hermes claw migrate --overwrite  # Overwrite existing conflicts
```

What gets imported:

- **SOUL.md** — persona file
- **Memories** — MEMORY.md and USER.md entries
- **Skills** — user-created skills → `~/.hermes/skills/openclaw-imports/`
- **Command allowlist** — approval patterns
- **Messaging settings** — platform configs, allowed users, working directory
- **API keys** — allowlisted secrets (Telegram, OpenRouter, OpenAI, Anthropic, ElevenLabs)
- **TTS assets** — workspace audio files
- **Workspace instructions** — AGENTS.md (with `--workspace-target`)

See `hermes claw migrate --help` for all options, or use the `openclaw-migration` skill for an interactive agent-guided migration with dry-run previews.

* * *

## Contributing

[Permalink: Contributing](https://github.com/nousresearch/hermes-agent#contributing)

We welcome contributions! See the [Contributing Guide](https://hermes-agent.nousresearch.com/docs/developer-guide/contributing) for development setup, code style, and PR process.

Quick start for contributors — use the standard installer, then work from the
full git checkout it creates at `$HERMES_HOME/hermes-agent` (usually
`~/.hermes/hermes-agent`). This matches the layout used by `hermes update`, the
managed venv, lazy dependencies, gateway, and docs tooling.

```
curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash
cd "${HERMES_HOME:-$HOME/.hermes}/hermes-agent"
uv pip install -e ".[all,dev]"
scripts/run_tests.sh
```

Manual clone fallback (for throwaway clones/CI where you intentionally do not
want the managed install layout):

Create the venv outside the cloned source tree — a venv inside the directory
the agent operates from can be wiped by a relative-path command the agent runs
against its own checkout, destroying the running runtime mid-session.

```
curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv ~/.hermes/venvs/hermes-dev --python 3.11
source ~/.hermes/venvs/hermes-dev/bin/activate
uv pip install -e ".[all,dev]"
scripts/run_tests.sh
```

* * *

## Community

[Permalink: Community](https://github.com/nousresearch/hermes-agent#community)

- 💬 [Discord](https://discord.gg/NousResearch)
- 📚 [Skills Hub](https://agentskills.io/)
- 🐛 [Issues](https://github.com/NousResearch/hermes-agent/issues)
- 🔌 [computer-use-linux](https://github.com/avifenesh/computer-use-linux) — Linux desktop-control MCP server for Hermes and other MCP hosts, with AT-SPI accessibility trees, Wayland/X11 input, screenshots, and compositor window targeting.
- 🔌 [HermesClaw](https://github.com/AaronWong1999/hermesclaw) — Community WeChat bridge: Run Hermes Agent and OpenClaw on the same WeChat account.

* * *

## License

[Permalink: License](https://github.com/nousresearch/hermes-agent#license)

MIT — see [LICENSE](https://github.com/NousResearch/hermes-agent/blob/main/LICENSE).

Built by [Nous Research](https://nousresearch.com/).

## About

The agent that grows with you

[hermes-agent.nousresearch.com](https://hermes-agent.nousresearch.com/)

### Topics

[ai](https://github.com/topics/ai) [ai-agent](https://github.com/topics/ai-agent) [ai-agents](https://github.com/topics/ai-agents) [anthropic](https://github.com/topics/anthropic) [chatgpt](https://github.com/topics/chatgpt) [claude](https://github.com/topics/claude) [claude-code](https://github.com/topics/claude-code) [clawdbot](https://github.com/topics/clawdbot) [codex](https://github.com/topics/codex) [hermes](https://github.com/topics/hermes) [hermes-agent](https://github.com/topics/hermes-agent) [llm](https://github.com/topics/llm) [moltbot](https://github.com/topics/moltbot) [nous-research](https://github.com/topics/nous-research) [openai](https://github.com/topics/openai) [openclaw](https://github.com/topics/openclaw)

### Resources

[Readme](https://github.com/nousresearch/hermes-agent#readme-ov-file)

[MIT license](https://github.com/nousresearch/hermes-agent#MIT-1-ov-file)

### Contributing

[Contributing](https://github.com/nousresearch/hermes-agent#contributing-ov-file)

### Security policy

[Security policy](https://github.com/nousresearch/hermes-agent#security-ov-file)

[Activity](https://github.com/NousResearch/hermes-agent/activity)

[Custom properties](https://github.com/NousResearch/hermes-agent/custom-properties)

### Stars

[**224.6k** stars](https://github.com/NousResearch/hermes-agent/stargazers)

### Watchers

[**853** watching](https://github.com/NousResearch/hermes-agent/watchers)

### Forks

[**43.5k** forks](https://github.com/NousResearch/hermes-agent/forks)

[Report repository](https://github.com/contact/report-content?content_url=https%3A%2F%2Fgithub.com%2FNousResearch%2Fhermes-agent&report=NousResearch+%28user%29)

## Releases

## Packages

## Used by

## Contributors

## Languages

You can’t perform that action at this time.