smtkit
smtkit is a small Rust toolkit for reproducible SMT workflows:
- Build constraints (typed IR in
smtkit-core). - Emit SMT-LIB2 (
smtkit-smtlib). - Run an external solver over stdio (optional).
- Capture artifacts (capability matrix, SMT2 scripts, models/cores/proofs) so solver-driven behavior is debuggable and comparable across solvers.
Why it exists
SMT integrations tend to go wrong in the same ways:
- Tooling silently depends on solver quirks (Z3 vs cvc5 behavior).
- Results are hard to reproduce (no stable script, no determinism hooks recorded).
- Debugging “why UNSAT?” is opaque (no unsat core, no minimal fragment, no provenance).
smtkit is built around the opposite posture: emit the script, run the solver, and keep the evidence.
Crates
smtkit: facade crate you depend on (re-exports the rest).smtkit-core: typed, backend-agnostic constraint IR.smtkit-smtlib: SMT-LIB2 s-expressions, script building, and an incremental stdio session.smtkit-z3: optional in-process Z3 backend (feature-gated).smtkit-ci: small CLI for CI + debugging (probe,smoke).
Quickstart: probe solver capabilities
If you have a solver on PATH (e.g. z3), run:
This prints JSON like:
- which command line was used (e.g.
z3 -in -smt2) - a capability matrix (best-effort):
check_sat_assumingget_modelget_unsat_coreget_proof(solver-dependent; primarily a debugging hook)- whether
:namedassertions appear in cores
You can also generate repro scripts:
Or write artifacts to disk:
If you want smtkit-ci to run the demo and capture a bounded result (including a proof preview),
use:
Notes on solver “proofs”
Some solvers support (get-proof) behind :produce-proofs. smtkit exposes this via the session API
and the capability probe (get_proof) so you can capture proof objects for debugging/provenance.
This is not a proof checker: verification of solver proofs (e.g. Alethe proof checking) is a separate layer.