Hermes v0.21.1: The Update That Made Hermes a Third Smaller — and Everything You Care About Faster

Most Hermes updates ask something of you: a new command to learn, a new config key to weigh, a new default that changes how your setup behaves. v0.21.1 (tag v2026.9.7, released September 7, 2026) is the rare opposite — an update you install and barely notice, because everything that changed is under the hood or in the parts of the workflow that used to annoy you the most. The project calls this a consolidation patch: roughly 5,139 commits, ~4,364 files changed and ~632 merged PRs since v0.21.0, with the official notes staying brief and full curation deferred to v0.22.0. We went through the window anyway so you don’t have to — here is what actually matters.
An update that made the codebase a third smaller
The biggest story of this window is invisible unless you open the repository: a whole-codebase simplification (PR #102117) took the source from 1,063,826 to 698,363 lines — a 34.4% cut — with behavior guaranteed unchanged. Thirty-seven files over 5,000 lines became six. The famous monsters are gone: gateway/run.py shrank from 34,847 to 5,512 lines, cli.py from 22,426 to 4,656, and the number of functions over 300 lines dropped from 192 to 2. Old files stayed behind as thin entry points, and the team verified byte-identical tool schemas, config defaults and wire formats against the pre-refactor tree before merging.
Why should you care, if nothing you see changed? Because a codebase that fits in a model’s head costs less to navigate: the PR’s own evals measured agent task success and token spend on repository navigation before and after, and every subsystem is now small enough that an agent (or a human) can actually hold it in context. Your next session on a big codebase loads faster and makes fewer missteps — the refactor is effectively a permanent token discount for agentic coding. The follow-up release page on this site has the full numbers if you like that sort of thing: v0.21.1 release notes.
Fan-outs report as they land
If you have ever sent five subagents off to research something and then stared at an empty chat for an hour because the slowest one was stuck, this one is for you. delegate_task previously returned one giant result after the last child finished; now each task returns the moment it completes (PR #104299). Tasks that belong together can opt into a group, and grouped results still arrive as one message:
{
"tasks": [
{ "goal": "check api latency", "group": "bench" },
{ "goal": "check db latency", "group": "bench" },
{ "goal": "scan the changelog" }
]
}
The two benchmark tasks come back together; the changelog scan lands by itself the second it’s done. You can start acting on early results instead of waiting for the straggler — and the whole call still counts as a single slot against delegation.max_concurrent_children, so capacity math doesn’t change. Pair this with the live subagent orchestration guide and a fan-out starts feeling like a team you can actually watch work.
Children hand you the wheel — including background processes
The same delegation pass fixed one of the nastier failure modes in multi-agent work: a child that spawns a long background process and then exits used to leave that process owned by nobody — the child’s cleanup killed it silently, or the parent waited for a completion notice that could never arrive, because the child’s notify=true was a promise nothing could keep. Now a subagent can hand a running process to you before it exits with process_manage(action="handoff", session_id=<id>, data="<purpose>") — ownership flips to the parent, and when the process finishes, the notice lands in your chat with the purpose attached (PR #105125). Leftovers are reported honestly as terminated, and children are told up front that notifications aren’t guaranteed. Orphaned-process mystery solved.
MCP logins without a browser
You SSH into a headless box, point Hermes at a self-hosted MCP server, and hit the wall: the server wants an OAuth browser flow, and the only browser in the building is on your phone. RFC 8628 device codes are exactly for this situation, and v0.21.1 wires them in end to end (PR #104891). One command starts the flow:
hermes mcp login <server> --flow device
Hermes finds the server’s device endpoint, prints a verification URI and code, and polls until you approve — from any device with a browser. Set oauth.flow: device in the server’s config and that becomes the default for login and reauth. Denied or expired grants never clobber your existing credentials, and background reconnects point you to an explicit login instead of quietly starting a device flow. If you run MCP servers on remote hosts, this removes a whole class of “can’t authorize here” pain — see our MCP context variables guide for the rest of the headless-friendly MCP tooling.
Picks that stay fresh, pins that stick
Two model-selection upgrades landed this window, and together they fix the “wait, why did it use that provider?” moment. First, OpenRouter routing can now be pinned per model, not just globally (PR #104159):
provider_routing:
sort: price
models:
"openai/gpt-6-astra": { only: [openai] }
"anthropic/claude-fable-5.1": { only: [anthropic] }
One config now locks GPT-6 Astra to OpenAI and Claude Fable to Anthropic while everything else still sorts by price — and because the rule applies at the single chokepoint every request path shares, cron jobs and delegated children honor it too. If you have been following the Astra discovery-gating guide, this is the knob that makes multi-provider Astra setups deterministic.
Second, the /model picker stopped going stale: remote catalogs refresh every 20 minutes instead of on a 1-hour TTL, and a gateway background loop keeps them warm even if nobody opens the picker (PR #101319) — a model that launched or got delisted shows up (or disappears) within twenty minutes on every surface. The Meta Model API provider also switched to its live /v1/models response as the authoritative catalog, so new Muse models appear without waiting for a client update (PR #101503). More catalog and override mechanics live in the model overrides guide.
Faster under the hood: search, compaction, and quieter cron
search_filesruns native ripgrep now on local POSIX machines (PR #104502) — content searches go from ~85 ms to ~15 ms and file-name searches from ~73 ms to ~12 ms. Same results, 5–6× less tool latency, which adds up fast in agent loops that search constantly.HERMES_NATIVE_FILE_READ=0restores the old shell path if anything odd shows up.- Compaction keeps its prefix cache in coding sessions (PR #104455): the coding workspace snapshot is pinned per session instead of re-probing
git statusat every compaction boundary, so long sessions stop paying to rebuild the prompt from scratch after every compact. - Finished subagents stop leaking memory (PR #102032): child transcripts are released from the parent heap and excluded from the full-text index — a 1,320-child run used to leave a 1.9 GB heap and ~1 GB of shadow tables behind.
- Cron tells the truth about missed fires (PR #100445, #104877):
hermes cron listnow shows aDispatch:line per job —⚠ catch-up after missed fireinstead of a deceptively clean “ok” — and quiet monitor ticks no longer erase the continuity context that the next run needs. More cron hygiene in the cron doctor guide.
Security got a real fix in the same window: approvals.deny rules are now enforced inside isolated Docker and cloud sandboxes (PR #103649), closing a path where a deny list could be bypassed with a sandboxed shell even under --yolo. The v0.21.0 Pantheon release was the big feature release; v0.21.1 is the cleanup that keeps the house standing. If you skipped the last few patches, our v0.20.6 rundown covers what rolled in before this.
hermes update
Upgrade, run hermes doctor, restart the gateway — and enjoy an update that changed a third of the code without asking you to change a single setting.