░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░ ░░░░ ░░░░░░░░░ ░░░░░░░░░ ░░░░░░░░░ ░░░░░░░░░ ░░░░ ░░░░░░░░ ░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░ ░░░░ ░░░░░░░ ▒▒▒▒▒▒▒ ▒ ▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒ ▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒▒▒▒▒▒▒▒▒▒▒▒▒ ▒▒ ▒▒▒▒▒▒▒ ▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓ ▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓ ███████ ██ ████████ ███████████ ███████████ ████ ████████ ████ ████████ ██████████████ ██████████████ █ █ ███████ ███████ ████ ████████ ████ ███████████ ████████████ █████████ ████ ████████ ████████ ████████ ████ ███████ ██████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████
Your AI agent just wrote
const STRIPE_KEY = "sk_live_51H8xj2..."
into src/utils/helpers.ts.
It was trying to "add payment support."
It's been in your public repo for 6 hours.
Someone in Minsk is running a $47,000 crypto arbitrage bot on your keys right now.
Agent: "I'll add a debug endpoint."
app.get('/debug', (req, res) => {
res.send(eval(req.query.code))
})
It genuinely thought this was helpful.
It just opened an RCE vector on your production server because you asked it to fix a typo.
You installed Cursor. You vibe-coded for 6 hours.
You shipped 4,000 lines.
You reviewed exactly 0 of them.
Your agent imported `child_process` in 17 files, hardcoded 3 API tokens, and wired the auth module directly to the raw database layer. You don't know any of this happened. Yet.
THE MATH ISN'T MATHING.
AGENTS GENERATE CODE FASTER THAN HUMANS CAN REVIEW IT.
YOU'RE NOT DOING CODE REVIEW. YOU'RE RUBBER-STAMPING MACHINE OUTPUT.
Every time an AI agent tries to save a file, WatchLLM intercepts the write before it touches disk. It parses the code into an AST. It runs a deterministic ruleset. It decides: ALLOW or BLOCK. In under 10 milliseconds. No network. No ML. No vibes. Just cold, hard, auditable logic.
Not regex. AST-level analysis. Distinguishes const key = "sk-live-xxx" (BLOCK) from const key = process.env.STRIPE_KEY (ALLOW). Knows the difference between a leak and a legitimate retrieval.
const OPENAI_KEY = "sk-proj-..."const DB_URL = "postgres://admin:pw@prod"
Blocks imports of child_process, vm, eval, and any module you declare off-limits. AST-aware — it knows a comment mentioning child_process isn't the same as actually importing it.
import { exec } from 'child_process'const { fork } = require('child_process')
Declare what each module can import. auth/ can talk to db/public/. auth/ cannot touch db/internal/. Your agents don't know your architecture. WatchLLM does.
// in src/auth/login.ts:import { rawQuery } from '../../db/internal'
Requires explicit auth guards before any protected database mutation. No auth check? No save. Your agent can't accidentally wire a public endpoint directly to a DELETE FROM users query.
app.post('/delete-account', handler)
Shadow mode. Too scared to block outright? Run WatchLLM in observation mode. It logs every violation to .watchllm/logs/violations.jsonl without blocking a single save. See what your agents are really doing. We guarantee you'll switch to enforce mode within 48 hours.
# Drop this in your repo root. Done. rules: - secret_literal: mode: enforce # block secrets. always. - forbidden_import: mode: enforce imports: - child_process - vm - repl - boundaries: mode: shadow # log first, block later - auth_flow: mode: enforce
$ watchllm evaluate src/auth/login.ts --strict WatchLLM Kernel Evaluation ┏━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ Rule ┃ Result ┃ Detail ┃ ┡━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩ │ secret_literal │ PASS │ No hardcoded credentials detected │ │ forbidden_import │ PASS │ All imports within allowlist │ │ boundaries │ BLOCK │ auth/login.ts > ../../db/internal/query.ts │ │ auth_flow │ PASS │ Auth middleware confirmed │ └───────────────────┴────────┴───────────────────────────────────────────┘ BLOCKED: 1 violation. Save denied. Evaluated in 3.2ms. Snapshot saved to .watchllm/snapshots/
GPT-4, Claude Opus, Gemini Ultra — doesn't matter. They all hallucinate. They're next-token predictors, not engineers. They don't know your codebase. They're improvising jazz on your production database. The best models just improvise more convincingly — which makes them more dangerous, not less.
You reviewed the first 40 lines. Then you got tired. Then the diffs got bigger. Then you started trust-merging. We've all been there. Agents write hundreds of lines in seconds. Humans review at maybe 200 lines per hour with full attention. The math doesn't work. You are a rubber stamp with imposter syndrome.
CI/CD catches things after they're committed. After they're pushed. After they're in your git history. Forever. You can rotate the key — congrats. The 14 people who cloned your repo in the 3 hours between push and detection? They all have your keys now. Pre-commit is the only enforcement that matters.
10 milliseconds. That's 1/100th of a second. Your agent spent 4.7 seconds generating that code. Your TypeScript LSP took 200ms to type-check it. You just waited 11 seconds for a test suite to run. And you're worried about 10ms? That's the time it takes light to travel 3,000 kilometers. Get a grip.
"We'll add auth later." "We'll add tests later." "We'll add monitoring later." Every post-mortem ever written contains one of these sentences. The best time to add a guardrail is before you need it. The second best time is right now, 15 lines of YAML and one pip install away.
If the kernel crashes, times out, or can't parse — the save proceeds. Availability over enforcement. Start in shadow mode (log-only, zero blocking) for a week. Review the logs. Tune the rules. Then flip to enforce. You're not jumping into the deep end. You're dipping a toe in. The water's fine. And it's full of all the shit your agent tried to save.
STAR ON GITHUB · READ THE DOCS · v0.1.0 — EARLY, AGGRESSIVE, HUNGRY