A minimal, working multi-model team for opencode: a that plans and reviews but , delegating every change to a cheaper, faster . Inspired by the Devin Fusion "sidekick" pattern from Cognition.
概览
A minimal, working multi-model team for opencode: a that plans and reviews but , delegating every change to a cheaper, faster . Inspired by the Devin Fusion "sidekick" pattern from Cognition.
README
opencode-fusion
A minimal, working multi-model team for opencode: a main agent that plans and reviews but cannot edit files, delegating every change to a cheaper, faster sidekick. Inspired by the Devin Fusion “sidekick” pattern from Cognition.
The main agent’s file editing is mechanically denied. Its only way to change a file is to hand a spec to the sidekick. That keeps frontier intelligence on the decisions that matter (the plan, the interpretation of ambiguity, the review) while a cheap model does the mechanical work. Cognition reports the pattern holds frontier-level quality at roughly 35% lower cost on their own FrontierCode benchmark, and in a July 2026 follow-up measured a Fable 5-led setup at 54% below pure Fable 5 with near-identical quality: cheaper in absolute dollars than an Opus 4.8-led setup, despite Fable’s 2x per-token price.
The main pair is backed by read-only helpers (explore, research) and optional specialists (design, reviewer, vision), each on a model you choose. See the full team.
Quick start • How it works • Setup • Customize • FAQ • Troubleshooting
Demo
https://github.com/user-attachments/assets/6d9e96e2-654a-4bc4-82af-3c3f1a8bde91
One full delegation cycle in 38 seconds: the main agent plans, hands a spec to the sidekick, reviews the returned diff, and verifies the result, without ever touching a file itself.
Quick start
Install the setup skill globally, then let opencode configure everything conversationally:
npx skills add mihneaptu/opencode-fusion --skill fusion-setup -g -a opencode -y
set up fusion
The installer needs Node 20.12 or newer. On older Node (including Ubuntu’s apt default) it crashes with a styleText error; Troubleshooting has three workarounds. The skill interviews you for a model per role, writes the global config, installs the agent prompts, and tells you when to restart. On a subscription (OpenCode Go/Zen, ChatGPT, or GitHub Copilot)? Name it and the skill starts from a ready-made profile instead of asking per role. Manual setup and provider examples live in Setup.
That command tracks main. To install an exact release instead, add the tag: npx skills add mihneaptu/opencode-fusion#v1.1.0 --skill fusion-setup -g -a opencode -y. Released versions are listed on the changelog.
Why it works
From Cognition’s blog post:
We’ve found that the main agent should take minimal actions, and only read what is absolutely necessary. By default it should delegate and monitor, while making the significant decisions: the plan, the interpretation of ambiguity, the final review.
This repo turns that into a hard constraint: the main agent’s edit, search, and freeform bash tools are denied at the permission layer, so delegating to the sidekick is its only way to change a file. Two payoffs fall out of the split:
Lower cost. Implementation mechanics are most of a session’s tokens. A cheaper sidekick handles them at near-parity while the expensive main model spends its tokens only on judgment: the plan, the spec, the review. The main agent’s prompt enforces this discipline: emit judgment not volume, keep context lean, reason once then hand off. Cognition’s follow-up study bears this out: in 81% of Fable-led Fusion runs, the lead model never made a single code edit. That is the behavior this repo makes mechanical rather than advisory.
Cross-vendor review, for free. When the main agent and sidekick are different model families (for example Opus reviewing Grok), every diff gets an independent second-family read before it lands. Models from one family share blind spots; a reviewer from a different lineage catches what same-family review misses. You get this just by picking a main and sidekick from different vendors.
How it works
The diagram shows one delegation cycle: the main agent delegates exploration, plans from what comes back, hands the sidekick a spec, reviews the returned diff, loops until it passes, then delivers the result.
| Agent | Role | Config key | Required | Suggested model (2026) |
|---|---|---|---|---|
build |
Main: plan, delegate, review | agent.build.model |
core | claude-opus-5 |
plan |
Plan mode: same brain as build, plans but does not execute | agent/plan.md (file) |
core | reuses main model |
sidekick |
Execute edits and commands | agent.sidekick.model |
core | grok-4.5 |
explore |
Fast read-only exploration (opencode’s built-in agent; no prompt file) | agent.explore.model |
core | deepseek-v4-flash |
research |
Read-only external research (web, docs) | agent.research.model |
optional | claude-sonnet-5 |
design |
Frontend/UI implementation | agent.design.model |
optional | kimi-k3 |
reviewer |
Critique a plan before implementation; audit a diff before commit | agent.reviewer.model |
optional | gpt-5.6-sol |
vision |
Transcribe images the main model cannot see | agent.vision.model |
optional | gemini-3.6-flash |
Models move fast. Treat these as 2026 starting points, not requirements. Use any provider you like; in config each model is written as provider/model-id (for example openai/gpt-5.6-sol), and the sidekick should stay cheaper and faster than the main agent. The mix above spans several vendors on purpose, so the main agent’s review of each sidekick diff is cross-vendor. If a subscription covers your models, a profile fills this table in for you.
Enforced vs. advised
The pattern’s guarantees live in two different layers, and being precise about which is which answers most “what if the model just ignores the instructions?” questions.
Enforced: the permission layer. opencode checks these on every tool call, no matter what the model reads, remembers, or intends:
- The main agent’s
edit,grep,glob, andlistare denied. Denied tools are removed from the model’s tool schema entirely; there is no edit tool for it to decline to use. - Its bash is deny-by-default with a short verification and git allowlist, so file-writing commands are blocked.
git commitandgit pushadditionally require per-command user approval; common direct force/mirror/delete/prune forms are denied by later rules. - Direct
git commitandgit pushinvocations plus common Git wrapper forms are denied for the sidekick and design agents, making review-then-commit the normal enforced path. - Delegation is bounded by an explicit
taskallowlist: the main agent reaches only its named specialists, and the sidekick can spawn only read-only searchers.
If the main agent “won’t delegate,” the result is visible inaction: nothing on disk changes. The failure mode is never a silent bypass.
Advised: the prompt layer. Spec precision, diff-review rigor, cost discipline, parallelization, and skill usage are instructions in the agent prompts. opencode loads skills at the model’s discretion (nothing can force an agent to read or apply one), which is exactly why no guarantee here depends on them; the skill in this repo is just the installer. If the model slacks at this layer, the cost is quality or wasted tokens, never an unauthorized edit.
Not guaranteed: the threat model. The permission layer bounds which tools each agent can call. It is not a sandbox, and it is worth being precise about what it does not protect:
- The
.envdenies on the executors stop the common accidental read (cat .envlanding a key in a transcript), not a determined one. An agent with broad bash has many equivalent ways to read a file or the process environment, so treat those rules as accidental-leak prevention, not secret isolation. The{env:VAR}config syntax keeps keys out of plaintext config and out of the chat; it does not hide them from the environment agents run in. - Git command rules match command text and are defense-in-depth, not a shell sandbox: wrappers, alternate executables, or obfuscation can bypass a finite pattern list when an executor has broad bash. They protect against common accidental commits and destructive pushes, not a hostile process. Editing files is the sidekick’s job, and catching a wrong edit is what the main agent’s diff review (and the optional reviewer) are for.
- The design agent’s path-aware opencode tools are fenced to the workspace (
external_directory: deny), but processes launched through broad bash are not OS-sandboxed by that rule. The sidekick keeps opencode’s defaultaskfor paths outside the project, because setup and reconfigure legitimately write the global config. Note that--automode auto-approvesaskrules, so use external sandboxing too if an executor must never leave the repo.
Auditable: verify instead of trusting. The optional fusion-audit plugin logs the delegation tree, and opencode’s session DB records every agent’s actual tool calls (opencode db path prints its location, typically ~/.local/share/opencode/opencode.db). “Did it really delegate?” is checkable ground truth, not vibes.
Setup
Fusion lives entirely in your global opencode config at ~/.config/opencode/ (Windows: %USERPROFILE%\.config\opencode\). There is no build step and nothing to clone into your projects.
Recommended: let opencode set it up
This repo ships a skill, fusion-setup, that configures everything conversationally. Install it globally (Node 20.12+):
npx skills add mihneaptu/opencode-fusion --skill fusion-setup -g -a opencode -y
Or copy the fusion-setup folder from this repo’s .opencode/skills/ into ~/.config/opencode/skills/. Skills are discovered on demand; no restart is needed to pick one up. Then say:
set up fusion
It asks which model and provider you want for each role, writes ~/.config/opencode/opencode.json, installs the agent prompts under ~/.config/opencode/agent/, and tells you to restart. The mechanical steps (timestamped backup, config merge, atomic write, file copies, validation, and undo) run through a small deterministic script bundled with the skill, so the sensitive part of setup does not depend on model compliance. To change models later, say “reconfigure fusion” or edit the config directly (see Customize); “undo fusion” restores the recorded backup and removes exactly what was installed.
Subscription profiles
If your models come from a subscription, skip the per-role interview: name the subscription during setup (or run /fusion-setup opencode-go) and the skill applies a bundled profile: a ready-made role-to-model mapping the installer merges like any other config fragment. Directly: node /scripts/install.js apply --profile --extras commands,plugin.
| Profile | Subscription | Main / sidekick | Beyond the core roles |
|---|---|---|---|
opencode-go |
OpenCode Go | Kimi K3 / DeepSeek V4 Flash | research, design, reviewer |
opencode-zen |
OpenCode Zen pay-as-you-go | Claude Opus 5 / GPT-5.6 Luna | research, design, reviewer |
opencode-zen-free |
OpenCode Zen free-tier models | Big Pickle / MiMo V2.5 Free | vision |
chatgpt |
ChatGPT Plus or Pro | GPT-5.6 Sol / GPT-5.6 Luna | reviewer |
github-copilot |
GitHub Copilot | Claude Sonnet 5 / GPT-5.6 Luna | research, reviewer |
Authentication stays out-of-band: connect the provider once with opencode auth login (or /connect inside opencode). Profiles contain no keys, adapters, or endpoints (opencode knows these providers natively), and the skill never asks for a key in chat. To adjust a pick, keep the profile and add a small override fragment (--profile --config ; your fragment wins on conflicts).
Five notes. opencode-zen-free includes a vision role because its main model cannot read images; the other profiles lead with models that read images directly. opencode-zen-free runs on free-period models (Big Pickle is a stealth model). OpenCode’s policy allows prompts to be used for training while a model is free, so keep sensitive code off this profile. The single-vendor chatgpt profile keeps every role on one vendor - its reviewer runs a different model (GPT-5.6 Terra) than the main agent, but a user with a second provider still gets a stronger check by overriding the reviewer across vendors; github-copilot defaults to Claude Sonnet 5 as the main for credit-cost sanity; override agent.build.model to github-copilot/claude-opus-5 if you want max quality and accept the burn rate. opencode-go leads with Kimi K3, the tightest model in that lineup: Go meters in dollars, so K3’s share of the cap works out to roughly 110 requests per 5h against GLM 5.2’s 880 - point agent.build.model at opencode-go/glm-5.2 if you hit that. There is no Claude Pro/Max provider profile: a Claude subscription login cannot be placed in opencode.json or exposed as agent.build.model. The optional bridge below can ask the official Claude Code CLI for a constrained plan review. Subscription lineups rotate; npm run check-profiles verifies every shipped id against models.dev, and CI runs it on each push.
Optional Claude Pro/Max plan review
The claude installer extra adds a small OpenCode plugin that invokes the official Claude Code CLI. It gives the Fusion build and plan agents two custom tools: fusion_claude_status and fusion_claude_review. Claude receives only the self-contained plan packet that Fusion sends. It cannot inspect the workspace, use tools, edit files, continue the session, or become the main model.
- Install Claude Code and run
claude auth loginyourself with a Pro or Max account. On Windows use the native build (the installer script orclaude install): the bridge launchesclaudewithout a shell, which the npmclaude.cmdshim does not support. - Run the Fusion installer with your normal OpenCode profile or config and add the extra:
--extras commands,plugin,claude. - Fully quit and restart OpenCode. Ask Fusion to check
fusion_claude_status, or say: “Have Claude review the plan before implementation.”
The plugin never reads or copies Claude’s stored OAuth token. Before every review it checks for a first-party Pro/Max login, removes API-key and alternate-provider routing from the Claude process, defaults to claude-opus-5 at high effort (the review tool accepts an optional full claude-* model id and an effort of low/medium/high/xhigh/max per call), uses Claude Code print mode, disables tools and customizations, and turns off session persistence. Reviews run from a neutral temporary directory rather than your workspace, and the tools refuse any caller other than the build and plan agents at runtime, so even a hand-copied plugin without the installer’s global deny serves no other agent. OpenCode denies these tools globally and grants them only to the build and plan agents through custom-tool permissions.
This remains an optional third-party integration. Anthropic says subscription usage is designed for its native applications, including Claude Code, and that some third-party-tool access may be allowed at its discretion or charged to usage credits. The bridge does not misrepresent itself or convert OAuth into an API credential, but it is not a promise that subscription access or billing behavior will never change.
Verify it works
Open a project with some lint errors and ask:
fix the lint errors in this project
You should see the main agent delegate exploration, receive the findings, make a plan, then delegate execution to the sidekick via the task tool. The sidekick makes the edits, and the main agent verifies by running npm run lint itself before reporting back.
[!NOTE] Along the way you may see the occasional command struck through with a permission error (for example the agent trying
git ls-files). That is not a bug. The main and plan agents run bash deny-by-default, so anything outside their short allowlist is mechanically blocked, and the agent recovers on its own by reading the file or delegating the search. A denied command is the guardrail working, not the setup failing.
Customize
Swap models
All agent models live in one place: ~/.config/opencode/opencode.json under agent, one model value per agent (keys and suggested models are in the table above).
Change the value, add a provider block if the model uses a new provider, and restart opencode. For a persistent default main model, also update the top-level model field. The sidekick should stay cheaper and faster than the main agent when possible.
Editing this file by hand is fine and loses nothing, but the installer records a hash of what it wrote, so the next reapply refuses once to make the mismatch visible. Re-run it with --adopt-config to accept your edited file as the new baseline; the fragment still merges into your current file rather than replacing it, and undo still restores the true pre-Fusion state. Reaching for “reconfigure fusion” instead keeps the manifest accurate without that step.
[!WARNING] Do not add a
model:line to the agent.mdfiles themselves: frontmatter overridesopencode.jsonon any key it sets, so a model baked in there would silently win over your config.
[!TIP] Run
/modelsin opencode to swap the active model for the current session only.
Adjust the bash allowlist
The main agent’s bash is allowlisted to verification and git commands (npm run lint, npm test, git diff, git status, git log, git show, git add); git commit and git push prompt for per-command approval, and force/mirror/delete-ref pushes are denied. Edit the installed ~/.config/opencode/agent/build.md to add or remove allowed commands in the permission.bash section. Keep "*": "deny" first so unlisted commands are blocked by default, and keep the specific push denies after "git push*"; opencode resolves overlapping patterns by last-match-wins. Note that the allowlist matches each command in a chained line separately and denies the call if any one of them fails to match, so a chain is only as allowed as its least-allowed segment. git status && git log runs when both are allowlisted; git status | head does not, because the pipe consumer counts as its own command and head is not on the list. The agent prompts tell the agents to run one command per call anyway, so a denial names the command that caused it.
[!IMPORTANT] The shipped verification commands assume a Node/JavaScript project. The git half of the allowlist is universal, but the JS entries only exist in a JS toolchain. On any other stack the main agent cannot run your tests, and you will see it denied on the command you expect it to use.
Each role ships its own subset, so check the file you are editing rather than assuming all three match:
Entry build.mdplan.mdreviewer.md"npm run lint*"yes yes yes "npm test*"yes yes yes "npx vitest run*"yes yes yes "npx tsc --noEmit*"yes yes no "npm run build*"yes no no (
build.mdalso allows"npm --version*", a read-only probe that needs no per-stack equivalent.)Replace the entries the file actually has, keeping
"*": "deny"first. These name the tool per stack; the exact pattern is yours to write, and the next paragraph is the part that matters:
Stack Verification tools Python pytest,ruff check,mypyRust cargo test,cargo clippy,cargo checkGo go test,go vetMake-driven make test,make lintPrefer an exact pattern over a trailing
*. A trailing*matches the entire rest of the command, so"ruff check*"also permitsruff check --fixandruff check --add-noqa, both of which rewrite your source."go test*"permits-o,-exec, and the-coverprofilefamily, all of which write files. Enumerating those flags as denies is a losing game - every tool keeps adding more. If you can pin the command your project actually runs ("pytest","make test","cargo test --workspace"), do that and skip the wildcard. Reach for*only where you genuinely need to pass varying paths, and then read your tool’s flag list before you paste it.Denies narrow an allow you cannot avoid making broad, the way the shipped list denies
npm run lint --fixandnpx vitest run -u. Put each deny after the allow it narrows: opencode resolves overlapping patterns by last-match-wins, so a deny above its allow is silently overridden. Treat the deny as a backstop, not the primary control - the tight allow is the control.The shipped JS entries are that unavoidable case, which is why they look like the thing this section tells you to avoid.
npm testandnpm run linttake project-specific arguments (a path,--workspace, a-tfilter), so pinning them exactly would deny the run you actually want; the trailing*stays and the denies below it carry the weight. Where your own command takes no varying arguments, you get the tighter option and should use it.Keep the commands read-only or idempotent. The point is that the main agent can verify without being able to mutate, so a formatter that rewrites files (
ruff format,cargo fmt,gofmt -w) belongs with the sidekick, not here. For the same reasongo buildand abuildMake target are absent above:go buildwrites an executable, and a Make recipe does whatever the project defined it to do - atesttarget that regenerates fixtures is a write, whatever it is called. Read the recipe before allowing it.One more thing worth knowing: these prompts install globally to
~/.config/opencode/agent/, not per project. If you work across several stacks with one opencode install, add your stack’s entries alongside the JS ones instead of replacing them - otherwise the next Node project you open cannot verify itself.
[!NOTE] Editing an installed prompt makes it yours. The installer records a hash of every file it writes, and a reapply refuses rather than overwrite a file that changed - deliberately, so your customization is never silently clobbered. There is no
--adoptoverride for prompts (unlikeopencode.json). To hand the file back to the installer, restore the bundled copy from.opencode/skills/fusion-setup/agent/first. Keep a note of your edit either way, since a reapply that does succeed installs the bundled version.
Uninstall
Say undo fusion, or run the bundled installer directly:
node /scripts/install.js undo
It restores opencode.json to its exact pre-install bytes, removes only the files Fusion created, restores any it replaced, and keeps every backup. If you hand-edited an installed prompt or the config afterwards, it refuses and names the conflict rather than overwriting your work. Restart opencode when it finishes.
Undo is all or nothing - there is no switch that suspends Fusion for a session. And since build and plan replace opencode’s built-in primaries, out of the box there is no unrestricted primary to fall back to either.
Escape hatch
If you want one, create ~/.config/opencode/agent/normal.md:
---
description: Unrestricted primary - plain opencode, no Fusion permissions
mode: primary
---
You are a standard opencode agent with no delegation requirements.
Restart once, then Tab cycles through the primary agents mid-session. Leave out the model key and it follows your top-level default. The installer never manages this file, so undo and reapply leave it alone.
This does not weaken the split: switching primaries is a keybind you press, not a tool the main agent can call. Two caveats:
- No guardrails at all, not just no delegation. It inherits opencode’s defaults, so destructive shell commands the sidekick would ask about run without a prompt.
- The transcript is shared between primary agents. After switching, the new agent reads earlier turns as its own - expect
buildto apologise for a direct edit the escape hatch made. Start a fresh session if that matters.
Limitations
- No dynamic mid-session routing. Devin Fusion’s second technique, swapping the active model mid-task during context compaction, needs Devin’s closed product surface and is not possible in opencode. This repo implements the sidekick pattern only; model assignments are fixed per role at startup. It is an explicit non-goal, not a missing feature.
- Config loads at startup. opencode reads config once when it launches. Any change to
opencode.jsonor an agent prompt requires a full restart to take effect. - Loop protection has two layers.
subagent_depth: 2caps Fusion at the required main -> executor -> read-only helper chain. Thetaskpermission graph independently controls which named agents each role may launch, so allowing the second level does not expose arbitrary subagents. - Targets opencode 1.x. These files are written against opencode’s stable 1.x config schema (verified on 1.18.x). The opencode 2.0 beta (
opencode2) has its own native schema (pluralagents, array-basedpermissions), but it reads the same config locations and translates v1-shaped configuration in memory without rewriting the file. So the Fusion config and agent prompts are expected to load underopencode2unconverted, and opencode treats a v1 file that stops working as a beta compatibility bug. Three things are genuinely not carried over:- The optional plugins will not work. The plugin API is one of v2’s three intentional breaking changes, and the docs are explicit that V1 plugins do not run in V2.
fusion-auditandfusion-claudeare V1 plugins, so the delegation log, the token accounting, and the Claude bridge are unavailable there until they are ported. Nothing enforced depends on them. - Three top-level keys have no native v2 equivalent:
small_model(v2 picks its own maintenance models),enabled_providers, andsubagent_depth. v2 bounds delegation depth with per-agentsubagentdeny rules instead of a global number. - Subagents do not inherit the parent’s permissions. v2 states that a custom subagent runs with its own permissions rather than a subset derived from its caller. Every Fusion role with a prompt file sets its own permissions explicitly, so this changes nothing here;
exploreis opencode’s built-in and carries whatever read-only policy your version ships. It matters if you hand-roll a narrower executor and expect it to inherit a caller’s limits.
- The optional plugins will not work. The plugin API is one of v2’s three intentional breaking changes, and the docs are explicit that V1 plugins do not run in V2.
FAQ
Troubleshooting
Slash commands and optional plugins
Files
Built with opencode-fusion
This repo was configured using the Fusion pattern itself. The main agent planned the structure, reviewed every change, and verified against real command output. The sidekick wrote the files and ran the commands. Every change went through the flow above.
Disclaimer
This project is not affiliated with, endorsed by, or built by the opencode team. opencode is a separate project by Anomaly. This repo provides configuration that works with opencode but is not part of it.
Credit
Inspired by Devin Fusion by Cognition: the “sidekick” framing, the principle that “the main agent should take minimal actions”, and the benchmark numbers quoted in this README are theirs, from the launch post and the July 2026 follow-up, “Making Fable Cheaper Than Opus”. The underlying split has older roots. Aider’s architect/editor mode separated code reasoning from code editing back in 2024: one model describes the solution, a second turns it into clean edits. The permission-layer enforcement, the cross-vendor review setup, and the specialist team are this repo’s own.
推荐工具
换一个关键词,或者移除筛选条件。
安装
npx skillfish add mihneaptu/opencode-fusion