OpenRouter
ShipCode ships with a first-class OpenRouter integration as the third executor alongside Claude Code and Codex. OpenRouter lets you route each pipeline phase to any model on their catalog — OSS, frontier, free-tier, or a routed meta-model.
Enabling
-
Create an account at openrouter.ai and generate an API key.
-
Export the key before launching the desktop app or CLI:
export OPENROUTER_API_KEY=sk-or-v1-... -
Flip on
openrouterEnabledin the desktop Settings → Pipeline panel (or set it directly in thesettingsrow of your local SQLite DB).
The shipcode onboard command also validates the key and prints a warning if it’s missing, invalid, unreachable, or pointed at a deprecated model.
Without a key, OpenRouter is silently skipped — the pipeline still works with claude and codex alone.
GitHub label variants
Route an individual issue to OpenRouter via label:
| Label | Effect |
|---|---|
shipcode:agent:openrouter | Uses the executor model configured in Settings (or the paid-tier default) |
shipcode:agent:openrouter/auto | OpenRouter auto meta-router — picks the best model per prompt |
shipcode:agent:openrouter/free | OpenRouter restricted to free-tier models |
These are defined in packages/agents/src/github/model-router.ts. Unknown or missing agent labels fall back to shipcode:agent:codex.
Per-phase model selection
Each pipeline phase can point at a different OpenRouter model. The fields live on the AppSettings row (see packages/shared/src/types.ts):
| Setting | Purpose | Default |
|---|---|---|
openrouterEnabled | Master switch — must be true or OpenRouter is skipped entirely | false |
openrouterPlannerModel | Override the planner model; null → falls through to the paid-tier default | null |
openrouterReviewerModel | Override the reviewer model; null → paid-tier default | null |
openrouterVerifierModel | Override the verifier model; null → paid-tier default | null |
openrouterExecutorModel | Override the executor model; null → paid-tier default | null |
openrouterDefaultPaidModel | Paid-tier fallback used when a per-phase override is null | set at onboarding |
openrouterDefaultFreeModel | Free-tier fallback used by shipcode:agent:openrouter/free | set at onboarding |
openrouterExplicitFallback | Final fallback when a routed model errors out | set at onboarding |
All four phase defaults are editable from the desktop Settings panel, and project/issue overrides can replace them when needed.
Tiers
- Tier 1 — Provider abstraction. Adds
openrouteras a validAgentType; CLI + desktop both recognize it. - Tier 2 — HTTP-backed planning/review. Planner, reviewer, revision, and verifier phases talk to OpenRouter directly over HTTP without spawning a local CLI subprocess.
- Tier 3 — In-process execute harness + routed models. The execute phase runs a tool-call loop inside the ShipCode process (no child CLI) and can use routed or free-tier OpenRouter models with per-phase telemetry.
All three tiers shipped in PR #9 (merged 2026-04-10).
Troubleshooting
- “OPENROUTER_API_KEY not set (optional)” from
shipcode onboard— you haven’t exported the key. The pipeline will still run withclaude/codexonly. - “invalid_key” / “unreachable” / “model_deprecated” — the onboarding doctor hit a live check and the key failed. Re-generate the key, check your network, or pick a different default model in Settings.
- The pipeline picks the wrong model for a phase — remember the resolution order:
openrouterEnabledmust betrue, then the per-phase override is consulted, thenopenrouterDefaultPaidModel(or the free-tier default when the label forces it), thenopenrouterExplicitFallback. shipcode:agent:openrouter/autopicks an unexpected model —autois OpenRouter-side routing; you get per-phase telemetry in the desktop Terminal drawer and Costs view so you can see which concrete model answered.
See also
- Configuration → GitHub labels — the full agent-label table
- Models — curated model IDs, presets, aliases, and reasoning-effort rules
- Pipeline overview — how the phase/model mapping works end-to-end
- CLI reference —
shipcode onboardOpenRouter auth check