Hermes yesterday, October 24, 2026: cron jobs get only the MCP servers they name
What landed on Hermes Agent main on October 24, 2026: cron jobs limited to the MCP servers they name, untrusted MCP approvals that show their arguments, a Docker Desktop crash-loop fix, one-shot runs that can write skills and 26 new plugins.

Table of contents
- 1. Cron jobs get only the MCP servers they name
- 2. Approvals show what an untrusted MCP write will do, and text prompts show the whole command
- 3. The gateway no longer crash-loops on Docker Desktop
- 4. One-shot runs can now create and edit skills
- 5. /review and /refine work on a session you left alone
- 6. Context7 API keys are masked everywhere
- 7. Plain audio files stop arriving as voice notes
- 8. Streamed replies send their images and stop flashing half-typed paths
- 9. Plugin skills load on the first try, under shorter names
- 10. 26 new plugins in the catalog, led by four model providers
- Meanwhile, in the engine room
- Watch the recap
A cron job that named one MCP server ran with every MCP server you had enabled, and a text approval prompt could cut off the rm -rf at the end of a long command. Both are fixed on main, along with a gateway that crash-loops on Docker Desktop since v0.22.5, one-shot runs that may now write skills, and 26 new plugins. 229 commits landed; here are the 10 that matter.
1. Cron jobs get only the MCP servers they name
Before: a cron job whose enabled_toolsets named an MCP server by its toolset name (mcp-filesystem) never matched the check that turns a named server into an allowlist, so the job ran with every enabled MCP server: asking for filesystem gave it filesystem, github and slack. A job that named a server you had switched off with enabled: false fell through the same way. After: mcp-filesystem and filesystem name the same server, the job gets only what it lists, and a disabled server stays off without widening the job. Unchanged: a job that lists only native toolsets still gets every enabled MCP server, and no_mcp still means none.
Pull request: Cron MCP allowlist.
2. Approvals show what an untrusted MCP write will do, and text prompts show the whole command
Before: the approval for a write call to an MCP server marked trust: untrusted named only the server and the tool, so you allowed it without seeing what it would change. On platforms without buttons, or when a card failed to send, the text /approve prompt cut every command at 200 characters, so a long command could hide its end: an echo of 320 characters followed by && rm -rf showed no rm -rf. After: the card lists the call’s arguments as JSON capped at 1,200 characters, with API keys, passwords, tokens and API-key headers masked even when security.redact_secrets is off, and control characters shown as escapes so the card matches what the server receives. The text prompt now shows up to 3,000 characters, as a button card does, for MCP calls and dangerous terminal commands alike. Limits: the Ink TUI shows only the first 10 lines of the prompt, and a password= written inside a free-text field is not masked.
Pull request: Untrusted MCP approvals.
3. The gateway no longer crash-loops on Docker Desktop
Before: v0.22.5 made the gateway’s control socket mandatory, and on the documented Docker layout, with HERMES_HOME bind-mounted from the host, Docker Desktop’s file sharing refuses sockets (Operation not supported, errno 95), including a stale gateway.sock an earlier container left behind. The gateway logged the failure as non-fatal, exited and restarted in a loop. After: when the home refuses sockets, the gateway listens in a private temporary directory (folder 0700, socket and pointer file 0600, the same fallback a too-long home path already used), and clients find it through the pointer. Any other bind error still stops the gateway. Heads-up: the fix is on main only, so v0.22.5 on Docker Desktop keeps crash-looping until the next release.
Pull request: Docker Desktop control socket.
4. One-shot runs can now create and edit skills
Before: hermes chat -q, --oneshot and hermes -z hid skill_manage, and their prompt told the model not to create or edit skills because no later session would reuse them; a one-shot owned by the gateway could still carry the tool under that same prompt. After: maintainers ruled that a one-shot run may author skills, so skill_manage stays in its tools on every path and the prohibition is gone from the prompt. The cost is about 1,343 extra tokens per one-shot request, because skill_manage is a core tool sent with every request. Unchanged: one-shot runs still load only domain skills and keep the subagent cap (delegation.oneshot_max_children).
Pull requests: skill_manage kept, Prompt line removed.
5. /review and /refine work on a session you left alone
Before: the gateway releases a session’s cached agent after an idle hour (agent.agent_cache.idle_ttl_secs), under memory pressure and around a /moa turn, and both commands read the conversation only from that agent, so they answered Nothing to review yet (or Nothing to refine yet) until you sent another message. With auxiliary.background_review.enabled: false, a bare /refine said it was reviewing and ran nothing. On messaging platforms, /refine ran as an unattended review, so memory removals and replacements were staged as proposals instead of applied. After: /review on every surface and /refine on messaging read the stored transcript and run on the session’s own model, tools, provider routing and backup providers, with the result posted in the same chat; local sessions already did this for /refine. A bare /refine runs while automatic reviews stay off, and a messaging /refine applies its memory changes like every other surface. Limit: two cold /refine commands at once on one chat each start a review.
Pull requests: /review on an idle session, Messaging /refine on an idle chat, Bare /refine with reviews off.
6. Context7 API keys are masked everywhere
Before: Context7 keys start with ctx7sk-, a prefix the secret redactor did not know, and the generic sk- pattern cannot match inside it, so a key was masked only when a secret-looking field name sat next to it. read_file on the Context7 MCP setup, which keeps the key in a header beside a url: line, returned it in clear text, and so did prose, command output and JSON arrays. After: ctx7sk- joins the known vendor prefixes, so the key is masked on every surface like the other prefix-matched credentials.
Pull request: Context7 key redaction.
7. Plain audio files stop arriving as voice notes
Before: Discord uploaded every audio file the agent sent as voice-message.ogg, a voice message that does not play when the file is an mp3 or a wav, with a duration guessed from its size; the WhatsApp bridge, WhatsApp Cloud, BlueBubbles and Feishu also turned plain audio into voice notes. Cron delivery dropped the voice flag, so a cron job’s [[audio_as_voice]] file reached Telegram as a music file. After: audio without [[audio_as_voice]] goes out as a regular attachment under its real name (on WhatsApp Cloud, as the original audio/mpeg), voice replies on Discord are real Ogg/Opus, transcoded with ffmpeg when needed, with their real duration, and cron forwards the flag. Not covered: QQ Bot still sends all audio as voice, and audio sent with the send_message tool still becomes a voice bubble on Matrix.
Pull request: Plain audio vs voice notes.
8. Streamed replies send their images and stop flashing half-typed paths
Before: with streaming on, a reply holding a markdown image () or an <img> tag showed the tag as text and never sent the picture, because the final send that turns tags into attachments is skipped after a streamed reply. Draft frames also showed half-typed MEDIA: paths (MEDIA:/home/t...), and a reply that was only a MEDIA: line streamed the bare path. After: the picture arrives as an attachment, as it already did with streaming off, the tag leaves the text, and frames hold back while the open line is a half-typed image tag or MEDIA: path, so each frame only grows. Prose such as social media: still streams, and plain links are unchanged. Tested on Telegram and Discord stand-ins, not the live services.
Pull requests: Images arrive as pictures, No half-typed MEDIA: paths.
9. Plugin skills load on the first try, under shorter names
Before: a portable plugin’s skills were named after a hashed folder (agent-plugin-blender-5a80e4ba:blender), and the skill_view description said to use the form plugin:skill, which models copied word for word: plugin:agent-plugin-blender-5a80e4ba:blender returned not found, and the agent went on without the skill. After: portable plugin skills take the plugin’s name (blender:blender), as native plugin skills already did; skill_view drops a leading plugin: and its description shows <plugin>:<skill> as a placeholder. Old hashed names saved in prompts or cron jobs still load, and plugin data stays in its hashed folder. Two plugins whose names slug alike (foo.bar and foo-bar) are kept apart, and disabling one no longer blocks the other.
Pull requests: Named after the plugin, plugin: prefix tolerated.
10. 26 new plugins in the catalog, led by four model providers
26 new entries, led by four model providers and three plugins that route or retry turns across models, plus guardrails, search, Desktop add-ons and game-engine tools. Heads-up: several send prompts, files or mail to their own services, and each entry’s disclosure says where. Catalog entries do not wait for a release: they go live once the published catalog refreshes.
Model providers:
Routing and fallback:
Guardrails and audit:
Search and files:
Desktop:
Developer tools:
Games:
Work and email:
Meanwhile, in the engine room
Dozens of fixes landed yesterday that most users never see, and the gateway took most of them: restart notices, streaming and background processes.
- A chat whose API key changed in
config.yamlbefore a backend restart answered Something went wrong, use/retry, and claimed some actions may already have run; it now says the key the chat started with changed, that/retryfails the same way and that/newstarts a chat on the current key, with a Start new session button in the Desktop (pull request) - MCP servers that send one SSE event over 1 MiB on Streamable HTTP (a 162-tool list, an Unreal Editor viewport capture) failed to connect or to answer; they now work up to the 10 MiB per-event cap Hermes already had, while the legacy
transport: ssekeeps the 1 MiB limit (pull request) - A background process a subagent handed to its parent completed into a parent turn that ran as the subagent:
notify_on_completecame back false, sudo was refused and the subagent’s Kanban fence leaked into the parent’s shell; that turn now runs as the parent (pull request) hermes gateway restarton Windows, andrestart --allon every OS, skipped the Gateway online notice in home channels; both now send it (pull request)
If you noticed none of this, it worked.
All on main, ships in the next release (Desktop app changes reach the Microsoft Store app with a release and the .exe and .dmg app with its next bundled release). Latest stable: v0.22.5.
Watch the recap
The 56-second motion recap, made with Remotion, is on X.
Was this configuration guide helpful?
If you have questions, encountered issues during setup, or want to discuss networking and security, connect or reach out on LinkedIn.
Connect on LinkedIn