How to stop Cursor from wiping your database
Nothing quite matches the cold sweat of watching an AI agent run a terminal command with a little too much enthusiasm.
TL;DR A .cursorrules file blocks nothing when an agent decides to act. Protect your data with manual confirmations in the terminal, a strict shell wrapper and restricted SQL privileges.
It's a classic scenario: one prompt, a minor backend bug, and you look away for three minutes. Meanwhile, the agent decides the shortest way to get a test passing is to start again from a clean database. So it runs supabase db reset in the built-in terminal.
The result: local database wiped, test data gone. The migration you were halfway through writing goes with it, and nothing in the conversation thread warned you it was coming. On a client project, the half-day you've just lost still gets billed.
This isn't a bug in Cursor. It's simply what happens when you hand an agent a terminal and count on a text file to hold it back. Text isn't a safety mechanism; it's a preference, politely worded.
Why a simple .cursorrules file won't protect you
The first reflex after an accident is to add a rule to .cursorrules, the instructions file the agent rereads on every turn. You usually end up writing something like this:
Always ask for explicit confirmation before running any destructive database commands.
It looks solid. It's even in the right place. Yet it changes nothing, because that sentence describes a procedure instead of imposing a ban.
The illusion of the conditional rule
Read that sentence the way a language model does. You haven't forbidden the command; you've attached a condition to it. And a condition is a door: it tells you how to get through, it doesn't say you have to stay outside.
So the agent writes the command into a terminal block and asks you the question in the same breath. You click "Accept" thinking you're answering the question, while the button runs the command at the same time. The rule was followed to the letter, and the database is gone anyway.
The model's optimization logic
There's also a deeper incentive problem. The model optimizes for one thing: making the error in front of it go away. Faced with an inconsistent schema or a migration that won't apply, a reset is objectively the shortest route back to "green".
Your test data isn't part of that equation. It has no value to the model, because it has no way of knowing what that data represents. That's not negligence; it's missing information, and you don't fix missing information with a sterner sentence.
That's also why the accident nearly always happens locally. Nobody hands production credentials to an agent, yet everybody lets it work on a local database that isn't backed up. Paradoxically, the least protected environment is the one that ends up most exposed.
1. Switch to absolute bans in your rules
If text is still your first line of defense, turn your instructions into outright bans. Forget the "unless" and the "ask first".
The strict negative constraint
# Database safety
- NEVER generate, write, or suggest `supabase db reset` or `supabase db drop`.
- No exceptions. Do not ask for confirmation. Refuse to write the command. The difference is subtle but it matters: there's no permitted behavior left to negotiate, so nothing left to interpret. It's still not a guarantee, and I won't pretend otherwise. But it's a rule the model can no longer reason its way around, which is already more than a preference.
2. Lock down automatic execution in the terminal
Cursor's agent can run commands on its own to check its fixes. That's what makes the tool feel smooth, but it's also what turns a suggestion into an irreversible action.
The mandatory manual gate
Go to Settings > Features > Terminal (the exact location can vary with your version) and turn on mandatory confirmation before any command runs. Keep that setting on, even on the days it slows you down, because it's precisely when you lower your guard that the accident happens.
It takes nothing away from the agent's usefulness. It still reads your files and proposes commands, sparing you tedious digging through documentation. The only thing it loses is the ability to act while you're looking elsewhere, and that was the only thing you wanted to take away from it.
The cost is real: you'll click more. That's the trade you're accepting. On a throwaway project, it may not be worth it; on a client project, it always is.
3. Intercept critical commands at the shell level
The only rule an agent can't reinterpret is one it never gets to read. So move the constraint out of the model and into the environment that actually runs the commands.
A Zsh wrapper that blocks the command
supabase() {
if [[ "$1" == "db" && "$2" == "reset" ]]; then
echo "BLOCKED: supabase db reset is disabled."
return 1
fi
command supabase "$@"
} Add this function to your ~/.zshrc, reload it with source ~/.zshrc, and the command gets stopped before it even reaches Supabase.
A word of caution: this protection only covers shells that read your ~/.zshrc. Cursor's built-in terminal generally does, but a subprocess or a script that calls sh directly could slip past it. Duplicate the guard in ~/.bashrc and think of it as an effective speed bump, not an unbreakable wall.
The only real barrier: permissions
Shell tricks stop the accidents you've anticipated. Permissions stop the ones you haven't thought of, and those are always the ones that hurt.
Strip destructive privileges locally
The account your local environment connects with has no reason to be able to run a DROP. Likewise, production credentials have no business on your development machine, not even in a .env file only you ever open.
Backups need to run on a schedule, not on your memory. A development database you can rebuild with one command from a versioned seed file is no longer a loss, just a minute of work. As long as your test data only exists on your machine, it stays your weak point.
Put these three layers in place and whatever the agent types becomes secondary. It's the same logic behind any serious AI automation : constraints first, speed second. Skip the first step and you haven't automated anything; you've just moved the risk somewhere you can't see it.
Ready to secure your environment before the agent runs?
"Zero trust" isn't about distrusting the model; it's about organizing things so you don't need to trust it. Text suggests to the agent what you'd prefer; permissions decide what's possible. Build on the second, and you can finally stop reading every terminal block with your finger hovering over Escape.
👉 Need the same guardrails around the automations you run in production? Get in touch