data-change-script
Skill0 starsChanged 52 days agoMITView on GitHub
Write or review a script that modifies real data — a backfill, migration, cleanup, bulk correction or one-off fix. Use whenever a change cannot be expressed as a code deploy and has to be applied to stored rows, and before running any script someone else wrote against real data.
In this repository17 other files it gives its agents.
- access-control-proofSkill
- agent-instructionsSkill
- contract-changeSkill
- deploy-safetySkill
- design-critiqueSkill
- evidence-layersSkill
- interface-craftSkill
- issue-ledgerSkill
- mobile-field-readinessSkill
- offline-first-syncSkill
- parallel-worktreesSkill
- requirements-elicitationSkill
- root-cause-investigationSkill
- solution-architectureSkill
- ux-state-coverageSkill
- versioned-publishingSkill
- skill-nameSkill
The file
We split this skill into the rules it gives an agent
11 rules. About 0 are common, 8 are distinctive, and 3 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈8
Distinctive · estimate
This author's own choices. Worth a look.
3
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 18
Never the other way round, and never --dry-run as the opt-in.
- Distinctive: line 53
Never blind-append to a list, increment a counter, or add a tag without checking.
- Very specific: line 60
Put the filter in the query, not in a post-fetch if.
- Very specific: line 72
Before the first --execute:
- Distinctive: line 76
Prefer soft changes — set a flag, move to an archive collection — over hard deletes.
- Distinctive: line 85
Run with the narrowest credential that works.
- Distinctive: line 87
If the script needs a secret, read it from the environment or a secret store at run time.
- Distinctive: line 93
Commit the script even though it runs once.
- Distinctive: line 102
Read it in this order, and stop at the first one that fails:
- Distinctive: line 104
Which environment does it resolve with no flags?: If the answer is production, stop.
- Distinctive: line 106
What is the filter?: Read it literally. Does it match what the description claims?
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Data change scripts
A deploy can be rolled back. A script that rewrote ten thousand rows cannot, unless you built the ability in before you ran it.
1. Dry run is the default; applying needs a flag
node scripts/fix-orphans.js # reports what it WOULD do, changes nothing
node scripts/fix-orphans.js --execute # does itNever the other way round, and never --dry-run as the opt-in. The half-second
of thought needed to add --execute is the entire safety mechanism.
The dry run must exercise the real read path and the real decision logic — same query, same filter, same transformation — and stop at the write. A dry run that only prints "would update 412 rows" without having computed the 412 new values has tested nothing.
2. Print the plan, not a summary
The dry run's output is the artifact that gets reviewed. Make it reviewable:
target: STAGING
scanned: 12,480 rows
matched: 412
UPDATE item#a1b2 status: 'draft' -> 'published'
UPDATE item#c3d4 status: 'draft' -> 'published'
SKIP item#e5f6 already published
...
unchanged: 12,068Show old and new values, identify rows by id, and show the skips — the skip count is what tells you the filter is right. If the plan is too long to read, write it to a file and report the path; do not truncate it silently.
3. Idempotent, always
Running it twice must be indistinguishable from running it once. Scripts get interrupted, half-applied, and re-run by someone who does not know it already ran.
- Match on the pre state, so already-fixed rows fall out of the filter naturally.
- Never blind-append to a list, increment a counter, or add a tag without checking.
- Make the second run's output the proof:
matched: 0is the completion signal.
4. Bound the blast radius
- Put the filter in the query, not in a post-fetch
if. A scan with no limit and client-side filtering will one day be shipped with the filter removed. - Support
--limit Nand use it for the first real run. Apply to ten, check those ten, then run the rest. - Support
--id <id>for a single-row rehearsal. - Refuse to run if the match count exceeds a sanity threshold unless the operator passes the expected number explicitly. A script that matches 100% of the table when you expected 3% has a bug, and the threshold is what catches it.
5. Be able to undo it
Before the first --execute:
- Take a backup, or write the pre-state of every touched row to a timestamped file next to the script's output. That file is the rollback.
- Prefer soft changes — set a flag, move to an archive collection — over hard deletes. Hard-deleting is a decision you cannot revisit.
- Note the reverse operation in the script's header comment. If you cannot describe it, you are not ready to run.
6. Never print secrets, never widen access
- Log ids and field names. Do not log tokens, password hashes, keys, full personal records, or anything you would not paste into a ticket.
- Run with the narrowest credential that works. A cleanup script does not need admin.
- If the script needs a secret, read it from the environment or a secret store at run time. A secret written into the script is in git forever, including after you delete the line.
7. Leave a record
Commit the script even though it runs once. It is the only description of what happened to that data.
The header comment carries: what it changes, why, the date it was run, which environment, the match count, and the rollback path. Six months later, when a row looks strange, this file is the answer to "what touched it?"
8. Reviewing someone else's before running it
Read it in this order, and stop at the first one that fails:
- Which environment does it resolve with no flags? If the answer is production, stop.
- What is the filter? Read it literally. Does it match what the description claims?
- Is there a write outside the
--executebranch? Including a log written to a table, a cache invalidation, or an event emitted. - Is it idempotent? Trace a second run.
- What is the rollback?
Then dry-run it yourself and read the plan. Do not accept someone else's dry-run output as evidence — it was produced against a different environment than the one you are about to touch, often enough to matter.
Checklist
- Dry run is the default;
--executeapplies - Dry run computes real values and prints old to new by id, with skips
- Idempotent; second run matches nothing
- Filter in the query;
--limitand--idsupported; sanity threshold - Pre-state captured or backup taken before the first apply
- Soft change preferred over hard delete; reverse operation written down
- No secrets printed; least-privilege credential
- Script committed with a header recording what was run, where, and when
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

