Real-Time Formal Verification
for AI-Generated Code
PostToolUse hooks intercept every Write and Edit in Claude Code. Deterministic checks. Zero LLM. The AI can't bypass it because the hook 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 — blocks the write
- 3. AI sees: "SQL injection detected. Fix before proceeding."
- 4. AI rewrites with parameterized query
- 5. Cost: $0. Time: milliseconds.
How It Works
The hook fires after every Write and Edit. It reads the full file, scans the changed region, and blocks if it finds issues. The AI must fix them before proceeding.
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
- HookBlock + inject 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) | — | ✓ | ✓ |
| Blocks AI tool calls in real-time | — | ✓ | — |
| Claim extraction from code | — | — | ✓ |
| Multi-pass LLM verification | — | — | ✓ |
| Formal override of LLM verdicts | — | — | ✓ |
| Works without AI in the loop | ✓ | ✓ | — |
| Cost per check | $0 | $0 | ~$0.50–2 |
Try It Now
Run a full assessment on any project. The hooks come with the CLI.