What it broke
create view public.…Claude made a Supabase view without security_invoker. Anyone with the anon key could read the rows behind it. I caught it the next day.
git add -AAnother Claude session was working in the same folder. Half of its unfinished changes went into my commit.
pkill -fMeant to restart one dev server. The pattern matched processes from my other sessions too.
"deployed, it's live"The deploy command exited 0 while production still served the old bundle 13 minutes later. Nobody had looked.
The rule against each one was already in my CLAUDE.md. Rules get skipped when the model is busy. A hook runs before the command, every time.
You can judge the approach before paying. Seatbelt Lite is the public version, with its tests, and this article shows one of the guards.
What each hook refuses
Auto mode now blocks some shell commands on its own, through a classifier. Its docs describe no check of what Claude tells you at the end of a turn, which is what the first hook covers. The others are fixed rules: the same command or SQL gets the same answer in any mode.
- "It's live" without checking
- If Claude deployed during the turn and says it's live without curling the URL or reading the deployment status, it's sent back to check first.
- SQL sent through MCP
DELETEorUPDATEwithoutWHERE,TRUNCATE, and on Supabase: views orSECURITY DEFINERfunctions reachable byanon, tables created without RLS. Checked before the SQL is sent, not by the advisor the next day.- Shell commands
rm -rfon/,~or., force push,reset --hard,clean -f,git add -A,git commit -a,pkill -f,curl | sh,DROPfrom the shell,supabase db reset --linked, andcat .env.rm -rf node_modulesstill goes through. Deterministic, whatever mode you run in.- API keys in code
- Anthropic, OpenAI, Stripe live, AWS, GitHub, Supabase service role and a few more, anywhere except
.envfiles. This one hasn't saved me yet. I'd rather not find out.
Install
python3 install.py --project # this project only
python3 tests/run_tests.py # 136 checks
Python 3.9+ standard library and nothing else. No network call. It's 277 lines across four plain scripts, and you can read them before you run the installer. Your settings.json is backed up first, and --uninstall removes the scripts and their hooks. macOS only for now: Linux and Windows aren't tested.
It's mostly regex, and you could write it yourself in an afternoon. You can also start for free with Seatbelt Lite (MIT). Here's what the 14 € adds:
| Blocked | Lite | 14 € |
|---|---|---|
| "It's live" after a CLI deploy (vercel, wrangler, netlify, fly, firebase) | yes | yes |
"It's live" after git push, npm run deploy or an MCP deploy | no | yes |
Supabase view readable by anon | yes | yes |
SECURITY DEFINER functions, tables without RLS | no | yes |
DELETE or UPDATE without WHERE, TRUNCATE | no | yes |
rm -rf on /, ~, $HOME, force push, git add -A | yes | yes |
reset --hard, clean -f, pkill -f, curl | sh, cat .env and the rest of the list above | no | yes |
| API keys written into code | no | yes |
If you only deploy from the CLI and don't send SQL through MCP, Lite may be all you need.
What it won't do
- It's a regex net
- It catches the common forms an agent types and misses others. For real isolation, use a container.
- A curl counts as a look
- Any curl to a non-local URL satisfies the deploy check, and the hook doesn't read the response. It makes Claude look. What Claude concludes from it is up to Claude.
- Only want shell safety?
- dcg and cc-safety-net are free and built for that. I haven't compared them rule by rule. Buy this for the deploy check and the SQL rules.
- It won't trap Claude in a loop
- The deploy check sends Claude back once per turn, then lets it stop. If a script goes missing, nothing gets blocked.
Questions
- How do I stop Claude Code from force pushing or running rm -rf?
- Deny rules in
settings.jsonsuch asBash(git push --force*)block the exact patterns you list and miss other spellings. A PreToolUse hook that exits with code 2 blocks the call before it runs, whatever the model makes of your rules. Seatbelt Lite, free on GitHub, does this forrm -rfon/,~and., force push,git add -Aandgit commit -a. - Why does Claude Code ignore rules in my CLAUDE.md?
- CLAUDE.md is text the model reads at the start of a session. In the middle of a long task it can skip a rule, and nothing stops the command. A hook is a script Claude Code runs before the tool call, so the rule holds even when the model forgets it. Which rules to move to hooks.
- How do I make Claude Code check a deploy before it says "it's live"?
- With a Stop hook. It reads the turn, and if a deploy ran and the last message says the site is live with no
curl,vercel inspector browser check afterwards, Claude is sent back to look. Any curl counts as a look, so it forces a check without judging the result. How it works. - Can Claude Code create a Supabase view that leaks data?
- Yes. A view in
publicruns with its owner's rights unless it setssecurity_invoker = true(Postgres 15+), so ifanoncan select from it, the RLS on the table underneath doesn't apply. Seatbelt refuses that view when the SQL goes through an MCP tool. - Is it free?
- Seatbelt Lite is free and MIT licensed. Seatbelt, with the SQL rules, the longer shell list and the API key guard, is 14 € paid once. Deploy Proof, 19 €, replaces the deploy check with one that also catches "it's pushed" and "tests pass", in English and French.
Guides
14 €, paid once
Buy Seatbelt for 14 €If it doesn't work on your setup, reply to the receipt and I'll fix it or refund you.
Personal and commercial use, on any number of your machines.
Deploy a lot? Deploy Proof, 19 € replaces the "it's live" hook. It also catches "it's pushed" and "tests pass", in English and French, and tells Claude the exact command to run. Sold separately, works without the other hooks. Same deal: fix it or refund you.