One catch per distinct rule. The hook's verbatim output, the write it blocked, and the fix that landed instead — never the rule's source.
Verify it yourself
Don't take the agent's word for it. These catches aren't testimonials — they're deterministic rules the hook runs on every write, every session, regardless of what the model remembers or intends.
Install the plugin. Tell your agent to write return value as User, or to wire a service_role key into client code, or to add 'use client' to a layout file. Watch the write fail with the same kind of message you see in the records below. Every enforcement entry on this page is a rule you can trigger in your own terminal.
That's the difference between a quote and a check you can run.
What the hooks catch — 8 shipped rules, 5 stacks. These are the catches with a real session behind each one; the full rule set is larger than this page.
| Rule class | What it prevents | Stack |
|---|---|---|
| Return-type assertion (as T) | Silent type lie — compiler sees T, runtime may not | TypeScript |
| Double cast (as unknown as T) | Bypassed narrowing — unknown treated as T without a check | TypeScript |
| Non-null assertion (!) | Runtime null deref — the undefined path is asserted away, not handled | TypeScript |
| Lazy Function / Object type | Unchecked signature — argument shape is invisible to the type system | TypeScript |
| SQL template literal with interpolation | SQL injection — user input assembled directly into the query string | SQL |
| service_role key in client code | RLS bypass / cross-tenant data leak — the master key ships to the browser | Supabase |
| 'use client' on a page or layout | Broken server-component boundary — RSC benefits silently lost | Next.js |
| Bare except Exception | Swallowed failures — any error passes silently, nothing gets logged | Python |
A `return ... as T` cast blocked at write time; the fix was a real type guard, not a silenced rule.
An `as unknown as T` the edit merely carried over from existing code still got blocked — and replaced with a mapper.
A `tab.children!` blocked at write time; optional chaining went in instead.
A bare Function-shaped type in an API route blocked at write time; the helper got rewritten with a specific signature.
The hook blocked an interpolated SQL string — twice — until the query became a fixed prepared statement.
Three write attempts blocked; the agent reverted to the clean committed state and flagged the RPC route instead of forcing a hack.
A layout about to become a client component got blocked; the interactive part became its own component instead.
The rules aren't TypeScript-only — a Python script's blanket exception handler got blocked the same way.
I tried to patch something fast and wrong. The system refused the write and told me the proper move — so the shortcut never shipped.