Hermes Agent is now the easiest coding agent to govern with ACP
Hermes Agent — Nous Research’s terminal-native coding agent — now has first-class ACP support via the new hermes-acp Python plugin. Three commands to install:
pip install hermes-acp
hermes plugins enable acp
hermes-acp login
That’s it. No feature flag dance. No MCP connector supplement to cover the tools your hook can’t see. No “wait, does this fire for apply_patch too?” footnote. Every Hermes tool call — terminal, file, web, browser, vision, cron, every custom skill — flows through your ACP workspace from the first restart.
Hermes turned out to be the cleanest integration we’ve built. This post is about why, and what it tells you about the future of governable coding agents.
The state of hook coverage in 2026
We’ve now shipped ACP integrations for four major coding-agent harnesses. They cover wildly different fractions of the tool surface:
| Harness | What pre_tool_call actually intercepts |
Feature flag? |
|---|---|---|
| Claude Code | All native tools + MCP | No |
| Codex CLI | Bash only. Read/Edit/Write/web fetch/MCP do not fire. | Yes ([features].codex_hooks = true) |
| Cursor | Most native tools. Some built-ins (e.g. Web Search) don’t emit. Bugs filed. | No |
| Hermes | Everything. Native and custom. Sync hooks, on by default. | No |
This isn’t a vendor scoreboard for its own sake. It’s a real, structural difference in what governance means on each platform.
On Codex, “I’ve governed my agent” today means “I’ve governed shell commands my agent runs” — which is most of the destructive-action risk (rm -rf, gh repo delete, psql DROP TABLE), but not all of it. File-edit governance on Codex requires routing edits through an MCP connector ACP also installs. It’s a real solution, but it’s a two-layer solution.
On Hermes, “I’ve governed my agent” means “I’ve governed every tool call.” Period. No supplementary layer.
Why Hermes ended up here
Hermes’s plugin system was designed for this. Where Claude Code’s hooks evolved out of a “shell out and pipe JSON” pattern (and Codex’s are essentially a port of that), Hermes hooks are first-class Python callbacks: register(ctx) registers a function that Hermes calls in-process before dispatching a tool call. The hook receives the tool name, the arguments, the session ID. Return a {"action": "block", "message": ...} and Hermes won’t run the call.
That design — in-process Python rather than out-of-process shell — has three consequences worth noting:
-
Hook coverage is automatic for every tool the agent has. There’s no “but does the hook fire for this one?” carve-out, because every tool dispatcher goes through the same code path. Adding a new built-in or custom skill doesn’t create a governance gap.
-
Hooks are synchronous. The tool call blocks until the hook returns. We bound the worst case with a 4-second HTTP timeout to the ACP gateway, fail open beyond that, and emit a stderr warning when we do — same fail-open posture as the Claude Code plugin. Sync hooks rule out async fire-and-forget patterns, but for a governance hook that’s the correct trade-off.
-
The plugin must be a Python module loadable by Hermes. We could not ship the same
govern.mjswe ship to Claude Code / Codex / Cursor. That’s why this integration is a separatepip install, not acurl -sf … | bash. (We thought about wrapping the pip step in the universal installer. It’s a worse UX — bash silently shelling out to whichever Python is on PATH, two uninstall paths, confusing failure modes. Don’t mix install paradigms.)
How the hermes-acp plugin works
Two registered hooks, both calling the same ACP gateway endpoints as the Claude Code / Codex / Cursor plugins:
-
pre_tool_call→ POST/govern/tool-use. Server returnsallow/deny/ask.denyandaskblock the tool call with a system message;allowpasses through. The plugin sendsX-GS-Client: hermes-plugin/<version>so per-client policies and dashboard filters work the same way they do for the other harnesses. -
post_tool_call→ POST/govern/tool-output. Observational only. Server-side audit, redaction logging, and DLP scanning all run, but the redaction result isn’t propagated back to the agent’s context — that’s a Hermes limitation, not an ACP limitation. Thepost_tool_callreturn value is ignored by design in Hermes today.
The plugin is zero-dependency — uses Python’s stdlib urllib for HTTP. No requests, no httpx, no aiohttp. That matters more than it sounds: every transitive dep on a governance plugin is a credential-adjacent supply-chain target, and the value of a thin wrapper over an HTTP API is being a thin wrapper.
What you’ll see in the dashboard
A new hermes-plugin row on cloud.agenticcontrolplane.com/agents, with activity tagged by Hermes’s task_id (its session identifier). The activity log shows:
tool_name—terminal,web_search,read_file, plus any custom skill namestool_input— the dict the model passedtool_output— the result, truncated to 200 KBduration_ms— Hermes’s measured execution time- Standard ACP attribution — workspace, user, policy decisions, delegation chain
Same shape as the Claude Code / Codex / Cursor log rows. Same policies apply. Cross-harness teams can mix freely.
Two real gotchas to know about
post_tool_call is observational only. If your governance model depends on catching a secret in terminal output before it reaches the model, Hermes can’t apply the redaction back to the agent’s context today. ACP still logs the redaction server-side for post-hoc review and DLP analytics — you just don’t get the inline rewrite that Claude Code’s PostToolUse supports. Most policy violations you actually care about are catchable at pre_tool_call anyway.
No native “ask user” semantic. Hermes only distinguishes block / not-block. When the ACP server returns decision: "ask", the plugin renders it as a block with the message "[ACP] Approval required: …; approve in the ACP dashboard and retry." The user reviews and approves out-of-band, then retries. Adding a /acp-approve slash command via Hermes’s register_command API would give a richer inline UX — open issue, PR welcome.
What this means for the agent landscape
The harnesses with the cleanest governance stories aren’t always the ones with the biggest installed base — they’re the ones that designed for it from day one. Hermes’s plugin system makes governance plug-in-able by construction. Claude Code’s hooks have been extended responsibly since they shipped. Codex’s hooks are explicitly marked Stage::UnderDevelopment and it shows in coverage.
If you’re building a new coding agent and want to be governable: pick a hook surface that fires for every tool dispatch, ship it on by default, make block the only operation a hook return value needs to encode, and document the contract. Hermes did all four and it shows.
Try it
pip install hermes-acp
hermes plugins enable acp
hermes-acp login
Full install guide: /integrations/hermes.
If you’re already running ACP for Claude Code / Codex / Cursor, the same ~/.acp/credentials works — hermes-acp login is idempotent and will short-circuit if you’ve already authenticated. One workspace, every harness.