Everyone is pointing Claude Code at their ChatGPT subscription this week. The recipe going around is Tibo’s claudex thread, 5,117 bookmarks in under a day: CLIProxyAPI in the middle, an alias carrying four env vars, and the orange crab speaks GPT-5.6 Sol. His version closes with “if this gets blocked, I owe you a reset.” It works, and I understand the pull of keeping the harness you know. But the proxy is scaffolding around a tool that was never asked to do this, and there is a shorter path: opencode signs into ChatGPT Pro/Plus natively with a device code, serves the whole 5.6 family on the sub with no middleman to get blocked over, and its agent config does what the alias cannot: subagents as plain config entries, a thinking tier pinned per subagent, parallel fan-out through the task tool.
Two config files let Fable 5 or GPT-5.6 Sol orchestrate workers on six other stacks: Composer and Grok on Cursor’s serving, Opus 4.8 over the claude CLI, Gemini Flash through Antigravity, Codex Cloud, Ollama, plus Sol’s own family fanned out at pinned thinking tiers. One model call per dispatch. Every token rides a flat-rate subscription, with my ~$400 of API credits left untouched. Both configs are in this post, every flag in them is verified against the live CLIs, the beta bug that eats isolated worktrees is filed with logs, and the whole pattern installs as a skill in one command if you want it without Brigade.
Proof it holds together: last night a Sol session polled six workers with the same question, “state your exact model name and your reasoning tier,” and compiled the answers into a table without writing a single file itself. Four of the workers were Sol and Terra at pinned thinking tiers, dispatched in parallel through opencode’s task tool. Two came back through Brigade: “I am Cursor Grok 4.5 (jointly trained by SpaceXAI and Cursor), running at a high reasoning/thinking tier” and “I am Composer (Cursor’s agent model).” The Fable side of the chart verified the same way: a Claude Code session fanned Haiku 4.5, Sonnet 5, and Opus 4.8 out as native subagents in parallel, 1.8 to 3.7 seconds each, pulled the same two Brigade seats through --worker, and then dispatched GPT-5.6 Sol itself through the opencode seat: “My exact model name is GPT-5.6 Sol.” The two harnesses point at each other. Whichever one you live in orchestrates, and the other becomes a seat.
The auth constraint came before any of the orchestration. Five subscriptions serve models here: ChatGPT (Codex OAuth), Cursor Ultra, Claude, Grok via X Premium+, and a Google account that Antigravity rides. So the rule going in: every seat shells out to a CLI that authenticates as me, and nothing holds a provider key.
The two pieces
The stack is two configs. An opencode agent file gives Sol its brain and its OpenAI-family subagents. A Brigade roster gives it hands on every other vendor.
Opencode’s ChatGPT login is a device-code flow (opencode auth login, pick OpenAI, then ChatGPT Pro/Plus), and once the credential exists, openai/gpt-5.6-sol and friends serve on the subscription. The part I did not expect: per-agent thinking tiers work in the stable release through a plain options block. I found the supported values by getting them wrong. Pin reasoningEffort: "minimal" and the error names the menu:
Error: Unsupported value: 'minimal' is not supported with the
'gpt-5.6-sol' model. Supported values are: 'none', 'low',
'medium', 'high', and 'xhigh'.
So the opencode.json at the project root defines the chef and a subagent per tier:
{
"$schema": "https://opencode.ai/config.json",
"agent": {
"chef": {
"mode": "primary",
"model": "openai/gpt-5.6-sol",
"prompt": "You are the chef, an orchestrator. You never answer worker questions yourself. For OpenAI-family models use your native subagents via the task tool. For any other vendor dispatch through Brigade with bash, one run at a time: brigade run --worker <seat> --allow-dirty \"<task>\". Synthesize all results faithfully.",
"options": { "reasoningEffort": "high" },
"tools": { "write": false, "edit": false, "patch": false }
},
"sol_none": { "mode": "subagent", "model": "openai/gpt-5.6-sol", "description": "GPT-5.6 Sol, thinking=none", "options": { "reasoningEffort": "none" } },
"sol_high": { "mode": "subagent", "model": "openai/gpt-5.6-sol", "description": "GPT-5.6 Sol, thinking=high", "options": { "reasoningEffort": "high" } },
"sol_xhigh": { "mode": "subagent", "model": "openai/gpt-5.6-sol", "description": "GPT-5.6 Sol, thinking=xhigh", "options": { "reasoningEffort": "xhigh" } },
"terra_high": { "mode": "subagent", "model": "openai/gpt-5.6-terra", "description": "GPT-5.6 Terra, thinking=high", "options": { "reasoningEffort": "high" } }
}
}
Note the chef’s tool block. Write, edit, and patch are off. The chef thinks, dispatches, and runs brigade run over bash. It cannot touch a file. That is not paranoia for its own sake, and I will get to why in a minute.
The second piece is the Brigade roster, ~/.brigade/roster.toml. Each seat names a CLI adapter and a model, and Brigade shells out to the tool you already logged into:
[agents.sol]
cli = "opencode"
model = "openai/gpt-5.6-sol"
role = "Frontier reasoning worker on the ChatGPT subscription."
[agents.composer]
cli = "cursor"
model = "composer-2.5"
role = "Fast first-pass implementation."
[agents.grok]
cli = "cursor"
model = "grok-4.5-xhigh"
role = "Alternate implementation and research worker."
[agents.claude]
cli = "claude"
model = "claude-opus-4-8"
role = "Cross-model reviewer and polish worker."
[agents.cloud]
cli = "codex-cloud:brigade"
role = "Long-running work dispatched to Codex Cloud; returns an unapplied diff."
[agents.flash]
cli = "antigravity"
model = "Gemini 3.5 Flash (Low)"
role = "Fast cheap worker for research, summaries, and scans."
[agents.local]
cli = "ollama:deepseek-v4-flash:cloud"
role = "Local-stack researcher."
[limits]
allow_models = ["codex", "cursor", "grok", "claude", "opencode", "codex-cloud:*", "antigravity", "ollama:*"]
A note on the claude seat first: it runs Opus 4.8, a heavier model than the orchestrator, and that inversion is deliberate. Cross-model review wants the strongest available skeptic, and the chef costs nothing extra by dispatching up. The same seat answers as Fable 5 if you point it there, which I verified and do not particularly recommend: a 5.6 chef sending work up to a Mythos-class model is a fun identity poll and a strange division of labor.
Three seat choices worth defending. Grok rides the cursor adapter, grok-4.5-xhigh, because Cursor Ultra is flat-rate and the grok CLI meters against the X Premium+ allowance. Same model, cheaper serving. The codex-cloud:brigade seat is Brigade’s newest adapter: it submits the task with codex cloud exec, polls to a terminal state, and returns the diff without applying it. My smoke test went submit to [READY] to a one-file diff in 52 seconds, and landing it stays a deliberate codex cloud apply <task-id>.
And the Antigravity seat earns more than the one line it gets in the roster. The agy CLI rides a Google account that none of the other four subscriptions touch, its model pin is the full display string, parentheses included, and its --sandbox flag is a real read-only jail rather than a prompt-level suggestion. The same CLI serves Claude Sonnet 4.6 with thinking, which scored a matching 100 on the code tasks, so there is a Claude-quality review seat here that spends zero Claude-subscription quota. It also reads images. I handed it a PNG of a broken TUI and it quoted the status-line error back verbatim, slug and retry count included, which makes it the one seat in the roster that can triage a screenshot. Its quota meter resets daily at 3:44 AM, and a 65-call benchmark burst never touched a throttle. The one Antigravity model to skip is GPT-OSS 120B: shared pool, and most calls bounce off a high-traffic error.
The bridge between the two configs shipped this week as brigade run --worker. Before it, an external orchestrator had to prompt Brigade’s own chef with “dispatch ONLY the composer worker,” which cost a plan round and a synthesis round on top of the actual work: three model calls to ask one model one thing. Now:
$ brigade run --worker grok --allow-dirty "which model are you?"
artifacts: .brigade/runs/20260712-135445-7d65954d
I am Cursor Grok 4.5 (jointly trained by SpaceXAI and Cursor), running at a high reasoning tier.
One call in, one answer out, no chef in the middle. The seat is the unit of dispatch now, which is what makes Sol’s fan-out cheap: six workers polled, six model calls, not eighteen.
Take the skill, skip the framework
If a roster file is more adoption than you want, the dispatch table stands alone. I shipped it today as stagiaire in skillet, and it installs into any SKILL.md-compatible harness:
# Claude Code, via the plugin marketplace
/plugin marketplace add escoffier-labs/skillet
# or any harness, via the skills CLI
npx skills add escoffier-labs/skillet
A stagiaire is a cook visiting from another kitchen, and that is the whole skill: your agent learns to dispatch one-shot workers on other vendors’ CLIs over your own logins. It carries the exact headless argv for each of the eight CLIs in this post, write-capable and read-only forms both, plus the silent-failure trap each one hides: cursor’s exit-0 trust refusal, grok’s approval stall, codex’s non-git refusal, agy’s 5-minute print clock, opencode’s wrong-project escape. The write-disabled-chef config from earlier ships inside it as the orchestration template. Same pattern, zero Brigade. And its last rule is the honest one: once dispatches become routine, that is a roster, and brigade run --worker replaces every incantation with one flag.
The escape that cost me a version
The harness that produced the benchmark numbers below runs each model in its own throwaway git copy under /tmp, so nothing a worker does can reach the real tree. Opencode’s v2 beta broke that promise. A worker launched with its cwd set to the copy would sometimes open a second instance rooted at a different registered project and edit files there instead. Its own copy stayed clean. The run reported success.
I caught it because a canonical benchmark file kept changing when no worker should have touched it. The logs showed one run id creating two instances, one at the copy and one at the suite root:
run=c0e1d15a "creating instance" directory=/tmp/work/t2/seat-a # its own copy
run=c0e1d15a "creating instance" directory=~/suite # someone else's project
It happened three times in about ten sweeps, and it kept happening with the copies moved to /tmp and the runs forced sequential. I filed it as anomalyco/opencode#36498 with the log evidence.
Then I rolled back to the stable release, 1.17.18, and ran the isolation repro seven times. Seven clean. The edit landed in the copy every time, the registered project stayed untouched every time. The escape is a v2-beta regression and stable does not carry it. Same ChatGPT credential, same gpt-5.6 models, same per-agent thinking tiers. The write-disabled chef in the config above is the belt to that suspenders: even if a regression comes back, the one opencode process with a real working directory cannot write a byte. Every file mutation goes through a Brigade seat, and those are separate CLIs the bug never reached.
The escape was the expensive lesson, but the full v2 ledger is longer, and anyone attempting this stack should walk in with it:
- Workers can edit a different registered project (anomalyco/opencode#36498). The story above. Two details for whoever debugs it: the daemon logs a
project copy refreshpass on boot, which smells like copied trees getting fingerprint-matched back to their original project, and a cold single run with the identical layout behaves, so warm daemon state is an ingredient. gpt-5.6-lunanever answers (anomalyco/opencode#36140). Root cause per that thread: Codex marks Lunaminimal_client_version: 0.144.0withuse_responses_lite: true, and opencode admits the model through its OAuth filter but sends its normal Responses request. On dev builds that surfaces as HTTP 404. On the beta it is worse: the TUI shows the request going out as an internal slug,gpt-5.6-luna-free-1p-codexswic-ev3, failing, and retrying without a bound (#21960 covers the unbounded retry policy), whileopencode runprints nothing at all. Two of my benchmark jobs sat at a 900-second timeout with empty stdout before I caught it. Luna works through the Codex CLI, through Cursor, and through pi on the same account, so route it through any of those as a Brigade seat, never as an opencode-native subagent.--continuelies about the agent (anomalyco/opencode#36499). Continue a session started with a custom primary agent and the banner names the defaultbuildagent while the custom agent’s prompt demonstrably keeps running. Cosmetic, but I burned a verification round proving my orchestrator had not silently reset, and an operator watching a chef session would misread it the same way.
All three are filed with repros and screenshots, and the v2 team is explicit that this is what the beta period is for: separate database that may get wiped, v1 plugins dead, /report built into the app for exactly this traffic. The stable release carries none of it. Orchestrate on 1.17.18 and check back.
If opencode is not your harness, pi covers the same ground with less ceremony. Same device-code login against the ChatGPT sub (/login, pick Codex, it is the OpenAI-endorsed “Codex for OSS” path), and thinking tiers ride the model ref itself: pi --model openai-codex/gpt-5.6-sol:xhigh -p "<task>", tiers off through max. It serves Luna where opencode cannot, 3.6 seconds to first answer. On my battery, terra through pi hit 261 points per minute, past composer’s 231, luna scored 97 across three tasks, and sol at xhigh took 86 seconds on the bug hunt against 30 at default, which is the tier knob visibly doing something. Two cautions: pi’s system prompt does not name the model, so identity self-reports hallucinate (mine claimed to be GPT-5.2 while the request layer sent gpt-5.6-sol), and an invalid tier suffix passes through as a literal model id instead of erroring. Update first, too: the 5.6 catalog arrived after 0.73.
Every seat scored 100
I gave eight seats a deliberately nasty repair job: two files, twelve pytest cases, five bugs that mask each other so a naive fix reopens a test that was already passing. Composer, Fable, Grok, GPT-5.5, three thinking tiers of 5.6, and Gemini Flash all landed 100. Nobody flinched.
When correctness saturates, the axis that matters is what each answer cost. Same task, same perfect score, 531 seconds of total wall-clock, and it did not spread evenly:
So the routing rule writes itself: send the cheap fast seats at the bulk of the work, and spend the slow tiers only on the task that earns them. Gemini Flash at its Low tier swept the same battery at 571 points per minute, the fastest competent worker I measured on any lane.
What Sol reaches
The roster’s last seat is ollama:deepseek-v4-flash:cloud. Point the chef at it and Brigade shells out to the ollama CLI like any other adapter: “I am the Brigade worker local model.” That closes the span: Codex, Cursor, Grok, Claude, Antigravity, Codex Cloud, Ollama, and whichever of opencode or pi is not currently being the chef. Every token spent tonight billed to a subscription I already pay for.