How to Add Multi-LLM Code Review to OpenCode with Chorus
You ask your coding agent to write a divide(a, b) function. It says looks correct. You ship. Production crashes at 2am because nobody handled b = 0.
I have had this exact feeling, trusting an AI that was itself too confident. That is why Chorus caught my attention. It runs 2-4 different AI models against the same diff in parallel and only green-lights when they agree. Because it drives the CLIs you already pay for (Claude Pro, ChatGPT Plus, Gemini Advanced), each review costs roughly $0 out of pocket.
This tutorial walks through installing Chorus, hooking it into OpenCode via MCP, and running your first multi-model review.
Prerequisites
- OpenCode installed (
~/.opencode/bin/opencodeor via brew) - Node 20+
- At least one AI CLI (Claude Code, Codex, Gemini CLI) or an OpenRouter API key
- A terminal open at your project root
What We Are Building
OpenCode already has tools like read, write, bash, search. Chorus adds a new category: multi-model review. You point it at a diff or piece of code, and it fans out across 2-4 different AI models, each from a different vendor. They review independently, then converge on a verdict.
The connection between OpenCode and Chorus goes through MCP (Model Context Protocol). OpenCode starts a Chorus subprocess, Chorus exposes tools like create_chat, wait_for_chat, list_templates, and OpenCode’s agent calls them when you say “use chorus.”
Step 1: Install Chorus
npm install -g chorus-codesCheck it worked.
chorus --versionYou should see something like 0.8.27.
Step 2: Initialize
chorus initThis scans your machine for AI CLIs (it looks for Claude Code, Codex, Gemini CLI, OpenCode, Cursor, Windsurf, Kimi) and registers itself as an MCP server with each one it finds. It also seeds your template library: code-review, architect-review, bug-diagnose, red-green, review-only, and tri-review.
The output should look roughly like:
✓ created /Users/you/.chorus
✓ database ready at /Users/you/.chorus/chorus.db
✓ MCP registered · 7 tool(s) approved
✓ OpenCode MCP registered
✓ AI CLIs ready: claude, codex, gemini, opencodeStep 3: Configure the OpenRouter Key
If you are using CLIs like Claude Code or Codex that already have their own auth, skip this. If you want Chorus to access OpenRouter models, you need to add your key to the MCP environment.
Open your OpenCode config at ~/.config/opencode/opencode.json and add the OPENROUTER_API_KEY to the chorus environment block:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"chorus": {
"type": "local",
"command": [
"node",
"/opt/homebrew/lib/node_modules/chorus-codes/bin/chorus.mjs",
"mcp"
],
"environment": {
"CHORUS_DAEMON_URL": "http://127.0.0.1:7707",
"OPENROUTER_API_KEY": "sk-or-v1-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
"enabled": true
}
}
}Replace the OPENROUTER_API_KEY value with your actual key.
Step 4: Start the Daemon
chorus startThis boots two things: a daemon on port 7707 (the backend that spawns AI subprocesses) and a web cockpit on port 5050 (where you can watch reviews stream live, manage templates, and tweak settings).
Step 5: Verify the MCP Connection
Check that OpenCode sees the new tools.
opencode mcp listYou should see:
● ✓ chorus connected
node .../chorus.mjs mcpOpenCode can now call Chorus tools. The nine tools available are:
| Tool | What it does |
|---|---|
create_chat | Kick off a review |
wait_for_chat | Wait for results |
get_chat_status | Poll without blocking |
cancel_chat / resume_chat | Control a run |
list_templates / list_personas | Discover patterns |
invoke_persona | Run a single reviewer |
list_blocked | See chats that need input |
Step 6: Run Your First Review
In OpenCode, you can now say things like:
Use chorus to review the staged diffOr target a specific template:
Use chorus to run the code-review template on the unstaged changes in src/payments/Or run a plain-English request:
Use chorus to get a second opinion on this implementation from claude + geminiChorus fans the work out to different models, waits for them to finish, and reports whether they agreed.
Templates
Six built-in templates ship with Chorus:
- code-review: One model writes, two others review. Both must agree.
- architect-review: One model drafts a design proposal, three others critique it.
- bug-diagnose: One model forms a hypothesis, another challenges it.
- red-green: Multi-phase TDD where the test writer cannot see the implementation. Catches the overfitting that happens when one model writes both sides.
- review-only: Paste a diff or text blob, get six independent opinions. No writer involved.
- tri-review: Three reviewers, two-out-of-three quorum.
Drop a YAML file in ~/.chorus/templates/ to make your own.
What Happens Under the Hood
When you tell OpenCode to use chorus:
- OpenCode calls
create_chatvia MCP, passing the template and the code - Chorus daemon spawns each reviewer as a subprocess of its assigned CLI
- Each model streams its thinking back to the daemon in real time
- When all reviewers finish, Chorus checks the quorum rule
- If the threshold is met, it returns a passing verdict. Otherwise, it reports what each reviewer flagged
- You see the results in OpenCode or open the cockpit URL to watch the replay
Your code never hits a Chorus server. It goes directly from your machine to the AI vendors you already use.
One Thing to Watch For
Built-in templates assume your AI CLIs are using their default vendor. The code-review template expects Claude Code to be running an Anthropic model. If you have Claude Code pointed at OpenRouter with a DeepSeek model, the writer slot fails. The review-only template sidesteps this (it has no writer slot), and is a good starting point if your CLIs are configured atypically.
What You Get
After this setup you have:
- Chorus daemon running on your machine (restart it with
chorus startwhen you reboot) - MCP server registered in OpenCode with 9 tools
- 6 built-in review templates
- The ability to run multi-model reviews from any OpenCode session
When you are done for the day, stop the daemon:
chorus stopStart it again tomorrow with chorus start.
Crepi il lupo! 🐺