Veriphy
Certified computer algebra for Lean 4, with agent skills that turn a physics or math statement into a machine-verified proof.
Veriphy connects SageMath and Lean 4 using the skeptical architecture: Sage is an untrusted oracle. Sage finds
what is expensive to find, such as coefficients, squares, multipliers, witnesses, closed forms and intermediate
expressions. A Lean tactic block built from that data is checked by the kernel, or rejected. Sage can be wrong, buggy
or malicious and your proofs stay valid. No sorry, ever.
Veriphy ships building blocks, procedures and skills, not ready-made certificates. Each certificate is created for the goal at hand, by an agent or by you, from a short Sage script. The script's output is checked by Lean, and the emitted proof is plain Lean that builds without Sage.
How it looks
import Veriphy
example (a b : ℝ) : 0 ≤ a ^ 2 * b ^ 2 - 2 * a * b + 1 := by
sage_run "proof = nlinarith([sq_nonneg(x0*x1 - 1, problem)])"
Lean extracts the goal and hypotheses into a problem, here with x0 = a and x1 = b. The script uses Sage and
Veriphy's toolkit to build a Lean tactic block, and assigns it to proof. Lean runs the block and checks it. It also
rejects sorry, rejects any axiom beyond the standard three, and replays the printed text. Then Lean offers the
Sage-free replacement to commit:
Try this: nlinarith [sq_nonneg (a * b - 1)]
Scripts usually live in your project's .veriphy/certificates/ directory and run with
sage_run file "<name>.sage".
What Veriphy provides
| Piece | What it is |
|---|---|
sage_run |
The tactic: runs a proof script against the goal, checks the emitted block, emits the replacement |
Toolkit (veriphy.toolkit) |
Problem binding, Lean emitters (linear_combination, sq_nonneg, nlinarith, calc, case splits, witnesses, refutations, …), and exact solvers (rational LP, SOS from an SDP) |
Recipes (prompts/recipes/) |
One per technique, each with when to use it, a tested template, a worked example and failure modes. Covers ideal membership, Farkas refutation, SOS, factorization rewrite, witnesses, hint search, calc derivations, case splits, matrix identities, sums by induction, rational inequalities, transcendental rewrites, derivatives and ODE solutions |
| Translation tables | Lean terms to Sage in three namespaces: the mathlib core, library packs (physlib) active when the library is imported, and the project's own entries in .veriphy/translations/, each checked by #veriphy_check_translations |
VeriphyCheck |
Mathlib-only kernel checkers (decide +kernel) with soundness theorems, for matrix products, brackets, traces, structure constants and primality certificates too large for entrywise proofs |
| Coverage | #veriphy_coverage measures which statements of a corpus translate without opaque atoms, and ranks the heads that do not |
| Skills | prove (statement to verified proof, end to end) and certify (build one certificate with sage_run) |
| Catalog | sage -python -m veriphy.certificates list lists a project's saved scripts, so they get reused |
| Advisory oracle | symbolic_check, matrix_check, solve, run_script: Sage as guidance while formalizing, never transcribed into proofs |
Committed proofs contain only the emitted replacements, so they build with Lean and mathlib alone, with no Sage installed. CI never needs Sage.
Setup
Prerequisites: SageMath (10.x, with sage on PATH) and the Lean
toolchain manager elan.
- Install the Sage daemon into SageMath:
sage -pip install veriphy
echo '{"id":1,"method":"ping"}' | sage -python -m veriphy.sage_server
- Require Veriphy from your Lake project (
lakefile.toml), pinned to a release tag:
[[require]]
name = "veriphy"
git = "https://github.com/georgedouzas/veriphy"
rev = "0.2.0"
Then run lake update && lake exe cache get && lake build, and add import Veriphy.
- Install the skills (below), if you work with an agent.
The tactic starts one daemon per Lean process, as sage -python -m veriphy.sage_server. Set VERIPHY_SAGE_CMD to the
sage executable if it is not on PATH. Set VERIPHY_SAGE_TIMEOUT (seconds, default 150) to bound each request.
Usage
Build a certificate:
- Inspect what the script will see:
sage_run "print(goal_kind, goal); print(hyps); print(atoms); proof = 'sorry'"
It fails on purpose, and the error shows the problem.
2. Pick a recipe from the index in prompts/prove.md (step 3c).
3. Copy the recipe's template from prompts/recipes/templates/ into your project's
.veriphy/certificates/, and adapt the lines marked EDIT.
4. Run it with sage_run file "<name>.sage", and iterate on the feedback. A failure shows the script's
output, the Lean text it built, and Lean's error.
5. Replace the sage_run call with the emitted Try this: block, and keep the script for reuse.
Reuse: sage -python -m veriphy.certificates list prints your project's scripts (name, technique, goal shape,
description), and … show <name> prints one. A saved script reads the bound problem, so it runs unchanged on any
goal of the same shape.
The full procedure is in prompts/certify.md.
Skills
prove: turns a formal Lean statement, an informal statement, or a backlog item from a repo you supply into a verified proof. It formalizes with lie detection (round-trip and numeric checks), builds certificates withcertifywhen needed, verifies, and reportsproved,blocked-library-gap,blocked-missing-building-blockorstatement-suspect. You own the outcome: it opens no PRs and keeps no state.certify: builds one certificate for one goal withsage_run. It reuses the project's saved scripts, follows the recipes otherwise, and saves what works in.veriphy/certificates/.
The skill logic is plain, agent-agnostic markdown (prompts/prove.md, prompts/certify.md, prompts/recipes/).
The skills/ files are thin Claude Code adapters.
Claude Code plugin (recommended). The repo is its own single-plugin marketplace:
claude plugin marketplace add https://github.com/georgedouzas/veriphy
claude plugin install veriphy@veriphy
Then use /veriphy:prove <statement> and /veriphy:certify from any project, or just ask "prove that …". Use the git
URL rather than a local clone, because a clone's path also copies its built .lake/ (about 8 GB) into the plugin
cache.
Manual copy (Claude Code, no plugin):
git clone https://github.com/georgedouzas/veriphy ~/veriphy
mkdir -p ~/.claude/skills && cp -r ~/veriphy/skills/prove ~/veriphy/skills/certify ~/.claude/skills/
export VERIPHY_HOME=~/veriphy # in your shell profile
Any other agent (Cursor, Copilot, a plain LLM loop): point it at prompts/prove.md. Nothing in the playbooks is
Claude-specific. Inside this repository, the project-scoped copies in .claude/skills/ load automatically.
Developing Veriphy
The repository is generated from copier-modern-python, and
copier update pulls template changes. The Python code follows openspec/constitution.md.
git clone https://github.com/georgedouzas/veriphy && cd veriphy
lake exe cache get && lake build
sage -pip install -e . # the tactic now uses this checkout's daemon
uv sync # development tools
uv run nox -s checks # ruff, mypy, bandit, docstrings, dependency audit
uv run nox -s tests # pytest and doctests on SageMath's interpreter
lake build VeriphyTest # Lean suite: kit (no Sage), sage_run examples, the benchmark
lake build VeriphyTest.Kit # the kit alone, no Sage needed
VeriphyTest/Benchmark.lean holds every problem the former certificate tactics solved, each now solved by a recipe
template through sage_run, with replay on. See the developer guide for how the pieces
fit and how to add a recipe or a toolkit building block.
Layers
Veriphy/ Lean library: sage_run, problem extraction, closeAndEmit (checks, replay), the daemon bridge
src/veriphy/ The `veriphy` Python package: the Sage daemon, the toolkit, the certificate catalog
VeriphyCheck/ Mathlib-only kernel checkers with soundness theorems, bundled by scripts/bundle_check.py
coverage/ Lake project measuring translation coverage on Physlib and mathlib corpora
prompts/ Playbooks (prove, certify) and recipes with templates — agent-agnostic markdown
skills/ Claude Code adapters for the playbooks
Protocol
The daemon reads one JSON request per line on stdin and writes one response per line on stdout. Every response carries the package version. The methods are:
ping;run, which runs a proof script against a serialized problem and returns its Lean text and output;- four advisory methods,
symbolic_check,matrix_check,solveandrun_script.
Advisory output is guidance for formalization and is never transcribed into a proof. Scripts run with the daemon's own privileges. This is deliberate: the daemon is a user-launched, untrusted oracle, and the trust boundary is the Lean kernel.
Status
The general route (sage_run, the toolkit, recipes and skills) solves every problem the former bespoke tactics
solved: 32 benchmark problems, including gauge-anomaly Farkas systems, sums of squares of field strengths and
eigenvector witnesses. The pipeline has cleared a real Physlib backlog item end to end (isBounded_iff_of_𝓵_zero).
Relationship to LeanSage
LeanSage solved the Lean↔Sage communication problem with a broad
translation pipeline (MathAST), but its flagship by sage mode closes goals with sorry (a trusted oracle). Veriphy
does what LeanSage does not: kernel-checked certification and the agent loop.
Veriphy's symbolic translation follows LeanSage's coverage tables (MIT License, credited in
Veriphy/Kit/Symbolic.lean). Scripts see each hypothesis and the goal both as polynomials over atoms and as Sage
symbolic expressions: rational functions, sqrt/exp/log/trigonometric functions, abs, pi, I, range sums,
matrix literals, determinants and polynomial evaluation. The domain conditions those expressions need come with the
hypotheses that discharge them. One deliberate difference is that abs is the absolute value of its own type
(LeanSage maps it to Int.natAbs).
The design rationale is in the user guide.