Pick the Right Model for Each Job
Goal of this page: spend expensive model capacity where it pays off, and cheap capacity where it doesn't matter.
The principle: plan expensive, implement cheap
A good OpenSpec change does the hard thinking up front: the proposal explains why, the design settles how, and tasks.md breaks the work into small, verifiable steps. Once that exists, implementation is mostly following instructions — and following instructions is exactly what smaller, cheaper models are good at.
So split your model budget:
- Planning (writing proposals, designs, and tasks): use your most capable model, in whatever tool you plan with. This is where quality is decided.
- Implementation (Shipper's
implementandarchivephases): configure a cheaper, faster model. The spec keeps it on rails, the repository checks catch its mistakes, and your PR review is the final gate.
If a cheap model repeatedly fails a particular change, that's usually feedback about the spec — tasks too big, ambiguous acceptance criteria — more often than about the model.
Configuring the model per provider
You can set the model at init time, in .openspec-shipper/config.json, or override it per run with environment variables. Precedence is: CLI flags > OPENSPEC_SHIPPER_* env vars > .openspec-shipper/.env > config.json > defaults.
OpenCode
{
"executor": {
"provider": "opencode",
"opencode": {
"model": "opencode-go/deepseek-v4-pro"
}
}
}Or per run:
OPENSPEC_SHIPPER_OPENCODE_MODEL=opencode-go/deepseek-v4-pro npx openspec-shipper queue runOpenCode is the easiest place to experiment with cheap implementation models, since it can route to many providers — try a budget model on a low-stakes change and compare queue stats runs.
Codex CLI
{
"executor": {
"provider": "codex-cli",
"codex": {
"model": "gpt-5.6-luna",
"reasoningEffort": "xhigh"
}
}
}Or per run:
OPENSPEC_SHIPPER_CODEX_MODEL=gpt-5.6-luna \
OPENSPEC_SHIPPER_CODEX_REASONING_EFFORT=xhigh \
npx openspec-shipper queue runreasoningEffort controls how deeply Codex reasons. The default is xhigh for maximum reliability on implementation tasks; use low, medium, or high when speed or cost matters more.
Claude Code
{
"executor": {
"provider": "claude-code",
"claude": {
"model": "sonnet",
"effort": "low"
}
}
}Also settable at init (npx openspec-shipper init --provider claude-code --model sonnet --effort low) or per run:
OPENSPEC_SHIPPER_CLAUDE_MODEL=sonnet \
OPENSPEC_SHIPPER_CLAUDE_EFFORT=low \
npx openspec-shipper queue runsonnet with low effort is a solid implementation default; reserve bigger models for changes you already know are gnarly.
Measure before you decide
npx openspec-shipper queue statsStats show what each run cost. Try the same kind of change on two models and let the numbers — and your PR reviews — pick the winner.
What's next
One last page on habits: Ship like a team of two.