# Courant: the full text > Courant reads a finished simulation run and returns accept, reject or insufficient, with every reason citing the file it read, the method, the threshold and the value, and with its own error rate measured on real solver runs and published. > Open source (Apache-2.0) and free on your machine; design partners through hello@courant.dev. The site's documentation as one text: install, the guide, the verdicts, the benchmarks with every number, the questions, and the security and network facts. The short index is https://www.courant.dev/llms.txt; the same facts as JSON are https://www.courant.dev/facts.json. ## Install (https://www.courant.dev/docs#install) ``` pip install 'courant-dev[mcp]' ``` Python 3.11 or later; the command is `courant`. PyPI's `courant` is an unrelated project. Or one signed file, no Python. For macOS (darwin-arm64, darwin-x86_64) and Linux (linux-x86_64, linux-arm64): ``` curl -fsSL https://github.com/courantdev/courant/releases/latest/download/install.sh | sh ``` It checks the binary's SHA-256 against the release's `SHA256SUMS`, and the Ed25519 signature of `SHA256SUMS` against the release key it carries when python3 with the `cryptography` package or OpenSSL 3 is available. With neither, it says that only the checksum was checked and how to check the signature by hand; set `COURANT_REQUIRE_SIGNATURE=1` to make it refuse instead. Then: ``` courant demo ``` Four real OpenFOAM runs, offline, and an HTML report. The first screen of its output (courant 0.5.0, 19 Oct 2026): ``` Courant demo · offline · read-only · four real OpenFOAM v2406 runs 1 A healthy run: icoFoam cavity, as OpenFOAM ships it accept (rule VER-5.6, grade A) 2 A broken run: the same cavity with a timestep ten times too large reject (rule VER-5.3, grade C) why cfl.max: Courant number exceeds stability limit: max Co=9.66 at t=0.15 exceeds limit 1.0; still 8.92 over the final fifth of the run why convergence.residual: transient solve judged on stability rather than a residual threshold — Courant number settled at 8.92, above the stability limit of 1 — a transient solve that does not respect its timestep criterion is not converged, whatever the residuals say (final worst residual 3.61e-01) cause NUM.CFL_VIOLATION (Courant number too high) next Suggested, not applied: Reduce deltaT in controlDict 3 Before the run: the cavity with its viscosity in the wrong units (courant preflight) SETUP_FAULT before the first timestep why physics.nu: Suspicious viscosity value: nu=1e-09 m^2/s is outside typical fluid range [1e-8, 1e-2] next Suggested, not applied: Correct nu in transportProperties (units m^2/s) 4 A steady run with a fixed budget: pitzDaily, 2,000 iterations, monitors on the walls and the inlet accept (rule VER-5.6, grade B); convergence PASS 1 Answer courantWallForces/moment:total_z: value -5.55254e-06 at step 977, -5.55373e-06 at the end (step 2,000) 2 Change 0.021% of scale after the stopping point (limit 1.0% of scale) 3 Iterations 1,023 of 1,999 past convergence (51.2%) 4 Wall clock 9 s of 21 s past convergence (solver ClockTime; rank-0 CPU 9.51 s) 5 Core-hours 0.0025 past convergence (1 rank, nProcs in the log, x wall clock) 5 The compute audit over these 4 runs (courant audit) 2 of 4 trustworthy · 1 of 4 with a setup fault preflight finds before the start · on 1 of 1 monitored runs the answer settled, with 51.2% of its iterations still to run On your runs it totals the core-hours, and the cost at your rate. ``` ## First verdict in seconds (https://www.courant.dev/docs#quickstart) Then point it at a case directory, or at a solver log on its own. ``` courant verify ./my_case # a case directory: finds the solver log itself courant verify log.simpleFoam # or a log on its own ``` ``` courant verify --about # the error rates published for this version ``` Every verdict travels with this version's measured error rate. ## Is it the problem that was asked? (https://www.courant.dev/docs#spec) A run can converge and still answer the wrong question: it checks every value the task names against the case. Lock the hash before the run: an edited specification makes the verdict `insufficient`. ``` courant spec init ./reference_case -o spec.json --task "pitzDaily, inlet 10 m/s, k-epsilon" courant spec hash spec.json # lock it before the run; keep the hash courant verify ./agent_case --spec spec.json --spec-sha256 ``` Every report states its basis: `validity`, `validity+conformance` or `validity+unlocked-spec`. ## For AI agents (https://www.courant.dev/docs#mcp) An agent that runs a simulation can check its own result before it reports success. ``` courant mcp --root ~/runs ``` ``` courant mcp --print-config --root ~/runs ``` ``` claude mcp add courant -- courant mcp --root ~/runs ``` The server offers six read-only tools, confined to the directories you name: `verify_run`, `score_agent_output`, `check_convergence`, `explain_code`, `list_failure_modes`, `verifier_certification`. ## In CI (https://www.courant.dev/docs#ci) Any CI system that reads JUnit shows each run as a test: GitHub Actions, GitLab, Jenkins, Azure. The batch exit code is 2 if any run is rejected, otherwise 3 if any is insufficient, otherwise 4 if any is unreadable. ``` courant verify --batch runs/ --junit courant.xml # exit 2: runs/ holds rejected runs ``` The GitHub Action: https://github.com/courantdev/courant/tree/main/.github/actions/courant-gate ## Verdicts and exit codes (courant.verdict/2) - `accept` (exit 0): No check failed, and the run produced enough output to be judged. In JUnit, a passed test. - `reject` (exit 2): At least one check failed. Each reason gives the file it read, the method, the threshold and the value. In JUnit, a failed test. - `insufficient` (exit 3): There was not enough to judge. The verdict carries one reason, `insufficient.`, from a closed list, and the report says what was missing. In JUnit, a skipped test. An unreadable input exits 4. Every reason cites input (the file it read), method, threshold, value. Every verdict lists what could not be checked. The eleven reasons for `insufficient`: - `insufficient.no_output` (rule VER-5.1, cause: run) - `insufficient.unrecognised_log` (rule VER-5.1, cause: fork) - `insufficient.no_residuals` (rule VER-5.5, cause: run) - `insufficient.no_time_markers` (rule VER-5.15, cause: run) - `insufficient.spec_hash_mismatch` (rule VER-5.8, cause: spec) - `insufficient.spec_value_unreadable` (rule VER-5.9, cause: spec) - `insufficient.unsupported_version` (rule VER-5.10, cause: fork) - `insufficient.spec_invalid` (rule VER-5.11, cause: spec) - `insufficient.spec_extracted_mismatch` (rule VER-5.12, cause: spec) - `insufficient.spec_role_unresolved` (rule VER-5.13, cause: fork) - `insufficient.time_scheme_unreadable` (rule VER-5.14, cause: fork) ## Commands (courant 0.5.0, released 12 Oct 2026) - `courant verify `: accept, reject or insufficient (exit 0, 2 or 3; courant.verdict/2), with the basis it was judged on and what was not checked. --spec with --spec-sha256 checks every value a task specification names against the case. --html, --report md, --json, --pack and --check-pack (an evidence pack anyone can re-derive), --batch with --junit, --record, --about - `courant spec init / hash / check / lock / confirm / extract`: Draft a task specification from a reference case, lock it by hash, and check a case against it before or after its run - `courant gate`: The CI check, and the GitHub Action: verify the runs a repository names, one summary row per run, one evidence pack per run - `courant preflight `: A broken setup, caught before the solver spends anything - `courant convergence `: Where the monitored answer stopped changing, and the iterations, wall clock and core-hours after it - `courant watch `: A read-only live advisory while the solver runs, with --exit-on-fail for job scripts - `courant audit `: What a folder of runs cost, and how much of it bought nothing - `courant test run --judge …`: The Courant Test: score any judge, including an AI model, on real OpenFOAM runs - `courant mcp`: The same tools for any AI agent over MCP, read-only and confined to the directories named; score_agent_output tells an agent, before it reports, whether its run is a silent error - `courant doctor, courant update, courant version`: Diagnostics and a support bundle you send yourself; a signed update of the binary ## Benchmarks (https://www.courant.dev/benchmarks) Courant and three Claude models judged the same 420 real OpenFOAM runs, given the same task. Then Courant alone, on 1,827. Courant’s counts here are gate version 2’s; courant 0.5.0, the release, judges without the changes version 2 adds, and version 1’s interim accepted 6 of 91 faulted runs given the task (95% CI 3.06–13.65%), inconclusive. Versions are never pooled. ### Four judges, one task Wrong runs each judge accepted, given the task, on the same 420 runs (15 Oct 2026). Abstentions are in no denominator. - Courant: all wrong runs 0 of 264 (0%, 95% CI 0–1%); wrong problem 0 of 140 (0%, 95% CI 0–3%); solver fault 0 of 124 (0%, 95% CI 0–3%). - Claude Opus 5.5: all wrong runs 69 of 264 (26%, 95% CI 21–32%); wrong problem 61 of 140 (44%, 95% CI 36–52%); solver fault 8 of 124 (6%, 95% CI 3–12%). - Claude Sonnet 5.5: all wrong runs 76 of 263 (29%, 95% CI 24–35%); wrong problem 59 of 139 (42%, 95% CI 35–51%); solver fault 17 of 124 (14%, 95% CI 9–21%). - Claude Haiku 5.5: all wrong runs 52 of 249 (21%, 95% CI 16–26%); wrong problem 46 of 129 (36%, 95% CI 28–44%); solver fault 6 of 120 (5%, 95% CI 2–10%). Right runs each judge rejected, and the runs it did not answer. - Courant: right runs rejected 10 of 140 (7%, 95% CI 4–13%); abstained 16 of 420 (right 0 of 140, wrong problem 0 of 140, solver fault 16 of 140); requests that failed 0 of 420. - Claude Opus 5.5: right runs rejected 5 of 140 (4%, 95% CI 2–8%); abstained 16 of 420 (right 0 of 140, wrong problem 0 of 140, solver fault 16 of 140); requests that failed 0 of 420. - Claude Sonnet 5.5: right runs rejected 0 of 138 (0%, 95% CI 0–3%); abstained 19 of 420 (right 2 of 140, wrong problem 1 of 140, solver fault 16 of 140); requests that failed 0 of 420. - Claude Haiku 5.5: right runs rejected 17 of 122 (14%, 95% CI 9–21%); abstained 49 of 420 (right 18 of 140, wrong problem 11 of 140, solver fault 20 of 140); requests that failed 0 of 420. Courant’s 10 are 8 of 20 pitzDaily and 2 of 20 hotRoom: the two families behind H3 (below). Does each model accept more of the wrong runs than Courant? Exact one-sided McNemar on the wrong runs both answered, α 0.0167 each, fixed before any request. - Claude Opus 5.5: answered by both 264; accepted by the model only 69; accepted by Courant only 0; p 1.69e-21; supported. - Claude Sonnet 5.5: answered by both 262; accepted by the model only 76; accepted by Courant only 0; p 1.32e-23; supported. - Claude Haiku 5.5: answered by both 249; accepted by the model only 52; accepted by Courant only 0; p 2.22e-16; supported. A statement about these models, this prompt and these dates, on tutorial runs, never about language models in general. ### Courant alone, 1,827 runs Pre-registered hypotheses on 1,827 real OpenFOAM runs (14 Oct 2026), each decided on the upper bound of its 95% CI against a bar fixed before any run. - H1, Faulted runs accepted, without the task: 3 of 609 (95% CI 0.17–1.44%); pre-registered bar under 1%; refuted. Without the task, 3 hotRoom runs set to laminar on a turbulent case were accepted; with it, none was. - H1b, Faulted runs accepted, with the task: 0 of 609 (95% CI 0.00–0.63%); pre-registered bar under 1%; supported. - H2, Wrong-problem runs accepted, with the task: 0 of 609 (95% CI 0.00–0.63%); pre-registered bar under 1%; supported. - H3, Right runs rejected, with the task: 34 of 609 (95% CI 4.02–7.70%); pre-registered bar under 2%; refuted. 30 of 87 pitzDaily right runs (epsilon still being clipped late in the solve) and 4 of 87 hotRoom (Courant number above the stability limit over the final fifth of the run, adjustTimeStep off). - H4, Right runs left insufficient, with the task: 0 of 609 (95% CI 0.00–0.63%); pre-registered bar under 5%; supported. - H5, Verifier exceptions: 0 in 3,654 verifications; pre-registered bar 0 exceptions; supported. ### Method - Pre-registered by commits in Courant’s development repository, which is not public: the judges before any request (3aba674, 15 Oct 2026), the run at scale before any run (25e3c87, 10 Oct 2026; its versions 194fa76, 13 Oct 2026). - Every judge got the same 420 runs and the same task: 140 right, 140 the wrong problem, 140 with a solver fault; Courant’s verdicts are the ones it recorded on them at scale. - The judges saw a rebuilt case configuration, not the case Courant read. - Courant’s verdicts here are gate version 2’s; courant 0.5.0, the release, judges without what version 2 adds: the cell aspect ratio computed from the mesh files when a case has no checkMesh log and each field’s residual bar from the case’s own residualControl, with a stalled-residual check. Version 1’s interim, stopped at 273 of its 2,100 runs, accepted 6 of 91 faulted runs given the task (95% CI 3.06–13.65%), inconclusive. Versions are never pooled. - Tutorial-sized OpenFOAM v2406 runs of seven families; no customer data. $77.50 in model requests, 1,262 of them. The data: https://www.courant.dev/data/benchmarks.json (CC BY 4.0, https://creativecommons.org/licenses/by/4.0/). A short results table in the source repository: https://github.com/courantdev/courant/blob/main/RESULTS.md. ## Questions ### How do I verify an OpenFOAM simulation? Install Courant (`pip install 'courant-dev[mcp]'`) and run `courant verify ./my_case` on the case directory. It reads the solver log and the case files and returns accept, reject or insufficient, each reason citing the file it read, the method, the threshold and the value. Give it the task’s specification and it also checks that the run is the problem that was asked. ### How do three Claude models compare with Courant at judging OpenFOAM runs? Given the same 420 OpenFOAM tutorial runs and the task, Claude Opus 5.5 accepted 69 of 264 wrong runs, Claude Sonnet 5.5 76 of 263 and Claude Haiku 5.5 52 of 249; Courant, at gate version 2, accepted 0 of 264. Of the right runs, Courant rejected 10 of 140, the models 5 of 140, 0 of 138 and 17 of 122, in the same order. A statement about these models, this prompt and these dates, on tutorial runs, never about language models in general. The judges saw a rebuilt case configuration, not the case Courant read. ### What does Courant check, and what does it not? It reads what a finished run left behind, the solver log and the case files, and checks convergence, stability, bounded fields and the setup. Given the task, it also checks that the case is the problem that was asked: on the same runs it accepted 118 of 140 wrong-problem runs without the task and 0 of 140 with it. It runs no solver, changes no case and does not replace a validation experiment. ### Does it send my files anywhere? Courant runs on your machine and has no account, no telemetry and no service of its own; it never sends your runs, cases or results anywhere. Its checks open no network connection. Only these contact the network, only when you run them, and each names the host first: `courant update` downloads a release from github.com; `courant doctor --models` reads OpenRouter’s public model list; and a language model you choose (an `llm:` judge for the Courant Test, or `courant spec extract`) sends that task’s text to the model provider with your own API key. ### How is its error rate measured? On real OpenFOAM tutorial runs whose truth is known by construction: right runs, runs with an injected solver fault, and the right physics on the wrong problem. At scale, given the task, it accepted 0 of 609 faulted and 0 of 609 wrong-problem runs, and rejected 34 of 609 right runs, a rate that missed its pre-registered bar; without the task it accepted 3 of 609 faulted runs, which also missed its bar. Both studies on /benchmarks were pre-registered before their first request or run and published whatever they showed, every rate with its denominator and its 95% CI. Courant’s counts here are gate version 2’s; courant 0.5.0, the release, judges without the changes version 2 adds, and version 1’s interim accepted 6 of 91 faulted runs given the task (95% CI 3.06–13.65%), inconclusive. Versions are never pooled. ### What does Courant do? It reads a finished simulation run, the solver log and the case files, and returns accept, reject or insufficient. Every reason cites the file it read, the method, the threshold and the value, and it lists what it could not check. ### Is Courant a solver? No. It never runs the solver, builds a mesh or edits a case. It reads what a run left behind. ### How often is it wrong? On 31 real OpenFOAM runs it accepted 0 of 23 wrong results (95% CI 0–14.3%) and rejected 0 of 8 good ones (95% CI 0–32.4%). The corpus is small, so the intervals are wide, and every run is published. On 1,827 further runs, given the task, it rejected 34 of 609 right runs (95% CI 4.02–7.70%), above its pre-registered bar of 2%; the study is on /benchmarks. ### What leaves my machine? Nothing is sent to Courant. Verifying opens no network connection; a command that does, such as courant update, runs only when you run it and names the host first. ### Which solvers? OpenFOAM (v2406), including decomposed parallel runs. ### Can it check AI-predicted fields? Yes. It checks predicted fields, calibrated on your own data. ### Does a language model decide anything? No. Code decides every verdict, grade, threshold and number. A model may draft prose, and never a value. ### Is it approved by a regulator? No. No regulator or standards body has approved or endorsed Courant. ### Is it open source? Yes. The gate is Apache-2.0: https://github.com/courantdev/courant. ### How do I try it? Install it: pip install 'courant-dev[mcp]', or the signed binary. To have Courant verify your runs, become a design partner: up to 50 runs, free, for eight weeks. ## Security (https://www.courant.dev/security) ### Where it runs On your machine. No hosted service, no account, no telemetry. ### What it touches It reads files. It never edits a case, never runs your solver, never opens a network socket while verifying. ### What leaves Nothing is sent to Courant, ever: no account, no telemetry. A command that goes out runs only when you run it, and names the host first. ### Open source The gate is Apache-2.0: read the code that decides every verdict. ### Signed releases Every release carries `SHA256SUMS` and its Ed25519 signature; `courant update` installs nothing unless it verifies. The installer checks both where it can; `COURANT_REQUIRE_SIGNATURE=1` makes it refuse otherwise. ### Tamper evidence Every pack carries a SHA-256 of every input and re-derives byte for byte. A task edited after it was locked makes the verdict insufficient. ### Deterministic The same inputs give the same verdict bytes, on every platform measured. No model decides. ### Agents Over MCP the gate is read-only tools, confined to the folders you name. ### Isolation and deletion The gate is not a service: it holds none of your data. A private evaluation runs on its own runner; its report is signed and carries the deletion log. ## Network The rule: no Courant command opens a network connection unless that is its documented purpose, you ran it, and it names what it contacts before it does. Courant has no account, no telemetry and no service of its own: nothing is sent to Courant, ever. - `courant update` contacts github.com (the releases of `courantdev/courant`, and the download host GitHub redirects to). When: a packaged binary, when you run it without `--check`. A pip installation and `--check` contact nothing. It sends: it downloads the binary for your platform, the release's `SHA256SUMS` and its signature, and installs nothing unless the signature checks against the release key built in. Nothing about your runs. - `courant doctor --models` contacts openrouter.ai. When: only with `--models`. It sends: requests for OpenRouter's public model and endpoint listings, without a key. Nothing about your runs. - `courant test run --judge llm::` contacts openrouter.ai for `openrouter`; api.anthropic.com for `anthropic` (paid: refused unless `COURANT_ALLOW_PAID_LLM=1` is set). When: only with an `llm:` judge, and only once the model door lets that model judge (it must be measured for judging). Until then the command stops with exit 3 and contacts nothing. It sends: with your own API key: a request for the key's daily allowance, then each Courant Test task's text. - `courant spec extract TASK` contacts the provider the model door chooses: openrouter.ai. When: only when the door lets the call through. Until a model is measured for extraction, it stops with exit 4 and contacts nothing. It sends: the task's text you gave it. With the default `--data customer`, only to an endpoint that retains nothing. To report a security issue: https://www.courant.dev/contact?topic=security, or privately on GitHub, https://github.com/courantdev/courant/security/advisories/new. ## Licence and source Open source under the Apache License 2.0 (Apache-2.0): https://github.com/courantdev/courant. Releases: https://github.com/courantdev/courant/releases. Package: https://pypi.org/project/courant-dev/. Every release's `SHA256SUMS` is signed (Ed25519, `SHA256SUMS.sig.json`); the release key is `0493639167582138b1e28f188354301ff23c6c881cd064c778a2db5d5c821192`. The benchmark data is licensed CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/). ## What Courant is not - Not a solver: It runs no solver, mesher or setup agent. It reads what a run left behind. - Not an editor: It changes no case. A suggestion is printed and never applied. - Not a validation: It does not replace a validation experiment, and with no reference data it says so under what it did not check. - Not a guess: Where it lacks an input it says so: the verdict is insufficient, or the check is listed as not checked, never passed. - Not endorsed: No regulator or standards body has approved or endorsed Courant. - No regulator or standards body has approved or endorsed Courant. "Certified" on this site means measured against real solver runs with locked labels, not certified by any body. ## Pages - https://www.courant.dev/ : the verifier, shown working on real runs - https://www.courant.dev/benchmarks : the two newest studies in tables: four judges on the same runs given the same task, and Courant alone at scale; the method and the questions (the earlier studies are on /evidence) - https://www.courant.dev/docs : install: one pip line or one signed file; the commands verbatim; the verdicts and exit codes - https://www.courant.dev/test : the Courant Test: the corpus, any judge scored, every run, the pre-registered hypotheses - https://www.courant.dev/evidence : every number with its denominator and the runs it counts, and a real report - https://www.courant.dev/security : what it reads and never does on your machine, and the evidence pack - https://www.courant.dev/pricing : the gate is open source and free on your own machine, commercial use included; design partners' terms; teams and enterprises talk to us; the expected-savings model with its sources and assumptions - https://www.courant.dev/start : one form: have Courant verify your team's runs as a design partner, or score your agent on SilentBench - https://www.courant.dev/company : the company: three measured numbers, the founder, and what it says - https://www.courant.dev/company/mission : why the company exists: every answer has a bound, and code, not a model, decides each verdict - https://www.courant.dev/silentbench : SilentBench: physics-graded tasks for engineering agents, and the hidden split's commitment - https://www.courant.dev/silentbench/pre-registration : SilentBench v0's pre-registration: the hidden split's record, committed before any agent ran, and the method - https://www.courant.dev/legal/privacy : what the site and the gate collect, where it goes and how long it is kept - https://www.courant.dev/legal/terms : the terms of the site and of the gate - https://www.courant.dev/contact : one form: teams and enterprises, the founder, press, or a security issue - https://www.courant.dev/data/verdicts.json : the 31 certified runs and their verdicts, as JSON - https://www.courant.dev/data/benchmarks.json : /benchmarks' numbers as JSON, licensed CC BY 4.0 - https://www.courant.dev/data/release.json : the release as JSON: version, licence, where to get it, the install lines, the platforms, the signing key, the network rule - https://www.courant.dev/silentbench/pre-registration.json : SilentBench v0's pre-registration as JSON: the hidden split's record and RM-19's hypotheses, verbatim ## Contact hello@courant.dev