A Claude Code plugin that asks AI coding agents the same question in parallel. Compare their answers when one model's bias could mislead you: architecture decisions, debugging dead ends, security reviews, or framework choices.
You need curl and jq on macOS, Linux, or Windows through Git Bash.
/plugin marketplace add hex/claude-marketplace
/plugin install claude-council
Give it at least one provider in the shell you start Claude Code from:
export OPENAI_API_KEY="..."
# Or GEMINI_API_KEY, XAI_API_KEY, PERPLEXITY_API_KEY,
# KIMI_API_KEY, OPENROUTER_API_KEYThe codex, agy (Antigravity), grok, kimi, and cursor-agent CLIs use
your existing subscriptions without an API key. Claude Code itself, the
Copilot CLI and OpenCode can sit too, when named in --providers. A local
ollama model needs no key or external network. With none of these, --local uses Claude
subagents. See provider selection and
local councils.
Read what gets sent and saved before asking about your code.
/claude-council:status
/claude-council:ask "Should I use UUID or BIGINT primary keys for a SaaS users table?"
Each provider answers independently. Claude writes a synthesis of their agreement, disagreements, and recommendation. Agreement is not verification: the models share your description and its assumptions. The synthesis names the premise that could change the answer.
| Capability | Guide |
|---|---|
| Ask providers together, or name one in plain words | Command examples |
| Choose providers and pin a standing roster | Provider selection |
| Assign specialist roles | Roles |
| Have providers challenge each other's answers | Debate |
| Gather code context with agents before asking | Agent mode |
| Use Claude subagents without an external provider | Local council |
| Include relevant files or choose your own | Auto-context |
| Attach a screenshot | Image input |
| Ask about the current conversation | /advise |
| Run in the background and fetch the result | Background jobs |
| Export the answers to a file | Export |
| Show only the synthesis | Quiet mode |
| Watch answers arrive and retry failed seats | The pane |
| Get a note from one seat while Claude works | Heads-up side-check |
| Have a second model review the diff before Claude stops | Stop-gate review |
| Call the scripts without Claude Code | Direct script usage |
The reference lists every flag, variable, model default, and limit. Architecture covers the implementation. TESTING.md covers tests, releases, and adding a provider.
Opt in through the "Heads-up side-check" row in /config or the project's
.claude/council-heads-up.json. One seat, codex by default, checks recent
turns and tool results while Claude works. For a Write or an Edit, it gets the
text Claude wrote. The note shows what went where.
Learn more expands it; Tell Claude puts a draft in the prompt without sending
it. Read the data limits and off switch
and the heads-up guide.
With CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1, the pane opens inside Claude Code,
as in the animation above. Each seat has one row with its model, a bar for
its state, its time, and a button for what it does now: cancel, retry, open,
or fold. When the run ends,
the synthesis opens at the top with the answers folded below it. Reopen the
last run with /council-pane. Inside tmux, the mod asks once which pane you want.
Mods are early access. The mod guide lists keys, settings, and limits. It also lets Claude call the council as a tool; every call asks you first.
The mod makes no network calls of its own. It starts the programs below
from an argument array, never a shell string, and never hands bash -c a
script. Your text reaches model providers only through the first two:
bash scripts/run-council.shwhen Claude calls the council tool and you chooseSend to the council. It sends your question to the providers you set up.bash scripts/heads-up.sh, only with the heads-up side-check on. It reads this session's transcript (by default the last 5 turns and up to 8 tool results of 2,000 characters each) and sends that digest to one seat,codexunless you pick another. The run directory keepsdigest.mdandprompt.md, exactly what left the machine, until the mod reads the result and removes it. The codex seat runs in that directory under a codex home of its own: your model and effort, a link to yourauth.jsonso a token refresh reaches your login (without one, yourCODEX_API_KEYorOPENAI_API_KEYsigns codex in), and none of your plugins, hooks,AGENTS.md, skills or MCP servers.bash scripts/seat-info.sh discover,model <seat>orallowlisted <seat>during/heads-up setupand/heads-up on <seat>. It checks which seats this machine can run and sends nothing.codex debug modelsduring/heads-up setupwith the codex seat, to list its models. That command belongs to codex, and so does any request it makes.kill -0 <pid>to check a council run is still alive. It sends no signal.rm -rfandmv -fon its own run directories under$TMPDIR/council-mod.<session id>, to clean up a finished run and to answer the retry offer.
It writes files in that $TMPDIR directory, including model.json and
avoid.txt, which heads-up.sh reads. Outside it, it writes one file,
.claude/council-heads-up.json in the project, and only from
/heads-up setup, /heads-up on, /heads-up off or a note's Turn off.
That file is the heads-up switch. Claude Code itself does not read it.
It touches the prompt in two places. With wake_on_async_done on, it
submits The background council job <id> has finished. Fetch it with /claude-council:result <id> and summarise it. once a background job
finishes. A note's Tell Claude puts a draft in the prompt box, and you decide
whether to send it.
It reads the text of each Bash command Claude runs, only to spot a call
to run-council.sh. Just before that call it sets COUNCIL_MOD_PANE_DIR,
so the run draws in this pane, and clears it when tmux owns the pane. It reads TMPDIR and TMUX. It turns on the
claude-council.heads_up setting only when you pick "every project" in
/heads-up setup.
Without the mod, tmux opens a side pane that streams answers and each
provider's status. It offers to retry failed seats. Esc closes it.
--no-pane or COUNCIL_NO_PANE=1 turns it off. Outside both pane modes,
answers arrive in the chat. See terminal integration.
The council and tmux animations show real answers to "Should a single-node demo app use SQLite or Postgres?" Codex and Antigravity use subscriptions; Gemini and OpenAI use their APIs. Kimi is a rate-limit fixture. The heads-up animation uses a fake seat and a real Claude Code host. Capture scripts and raw frames record how to reproduce them.
Every CLI seat runs from an empty directory, $TMPDIR/claude-council-<uid>/seat,
where <uid> is your numeric user id. The CLAUDE.md, AGENTS.md, rules,
skills, hooks and MCP servers of the project you ask from don't reach it. The
directory doesn't limit what a seat can read: codex, for example, can still
open any file by its full path.
The directory is read-only. That stops a seat writing a file there, but not a seat that changes the mode first. A seat also refuses to start when it finds anything in it, and names the path so you can look before you remove it. A file that lands while other seats are running can reach them; the next seat to start refuses.
The seats below also run under a home of their own, in
$TMPDIR/claude-council-<uid>/seat-home. It links only to what the CLI needs to
sign in and start. Only you can open either directory, and a seat refuses to
start when one of them belongs to another user or is a symlink.
| Seat | No longer loads | Still loads |
|---|---|---|
cursor-cli |
Skills and plugins from ~/.cursor, ~/.claude, ~/.codex, ~/.grok and ~/.agents, Cursor and Claude hooks, ~/.cursor/mcp.json |
Team commands from your Cursor dashboard (read from the CLI's bundle, not seen in a run) |
grok-cli |
Claude plugins, ~/.agents skills, grok's memory across sessions |
Your ~/.grok config and the hooks in ~/.grok/hooks, since no grok setting turns them off. The seat home links your login keychain (macOS) and ~/.docker/run, for Docker Desktop's socket |
antigravity |
On macOS: your ~/.gemini rules, skills, MCP servers and saved conversations |
On Linux: everything under ~/.gemini, because where agy keeps its login there is not confirmed |
opencode |
The ~/.claude and ~/.agents skills, agents and CLAUDE.md |
Your login and session history in ~/.local/share/opencode |
codex |
Your plugins, hooks, skills, memories and MCP servers. Each question gets its own codex home with your model, your effort and a link to auth.json |
Nothing. With no auth.json and cli_auth_credentials_store set to keyring or auto, your login is in the system keyring, which codex can't read from another home, so the seat runs under your own codex home and the answer starts with a note. An exported OPENAI_API_KEY doesn't change that; an exported CODEX_API_KEY still signs codex in ahead of any login, as it does when you run codex yourself. Set cli_auth_credentials_store = "file" and run codex login again to isolate it. With no login at all, the seat stops and says so |
claude-cli |
The git status and commit instructions a repository adds | Admin policy and your organisation's instructions |
kimi-cli, copilot-cli |
The project's files | Your home: kimi's hooks in ~/.kimi-code/config.toml, copilot's skills in ~/.copilot and ~/.agents |
Cursor and Antigravity keep the model you picked in their own config: the seat
reads it from your real home and passes it on. On Windows the seats keep your
home, because the native CLIs find it through USERPROFILE.
Seat isolation has each seat's details.
| Problem | Fix |
|---|---|
| Cloned the repo and nothing loads | Don't clone into ~/.claude/plugins/. pluginDirectories is not a setting. Follow running from a local clone. |
| No providers found | Run /claude-council:status. Export keys in the shell that starts Claude Code, or use --local. |
| A different model answered | A header such as grok-4.7 (grok-latest unavailable) records a model fallback. Setting that provider's _MODEL variable disables fallback. |
| No pane | Use tmux or set CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 for the pane inside Claude Code. |
| Updating | Run /plugin update claude-council, then restart Claude Code. |