An Agent Skill for the moment before a bulk write — archiving users, revoking access, deleting rows, mailing a batch.
A query is a claim about rows. A bulk operation is a claim about the world. This is the checklist for the gap between them, plus a hook that fires it automatically.
- Absence ≠ departure — "not in the system" merges never arrived with left
- Ghost activity — rows a cron created look like rows a human caused
- The field changed meaning — a column was write-once until some commit landed
- Status lags the artifact — the row says
pending; the thing already happened - Clustered timestamps — a tight age band is one bulk edit, not independent decay
- Loose matching invents members — surname and prefix matching pull in strangers
Then: classify every row into act / exclude / unknown, and unknown is never act.
Every example in the skill is real, from one afternoon of ordinary admin work on an internal platform:
- "Archive everyone with no chat account" would have archived the research director, a lead researcher with four publications, and a physician hired three weeks earlier. Of 505 active members, exactly one had ever left. Eighty had never joined.
- "Revoke the 98 stale permission grants" would have cut off the service account and the team leads. Classified, only 18 were stale.
- "These are new applicants" — both were already in the database from five days earlier.
- One batch email would have gone to someone who already had an offer, rotating their token and invalidating the accept link in their inbox. Their status said otherwise.
- "78 of 80 file weekly reports, so they're working" — 3,037 of 3,392 were auto-generated drafts.
None were caught by being careful. They were caught by splitting a count into named rows.
Personal, available in every project:
git clone https://github.com/kishormorol/blast-radius ~/.claude/skills/blast-radiusProject, committed and shared with your team:
mkdir -p .claude/skills && git clone https://github.com/kishormorol/blast-radius .claude/skills/blast-radiusThen /blast-radius, or let the agent invoke it from the description.
A skill about not trusting a query only helps if it loads, and the agent that would blindly run the query is exactly the one that won't think to load it. Self-triggering safety guidance catches the agent that was already being careful.
So the checklist also ships as a PreToolUse hook that fires on the command itself.
Add to ~/.claude/settings.json (or .claude/settings.json for a project):
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{ "type": "command",
"command": "$HOME/.claude/skills/blast-radius/scripts/blast-radius.sh" }
]
}
]
}
}What it does:
| Command shape | Behaviour |
|---|---|
deleteMany(), DELETE FROM t;, TRUNCATE — no filter at all |
ask — pauses for confirmation |
Filtered bulk writes, a write inside a loop, batch sends, -X DELETE |
injects the checklist as context, no interruption |
Anything with --dry, SEND=0, --plan |
silent — dry runs are the behaviour it wants |
grep, cat, git status and other read-only commands |
silent |
It fails open: no jq, unparseable input, any error — it exits 0 and gets out of the
way. A safety hook that breaks your workflow gets deleted, and then it protects nobody.
Requires jq. Verify it with:
printf '%s' 'node -e "prisma.user.deleteMany()"' \
| jq -Rs '{tool_input:{command:.}}' \
| ~/.claude/skills/blast-radius/scripts/blast-radius.shNot a linter, not a framework, not code that runs against your data. It is a checklist that arrives at the one moment that matters, and it mostly tells you to turn a count into named rows before you trust it.
Apache-2.0. SKILL.md is an open format, so this works with
any agent that reads it.