Fake Data Guard
Install
Save this file as ~/.claude/skills/fake-data-guard/SKILL.md, or
.claude/skills/fake-data-guard/SKILL.md to scope it to one repo. Claude Code
auto-discovers it. Invoke with /fake-data-guard or by asking "could any fake
data reach production?".
Why this exists
Every project grows demo data. Seed scripts with plausible users, fixtures with realistic-looking metrics, a placeholder testimonial nobody removed. All of it is correct locally and radioactive in production.
The damage is asymmetric. A crash is embarrassing and recoverable. Published invented traction is a trust failure, and for anything that sells, reviews, or reports numbers it is the one mistake that cannot be walked back. It is also usually invisible: the fake row looks exactly like a real row.
The path is almost always short and boring. A seed script one keystroke from a migration command in a runbook. A fixture imported by a component that ships. A constants file someone reached for because the real query was not ready yet.
Step 1 — Find the fabricated data
Search for the shapes, not the word "fake". Fabricated data rarely labels itself.
Invented people. Realistic full names next to handles or emails in source:
rg -n "name:\s*['\"][A-Z][a-z]+ [A-Z][a-z]+['\"]" --type-add 'src:*.{ts,tsx,js,jsx,py,rb,go}' -tsrc
rg -n "@(example|test|demo|acme)\.(com|org|local)" -tsrc
Invented numbers. Hardcoded counts, ratings, revenue, follower counts:
rg -n "(downloads|stars|users|revenue|rating|reviews|followers|installs|customers)\s*[:=]\s*[0-9]{2,}" -tsrc
Invented words. Testimonials and quotes with no source:
rg -n "(testimonial|quote|review|says|praise)" -tsrc
The seeders themselves:
rg --files -g '*seed*' -g '*fixture*' -g '*factory*' -g '*mock*' -g '*demo*' -g '*sample*'
Read what each one WRITES, not just its name. A file called sample-data.ts may
be inert; a file called bootstrap.ts may create 500 users.
Step 2 — Trace the reach of each finding
For every candidate, answer one question: can this reach a real database or a real user? Trace it, do not assume.
rg -n "getProducts|SEED_|FIXTURES|DEMO_" --type-add 'src:*.{ts,tsx,js,jsx}' -tsrc
Follow every import. Classify honestly:
- REACHABLE — writes. A script or job that inserts fabricated rows into whatever database it is pointed at. Highest severity.
- REACHABLE — renders. Fixture data imported by shipped UI. It will be seen.
- DORMANT. Present but nothing imports it today. Still report it: dormant data is one careless import from reachable, and it will be reached for precisely when someone is in a hurry.
- CONTAINED. Provably test-only, by a guard you have READ, not by convention.
Watch for partial safety, which is the most dangerous result. A script that discards fabricated sellers but copies fabricated counts is not safe, and it will be described as safe by whoever wrote it.
Step 3 — Check whether anything actually stops it
For every REACHABLE-writes finding, look for a guard and read it:
- An environment check (
NODE_ENV, an explicit opt-in variable). - A target check: does it inspect the connection string and refuse a non-local host?
- An interactive confirmation.
Then check how easy the mistake is. Is it exposed as a friendly script name
(npm run seed)? Does documentation put it next to a command someone runs on a
real environment? Is it named similarly to a safe script? A guard's job is to
survive a tired person at 3am, not a careful person at noon.
NODE_ENV !== "production" is weak on its own. Local shells frequently have no
NODE_ENV while pointing at a production connection string. Prefer inspecting
the actual target.
Step 4 — Fix, in this order
- Delete anything fabricated that nothing needs. Least code, least risk.
- Guard what must stay. Refuse by default, inspect the real target, exit non-zero, and print what to run instead:
REFUSING: DATABASE_URL does not point at a local database.
target host: <host>
This script creates FABRICATED users and metrics. Local development only.
To populate a real environment, run instead: <the safe command>
- Separate. Move fabricated fixtures out of any directory shipped code imports from.
- Verify the guard fires. Run it against a production-shaped connection string and confirm it refuses and exits non-zero. Run it against a local one and confirm it still works. An unverified guard is decoration.
Step 5 — Report
Fabricated data found: <n> sites
REACHABLE-writes: <n> <- fix first
REACHABLE-renders: <n>
DORMANT: <n>
CONTAINED: <n>
Guards present: <yes/no, and whether you verified them firing>
Shortest path to production: <the actual command sequence>
That last line is the finding. "A seed script exists" is not alarming. "npm run seed is one line below db push in the recovery runbook and has no guard" gets
fixed today.
Rules
- Trace reachability; never assume a file is unused because of its name.
- Report dormant data too, with its severity honestly lowered.
- Never propose replacing fabricated data with better fabricated data. If a number is not real, the fix is to show nothing, or to show zero and say zero.
- An empty state is not a bug. "No reviews yet" outperforms an invented review the first time someone checks.
From Toolbay. Free to use, modify, and share. Keep this line and others can find it too.