Demo, all content is generated
Question

How do I let Claude Code look at my database without it being able to drop tables?

Solved · 961 views · asked by lily_chen · edited

I want Claude to see my real schema and some data so it stops guessing column names. But I read horror stories about AI deleting production data. What's the safe setup? It's a Supabase project with real customers (small bakery shop).

What I’ve tried

Currently I copy the schema from the dashboard SQL editor into the chat, which works but gets outdated.

Comment

3 answers

Marked as helpful by the asker
hannah_reyes · edited

Layered, from most to least important:

  1. Schema doesn't need data. Generate types and a schema dump into the repo: supabase gen types typescript --project-id <ref> > lib/database.types.ts. Claude reads the file; no connection needed. This solves 90% of the guessing.
  2. If it must query: Supabase MCP with --read-only (it runs queries as a read-only Postgres user) and --project-ref so it's scoped to one project.
  3. Better: point it at a dev project or local Supabase, never prod. Customer data (emails, addresses) shouldn't flow into a chat by default.
  4. Deny destructive commands anyway in .claude/settings.json, e.g. "deny": ["Bash(supabase db reset:*)", "Bash(psql:*)"].
Comment
Did 1 and 3. The types file alone already stopped most of the wrong column names. lily_chen · edited
+1 on types first. Regenerate them after every migration, or add it to your migration script. jb_supa · edited
Saved this whole answer. Types first is so simple. kimberly_j · edited
chidi_eze · edited

Agree with Hannah. One nuance: read-only still reads. If the MCP can see auth.users or an orders table, that data ends up in the model context. For a shop with customer data, local/dev is the answer, not read-only prod.

Comment
Good point, I hadn't thought about the customer data going into the chat itself. lily_chen · edited
mira_dev · edited

If you go the SQL route yourself (psql or another tool), create a dedicated role instead of using the postgres user:

create role claude_readonly login password '...';
grant usage on schema public to claude_readonly;
grant select on public.products, public.orders to claude_readonly;

Only the tables you list, and nothing in auth. Grants are something the database enforces, no matter what the model decides to do.

Comment