Real-Time Formal Verification
for AI-Generated Code
PostToolUse hooks check every Write and Edit in Claude Code. Deterministic checks. Zero LLM. Findings land in the AI's context the moment it writes the bug, and it runs outside the AI's control.
The Problem
AI writes code. That code ships. Nobody checks if the AI hallucinated a SQL injection, used a non-existent API, or forgot error handling.
Without Hooks
- 1. AI writes
SELECT * FROM users WHERE id = " + userId - 2. Code passes review (human or AI — both miss it)
- 3. Ships to production
- 4. Vulnerability discovered in prod (or by attacker)
- 5. Incident response, data breach, trust loss
With Hooks
- 1. AI writes the same bad code
- 2. Hook fires instantly — findings injected into the AI's context
- 3. AI sees: "Assay found 1 potential issue: SQL string concatenation"
- 4. AI rewrites with parameterized query
- 5. Cost: $0. Time: milliseconds. Your session never gets bricked by a false positive.
How It Works
The hook fires after every Write and Edit. It reads the full file, scans the changed region, and injects any findings straight into the AI's context. Advisory by design: the AI fixes what it sees, and a false positive can never brick your session.
When code is clean
When code has issues
What It Catches
Five deterministic checkers that run in under 100ms. Pure regex. No LLM, no network call, no hallucination possible.
| Check | What It Detects | Severity | Languages |
|---|---|---|---|
| SQL Injection | String concatenation in SQL queries instead of parameterized statements | critical | All |
| API Misuse | Non-existent methods: .flatten(), .contains(), Object.fromPairs() | critical | JS/TS, Python |
| Error Handling | Async functions with no try/catch or .catch() | high | JS/TS |
| Input Validation | Direct use of req.body/params/query without validation | high | JS/TS |
| Null Safety | Non-null assertions (value!.prop) covering nullable access | medium | TypeScript |
Two Enforcement Points, One Verifier
The same formal verifier powers both real-time hooks and batch assessment. One engine, two doorways.
Development-Time
- HookPostToolUse on Write/Edit
- FormalClaimless pattern scanning
- FormalDiff-aware region filtering
- HookAdvisory injected on findings
formal-verifier.ts
Pure TypeScript
Zero dependencies
Can't hallucinate
Assessment-Time
- LLMMulti-pass claim verification
- FormalPost-pass overlay on LLM verdicts
- FormalOverride when formal disagrees
- FormalReal coverage stats in output
Setup in 30 Seconds
Install the CLI, register the hook, and every Write/Edit gets verified automatically.
Why Not Just Use a Linter?
Linters check syntax. Assay checks what the AI claimed vs what the code does.
| Capability | ESLint / Biome | Assay Hooks | Assay Assess |
|---|---|---|---|
| Syntax & style checks | ✓ | — | — |
| SQL injection detection | Plugin | ✓ | ✓ |
| API misuse (non-existent methods) | — | ✓ | ✓ |
| Real-time findings in the AI’s context | — | ✓ | — |
| Claim extraction from code | — | — | ✓ |
| Multi-pass LLM verification | — | — | ✓ |
| Formal override of LLM verdicts | — | — | ✓ |
| Works without AI in the loop | ✓ | ✓ | — |
| Cost per check | $0 | $0 | ~$1–10 by repo size |
Try It Now
Run a full assessment on any project. The hooks come with the CLI.