THE HIGH COUNCIL
"A beginning is the time for taking the most delicate care that the balances are correct"
— Frank Herbert, Dune
You bring an idea for a new project, a feature or any kind of update.
THC debates on your idea and the Software Engineering behind it.
Through multiple debate rounds and 3 layers of judges, they catch a lot of things that even your strongest initial draft-writing LLM will not have thought about.
The goal is to get everyone to work together, in harmony and with manners. Exact effectiveness numbers are unmeasured by decision.
Update 0.8.3 brought: Recursive Councils - "Plans within Plans within Plans"
Website · Pricing · AI-Readme (the full text) · Changelog · Known limits
Try it in 30 seconds
npx the-high-council council demo
No keys, no network, $0. Add it to Claude Code as an MCP server:
claude mcp add council -- npx -y the-high-council council --mcp
For Claude Desktop, download the .mcpb bundle (the-high-council-<version>.mcpb) from Releases.
Contents
- Your first ten minutes · Words used here
- How it works · Reading a run with a program
- Requirements · Setup · Quick start (CLI) · Quick start (MCP)
- The spend cap · Pricing · Chains
- How this was built · Skills
- Known limits · Privacy · Accessibility · Reporting a bug · License
- AI-Readme (the full text) · Troubleshooting · Agent skills · Personas · Contributing
What you get
- Criteria before planning. Your request becomes a short list of yes/no checks the plan has to pass, written before anyone plans.
- Blind proposals and a recorded debate. Each lab proposes without seeing the others, then reads the rest with the names hidden and posts support, an objection or a merge. Every author then keeps, amends or withdraws its own proposal, on the record.
- Review and revision. A panel of judges checks the draft against the criteria, and a failed check sends it back for a revision. The planning chains judge in three layers. An objection that was never settled stays on the record; nothing is averaged away.
- A handoff for building.
HANDOFF.mdis written for whoever builds the plan: the acceptance checks and the instructions a coding agent works from, and in the planning chains the milestones too.
Every run writes a folder, runs/<id>/:
| File | What it gives you |
|---|---|
deliverable.md |
The plan |
BOARD.md |
The whole debate: every post, every withdrawal |
HANDOFF.md |
The build instructions and the acceptance checks, for the coding agent |
report.json |
The same board, structured, with the token and cost accounting |
On what this does and doesn't claim. This repo publishes the mechanism: the chains, the seat rosters, the stage order. We did have the Council measured by frontier AI on the run that planned update 0.8.3: the plan improved in every measured rubric but one, and that one was that it got longer and harder to read. What the repo does, concretely, is make disagreement between models visible and recorded instead of averaged away - you can read who objected to what, who withdrew a proposal under argument, and who held their position.
Your first run
The quick-start chain, plan-default-opro-council, runs on one OpenRouter API key: one account that reaches many labs' models. Put the key in a file called .env in the folder you run from:
OPENROUTER_API_KEY=your-key-here
Add .env to your .gitignore (and runs/ if your ideas are private). Then:
npx the-high-council init
npx the-high-council doctor
init writes tasks/my-first-task.md. Edit it into your own idea, in plain words: what you want, the constraints that matter, and what done looks like. Price it, then run it:
npx the-high-council --task tasks/my-first-task.md --chain plan-default-opro-council --dry-run
npx the-high-council --task tasks/my-first-task.md --chain plan-default-opro-council --max-usd 10
The first command spends nothing. A paid run starts only after you type its spending limit on a screen; --max-usd 10 puts $10 there as the suggestion. A run can also pause and wait for an answer from your Claude Code session, or from you; a swing between two judge layers' objections is one such pause.
A run that stops at its limit keeps every stage it paid for. npx the-high-council --resume runs/<id> continues it: the screen asks for a new total above what the run has counted, and the finished stages cost nothing the second time.
Use it with your coding agent
Runs as an MCP server (so a coding-agent session such as Claude Code can drive it) or as a CLI. Bring your own API keys. Nothing is resold, nothing is hosted for you, and your keys go only to the providers you choose, never to us.
For Claude Code:
claude mcp add council -- npx -y the-high-council council --mcp
Or as a Claude Code plugin, which registers the same server and also installs the skills in
skills/:
claude plugin marketplace add muad-yasin/the-high-council-mcp
claude plugin install the-high-council@the-high-council
Claude Desktop: download and open the-high-council-<version>.mcpb from Releases.
Other MCP clients · Plugin settings and keys · Standalone binaries
Pricing
What each shipped chain costs per run, in US dollars. Expected and Upper estimate are worked out by the code
before anything is sent, from the shipped price table and the chain's own size estimates. council doctor prints
the same figures; --dry-run prices your own task, and a longer task costs more. Upper estimate prices every planned call at its
whole output allowance, with every allowed round used. It leaves out re-asks and retries, so it is not a
ceiling: the limit you type is what stops a run. Tested is what real runs cost; – means no run has been reported yet. Seats your Claude Code session answers cost $0 here, because they run on your own
subscription. The two advise- rows show what the advice add-on itself shows and enforces: a brief at its
48,000-character limit, and Upper estimate includes one retry of a reply that was cut off.
| Chain | Expected | Upper estimate | Tested (real runs) |
|---|---|---|---|
| Planning chains | |||
plan-mini-council |
$1.51 | $5.27 | – |
plan-medium-council |
$7.16 | $23.04 | – |
plan-high-council |
$25.89 | $272.24 | – |
| Variants | |||
plan-claude-council |
$0.00 | $0.00 | – |
plan-mini-council-sol-session |
$1.41 | $4.46 | – |
plan-default-opro-council |
$2.95 | $16.26 | – |
| Chinese-lab alternatives | |||
plan-china-mini-council |
$1.69 | $6.15 | – |
plan-china-medium-council |
$5.78 | $17.71 | – |
plan-china-high-council |
$18.64 | $175.72 | – |
| Advice add-on | |||
advise-single |
$0.08 | $1.32 | $0.03–$0.15 (3 runs) |
advise-standard |
$0.75 | $1.40 | – |
| Other | |||
local-ollama |
$0.00 | $0.00 | – |
verify |
$0.48 | $3.20 | – |
daily7-sub-a |
$1.39 | $5.06 | – |
With recursive councils, a tree at the default limits runs up to 12 councils (the root and 11 sub-plans), each on the chain you name for it, so with one chain throughout it can cost up to 12 times that chain's figures; council tree start --dry-run prints the projection for your own task and chains, and the limit you type stops the tree.
Ran one of these chains? CONTRIBUTING.md says how to send us the figure.
Recursive Councils: Plans within Plans within Plans
New in 0.8.3. A milestone of the plan can get a Council of its own, and its milestones can again, so the runs form a tree under one root plan. You type the tree's spending limit once, and every sub-plan runs under it. A sub-plan inherits the acceptance criteria its parent delegates to it and cannot narrow the ones that hold for the whole tree. Approvals, and the decisions taken when a run gets stuck, are recorded, and the record says who made each: you, or the Claude Code session driving the tree.
Price a whole tree before anything is spent:
npx the-high-council tree start --task tasks/my-first-task.md --chain plan-mini-council --child-chain daily7-sub-a --dry-run
Known limits, stated plainly
- The panel signs one draft; later stages can change what you receive, and nobody re-reads it. The dispute pass, the post-sign-off challenge and the final edit are model edits made after
the last review, and the dissent and cold-read blocks are written by the harness. The run labels this and does not repair it:
report.jsonhassigned_textanddelivered_text(hashes,same_as_signed,changed_by),BOARD.mdsays so when it applies, andHANDOFF.mdopens with a banner when a model edit changed the text after the panel signed it (a run the panel did not sign keeps its own "not a signed-off plan" banner). A cold-read or dissent block the harness adds is named indelivered_text.harness_notesand gets no banner. The panel is not run again on the changed text (that would be a further paid pass per run), andrun_statussays so after "every lab signed off" when the delivered text differs (delivered_text.same_as_signedinreport.json). - An early finish needs a reviser that is your own session. On a layered chain the reviser may end its reply with
EARLY-FINISH: <why>, and the top layer then decides whether the run stops there; that works only when the reviser seat is your Claude Code session (external). A chain whose reviser is an API seat has no early finish: the line is removed from its text and the log says so. An early finish is not agreement:passedis false, the run exits 22, and every open objection is a named builder task at the end ofHANDOFF.md. - The spend cap is enforced against a worst case, not a prediction: the whole prompt billed as
input plus the seat's entire
maxTokensbudget billed as output (for Anthropic seats, plus the bigger cap of the one retry they may make). Real stages almost never cost that much, so a run can stop with headroom left. That is the intended trade - resume it: a paid run asks for a new, higher total on the limit screen (a chain with no paid seat takes--max-usd). - The dry run (
--dry-run, MCPdry_run) prices the task alone and does not read--contextdocuments, so for a run with context its estimate is too low. The spend cap is not affected: it checks every real prompt, context included, before each call. - A seat whose model has no price, neither in
src/pricing.jsonnor in your project'spricing.user.json, cannot be held by a spend cap, because the cap would count every call to it as $0. Since 0.8.2 a run refuses such a seat before it sends anything (exit 5; the message names the seat and, since 0.8.3, the way out: add a row for it topricing.user.jsonin your project folder, for example{ "openrouter/vendor/model": { "in": 1.0, "out": 4.0 } }, in US dollars per million tokens; your row can add a missing price or raise a shipped one and can never lower a shipped one, and a file that cannot be read in full is refused as a whole), and--dry-runshows the same refusal at $0.mock,externalandollamaseats are exempt:ollamaprices at an explicit $0 for any model name, because it is genuinely free to run. What remains: the cap is only as good as the price table (it is dated, and the dry run says when it is old), and a model that answers in place of a priced one (an OpenRouter fallback inextra.models) is charged at the priced seat's price, which can differ from its own. - A call that fails after it reached the provider - the connection drops while a 200 reply is
being read, a 200 carries a body that is not JSON, or the request times out waiting for headers -
is not retried, because the generation was probably already billed. Its real usage cannot be
read, so it is counted toward the per-run cap at its worst-case projection, and recorded as
superseded/<label>.charge-<n>.usage.json, whichcouncil --spendand a resume count. - Some hosted reasoning models stop at a provider-side reasoning ceiling well below the seat's own
cap, before writing any answer (seen 2026-09-23:
deepseek/deepseek-v4.1-flashvia OpenRouter, 6 of 28 calls stopped at ~4.2k tokens, all reasoning, under a 36k cap). A bigger cap cannot fix that, so such a reply is recorded asREASONING_EXHAUSTEDand is not retried: the seat abstains, which blocks unanimity and never counts as consent. Whether to change a chain's reasoning settings for it is a roster decision, not something the harness does for you. - The Claude Code plugin installs from the repository root.
claude plugin validate .passes with one warning, andclaude plugin validate --strict .fails on it: "CLAUDE.md at the plugin root is not loaded as project context" (the file is this project's own instructions and is not part of the plugin). A separateplugin/directory would not have it; that layout was declined for 0.8.1 and comes back with the plugin directory listing. What Claude Code passes for an unset optional dialog field was seen once, in a scratch plugin on Claude Code 2.1.289 (an empty string), not across versions or on Claude Desktop's own client. - The reasoning fields were set from the providers' documents and OpenRouter's public model list,
not exercised in a live call (src/reasoning-table.json; its
asOffield is the date they were read). A provider that rejects a field fails that seat's call with the provider's own error; the first real run of a changed chain is the live test. The table turns stale after 60 days and a release test fails then. Seats that now reason at high use their output cap faster, and a cap sized for a short answer (a questions or criteria stage) can be spent on thinking: such a seat is retried once at a bigger cap and, past the limit, is recorded with no answer. A direct Anthropic call is not streamed, so its retry is bounded at 64,000 tokens; streaming is not built. - Prices in
src/pricing.jsonare hand-maintained list prices. ItsasOfdate (2026-10-23: the oldest date every entry was last checked) is printed bycouncil doctorand--dry-run, with a warning once it is more than 60 days old. A model whose provider has retired it or no longer lists a price keeps the figure the table already had for it, and its row's_sourcesays so: the date records the read, not that figure. The spend cap and every estimate use these static prices. They are estimates, not invoices. Your provider's bill is the real number. A row whose price is known to change carries anexpiresdate (GPT-5.6 Sol's promotional price, at least through 2026-11-21; Gemini 3.8 Flash and Gemini 3.6 Flash, whose prices double on 2027-01-01): past it,council doctorand--dry-runwarn, but the projection and the cap keep the old price, so they can project low until the table is updated. - The retired
plan-highest-7(inchains/outdated/) was never run with real models, andplan-daily-7ran once (2026-09-28) with the roster it had before the 7 Oct 2026 redesign. None of the tiered councils' mechanisms (tiers, the deep-dive seat, the majority guard) has been measured. Their dry-run prices are projections. run_testsruns a repository's own test files as trusted code, with no sandbox. It belongs to the opt-in seat tools (verify.toolsnamingrun_tests; no shipped chain does; a seat may request it mid-stage only when the chain also setstools.seat_requests). Since 0.8.2 the test process gets an allowlisted environment:PATH,HOME(USERPROFILE), the temporary-folder variables,LANG,LANGUAGE,LC_*,TERM,CIand the Windows system variables (SystemRoot,ComSpec,PATHEXT,WINDIR). No provider key is in its environment, but a test is code you trust: it can still read the parent process's environment and files on disk (for example/proc/<pid>/environ). A project's tests that need another variable (a database URL, say) will not see it. It can still read every file you can
