
Product
Socket Now Protects the Firefox Extension Ecosystem
Socket is bringing experimental protection to Firefox, scanning 97,000+ extensions in Mozilla's official directory for malware and risky updates.
Does a Dafny lemma actually mean what a natural language requirement says? Dafny can verify proofs, but it can't verify meaning. Claimcheck fills that gap.
Does a Dafny lemma actually mean what a natural language requirement says? Dafny can verify proofs, but it can't verify meaning. Claimcheck fills that gap.
Someone else (Claude Code, a human, any agent) writes the lemmas and claims "requirement X is covered by lemma Y." Claimcheck verifies that claim via a round-trip: informalize the lemma back to English (without seeing the requirement), then compare.
Blog post: claimcheck: Narrowing the Gap between Proof and Intent.
npm install -g claimcheck
or
npm install
npm link
Structural separation — different models for informalization and comparison:
1. Extract mapped lemmas from claims .dfy file
2. Batch informalize all lemmas (haiku) — does NOT see requirements
3. Batch compare back-translations against requirements (sonnet)
4. Report: confirmed / disputed
--single-prompt)Prompt-level separation — one model does both passes sequentially:
1. Extract mapped lemmas from claims .dfy file
2. For each mapping: single LLM call with two-pass prompt
a. Pass 1: informalize the lemma (before seeing the NL requirement)
b. Pass 2: compare, check vacuity, flag surprising restrictions
3. Report with richer verdicts: JUSTIFIED / PARTIALLY_JUSTIFIED / NOT_JUSTIFIED / VACUOUS
eval/bench-cc.js)Same single-prompt approach piped through claude -p — no structural or prompt-level separation (the model sees everything at once). Useful for comparing whether look-ahead matters.
# Two-pass audit (default)
claimcheck \
-m test/integration/mappings/counter.json \
--dfy test/integration/claims/counter.dfy \
-d counter
# With explicit module (needed for --verify with module-based .dfy files)
claimcheck \
-m test/integration/mappings/counter.json \
--dfy test/integration/claims/counter.dfy \
--module CounterDomain -d counter --verify
# Single-prompt audit
claimcheck \
-m test/integration/mappings/counter.json \
--dfy test/integration/claims/counter.dfy \
-d counter --single-prompt --json
Pre-extract your claims and pipe them in:
echo '{
"claims": [
{
"requirement": "The counter value is always non-negative",
"lemmaName": "CounterNonNegative",
"dafnyCode": "lemma CounterNonNegative(m: int)\n requires Inv(m)\n ensures m >= 0\n{}"
}
],
"domain": "counter"
}' | claimcheck --stdin
import { claimcheck } from 'claimcheck';
const { results, tokenUsage } = await claimcheck({
claims: [
{
requirement: 'The counter value is always non-negative',
lemmaName: 'CounterNonNegative',
dafnyCode: 'lemma CounterNonNegative(m: int)\n requires Inv(m)\n ensures m >= 0\n{}',
},
],
domain: 'counter',
});
# All test projects
node test/integration/run-all.js
# Single test project
node test/integration/run-all.js counter
# Run benchmarks
node eval/bench.js --runs 3 --label two-pass
node eval/bench.js --runs 3 --label single-prompt --single-prompt
node eval/bench-cc.js --runs 1 --label cc-sonnet
# Run a single domain or lemma
node eval/bench-cc.js --runs 1 --label test --domain counter
node eval/bench-cc.js --runs 1 --label test --domain counter --lemma CounterNonNegative
# Compare results
node eval/compare.js two-pass single-prompt
node eval/compare.js two-pass cc-sonnet
| Flag | Description |
|---|---|
-m, --mapping <path> | Path to mapping file (JSON: [{requirement, lemmaName}, ...]) |
--dfy <path> | Path to claims .dfy file (contains the lemmas) |
--module <name> | Dafny module name (optional; needed for --verify with module-based files) |
-d, --domain <name> | Human-readable domain name (default: from --module or .dfy filename) |
--json | Output JSON instead of markdown |
--single-prompt | Use single-prompt claimcheck mode (one call per pair) |
--model <id> | Model for single-prompt mode (default: sonnet) |
--verify | Also run dafny verify on each lemma |
--informalize-model <id> | Model for back-translation in two-pass mode (default: haiku) |
--compare-model <id> | Model for comparison in two-pass mode (default: sonnet) |
--stdin | Read JSON from stdin (pure claimcheck, no file extraction) |
-v, --verbose | Verbose API/verification logging |
For each mapping entry, one of:
| Status | Meaning |
|---|---|
| confirmed | Round-trip passed — lemma faithfully expresses the requirement |
| disputed | Round-trip failed — discrepancy between lemma meaning and requirement |
| verify-failed | Dafny verification failed (only with --verify flag) |
| error | Lemma not found in source |
In single-prompt mode, disputed results include richer detail: verdict category, vacuity analysis, and surprising restrictions.
| Project | Claims file | Domain module |
|---|---|---|
| counter | test/integration/claims/counter.dfy | CounterDomain |
| kanban | test/integration/claims/kanban.dfy | KanbanDomain |
| colorwheel | test/integration/claims/colorwheel.dfy | ColorWheelDomain |
| canon | test/integration/claims/canon.dfy | CanonDomain |
| delegation-auth | test/integration/claims/delegation-auth.dfy | DelegationAuthDomain |
Each claims file includes its domain from ../dafny-replay/. Mappings in test/integration/mappings/.
Accuracy across 5 domains (counter, kanban, colorwheel, canon, delegation-auth) with 36 requirement-lemma pairs, including 8 deliberately bogus lemmas (tautologies, weakened postconditions, narrowed scope):
| Variant | Accuracy | Time/run | API calls/run |
|---|---|---|---|
| Two-pass (default) | 96.3% (104/108) | ~108s | 2 (batch informalize + batch compare) |
| Single-prompt | 86.1% (31/36) | ~353s | 36 (one per pair) |
Claude Code (bench-cc) | 69.4% (25/36) | ~693s | 36 (one claude -p per pair) |
Two-pass had 3 runs; single-prompt and Claude Code had 1 run each.
Key takeaways:
ANTHROPIC_API_KEY environment variable (or use --vertex / --bedrock)dafny in PATH (only for --verify).dfy files include domain files from ../../dafny-replay/)By default, claimcheck calls the Anthropic API directly using ANTHROPIC_API_KEY. You can route through other backends instead:
--vertex — Vertex AI. Requires --vertex-project (or GOOGLE_CLOUD_PROJECT_ID); region defaults to us-east5 (or GOOGLE_CLOUD_REGION).--bedrock — AWS Bedrock. Region defaults to us-east-1 (or AWS_REGION); credentials come from the standard AWS credential chain (env vars, ~/.aws/credentials, SSO, IMDS). Default model IDs use the us. cross-region inference profile prefix:
us.anthropic.claude-haiku-4-5-20251001-v1:0us.anthropic.claude-sonnet-4-6Override any default with --model, --informalize-model, or --compare-model.
FAQs
Does a Dafny lemma actually mean what a natural language requirement says? Dafny can verify proofs, but it can't verify meaning. Claimcheck fills that gap.
The npm package claimcheck receives a total of 2,377 weekly downloads. As such, claimcheck popularity was classified as popular.
We found that claimcheck demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Product
Socket is bringing experimental protection to Firefox, scanning 97,000+ extensions in Mozilla's official directory for malware and risky updates.

Research
/Security News
Three compromised Rust crates pulled in a malicious dependency that downloaded and executed cross-platform malware during Cargo builds.

Research
/Security News
Socket uncovered 77 linked Firefox extensions, including 40 that steal wallet secrets or credentials and 37 deceptive sports-score shells.