Hermes yesterday: heads-up, Hermes stops deleting your old sessions by default. Auto-prune is opt-in again on main, and Hermes asks once when the disk runs low. The rest of the day went to the one-gateway runtime that landed on Wednesday: API keys that went to the wrong host, plugins that outlived their disable, and approvals that asked too often. 696 commits landed on main; here are the 10 that matter.
1️⃣ Hermes stops deleting old sessions unless you say so
Before: with https://t.co/HKhMpRKZ3k_prune on by default, Hermes quietly deleted ended sessions older than retention_days (90 by default) from state.db. After: auto-prune is off by default again. While your config.yaml has no https://t.co/HKhMpRKZ3k_prune key, Hermes asks once when the disk holding state.db runs low (under 2 GiB free, or under 10% free with less than 20 GiB left): a y/n question at classic CLI startup, one notice in the TUI and Desktop, and a message on each served profile's home channel for the messaging gateway. /autoprune on|off|later|status answers it everywhere (on Slack, /hermes autoprune); on or off saves the key for good, later asks again in a week. The question estimates what pruning would free and says plainly when it would not fix the disk. Who gets it: auto_prune: true keeps pruning, false keeps everything and is never asked, and a value your administrator manages is never asked about. After a prune, the state.db file shrinks only at the next VACUUM. Heads-up: v0.22.2 still prunes by default until the next release.
2️⃣ API keys stay with their own endpoint
Before, on main: a --provider pick without a base_url kept the profile's endpoint, so the new provider's key went to the old provider's host; Desktop onboarding's provider: auto with an OpenRouter base_url sent the Google key to OpenRouter; a model pick in a Bot Chat whose profile had moved checked the new key against the old endpoint; a pre-0.22.1 session resumed after the upgrade lost its saved route and got HTTP 404 on every turn, aimed at the profile's server with the profile's key; and changing any secret in config.yaml, even an unrelated MCP token, broke every older session after a restart with a generic error. After: a provider pick drops the replaced provider's endpoint and key settings (an explicit base_url in the same request still wins); endpoint and key move together on every pick, or the pick is refused by name; adopted older sessions keep their saved route and never borrow the profile's key; and a changed secret stops only the sessions whose route uses it, naming it (providers.left.api_key: changed in config.yaml since this session started). Not covered: a stale model.key_env sending an old key to NVIDIA NIM predates these changes and is left for a follow-up.
3️⃣ Disabled plugins really stop, websockets included
Before: on the shared gateway, a plugin disabled while it ran kept accepting new websocket connections until a restart, and a secondary profile could still reach a plugin the launch profile had disabled. hermes plugins disable said Takes effect on next session while the gateway kept the plugin's hooks, commands and tools. Classic CLI plugin commands ran in a second copy of the plugin, so https://t.co/iO9tnN7xgL_mcp failed with MCP server not connected, and pre_gateway_dispatch fired twice for every message from a messaging platform. After: one gate covers HTTP, websockets, assets and the plugin list, and a secondary profile's own dashboard plugins run in its own plugin host; disable unloads the plugin from the running gateway and says what happened; CLI plugin commands run in the gateway; pre_gateway_dispatch fires once per message, and pre_command fires in the gateway for the commands local clients send. Not covered: callbacks a plugin already wired into a platform adapter keep running until hermes gateway restart, Desktop's own pickers and several TUI commands do not fire pre_command yet, and project plugins in ./.hermes/plugins still do not load (you now get a warning).
4️⃣ execute_code stops asking for the whole script in your own turns
Before: since the one-gateway change, approvals.mode: manual raised a whole-script approval on every execute_code call in classic CLI, TUI, Desktop and ACP sessions, which the classic CLI and ACP never did before. After: a turn you typed, with a window that can approve attached, skips the whole-script prompt, and each dangerous terminal() command inside the script still asks on your prompt; smart mode likewise drops its whole-script check there. Everything else keeps the gate: plugin-injected turns, /loop ticks, delegation and background completions, heartbeats, delegated children, side tasks, turns that run after you detached, messaging, API and cron. Heads-up: as in the classic CLI before the one-gateway change, Python code in the script that deletes or runs things without terminal() (shutil.rmtree, subprocess) is not prompted in your own turns.
5️⃣ A model pick made mid-turn applies to the next turn
Before, on main: a model, provider or reasoning pick in Desktop while a turn ran was refused as session_busy and Desktop showed nothing; reasoning changes failed over and over with stale_generation; a typed /model in the TUI was announced but never reached a request, and its picker failed whenever a reasoning row was picked; and on a gateway serving several profiles, a secondary profile's Desktop pick was ignored until a restart. After: the running turn keeps its model, the pick is saved (it survives a restart) and applied when the next turn starts, and Desktop says the model applies from your next message, or names why the pick was refused. Not covered: /model --once on a local session is refused by name, and session info shows the old model until the next turn starts.
6️⃣ Your tools run with your shell's toolchain again
Before: with one gateway running every session, terminal commands, background processes and execute_code started from the classic CLI or TUI used the gateway's environment, so python and node resolved to whatever the gateway started with instead of your activated venv or nvm; and HERMES_EPHEMERAL_SYSTEM_PROMPT, HERMES_PREFILL_MESSAGES_FILE and HERMES_INFERENCE_PROVIDER from whichever client started the gateway applied to every session, messaging and cron included. After: the CLI and TUI send an allowlisted toolchain (PATH, VIRTUAL_ENV, CONDA_*, NODE_*, NVM_*, PYENV_*, GOPATH, CARGO_HOME, JAVA_HOME and more, plus names in the new terminal.client_env_passthrough), applied to that session's tools only and only when the client is proven to run on the same machine; the HERMES_* values apply to their own session; credential-looking names are never sent or stored. Not covered: Desktop, messaging and cron keep the gateway's environment, a login shell's .bash_profile still runs over it, and when the gateway cannot find hermes on its own PATH, Hermes's bin folder can land ahead of yours.
7️⃣ Exit and /new end a session's delegations
Before: once the CLI and TUI became viewers of a session on the gateway, async delegations kept running after you left, and their completions and background-process notices started model turns nobody watched. After: when the last viewer exits, runs /new or switches with resume, the gateway interrupts that session's own delegations at once and refuses new ones until a viewer comes back; a completion that reaches the queue with nobody attached is written into the session as a note the next turn reads, with no model call; with a viewer attached it runs as a turn, as before. A plain detach (closing Desktop, a dropped connection) cancels nothing. Not covered: background processes keep running after exit, as they always did.
8️⃣ Follow-up questions about a photo see the photo again
Before: the session database stores each image as a [screenshot] line, so every turn rebuilt from it (API-server sessions continued with X-Hermes-Session-Id, hermes chat --resume, a gateway restart) sent the model that placeholder, and a question about the photo you sent one message earlier got a guess. After: when the model takes images natively, Hermes re-attaches the newest images (vision.replay_recent_images, default 3, 0 turns it off) from the copy it already keeps, byte-identical to the original, so the prompt cache still hits. Not covered: on the gateway, the kept copy of a chat image is removed after 24 hours, so a follow-up a day later sees [screenshot] again; images attached through the legacy TUI sidecar and remote image URLs stay text.
9️⃣ Fresh Macs install Hermes again
Before: on a Mac without Apple's Command Line Tools, /usr/bin/git is a stub, so the installer printed prerequisites ok and then died at the clone with git clone failed ... see man xcode-select (reported from a live workshop). After: the installer checks that git actually runs; it installs git with Homebrew when present, otherwise opens Apple's Command Line Tools dialog, waits up to 15 minutes and continues the install in the same run. Hermes-Setup waits too, a plain --non-interactive run fails at once with the remedy, and a Mac whose developer tools exist but are broken gets git's own error. Already live: the curl one-liner serves the installer from main.
🔟 30 new plugins in the catalog, and a new Verified tier
30 new entries, all community tier, and model providers were the day's theme. Heads-up: the catalog gained a third tier, verified, for plugins made by the company behind the product they integrate, granted only by Nous; none of these 30 carries it. Several entries disclose that they run a local server, install a CLI or send data to a hosted service: read the disclosure before installing. Catalog entries do not wait for a release: they go live once the published catalog refreshes.
• Models and providers: cliproxyapi-provider, codex-truly, cursor-sdk, ngrok-ai-gateway, wallaby-provider, effortless-hermes, ms-decision-provider, agent-hint
• Memory, context and prompts: mnemoverse, superlocalmemory, hermes-vcc-engine, hermes-minimizer
• Web and research: browserless, machine-library, specstream
• Messaging and other agents: max-platform, session-mirror, antenna, opencode-shepherd
• Safety and diagnostics: scamgate, skill-integrity, doctorpack, hermes-windows-ops
• Secrets and deploys: protonpass, render-platform
• Desktop and tools: devkit, kanban-graph, hermes-boot-screen, wolfmarkdown, make-parts-now
━━━━━━━━━━
⚙️ Meanwhile, in the engine room
Dozens of fixes landed yesterday that most users will never see, and most of them went to the one-gateway runtime: sessions that resume, restart and queue the way separate processes used to.
• Messages queued behind a turn that ran out of context now run, in order, on the fresh session the auto-reset creates, instead of staying stuck on the old one
• Resuming a chat re-reads its config, so hermes tools disable web followed by hermes -c no longer offers web tools, and a newly added MCP server reaches it
• Oversized tool results saved to disk are kept for the session retention window instead of 24 hours, so a session resumed the next day can still read them
• 19 Dependabot alerts cleared, including critical PyJWT, shell-quote and proxy-addr bumps
If you noticed none of this, it worked.
All on main, ships in the next release; the macOS installer fix is already live on the one-liner. Latest stable: v0.22.2.
Which one hits you most? 👇
@kidtsang Generally, Hermes may not be very beginner-friendly, but fixing that is also just a prompt away with a session with Hermes himself; he's very good at solving his own problems.
Hermes yesterday: heads-up, Hermes stops deleting your old sessions by default. Auto-prune is opt-in again on main, and Hermes asks once when the disk runs low. The rest of the day went to the one-gateway runtime that landed on Wednesday: API keys that went to the wrong host, plugins that outlived their disable, and approvals that asked too often. 696 commits landed on main; here are the 10 that matter.
1️⃣ Hermes stops deleting old sessions unless you say so
Before: with https://t.co/HKhMpRKZ3k_prune on by default, Hermes quietly deleted ended sessions older than retention_days (90 by default) from state.db. After: auto-prune is off by default again. While your config.yaml has no https://t.co/HKhMpRKZ3k_prune key, Hermes asks once when the disk holding state.db runs low (under 2 GiB free, or under 10% free with less than 20 GiB left): a y/n question at classic CLI startup, one notice in the TUI and Desktop, and a message on each served profile's home channel for the messaging gateway. /autoprune on|off|later|status answers it everywhere (on Slack, /hermes autoprune); on or off saves the key for good, later asks again in a week. The question estimates what pruning would free and says plainly when it would not fix the disk. Who gets it: auto_prune: true keeps pruning, false keeps everything and is never asked, and a value your administrator manages is never asked about. After a prune, the state.db file shrinks only at the next VACUUM. Heads-up: v0.22.2 still prunes by default until the next release.
2️⃣ API keys stay with their own endpoint
Before, on main: a --provider pick without a base_url kept the profile's endpoint, so the new provider's key went to the old provider's host; Desktop onboarding's provider: auto with an OpenRouter base_url sent the Google key to OpenRouter; a model pick in a Bot Chat whose profile had moved checked the new key against the old endpoint; a pre-0.22.1 session resumed after the upgrade lost its saved route and got HTTP 404 on every turn, aimed at the profile's server with the profile's key; and changing any secret in config.yaml, even an unrelated MCP token, broke every older session after a restart with a generic error. After: a provider pick drops the replaced provider's endpoint and key settings (an explicit base_url in the same request still wins); endpoint and key move together on every pick, or the pick is refused by name; adopted older sessions keep their saved route and never borrow the profile's key; and a changed secret stops only the sessions whose route uses it, naming it (providers.left.api_key: changed in config.yaml since this session started). Not covered: a stale model.key_env sending an old key to NVIDIA NIM predates these changes and is left for a follow-up.
3️⃣ Disabled plugins really stop, websockets included
Before: on the shared gateway, a plugin disabled while it ran kept accepting new websocket connections until a restart, and a secondary profile could still reach a plugin the launch profile had disabled. hermes plugins disable said Takes effect on next session while the gateway kept the plugin's hooks, commands and tools. Classic CLI plugin commands ran in a second copy of the plugin, so https://t.co/iO9tnN7xgL_mcp failed with MCP server not connected, and pre_gateway_dispatch fired twice for every message from a messaging platform. After: one gate covers HTTP, websockets, assets and the plugin list, and a secondary profile's own dashboard plugins run in its own plugin host; disable unloads the plugin from the running gateway and says what happened; CLI plugin commands run in the gateway; pre_gateway_dispatch fires once per message, and pre_command fires in the gateway for the commands local clients send. Not covered: callbacks a plugin already wired into a platform adapter keep running until hermes gateway restart, Desktop's own pickers and several TUI commands do not fire pre_command yet, and project plugins in ./.hermes/plugins still do not load (you now get a warning).
4️⃣ execute_code stops asking for the whole script in your own turns
Before: since the one-gateway change, approvals.mode: manual raised a whole-script approval on every execute_code call in classic CLI, TUI, Desktop and ACP sessions, which the classic CLI and ACP never did before. After: a turn you typed, with a window that can approve attached, skips the whole-script prompt, and each dangerous terminal() command inside the script still asks on your prompt; smart mode likewise drops its whole-script check there. Everything else keeps the gate: plugin-injected turns, /loop ticks, delegation and background completions, heartbeats, delegated children, side tasks, turns that run after you detached, messaging, API and cron. Heads-up: as in the classic CLI before the one-gateway change, Python code in the script that deletes or runs things without terminal() (shutil.rmtree, subprocess) is not prompted in your own turns.
5️⃣ A model pick made mid-turn applies to the next turn
Before, on main: a model, provider or reasoning pick in Desktop while a turn ran was refused as session_busy and Desktop showed nothing; reasoning changes failed over and over with stale_generation; a typed /model in the TUI was announced but never reached a request, and its picker failed whenever a reasoning row was picked; and on a gateway serving several profiles, a secondary profile's Desktop pick was ignored until a restart. After: the running turn keeps its model, the pick is saved (it survives a restart) and applied when the next turn starts, and Desktop says the model applies from your next message, or names why the pick was refused. Not covered: /model --once on a local session is refused by name, and session info shows the old model until the next turn starts.
6️⃣ Your tools run with your shell's toolchain again
Before: with one gateway running every session, terminal commands, background processes and execute_code started from the classic CLI or TUI used the gateway's environment, so python and node resolved to whatever the gateway started with instead of your activated venv or nvm; and HERMES_EPHEMERAL_SYSTEM_PROMPT, HERMES_PREFILL_MESSAGES_FILE and HERMES_INFERENCE_PROVIDER from whichever client started the gateway applied to every session, messaging and cron included. After: the CLI and TUI send an allowlisted toolchain (PATH, VIRTUAL_ENV, CONDA_*, NODE_*, NVM_*, PYENV_*, GOPATH, CARGO_HOME, JAVA_HOME and more, plus names in the new terminal.client_env_passthrough), applied to that session's tools only and only when the client is proven to run on the same machine; the HERMES_* values apply to their own session; credential-looking names are never sent or stored. Not covered: Desktop, messaging and cron keep the gateway's environment, a login shell's .bash_profile still runs over it, and when the gateway cannot find hermes on its own PATH, Hermes's bin folder can land ahead of yours.
7️⃣ Exit and /new end a session's delegations
Before: once the CLI and TUI became viewers of a session on the gateway, async delegations kept running after you left, and their completions and background-process notices started model turns nobody watched. After: when the last viewer exits, runs /new or switches with resume, the gateway interrupts that session's own delegations at once and refuses new ones until a viewer comes back; a completion that reaches the queue with nobody attached is written into the session as a note the next turn reads, with no model call; with a viewer attached it runs as a turn, as before. A plain detach (closing Desktop, a dropped connection) cancels nothing. Not covered: background processes keep running after exit, as they always did.
8️⃣ Follow-up questions about a photo see the photo again
Before: the session database stores each image as a [screenshot] line, so every turn rebuilt from it (API-server sessions continued with X-Hermes-Session-Id, hermes chat --resume, a gateway restart) sent the model that placeholder, and a question about the photo you sent one message earlier got a guess. After: when the model takes images natively, Hermes re-attaches the newest images (vision.replay_recent_images, default 3, 0 turns it off) from the copy it already keeps, byte-identical to the original, so the prompt cache still hits. Not covered: on the gateway, the kept copy of a chat image is removed after 24 hours, so a follow-up a day later sees [screenshot] again; images attached through the legacy TUI sidecar and remote image URLs stay text.
9️⃣ Fresh Macs install Hermes again
Before: on a Mac without Apple's Command Line Tools, /usr/bin/git is a stub, so the installer printed prerequisites ok and then died at the clone with git clone failed ... see man xcode-select (reported from a live workshop). After: the installer checks that git actually runs; it installs git with Homebrew when present, otherwise opens Apple's Command Line Tools dialog, waits up to 15 minutes and continues the install in the same run. Hermes-Setup waits too, a plain --non-interactive run fails at once with the remedy, and a Mac whose developer tools exist but are broken gets git's own error. Already live: the curl one-liner serves the installer from main.
🔟 30 new plugins in the catalog, and a new Verified tier
30 new entries, all community tier, and model providers were the day's theme. Heads-up: the catalog gained a third tier, verified, for plugins made by the company behind the product they integrate, granted only by Nous; none of these 30 carries it. Several entries disclose that they run a local server, install a CLI or send data to a hosted service: read the disclosure before installing. Catalog entries do not wait for a release: they go live once the published catalog refreshes.
• Models and providers: cliproxyapi-provider, codex-truly, cursor-sdk, ngrok-ai-gateway, wallaby-provider, effortless-hermes, ms-decision-provider, agent-hint
• Memory, context and prompts: mnemoverse, superlocalmemory, hermes-vcc-engine, hermes-minimizer
• Web and research: browserless, machine-library, specstream
• Messaging and other agents: max-platform, session-mirror, antenna, opencode-shepherd
• Safety and diagnostics: scamgate, skill-integrity, doctorpack, hermes-windows-ops
• Secrets and deploys: protonpass, render-platform
• Desktop and tools: devkit, kanban-graph, hermes-boot-screen, wolfmarkdown, make-parts-now
━━━━━━━━━━
⚙️ Meanwhile, in the engine room
Dozens of fixes landed yesterday that most users will never see, and most of them went to the one-gateway runtime: sessions that resume, restart and queue the way separate processes used to.
• Messages queued behind a turn that ran out of context now run, in order, on the fresh session the auto-reset creates, instead of staying stuck on the old one
• Resuming a chat re-reads its config, so hermes tools disable web followed by hermes -c no longer offers web tools, and a newly added MCP server reaches it
• Oversized tool results saved to disk are kept for the session retention window instead of 24 hours, so a session resumed the next day can still read them
• 19 Dependabot alerts cleared, including critical PyJWT, shell-quote and proxy-addr bumps
If you noticed none of this, it worked.
All on main, ships in the next release; the macOS installer fix is already live on the one-liner. Latest stable: v0.22.2.
Which one hits you most? 👇
@CloudDogx It will be difficult to find a middle ground, but we will end up having something focused on agent and cron sessions that generate useful things at that moment... I believe that will already help a lot.
Hermes yesterday: race day, and the bugs lost. One pull request hunted down 27 race conditions, the kind where two writers grab the same file and one of them quietly loses. Meanwhile the installer stopped handing new users unreleased code, and the shared gateway learned to come back after a restart. 227 commits landed on main; here are the 10 that matter.
1️⃣ New installs land on the latest stable release
Before: hermes update has followed stable releases on official checkouts for a while, but https://t.co/N55KRzrRfk, install.ps1 and Hermes-Setup still cloned the tip of main, so every new user started on unreleased code and only reached stable at the next release. After: a fresh install of the official repository looks up the latest vX.Y.Z release (GitHub API, then the releases redirect, then the repository's own tags) and checks it out, which today is v0.22.2. If no release can be reached, a fresh install stops with a retryable error instead of falling back to main. --channel main, -Channel main or HERMES_INSTALL_CHANNEL=main installs main's tip and saves that choice for later updates. Who gets it: this is already live, because the hosted one-liners serve the script from main, and Hermes-Setup downloads it at install time. A rerun over an existing main checkout keeps it where it is and leaves the move to hermes update and its downgrade guard; forks, mirrors, other branches and --commit pins are unchanged.
2️⃣ Allowlist edits take effect without a restart
Before: on the shared gateway, command_allowlist was read once at startup, so a pattern you removed from config.yaml by hand stayed auto-approved until a gateway restart (rm -rf build ran with no prompt), and a pattern you added was ignored. Desktop requests could also still reach a disabled plugin's /api/plugins routes. After: every approval check applies what changed on disk, so a removed pattern prompts again and an added one matches; always approvals the gateway made but could not save are kept, and a pending always-save can no longer write a removed entry back. A malformed allowlist counts as empty, so commands prompt. Desktop requests to a disabled plugin get 404 like every other caller. In review: the same plugin gate for WebSocket connections and for every profile the gateway serves.
3️⃣ The gateway comes back after a restart, and the CLI with it
Before: hermes gateway restart on a gateway you or a client started by hand waited for a supervisor that did not exist, exited 1 and left no gateway running, so cron and bots stayed down. The classic CLI never re-attached afterwards and blamed every prompt on the model. API callers queued behind a running turn got a 503 with Retry-After, so the OpenAI and Anthropic SDKs resent work that was going to run anyway. After an unclean exit, every local client hung while state.db was checked: 41 to 76 seconds on a 5.3 GB store. After: restart stops the gateway and starts a new one; the CLI redials on the next call and resumes its open sessions, and a turn cut off by the restart is reported as unknown and never resent; queued API callers are told their input is saved and must not be resent (x-should-retry: false, and /v1/runs reports them queued); and the database check runs in the background on WAL stores, with a 30 minute bound, and is skipped with one warning on rollback-journal stores.
4️⃣ Bots stop answering Sorry, I encountered an error
Before: on a gateway serving several profiles (this turns on by itself once a named profile has its own bot credentials), every message to a profile running a plugin that rewrites incoming text was refused with RuntimeStoreError invalid_params, and so was every /retry from Telegram, Discord or any other platform. On Mattermost, every plain text post without an attachment was refused the same way. After: rewritten messages keep the provenance of the message they came from, /retry re-runs the last turn, and text-only posts pass admission on every platform. A refusal now names the failed check in gateway.log, and the chat reply names it only when it is about the content, never a trust check. Not covered: a /retry that is still refused (a paused session, for one) leaves the last turn removed from the transcript; that is tracked in an open issue. The Mattermost fix was not run against a live server.
5️⃣ Background jobs report back on Discord and Telegram
Before: when a background process finished, its completion wake on Discord or Telegram was refused because it carried no message id while the chat's stored source did, and it was retried every 5 seconds until the process was pruned 30 minutes later, so the agent never got the result. On Telegram DM topics the reply failed even once admitted. After: the wake is admitted and answers in the right topic; if a refusal persists, the watcher retries 8 times over about five minutes and then sends the plain completion notice. Not covered: in a shared thread where a different user started the job, the wake is still refused and falls back to that plain notice. In review: Discord threads whose title changed after creation.
6️⃣ The real browser profile stops breaking the browser tool
Before: with browser.use_real_profile on, every browser call failed when the profile could not be copied: Chrome running on macOS or Linux (it locks the saved-password and autofill files), Windows with Chrome open, a non-Chromium default browser, a bad pin or a launch failure. After: with Chrome running, Hermes copies the cookies and skips the locked password and autofill files, so you stay signed in; when the profile cannot load at all, the session gets a fresh browser without your logins and the first result tells the model why, so it says it is signed out instead of failing. browser_exec with local=true falls back to a fresh local browser, never the cloud one.
7️⃣ The classic CLI catches up with the shared gateway
Before: the classic CLI now drives a session on the shared gateway, and several commands still looked at its own empty process: /model, /refine, /review and /moa did not reach the session, /agents showed 0 running processes, /diff session crashed or said checkpoints were off, /stop mid-turn froze input until every job exited, a stale toolset left in config refused every hermes chat with invalid_params, and @file and @folder references resolved against the gateway's folder instead of yours. After: those commands run on the gateway session; -s skills and the other launch flags are carried in, and resuming with a different flag is refused by name instead of silently ignored; and when the last window closes, the session's memory is committed on the gateway, once. Not changed: nothing runs those end-of-session hooks after a gateway crash. In review: /resume or /sessions as the first action of a fresh CLI is refused at the next prompt.
8️⃣ Editors over ACP get their commands back
Before: editors talking to Hermes over ACP went through a gateway client that dropped most of what the old in-process server returned: no model picker or modes, no slash commands, empty replies to /model and /compress, no usage updates, and a load with a changed MCP server list failed with acp_mcp_policy_conflict. After: the model picker, modes, slash commands (/help, /tools, /context, /reset, /steer, /queue, /version, /usage, /status), usage and title updates are back; the gateway owns each session's editor MCP servers, applies a changed list on load and keeps them connected while the session has a viewer; tool names keep the server name; and /steer only redirects this editor's own turn. Not yet: the Accept Edits and Don't Ask modes are not offered.
9️⃣ /loop counts down to its next wakeup
Before: a running /loop printed a one-time next in 45m line in the CLI that never moved, showed nothing in the TUI, and sat frozen in Desktop. After: the CLI's live-work dock gets a loop row with cadence, run count and a countdown (per minute, seconds in the last one), the TUI shows a loop bar under the goal bar, and Desktop counts down by the second and says due, waiting for idle when it is overdue; all three show running now during a wakeup and the reason when paused.
🔟 1 new plugin in the catalog
One new entry, and it is official: REA reverse-engineers native binaries, .NET assemblies, Electron and JavaScript apps, Android packages and firmware through its MCP server; it needs Node.js 22.19 or newer and your own Ghidra, Hopper or IDA for native decompilation. Heads-up: a few REA tools run a command, drive an app, change a connected Android device or overwrite a file without a Hermes prompt; its bundled skill tells the agent to ask first. Its first pin could not install on v0.22.2 because of a manifest key that release did not know; the catalog was re-pinned the same day, and on main a plugin with a newer manifest key now installs with a warning instead of failing. Catalog entries do not wait for a release: they go live once the published catalog refreshes.
• Reverse engineering: rea
━━━━━━━━━━
⚙️ Meanwhile, in the engine room
Dozens of fixes landed yesterday that most users will never see, and the biggest share came from that race-condition hunt: files rewritten while another process read them, caches saved over each other, and timers that counted a sleeping laptop as idle.
• Windows Desktop attaches again to a gateway running as a Scheduled Task, which hermes gateway ensure refused for every task the installer registered
• On macOS, Desktop no longer hangs at startup when the home path's letter case differs from the disk, and symlinked profiles get their tickets
• Desktop's own UI tools (preview, focus pane and the rest) work again on sessions the shared gateway owns, instead of saying they only run in the Desktop app
• A successful hermes update is no longer reported as failed because the gateway read its exit-code file mid-write
If you noticed none of this, it worked.
All on main, ships in the next release; the installer change is already live on the one-liners. Latest stable: v0.22.2.
Which one hits you most? 👇
@Teknium@HermesWatcher@witcheer@NousResearch If I may add something to the conversation, sub-agents often create many sessions containing information that is generally only useful in the moment. How about a more aggressive pruning process focused on sub-agent sessions?
Hermes yesterday: a heads-up for everyone who runs Hermes on their own machine. One merge, about 1,900 commits long, rewired how every chat runs: the CLI, TUI, Desktop, API, editors, bots and cron now all go through one gateway per profile. It is on main; the current stable, v0.22.2, does not have it. Here are the 10 that matter.
1️⃣ One gateway now owns every local chat
Before: the CLI, the TUI, the Desktop backend, the API server, editors over ACP and cron each ran their own agent on the same state.db, so two of them could write one conversation at once. After: each profile has one gateway that owns its sessions, and every local surface attaches to it. A chat is one conversation with one queue and one writer wherever you open it, and an approval or question answered in one window settles in all of them. Closing the terminal detaches instead of ending the turn, and quitting Desktop no longer stops the gateway, which also runs cron, bots and messaging. A turn cut off by a gateway crash is never replayed on its own: Discard in Desktop, /discard or hermes sessions discard clears it. Heads-up: --safe-mode now needs --model; hermes setup asks before installing the gateway service and hermes import no longer installs it; a gateway a client started by itself exits after 10 idle minutes when no client, messaging platform or cron job needs it; dashboard bulk delete and prune answer 409 while the gateway runs; a failed hermes cron run exits 1; the Desktop backend pool settings are gone; and hermes update refuses to move back to a release without the runtime once state.db depends on it. Still on their own agent: the browser dashboard and Desktop SSH mode. In review: a fix for model picks in a Desktop Bot Chat or via /model that can fail, or check the new provider's key against the old endpoint. The runtime slipped into v0.22.1 by mistake; v0.22.2 takes it back out, so it ships with v0.23.0.
2️⃣ The terminal runs your own tools first
Before: Hermes put its own pinned node, npm, python, rg and other tools ahead of yours on the terminal's PATH, so commands the agent ran used Hermes's copies. On the Windows Store build, npx MCP servers, terminal npx and python -m venv failed with Access is denied. After: on every platform the terminal finds your own copy of each tool first and falls back to Hermes's (node, npm, python, rg, git, gh, ffmpeg and the rest, whichever you have installed), and on the Store build npx MCP servers and python -m venv work. Hermes's own work keeps its pinned tools: file search uses its own ripgrep, and a bare npx MCP command still runs on Hermes's Node. Heads-up: a workflow that relied on Hermes's Node version in the terminal now runs on yours. Not covered: execute_code, computer use, cron scripts and hermes bang build their environment without this, so on the Store build an npx they start still fails.
3️⃣ Skills keep a reload marker across compaction
Before: when compaction removed a loaded skill, only bodies over 5,000 characters left a marker telling the model to reload it. Smaller skills (about a quarter of the bundled ones) and skills loaded with /skill-name just disappeared, so the model carried on without its instructions and no hint they were gone. In lean mode the verbatim user block also quoted the first 4K of the skill body as your words and cut the request you typed after it. After: every skill leaving the window gets a reload marker and a line under Pruned Skills, whatever its size or how it was loaded (slash command, bundle, gateway auto-load); a /skill turn is quoted as you typed it; and a failed skill view is marked failed and never offered for reload.
4️⃣ Five advisories off the MCP HTTP stack, npm audits back to zero
Before: every HTTP MCP connection ran on httpx2 2.7.0, which has five published advisories, and hermes doctor reported npm audit findings in the root, web, TUI and WhatsApp bridge trees, then told you to run hermes doctor --fix, which never touches them. After: httpx2 and httpcore2 move to 2.12.0, the first release that clears all five, and the build fails if a pin drops below it; the npm trees audit at 0, including a sharp bump in the WhatsApp bridge for a high-severity librsvg CVE; and doctor lists npm findings as manual, with the real fix: wait for an upstream lockfile update and, on Docker, pull a rebuilt image, because recreating the same image restores the same dependencies.
5️⃣ hermes update stops rolling back over a plugin's pyproject
Before: a plugin whose pyproject.toml had no [project] table or no version made uv reject the generated workspace, and the whole hermes update rolled back. On Windows, real-time antivirus could lock uv's optional bytecode-compile script after the packages were already installed and fail hermes pm repair and bootstrap. After: those plugins get the inert version 0.0.0 (unless they declare a dynamic version), so the update goes through, and a failed compile step is retried once without bytecode compile; any other uv failure still fails.
6️⃣ New profiles keep your custom endpoint
Before: creating a profile from one whose model ran on a custom endpoint, selected as custom:<name>, a display name, a ${VAR} reference or a legacy custom_providers entry, copied only the model block, so the new profile's first turn failed with Unknown provider. In Desktop and the TUI, a bare custom model with a base_url left the new profile with no model at all. After: new profiles get the launch profile's endpoint entry from the CLI, the TUI and Desktop alike, with ${VAR} secrets kept as references, and the inherited endpoint wins over a same-named entry already in the new profile. Existing profiles are not repaired: recreate them or fix the provider entry by hand.
7️⃣ Desktop updates say what is in them
Before: every stable-channel update and many main updates in Desktop said only In this update · Improvements and fixes. After: on stable the dialog shows up to five headlines from the release's own notes with a Release notes link; on main it shows the five newest merged PR titles in the update, with a See all changes link to the compare view. When GitHub is unreachable it falls back to the commit list, and a custom branch or a rollback keeps the old view. Not tested live: the dialog through a remote SSH connection.
8️⃣ Long MCP calls get the deadline you set
Before: Hermes's sequential tool executor stopped any call after 420 seconds, even when the MCP server had a longer timeout configured, and portable plugin packages had no way to declare one. After: a server's explicit timeout holds through the whole call path, plugin.json can declare one per server, and a call that needs more than the shared batch budget runs as its own step so other tools keep their deadlines. Servers without an explicit timeout keep the generic deadlines. The test case: a Ghidra-based reverse-engineering server answered its first query at 580 seconds.
9️⃣ Mistral stops rejecting replayed tool ids
Before: Mistral accepts only tool ids of exactly 9 letters and digits, while Hermes stores ids like call_ plus 12 hex characters, so replaying a conversation that held them on a Mistral model could fail with HTTP 400. After: on Mistral routes the ids sent on the wire are mapped to stable 9-character ones, with a call and its result mapped from the same key; stored history is unchanged and other providers are untouched. Mistral models on other hosts (NIM, LM Studio, Ollama Cloud, vLLM) are matched by model name. Not tested live against https://t.co/ZlfJCyq66B itself.
🔟 13 new plugins in the catalog
Guardrails for coding agents are the day's theme: a mixer with enforced dials on how much an agent may change, a ledger of every time Hermes stopped to wait for you, and a janitor for the background processes agents leave behind. Heads-up: agent-janitor is dry-run by default; once you switch it to enforce, its sweep kills every process re-parented to PID 1 for over a minute that is not exempt or on your whitelist, whoever started it. Catalog entries do not wait for a release: they go live once the published catalog refreshes.
• Guardrails and oversight: hermes-agent-mixer, wait-ledger, agent-janitor
• Models and providers: lightningai, lightningai-rate-limit, teamorouter
• Languages: hermes-lang-ko, hermes-lang-pt-br
• Desktop pages: hermes-aac, anatomy-museum
• Feeds, finance and web: author-feed, openinvest, showly
━━━━━━━━━━
⚙️ Meanwhile, in the engine room
Dozens of fixes landed yesterday that most users will never see, and nearly all of them rode in with the gateway merge, on how sessions queue, recover and settle.
• hermes update, hermes pm install and hermes debug share name a CDN firewall block (Cloudflare or Vercel) and say your install is fine, instead of a bare HTTP 403
• Nemotron 3.5 Super VL is known as a 1M-token model instead of falling back to 128K, so Hermes stops compressing it early, and curated models now lead the hermes model list
• Docker plugin installs no longer rebuild python-olm from source
• Stable releases publish the final vX.Y.Z Docker tag again
If you noticed none of this, it worked.
All on main. Items 1, 3, 7 and 8 ship with v0.23.0; the rest are already in v0.22.2. Latest stable: v0.22.2.
Which one hits you most? 👇
@deeponailabs Exactly. The trial is a one-time thing for the first launch. Replaying onboarding from Settings uses your own configured model, and nothing stops that from being a free one: Nous Portal's free models, OpenCode Zen and so on.
Hermes yesterday: 512 commits hit main, more than double any day this series has covered, and the release was cut right behind them: v0.22.0 stable shipped overnight from the day's last commit. The headline: a fresh Desktop install now opens a setup chat, and the free model turns into a one-time trial for it. Here are the 10 that matter.
1️⃣ A fresh Desktop install opens a setup chat
Before: first-run setup lived in a separate hermes-setup profile, started with /initiate-setup, asked its questions on generic cards and handed off to a new chat at the end. After: a fresh Desktop install opens one chat in the default profile that walks through your name, an accent color, a layout, apps to connect, plugins, a quick tour and up to four first tasks picked for you, one card per step; typing in the composer answers the waiting card. Skip setup ends it, closing the app midway starts it over on the next launch, and Settings > Run onboarding again replays it on your configured model. Along the way the agent gained set_theme (it replaces apply_layout), so make it violet, dark mode works in any Desktop chat, and manage_connections can show a browsable connector directory card. Heads-up: /initiate-setup is gone on every surface, and an existing hermes-setup profile stays as an ordinary profile.
2️⃣ The free model becomes a one-time Desktop trial
Before: only the Microsoft Store build had the free model, and there it was on for the whole process: every CLI, gateway and backend boot created an anonymous Nous account, even with another provider configured, and any guest account could run inference. After: the free nous/welcome model is a one-time trial for the first Desktop install of an OS user who never used Hermes on that computer, on any bundle, and only on the Desktop's local backend. The CLI, TUI and messaging gateway no longer create an account at boot or offer the free model; connectors still create their connectors-only identity on first use. Desktop guests that already chatted on the free model keep it, a lost trial (signed in, auth.json deleted) is never claimed again, and the split between trial and connector guests is enforced on the client until a server-side check lands.
3️⃣ Memory edits stop wiping neighboring facts
Before: to change one fact, the memory tool's replace rewrote the whole entry, and models often dropped the other facts in it: NVIDIA measured Opus 4.8 doing it in 19 of 40 tasks. A write without a target fell back to MEMORY.md, so user facts could land there. After: replace is gone and patch is the only edit: it changes exactly one span inside an entry and keeps the rest (1 of 40 in the same test), and a span that appears twice is refused with a request for more context. Every write needs a top-level target. Writes staged for approval before the change still replay, and external memory providers receive a patch as a whole-entry replace. Heads-up: patch does not yet match a span retyped with straight quotes, a plain dash or re-wrapped lines where the entry has the original; a fix is in review.
4️⃣ Stable installs stay on stable
Before: rerunning the installer moved a stable install back to main, because Hermes-Setup bakes --branch main, and its update mode dropped the channel the Desktop asked for. The update check then offered an older stable release as a new update. After: an installer rerun keeps an install whose recorded channel is not main where it is and leaves the move to hermes update, and Hermes-Setup forwards the channel. When the checkout is newer than the chosen stable release, Desktop, hermes update --check, hermes --version and the dashboard call it a rollback (Roll back to v0.21.7) instead of an update. Installs with no channel record, a main record or an explicit --commit behave as before. Not run for real yet: the macOS Hermes-Setup app; the Windows installer is covered by CI tests only.
5️⃣ Connector tools send and save real files
Before: a connector tool that takes a file, like a mail attachment or a drive upload, asked the model for a storage key only the tool gateway can create, so every such call failed, and files a tool returned came back as storage links that expire in about an hour. After: the model passes a local path; Hermes checks it, uploads it (up to 20 MB) and runs the tool, and returned files are saved under downloads/connectors in the Hermes home, where the model can send them on with MEDIA:. Which files may leave follows the MEDIA: rule: on a default install any regular file outside the credential and system denylist, in strict mode (gateway.strict) only caches, allowed folders and recent files. SSH, Modal and other remote terminal backends are refused, downloads stay until you delete them, and the PR's live checks against the real gateway were listed without results when it merged.
6️⃣ A dead MCP login stops hammering the server
Before: an OAuth MCP server whose refresh token was rejected re-sent that dead token on every new session (Desktop and TUI rediscover on every agent build while nothing is connected, the gateway once per cron job), four requests each time. One user hit about 200 failed refreshes a minute and got his IP rate-limited out of the Nous Portal. After: the parked server stays quiet until hermes mcp login or a Desktop re-auth rewrites its token files, then comes back on the next session. The 5-minute self-probe still retries, and three fixes for that slower drip are still in review.
7️⃣ Gemini 4 Argon, and Gemini thinking settings that stick
Before: Argon was not in the model lists, any reasoning effort left it at its medium default, and output past 32,768 tokens was cut and reported as a normal stop. On Gemini 3.x, turning reasoning off sent a budget of 0 that those models reject or ignore. After: gemini-4-argon is selectable on Gemini, Vertex, OpenRouter and Nous (Gemini 3.8 Flash stays the default), and effort maps to Google's thinkingLevel by version number for every Gemini 3 and up. On the native endpoints, xhigh and max turn on long decode, up to 262,144 and 1,048,576 output tokens, with a hop ceiling so a server cannot keep billing, and a dropped stream resumes from its last checkpoint instead of starting over. Gaps: no long decode on OpenRouter, proxies or the OAuth Vertex provider, and after a resume the tokens generated before the drop are missing from reported usage. Introductory price: $2 in, $10 out per million tokens, doubling on 1 Dec per Google.
8️⃣ Typing answers the question card
Before: in Desktop, typing in the composer while a clarify card waited cancelled the card with every question unanswered and sent your words as a separate steer, so the model did not know which question they answered. After: the words answer the card's first open question, text that matches a choice label picks that choice, and each Enter answers one question. Slash commands, attachments and an empty Enter (Stop) work as before. The onboarding cards, theme pickers and the connector directory take typed words the same way; the CLI, TUI and messaging apps are unchanged.
9️⃣ MCP tool schemas: reloads and $refs that work
Before: /reload-mcp said reloaded, but a tool that kept its name also kept its old description and parameters. And values behind a $ref in an MCP tool's schema, common with pydantic and zod servers, reached the tool as the model typed them: 5 as a string for an integer field, first_name where the server named the key first name. After: an explicit reload publishes same-name schema changes (the automatic refresh between turns still does not, to protect the prompt cache), and local $refs are followed for type conversion and key mapping. Still not parsed: a JSON string sent for a union with no top-level type.
🔟 29 new plugins in the catalog
Keeping an eye on the agent is the day's theme: two ledgers, an independent verifier, runtime guardrails and a fleet operations page. BrowserPaw, delisted on 3 Oct, is back with credential-free MCP delegation. Catalog entries do not wait for a release: they go live once the published catalog refreshes.
• Oversight and observability: agent-ledger, context-audit, hermes-call-ledger, hermes-guide, hermes-verifier, llm-antidote, operations
• Memory and context: betterdb, hermes-vcc, kumiho-memory, long-conversations, wicked-memory
• Workflows and automation: auto-pin, heartbeat2, myswarm
• Data and search: colorado-traffic, event-read, index-search
• Shopping and ads: adwhispr, channel3
• Languages: hermes-lang-ca, hermes-lang-el, hermes-lang-th
• Phones and apps: hermes-mobile, phone-harness
• Models and accounts: account-pool, netmind-provider
• Messaging and voice: telegram-stickers, ttsbuddy
━━━━━━━━━━
⚙️ Meanwhile, in the engine room
Dozens of fixes landed yesterday that you will probably never see. Most of them went into polishing the new Desktop onboarding before the release cut.
• Telemetry that stopped sending after an update dropped a value old rows still held, like a v0.21.6 Spotify row, now re-buckets or skips that row and sends the rest of the day
• On Linux, a git exiting anywhere on the machine during the launch-time index.lock check no longer fails the Hermes launch
• Windows Store and App Installer updates get past Could not register automatic relaunch, which aborted them before installing
• hermes://plugin/install catalog links, broken since they shipped, now ask the backend for the entry
If you noticed none of this, it worked.
All on main and already shipped. Latest stable: v0.22.0.
Which one hits you most? 👇