Hermes Runner¶
Hermes is a headless coding agent that runs against OpenRouter. kew reaches it through a thin adapter (kew/runners/hermes.py) that shells out to the hermes CLI once per dispatch and supervises it like any other runner — same worktree isolation, budget gate, audit log, and kill switch.
OpenRouter only
Hermes runs OpenRouter models only. kew deliberately does not wire it to Anthropic or any other provider — route those to claude-code or opencode instead. A route to hermes with a non-OpenRouter model fails closed at command-build time rather than silently falling back.
Setup¶
- Install the
hermesCLI via itsinstall.sh. - Create an OpenRouter account and API key at https://openrouter.ai/settings/keys, and make it available to hermes (hermes manages the credential — kew does not see or store it).
- Configure your OpenRouter account's data policy and credits before dispatching real code — see the OpenRouter data-policy prerequisites. Dispatched runs send your repository's code as prompt content, and hermes bills against your OpenRouter credit balance, so set the training opt-out (and optionally pin ZDR providers) first.
Configuration¶
Select hermes explicitly — it is never inferred from the model name (the openrouter/ prefix stays mapped to OpenCode, so existing OpenRouter-via-OpenCode routes are unaffected):
Or route a complexity tier to it:
[routing]
default = "claude-code"
simple = { runner = "hermes", model = "openrouter/deepseek/deepseek-v4-flash" }
kew model strings are openrouter/<vendor>/<model>. The runner strips the openrouter/ prefix and invokes hermes as --provider openrouter --model <vendor>/<model>.
[hermes] options¶
| Key | Default | Meaning |
|---|---|---|
extra_args |
[] |
Extra flags passed through to the hermes invocation. |
How it works¶
Unlike Claude Code / OpenCode / pi, hermes emits no mid-run event stream — stdout is the final response text only. Instead, on completion it writes a single JSON usage file (kew hands it a run-scoped --usage-file path under the log directory, never inside the worktree, so it can never land in a PR branch, and cleans it up on every exit path).
That usage file — not the exit code — is authoritative:
- Success/failure. hermes exits
0even on a credential/config failure. kew trusts the usage file:completed: true→ success,failed: true→ a permanent failure (or transient on a rate-limit/network marker). A SIGTERM/timeout kill leaves no usage file and is classified transient. - Cost. kew reads
estimated_cost_usdfrom the usage file as the runner-reported native cost. This is hermes's own OpenRouter models-API estimate — the same fidelity class as OpenCode's figure, and framed honestly via theopenrouter:via-hermesendpoint on the audit record. A killed run with no usage file meters$0native and is bounded by the outer budget gate and watchdog.
Resume¶
Hermes supports session resume on transient-retry: kew captures the session_id from the usage file and resumes with hermes --resume <session_id> (a fresh usage file per attempt).
Next¶
- OpenRouter models — the data-policy settings to configure before dispatching real code.
- Runners overview — routing and cross-runner cost honesty.