---
name: Fusion Setup
slug: fusion-setup
category: AI Engineering
description: "Fusion Setup configures the opencode Fusion agent team in the user's global opencode config. Use it to install, reconfigure, or remove the main, sidekick, explore, and optional specialist agents."
github: "https://github.com/mihneaptu/opencode-fusion/tree/main/.opencode/skills/fusion-setup"
language: JavaScript
stars: 216
forks: 15
install: "npx degit https://github.com/mihneaptu/opencode-fusion/tree/main/.opencode/skills/fusion-setup ~/.claude/skills/fusion-setup"
installs_to: ~/.claude/skills/fusion-setup
source_path: .opencode/skills/fusion-setup/SKILL.md
collection_size: 1
category_size: 2970
added: 2026-09-04T05:25:40.889Z
last_synced: 2026-09-04T05:25:40.889Z
canonical_url: "https://dirskills.com/skills/fusion-setup"
---

# Fusion Setup

Fusion Setup configures the opencode Fusion agent team in the user's global opencode config. Use it to install, reconfigure, or remove the main, sidekick, explore, and optional specialist agents.

**Install:**

```bash
npx degit https://github.com/mihneaptu/opencode-fusion/tree/main/.opencode/skills/fusion-setup ~/.claude/skills/fusion-setup
```

## README

# Fusion setup

This skill configures the Fusion agent team (a main agent, a sidekick executor, an explore searcher, and optional specialists) by writing the user's GLOBAL opencode config at `~/.config/opencode/` (on Windows: `%USERPROFILE%\.config\opencode\`). It does not require cloning any repository.

opencode resolves that directory as `$XDG_CONFIG_HOME/opencode/` when `XDG_CONFIG_HOME` is set and non-empty, falling back to `~/.config/opencode/` otherwise. Every `~/.config/opencode/...` path below means that resolved directory. The bundled installer in Step 4 works this out itself, so the normal flow needs no special handling; only the manual fallback in Step 4b and the verification in Step 5 need you to resolve it by hand. Installing into `~/.config/opencode/` on a machine with a different `XDG_CONFIG_HOME` writes a tree opencode never reads - the install looks successful and Fusion silently never loads.

## What Fusion is

Fusion splits work across agents with asymmetric permissions:

- `build` (main, primary): a strong model that plans, makes judgment calls, and reviews. It CANNOT edit files, search the codebase, or run arbitrary shell. Its only path to changing files is delegating to the sidekick via the `task` tool.
- `plan` (primary): plan mode - the same planning brain as build. Produces a reviewed plan and delegates exploration, but does not execute; switch to build to carry it out. Overrides opencode's built-in plan agent so plan mode stays Fusion-aware.
- `sidekick` (subagent): a cheaper, fast model with full `edit` and broad `bash` access (direct `git commit`/`git push` and common wrappers are denied as defense-in-depth - committing stays with the main agent). It executes precise specs handed to it by the main agent.
- `explore` (subagent): a cheap model used for read-only codebase exploration.
- `research` (subagent): read-only external research - web search and docs. No edit access.
- `design` (subagent): frontend/UI implementation. Loads design skills, edits files, runs the dev/build tooling.
- `reviewer` (subagent): critiques a plan before implementation and audits a diff before commit (correctness, scope, security). Read-only plus lint/test; no edit access.
- `vision` (subagent): reads images/screenshots the main model cannot see and reports them as text. Only needed when the main model lacks image input.

Think of the repo as a catalog of roles: the core (build/plan/sidekick/explore) is required, and the rest are optional pieces you install only if your workflow needs them. The research/design/reviewer/vision specialists are optional. Each role's model is chosen independently - that is a key reason to use Fusion: put your favorite design model on `design` and a different reviewer model on `reviewer`.

The asymmetry is enforced by the permission layer, not by convention. Preserving the exact permission frontmatter in the bundled agent files installed during Step 4 is what makes Fusion work.

## Step 0 - Offer a subscription profile

Before the per-role interview, ask whether the user's models come from one of these subscriptions. Each maps to a bundled profile - a ready-made config fragment in `<this-skill-dir>/profiles/` with sane per-role defaults:

| Profile | Subscription |
| --- | --- |
| `opencode-go` | OpenCode Go (low-cost open-model plan on OpenCode Zen) |
| `opencode-zen` | OpenCode Zen pay-as-you-go credits |
| `opencode-zen-free` | OpenCode Zen free-tier models only |
| `chatgpt` | ChatGPT Plus or Pro |
| `github-copilot` | GitHub Copilot |

If the user names one (including as a `/fusion-setup` argument):

1. Read `<this-skill-dir>/profiles/<name>.json` and show its role -> model table for confirmation. The JSON is the single source of truth - never quote model ids from memory or from this document.
2. Remind them that authentication is out-of-band: the provider must be connected once via `opencode auth login` (or `/connect` inside opencode) with their subscription login or key. NEVER ask for a key in the chat. Profile provider blocks deliberately contain no npm adapter, baseURL, or apiKey - opencode knows these providers natively; the blocks only carry display names.
3. Skip Steps 1-3 and run the installer with the profile (Step 4's delegation rules still apply):

   ```bash
   node <this-skill-dir>/scripts/install.js apply --profile <name> --extras commands,plugin
   ```

   No `--roles` flag is needed: the installer derives the role list from the profile, so every role the profile assigns a model also gets its permission-bearing agent file.
4. To change one or two picks, keep `--profile <name>` and add `--config <fragment.json>` holding just the delta (for example a different `agent.reviewer.model`, plus a provider block only if that model's provider is outside the profile). The fragment wins over the profile. Removing an optional role a profile assigns cannot be expressed as an override - use the custom interview (Steps 1-4) without `--profile` instead.

Caveats worth mentioning when they apply: `opencode-zen-free` includes a `vision` role because its main model cannot read images, while the other profiles lead with models that read images directly; `opencode-zen-free` runs on free-period models whose prompts may be used for training under OpenCode's policy - warn users to keep sensitive code off it; the single-vendor `chatgpt` profile keeps every role on one vendor, so its reviewer differs from build by model (GPT-5.6 Terra) rather than by vendor - a user with a second provider may still want to override the reviewer for true cross-vendor review; `github-copilot` defaults its main to Claude Sonnet 5 for credit-cost sanity - a user who wants max quality can override build to `github-copilot/claude-opus-5` (billed much higher per token). There is deliberately NO Claude Pro/Max provider profile. A subscription login cannot become `agent.build.model`. If the user wants a limited Claude Pro/Max integration, offer the optional Claude Code review bridge below. Subscription lineups rotate - if a profile model errors as unknown, the ids may have drifted; fall back to the custom interview and report it.

### Optional Claude Pro/Max review through Claude Code

If the user asks for Claude subscription OAuth, keep another normal OpenCode provider or profile as the build model and offer the `claude` extra. It installs a local OpenCode plugin with two custom tools: a sanitized readiness check and a stateless plan review. Only the build and plan agents may call them.

The bridge invokes Anthropic's official `claude` CLI in print mode. It does not read the credential store, extract an OAuth token, put a token in `opencode.json`, or expose Claude as an OpenCode model. It verifies that `claude auth status` reports a first-party Pro or Max login, removes API-key and third-party routing variables from the child 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, or max per call), disables tools and customizations, sends the review packet over stdin, and disables session persistence. It runs the CLI from a neutral temporary directory, honors session cancellation, and its tools refuse callers other than the build and plan agents even before permissions apply.

Ask the user to install Claude Code and authenticate directly with `claude auth login`; never ask them to paste a token. On Windows they need the native Claude Code build (the installer script or `claude install`), not the npm shim - the bridge spawns `claude` without a shell. Then include `claude` in Step 4's extras, for example `--extras commands,plugin,claude`. Do not enable this by default. Anthropic describes subscription usage as intended for its native applications, including Claude Code, and says third-party-tool access may be allowed at its discretion or charged to usage credits. Present this as an optional compatibility bridge, not as a guaranteed subscription entitlement or an API replacement.

If the user has none of these subscriptions, or wants full control over every pick, continue with Step 1.

## Step 1 - Gather the user's model choices

Ask the user which model to use for each role. Do not assume; let them choose their own provider and models. Collect:

1. Main/build model (a strong model - e.g. an Opus/GPT-class model).
2. Sidekick model (a fast, cheaper coding model).
3. Explore model (cheap; can be the same as sidekick).
4. Research model (read-only external research; a solid general model).
5. Design model (frontend/UI work; pick whichever model does design best in your opinion).
6. Reviewer model (critiques plans and audits diffs; often a strong model, and deliberately can differ from the main model).
7. Vision model (reads images) - ONLY ask this if the user's main/build model does not support image input. Most frontier models read images directly, so skip this question unless the main model cannot. The vision model must be one that accepts image input.

Roles 4-7 are optional a-la-carte pieces. If the user only wants the core build/plan/sidekick/explore roles, skip them - but offer them, since choosing a different model per specialist is a key reason to use Fusion. The `plan` agent activates from its installed `agent/plan.md` (Step 4), which overrides opencode's built-in plan agent - it reuses the main/build model and needs no `agent.plan` block in opencode.json and no separate model question. Do not offer `vision` when the main model already reads images.

For each distinct provider the chosen models use, collect the connection details:
- provider id (e.g. `kiro`, `progrok`, `anthropic`, `openai`)
- the npm adapter (for OpenAI-compatible local gateways use `@ai-sdk/openai-compatible`)
- baseURL (for local gateways / custom endpoints)
- if the endpoint needs a key: the NAME of an environment variable that holds it (e.g. `MYPROVIDER_API_KEY`). NEVER ask the user to paste the actual key into the chat - the config references the variable and opencode resolves it at startup, so the secret never appears in the conversation or in plaintext config.
- the model id(s) and a display name

If the user is unsure, offer the OpenAI-compatible local-gateway shape as the default pattern and ask for their baseURL and key env var name.

## Step 2 - Build the provider blocks

For each provider, build a block under `provider`. OpenAI-compatible template:

```json
"<provider-id>": {
  "npm": "@ai-sdk/openai-compatible",
  "name": "<display name>",
  "options": {
    "baseURL": "<baseURL>",
    "apiKey": "{env:<ENV_VAR_NAME>}"
  },
  "models": {
    "<model-id>": {
      "name": "<display name>",
      "attachment": true,
      "modalities": { "input": ["text", "image"] }
    }
  }
}
```

The `{env:...}` placeholder is documented opencode config syntax: the key is read from the user's environment at startup, so it never sits in plaintext in opencode.json. An UNSET variable silently resolves to an empty string, which surfaces later as auth errors - tell the user to set the variable in the environment they launch opencode from. If they prefer a key file, `"apiKey": "{file:~/.secrets/<name>}"` works the same way.

Only include `attachment`/`modalities` for models that actually support image input. A main model with image input means no separate vision agent is needed.

The template above shows the OpenAI-compatible shape (`@ai-sdk/openai-compatible`). If a provider is a native vendor rather than an OpenAI-compatible gateway, use that vendor's adapter instead - for example `@ai-sdk/anthropic` for an Anthropic-style endpoint or `@ai-sdk/openai` for OpenAI. Only the `npm` value changes; the rest of the block shape is the same.

If two roles use different models from the SAME provider (for example a main model and a cheaper research model both on provider `kirocc`), do NOT emit two provider blocks with the same id - that is a duplicate key. Emit ONE block for that provider with BOTH models listed under its `models` object, like this:

```json
"kirocc": {
  "npm": "@ai-sdk/anthropic",
  "name": "Kirocc",
  "options": { "baseURL": "<baseURL>", "apiKey": "{env:KIROCC_API_KEY}" },
  "models": {
    "claude-opus-4-8": { "name": "Opus", "attachment": true, "modalities": { "input": ["text", "image"] } },
    "claude-sonnet-5": { "name": "Sonnet" }
  }
}
```

## Step 3 - Build the config fragment

Build a config FRAGMENT with this exact structure and save it to a temporary file (OS temp dir is fine). Do NOT write `~/.config/opencode/opencode.json` yourself - the installer script in Step 4 merges the fragment in deterministically. When running as the restricted Fusion build agent, delegate creation of the temporary fragment and the Step 4 installer command together in one sidekick task so build never needs direct filesystem access. In plan mode, stop after specifying the choices and tell the user to switch to build (or run the command themselves); plan must not execute the install. Replace the `<...>` placeholders with the user's choices. Model references are always `provider-id/model-id`. The JSON only assigns models - each role's mode, permissions, and prompt come from its agent file (Step 4), and the build agent's permission frontmatter is the core of Fusion and must not be loosened.

```json
{
  "$schema": "https://opencode.ai/config.json",
  "subagent_depth": 2,
  "model": "<main-provider>/<main-model-id>",
  "provider": {
    "<main-provider-id>": { "npm": "...", "options": {}, "models": {} },
    "<sidekick-provider-id>": { "npm": "...", "options": {}, "models": {} }
  },
  "agent": {
    "build": { "model": "<main-provider>/<main-model-id>" },
    "explore": { "model": "<explore-provider>/<explore-model-id>" },
    "sidekick": { "model": "<sidekick-provider>/<sidekick-model-id>" },
    "research": { "model": "<research-provider>/<research-model-id>" },
    "design": { "model": "<design-provider>/<design-model-id>" },
    "reviewer": { "model": "<reviewer-provider>/<reviewer-model-id>" }
  }
}
```

Notes:
- Keep `"subagent_depth": 2`. OpenCode 1.18.2+ defaults to `1`, which lets build start sidekick but prevents sidekick from starting its permitted read-only explore/research helper. The installer enforces a minimum of `2` and preserves a larger existing value.
- Replace the two `"<...-provider-id>": { ... }` placeholder lines under `provider` with the ACTUAL provider block(s) you built in Step 2. If your main and sidekick share one provider, that is a single block (see Step 2 on merging models); if they use different providers, include one block each. The placeholder shape shown is not valid config on its own - it must be filled in.
- opencode auto-loads every markdown file in `~/.config/opencode/agent/` as an agent definition: frontmatter supplies the role's `mode` and `permission`, and the body is its prompt. No `prompt` fields belong in opencode.json - Step 4 installs the files that carry them.
- Backup and merge are the installer's job (Step 4): it backs up any existing config to `opencode.json.backup.<timestamp>` and deep-merges the fragment - your fragment wins on conflicting keys, everything else in the user's config is preserved. Never silently discard an existing config: if the user explicitly wants a clean overwrite instead of a merge, they should move the old `opencode.json` aside first.
- Add `"vision": { "model": "<vision-provider>/<vision-model-id>" }` to the `agent` block ONLY if the user configured a vision role (main model lacks image input). Omit it otherwise.
- OPTIONAL top-level hardening keys (documented opencode fields; add if the user wants a tighter, cheaper, more private local setup):
  - `"small_model": "<cheap-provider>/<cheap-model-id>"` - opencode uses a small model for background tasks like title generation; if unset it may fall back to a remote default. Pin it to one of the user's own cheap local models to keep everything on their providers.
  - `"enabled_providers": ["<provider-a>", "<provider-b>"]` - allowlist of providers to load; keeps the model picker deterministic and ignores any other credentials present.
  - `"compaction": { "prune": true }` - drops stale tool outputs when compacting context, which cuts main-agent token cost in a delegation-heavy Fusion flow.
  - Per custom model, an optional `"limit": { "context": <n>, "output": <n> }` inside the model block lets opencode track remaining context accurately (models on models.dev supply this automatically; custom local gateways do not). Use the real context/output window for that model; do not guess.

## Step 4 - Run the deterministic installer

The skill bundles an installer at `<this-skill-dir>/scripts/install.js` (plain Node, no dependencies). It owns every mechanical step - timestamped backup, deep merge, atomic write, prompt-file copies, an undo manifest, and post-install validation - so none of that depends on improvised file operations. Its version-2 manifest stores the original bytes and permissions of every managed file, plus hashes of the exact installed state. Reapply and undo refuse before writing if the config or a managed file changed after installation; they never guess which content belongs to Fusion. Run it with the fragment from Step 3:

```bash
node <this-skill-dir>/scripts/install.js apply --config <path-to-fragment.json> --extras commands,plugin
```

- `--profile <name>` applies a bundled subscription profile (Step 0) as the base fragment; a `--config` fragment, when also given, overrides it key by key. Unknown profile names fail listing the available ones.
- `--roles` is normally omitted: the installer derives the list from the config - the core `build,plan,sidekick` plus every optional role the fragment or profile assigns a model (explore needs no file by design). An explicit `--roles` can add extra roles, but one that omits a role the config assigns a model is refused: a role with a model and no agent file would run without Fusion's permissions.
- `--extras commands,plugin` installs the optional slash commands and audit plugin described below. Add `claude` only when the user explicitly wants the Claude Code Pro/Max review bridge: `--extras commands,plugin,claude`.
- Add `--dry-run` to print the full plan (backup name, merged keys, files) without writing anything - offer this if the user seems cautious. The plan also prints an `OVERRIDES:` line naming any top-level key whose current value the fragment would replace.
- `--adopt-config` is for reapplying over an `opencode.json` the user edited by hand since the last install. Without it that mismatch refuses, which would otherwise wedge reapply permanently - including a prompt-only refresh whose managed files are all intact. The merge folds the fragment into the CURRENT file, so hand edits survive; the flag only re-records the baseline hash. The manifest keeps the pre-install `originalContent`, so a later undo still restores the true pre-Fusion state. It deliberately does NOT excuse a modified managed prompt: that refusal protects a deliberate local customization from being overwritten.
- The script refuses with exit 1 and changes nothing when validation or ownership checks fail, including invalid JSON/config shapes, unsafe paths, changed managed files, and invalid destination parents. It warns when a model references a provider that has no provider block.
- If the agent running this skill cannot execute bash (for example the Fusion build agent's allowlist), delegate both the fragment creation and this exact command to the sidekick. In plan mode, switch to build or have the user run it. Use the manual fallback below only when Node is unavailable.

### Manual fallback - install the agent prompt files by hand

Only when Node is unavailable. Before merging or copying anything, make a timestamped backup of `opencode.json` and of every destination file that already exists, and record which destinations did not exist. Then copy the prompt files bundled with this skill into the global agent folder
