Most people run their coding agent with one setup and leave it there. That causes problems both ways. You either pay top-tier model prices to rename a variable, or you use cheaper models for a messy cross-repo auth change and then spend the afternoon fixing a bad plan.
The answer is not just “cheap profile” and “expensive profile”. That framing makes it about cost alone. It can push you into avoiding better models out of guilt, then fighting the agent all day to save a few cents.
A better framing is two intentional modes:
Daily mode should be good enough to use all day without second-guessing it. Use strong models, but not the most expensive ones for routine search and utility work.
Hard mode should use the strongest reasoning models when the task is hard enough that the extra token cost is clearly cheaper than wasted engineering time.
This post shows how I set this up with OpenCode and the Oh My OpenAgent plugin, using GitHub Copilot as the model provider. The same idea works with any agent that lets you switch config per run.
The shape of the setup
The key is to keep each mode fully isolated. They should not bleed into each other or into your existing default config. OpenCode reads its config from a directory, and you can point it somewhere else with environment variables. So I keep three config trees:
~/.config/opencode # left untouched, the default
~/.config/opencode-daily # daily-driver profile
~/.config/opencode-hard # hard-mode profile
Two shell aliases select the profile by overriding the config directory:
# Daily driver, isolated from the default ~/.config/opencode
alias ocx-daily='OPENCODE_CONFIG_DIR="$HOME/.config/opencode-daily" OPENCODE_CONFIG="$HOME/.config/opencode-daily/opencode.json" opencode'
# Hard-task mode, also isolated
alias ocx-hard='OPENCODE_CONFIG_DIR="$HOME/.config/opencode-hard" OPENCODE_CONFIG="$HOME/.config/opencode-hard/opencode.json" opencode'
Run source ~/.zshrc, and now ocx-daily and ocx-hard are two separate agents with two separate brains.
When to use each mode
I use daily mode for almost everything: normal tickets, bounded bug fixes, test generation, ordinary implementation, repo investigation where ownership is fairly clear, small-to-medium cross-repo changes, docs, and operational updates.
I switch to hard mode when a wrong plan would cost more than the model run:
- unclear ownership across repos
- complex multi-repo changes
- security-sensitive work, such as auth, permissions, data migrations, or anything where “mostly right” is a future bug report
- difficult production bugs
- large refactors
- unclear tickets where the agent has to think before touching code
- final review before a risky change
- anything that has already failed once in daily mode
The practical rule: start in daily mode, then switch to hard mode when the task is unclear, cross-repo, high-risk, or already wasting your time.
Model mappings
Oh My OpenAgent splits work across named agents, such as orchestration, planning, implementation, review, and search. The two profiles assign different models to each one.
| Agent / category | Daily | Hard |
|---|---|---|
| sisyphus (main orchestration) | claude-sonnet-4.6 | claude-opus-4.8 |
| hephaestus (implementation) | gpt-5.3-codex | claude-sonnet-4.6 |
| oracle (planning) | gpt-5.4 | claude-opus-4.8 |
| prometheus (planning) | gpt-5.4 | claude-opus-4.8 |
| metis (synthesis) | gpt-5.4 | claude-opus-4.8 |
| momus (review/critique) | gemini-3.1-pro-preview | gpt-5.5 |
| librarian (search) | gpt-5.4-mini | gpt-5.4-mini |
| explore | gpt-5-mini | gpt-5.4-mini |
| atlas | gpt-5.4-mini | gpt-5.4 |
| designer | gemini-3.1-pro-preview | gemini-3.1-pro-preview |
| quick | gpt-5-mini | gpt-5.4-mini |
| unspecified-low | gpt-5.4-mini | gpt-5.4 |
| unspecified-high | claude-sonnet-4.6 | claude-opus-4.8 |
| writing | gpt-5.4-mini | gpt-5.4 |
| visual-engineering | gemini-3.1-pro-preview | gemini-3.1-pro-preview |
The important part: hard mode does not put the heaviest model on every role. Search and exploration stay cheap in both profiles, because high-volume utility work is exactly where you do not want to spend Opus tokens. Hard mode upgrades the roles where reasoning quality changes the result: orchestration, planning, synthesis, and review.
The configs
Each profile has an opencode.json that sets the base model, loads the plugin, and configures language servers.
Here is the daily version. The hard version is the same, except the base model is github-copilot/claude-opus-4.8.
{
"$schema": "https://opencode.ai/config.json",
"model": "github-copilot/claude-sonnet-4.6",
"plugin": ["oh-my-openagent"],
"lsp": {
"typescript": {
"command": ["/path/to/typescript-language-server", "--stdio"],
"extensions": [".ts", ".tsx", ".js", ".jsx", ".mts", ".cts", ".mjs", ".cjs"]
},
"eslint": {
"command": ["/path/to/vscode-eslint-language-server", "--stdio"],
"extensions": [".ts", ".tsx", ".js", ".jsx", ".mts", ".cts", ".mjs", ".cjs"]
},
"terraform": {
"command": ["/path/to/terraform-ls", "serve"],
"extensions": [".tf", ".tfvars"]
},
"json": {
"command": ["/path/to/vscode-json-language-server", "--stdio"],
"extensions": [".json", ".jsonc"]
},
"yaml": {
"command": ["/path/to/yaml-language-server", "--stdio"],
"extensions": [".yml", ".yaml"]
}
}
}
A note on the LSP paths. Use absolute paths here, and use your own. Run
which typescript-language-serverand similar commands to find them. Absolute paths matter because version-managed binaries, such as Volta, asdf, and nvm, are often available in your interactive shell but invisible to OpenCode’s subprocesses. Relative names will work until they suddenly do not.
The per-agent model assignments live in a separate plugin config.
Daily version:
{
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
"agents": {
"sisyphus": {
"model": "github-copilot/claude-sonnet-4.6",
"variant": "high",
"ultrawork": { "model": "github-copilot/claude-sonnet-4.6", "variant": "high" },
"fallback_models": [
{ "model": "github-copilot/gpt-5.3-codex", "variant": "high" },
{ "model": "github-copilot/gpt-5.4", "variant": "medium" }
]
},
"hephaestus": {
"model": "github-copilot/gpt-5.3-codex",
"variant": "high",
"fallback_models": [
{ "model": "github-copilot/claude-sonnet-4.6", "variant": "high" },
{ "model": "github-copilot/gpt-5.4", "variant": "high" }
]
},
"oracle": {
"model": "github-copilot/gpt-5.4",
"variant": "high",
"fallback_models": [{ "model": "github-copilot/claude-sonnet-4.6", "variant": "high" }]
},
"prometheus": {
"model": "github-copilot/gpt-5.4",
"variant": "high",
"prompt_append": "Prefer concise but complete plans. For cross-repo work, identify repo ownership, implementation order, risks, validation steps, and only then propose edits."
},
"metis": { "model": "github-copilot/gpt-5.4", "variant": "high" },
"momus": {
"model": "github-copilot/gemini-3.1-pro-preview",
"variant": "high",
"fallback_models": [{ "model": "github-copilot/gpt-5.4", "variant": "high" }]
},
"librarian": { "model": "github-copilot/gpt-5.4-mini" },
"explore": { "model": "github-copilot/gpt-5-mini" },
"atlas": { "model": "github-copilot/gpt-5.4-mini" },
"designer": { "model": "github-copilot/gemini-3.1-pro-preview", "variant": "high" }
},
"categories": {
"quick": { "model": "github-copilot/gpt-5-mini" },
"unspecified-low": { "model": "github-copilot/gpt-5.4-mini" },
"unspecified-high": { "model": "github-copilot/claude-sonnet-4.6", "variant": "high" },
"writing": { "model": "github-copilot/gpt-5.4-mini" },
"visual-engineering": { "model": "github-copilot/gemini-3.1-pro-preview", "variant": "high" }
},
"background_task": {
"providerConcurrency": { "github-copilot": 5 },
"modelConcurrency": {
"github-copilot/claude-sonnet-4.6": 3,
"github-copilot/gpt-5.3-codex": 3,
"github-copilot/gpt-5.4": 4,
"github-copilot/gpt-5.4-mini": 10,
"github-copilot/gpt-5-mini": 12,
"github-copilot/gemini-3.1-pro-preview": 2
}
},
"experimental": { "aggressive_truncation": true, "task_system": true },
"tmux": { "enabled": false }
}
Hard version: same structure, heavier models on the reasoning roles, variant: "max" where it matters, and tighter concurrency on the expensive models so you do not accidentally fan out five Opus agents at once.
{
"$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-openagent/dev/assets/oh-my-opencode.schema.json",
"agents": {
"sisyphus": {
"model": "github-copilot/claude-opus-4.8",
"variant": "max",
"ultrawork": { "model": "github-copilot/claude-opus-4.8", "variant": "max" },
"fallback_models": [
{ "model": "github-copilot/gpt-5.5", "variant": "high" },
{ "model": "github-copilot/claude-opus-4.8-fast", "variant": "high" },
{ "model": "github-copilot/claude-sonnet-4.6", "variant": "high" }
]
},
"hephaestus": {
"model": "github-copilot/claude-sonnet-4.6",
"variant": "high",
"fallback_models": [
{ "model": "github-copilot/gpt-5.3-codex", "variant": "high" },
{ "model": "github-copilot/claude-opus-4.8", "variant": "high" }
]
},
"oracle": {
"model": "github-copilot/claude-opus-4.8",
"variant": "max",
"fallback_models": [
{ "model": "github-copilot/gpt-5.5", "variant": "high" },
{ "model": "github-copilot/claude-opus-4.8-fast", "variant": "high" }
]
},
"prometheus": {
"model": "github-copilot/claude-opus-4.8",
"variant": "max",
"prompt_append": "Use deep planning. For hard cross-repo work, first map ownership, dependencies, control flow, risks, rollback strategy, and validation plan. Prefer correctness over speed."
},
"metis": {
"model": "github-copilot/claude-opus-4.8",
"variant": "max",
"fallback_models": [{ "model": "github-copilot/gpt-5.5", "variant": "high" }]
},
"momus": {
"model": "github-copilot/gpt-5.5",
"variant": "high",
"fallback_models": [{ "model": "github-copilot/claude-opus-4.8", "variant": "high" }]
},
"librarian": { "model": "github-copilot/gpt-5.4-mini" },
"explore": { "model": "github-copilot/gpt-5.4-mini" },
"atlas": { "model": "github-copilot/gpt-5.4", "variant": "high" },
"designer": { "model": "github-copilot/gemini-3.1-pro-preview", "variant": "high" }
},
"categories": {
"quick": { "model": "github-copilot/gpt-5.4-mini" },
"unspecified-low": { "model": "github-copilot/gpt-5.4" },
"unspecified-high": { "model": "github-copilot/claude-opus-4.8", "variant": "max" },
"writing": { "model": "github-copilot/gpt-5.4" },
"visual-engineering": { "model": "github-copilot/gemini-3.1-pro-preview", "variant": "high" }
},
"background_task": {
"providerConcurrency": { "github-copilot": 4 },
"modelConcurrency": {
"github-copilot/claude-opus-4.8": 1,
"github-copilot/claude-opus-4.8-fast": 2,
"github-copilot/gpt-5.5": 1,
"github-copilot/claude-sonnet-4.6": 3,
"github-copilot/gpt-5.3-codex": 3,
"github-copilot/gpt-5.4": 5,
"github-copilot/gpt-5.4-mini": 10,
"github-copilot/gemini-3.1-pro-preview": 2
}
},
"experimental": { "aggressive_truncation": true, "task_system": true },
"tmux": { "enabled": false }
}
One naming gotcha
Oh My OpenAgent is part-way through a rename. Both oh-my-opencode and oh-my-openagent appear across tooling and docs. To avoid the plugin reading from the wrong file, I keep identical copies under both names in each profile:
cp ~/.config/opencode-daily/oh-my-opencode.jsonc ~/.config/opencode-daily/oh-my-openagent.jsonc
cp ~/.config/opencode-hard/oh-my-opencode.jsonc ~/.config/opencode-hard/oh-my-openagent.jsonc
Belt and braces, but it costs nothing and avoids a confusing afternoon.
Why LSP is worth the trouble
The lsp blocks above are not decoration. Language servers give the agent structured code intelligence: go-to-definition, references, symbols, and diagnostics. Without that, it has to grep, read whole files, and guess.
For a typical JS/TS, Terraform, and config stack, this is the baseline I install:
npm install -g typescript typescript-language-server
npm install -g eslint vscode-langservers-extracted # provides eslint + json language servers
npm install -g yaml-language-server
brew install hashicorp/tap/terraform-ls
# fast, deterministic local search and structured inspection
brew install ripgrep fd jq yq
The payoff is mostly efficiency and fewer hallucinations: faster symbol navigation, fewer unnecessary file reads, real TypeScript diagnostics before and after edits, lint-aware implementation, and fewer invented imports, resource attributes, or config keys.
It works best with repo-level AGENTS.md files that document commands, package manager, important paths, and “do not touch” rules.
What this actually saves
This is the part people often get wrong. The two-profile split is not a 10x cost saving. When someone claims that, they have usually only timed search-heavy runs.
A more honest planning number is roughly 2x cheaper when daily mode is the default instead of running hard mode for everything. The realistic range is about 1.5x to 2.5x. It is not bigger because hard mode still uses cheap models for search and exploration, where much of the token volume lives. The savings mostly come from not burning Opus and GPT-5.5 on routine planning, synthesis, and review.
By workload type:
| Workload | Saving from daily vs hard |
|---|---|
| Mostly search, repo exploration, summaries | 1.1x to 1.4x |
| Normal implementation with some planning | 1.5x to 2.0x |
| Cross-repo investigation and planning | 2.0x to 2.8x |
| Review-heavy or synthesis-heavy work | 2.0x to 3.0x |
| Routine work that would otherwise trigger multiple heavy agents | 3.0x+ |
To measure it yourself, run the same prompt through both profiles and compare them with opencode stats. Track total token cost, input versus output tokens, tool calls, time to a useful answer, and how many human corrections you needed afterwards. That last one matters most:
saving factor = hard profile cost / daily profile cost
A cheaper run that produces a worse diff is not a saving. It is deferred cost. The point of hard mode is that, on the right task, the expensive run is the cheap option once you include your own time.
A few things that bit me
The profile keeps reading ~/.config/opencode instead of the isolated directory. Check that the alias exports both OPENCODE_CONFIG_DIR and OPENCODE_CONFIG. You can also bypass the alias with a one-off command:
OPENCODE_CONFIG_DIR="$HOME/.config/opencode-daily" \
OPENCODE_CONFIG="$HOME/.config/opencode-daily/opencode.json" \
opencode
npm i -g opencode-ai@latest “works”, but the version does not change. Your shell is probably resolving a binary at ~/.opencode/bin/opencode before the npm global. Check with which -a opencode, and use OpenCode’s own opencode upgrade instead.
The installer fails with failed to execute Bun: spawnSync bun ENOENT. The installer needs Bun. Run brew install oven-sh/bun/bun, then bunx oh-my-openagent install. Fall back to bunx oh-my-opencode install if the rename bites.
An old plugin version keeps loading from cache. Clear it:
rm -rf ~/.cache/opencode/node_modules/oh-my-openagent
rm -rf ~/.cache/opencode/packages/oh-my-openagent@latest
The operating model, in one line
Default to daily. Switch to hard when the task is unclear, cross-repo, high-risk, security-sensitive, or already wasting your time.
You get strong agent support all day without flinching at the bill, and you keep the most expensive reasoning for the work where a bad plan is the expensive outcome, not the model run.