Runners¶
kew is runner-agnostic. It owns the parts that make autonomous dispatch safe — the queue, worktree isolation, budgets, the security hook, the tamper-evident audit log, and governance — and treats the coding agent itself as a pluggable, supervised subprocess. The same controls apply no matter which agent does the work, so you can route different issues to different agents without giving up the control plane.
Governance that lives inside one vendor's console governs one vendor. kew keeps budgets, audit, approval, and the kill switch outside the runner, so they hold across every agent — cloud or local.
Supported runners¶
| Runner | Use it for | Models | Config section |
|---|---|---|---|
claude-code (default) |
The deepest integration — session resume on retry, structured stream-json events, cost reported by the runner itself | Claude (Opus / Sonnet / Haiku) | [claude_code] |
opencode |
One integration that reaches many providers, including local models. See OpenCode. | Gemini, GPT / o-series, Codex, Ollama, OpenRouter, and 70+ others | [opencode] |
pi |
The pi coding agent (@earendil-works/pi-coding-agent) |
pi | [pi] |
hermes |
A headless OpenRouter-only agent — one integration, hundreds of OpenRouter models, native cost from a usage file. See Hermes. | OpenRouter (openrouter/<vendor>/<model>) |
[hermes] |
Runner comparison¶
The following table compares the available runners to help you choose the right one for your needs:
| Runner | Provider(s) | Cost | Best for |
|---|---|---|---|
| Claude Code | Anthropic | Metered | Hard work |
| OpenCode | Multi-provider | Metered | Provider-flexible |
| Hermes | OpenRouter only | Metered | OpenRouter models, native usage-file cost |
| Lemonade | Any local OpenAI-compatible endpoint | $0 | Private/sovereign work |
Each runner is a thin adapter (in kew/runners/) that kew shells out to and supervises. Per-runner options — binary path, extra flags, provider knobs — live in that runner's kew.toml section; see Configuration.
Running a runner in a sandbox¶
With [sandbox] enabled = true a runner does not run as a host subprocess — it runs inside a container image. The host-side interface to that image is fixed and normative: see the container entrypoint contract. It is also the spec you build a new agent image against — per-runner variation belongs inside the image, not in kew.
Sandboxed dispatch is Claude-only today
The contract is runner-agnostic; the host code that drives it is not yet. Three gaps, each closed by a containment-epic node:
[sandbox] imageis a single string, so every contained dispatch gets the same (Claude) image whatever runner it routed to — closed by N2 (per-runner image map).- ~~The host appends a fixed Claude argument block rather than deriving it from the runner.~~ Closed by N3: the container args now come from the resolved runner's
container_args(). - The sandbox stream is parsed as Claude
stream-jsondirectly; it never callsrunner.parse_line(), so a non-Claude image's telemetry is silently lost. Closed by N4.
Do not route a non-claude-code runner through the sandbox until N2–N4 land. See what is built today.
Routing¶
Set a default runner, then optionally route by issue complexity (simple / medium / complex). Each tier can pick its own runner and model:
[routing]
default = "claude-code" # default runner
simple = { runner = "opencode", model = "gemini-2.5-flash" } # cheap model for easy issues
complex = { runner = "claude-code", model = "claude-opus-4-8" } # strongest for hard issues
A tier may be a full { runner, model } table or a bare string shorthand (medium = "claude-code"). kew classifies each issue's complexity (from labels / heuristics) and picks the matching tier, falling back to default.
Inferring the runner from the model¶
If you set only a model, kew infers the runner from the model name, so most setups need no explicit runner:
| Model prefix | Runner |
|---|---|
claude-* |
claude-code |
gemini-*, gpt-*, o1-*, o3-*, o4-*, ollama/* |
opencode |
pi is never inferred — select it explicitly with runner = "pi". hermes is likewise never inferred: the openrouter/* prefix stays mapped to opencode, so reach hermes only via an explicit runner = "hermes" route.
Cost & honesty across runners¶
kew records cost per run from the runner's own usage where it reports one (Claude Code, pi), and prices token usage from its pricing table otherwise. Costs are list-price/API-equivalent, not necessarily your actual bill — see the value-leverage framing in kew report. The per-model scorecard (kew report --models) compares merge rate, review cycles, and cost per merged PR across whichever runners and models your fleet actually used — measured from your own outcomes, not a benchmark.
For runners that emit OpenTelemetry usage (e.g. Claude Code interactive sessions), kew ingest folds that into the same record so dispatched and interactive spend live in one place.
Next¶
- OpenCode runner — provider auth and setup for Gemini / GPT / Ollama / OpenRouter and 70+ others.
- OpenRouter models — hundreds of models behind one key via OpenCode, plus the data-policy settings to configure before dispatching real code.
- Configuration — the
[routing],[claude_code],[opencode], and[pi]sections.