This article comes with a free Claude skill
The rule this story ends with is packaged as hook-tuning – one small file you drop into Claude Code so your own assistant works this way too. It is public domain: copy it, change it, no attribution and no permission needed. How to install it is at the end of this article.
The command was refused, and I overrode it without reading the message.
That is the whole story, and it took me a while to understand why it was a story at all. The check was working. It had refused something it was designed to refuse. I typed the override flag, the command ran, nothing bad happened, and I carried on.
I overrode it because the week before it had refused something harmless, and the week before that, and by then I had stopped reading its output and started treating it as a toll booth.
The check was not broken. Its relationship with me was broken, and no amount of making it more correct would have fixed that, because I was no longer reading it.
The arithmetic nobody does
Say a blocker is right 95% of the time. That sounds excellent. Now say it fires ten times a week.
That is one false refusal a week. One a week is enough to teach a person that the fastest path through this thing is the override flag – and once that is learned, the blocker’s accuracy stops mattering entirely, because its output is no longer an input to anyone’s decision. You have not bought 95% protection. You have bought 0%, plus friction, plus a habit that will carry over to the next blocker you write.
A false positive in a blocker is not a small cost paid for a large benefit. It is a payment made directly out of the mechanism’s own credibility, which is the only thing it has.
The line
Block only on deterministic facts. Warn and log on judgement.
The test is whether the check can be wrong about this specific instance in a way a reasonable person would dispute. Not whether the rule is a good rule – whether this firing is arguable.
- “This file contains GPS coordinates in its metadata” – a fact. The bytes are there or they are not. Block.
- “This version number is lower than the one already deployed” – a fact. Block.
- “This text sounds like it might identify someone” – a judgement. Warn, log it, and let a human decide, because you will be wrong often enough to be ignored.
The tempting move is to block on the judgement calls, because those are the expensive mistakes. That is exactly backwards. The expensive mistakes are where you most need the human’s attention, and blocking on ambiguity is how you lose it.
What a refusal owes you
If a check does block, it has an obligation, and it is not “explain the rule.” It is:
- Name the specific thing. Not “OPSEC violation” but the exact string, at the exact line.
- Name the fix, as a command that can be run.
- Name the override, and log every use of it.
That last one matters more than it looks. An override that is logged is a measurement: if that log grows, the check is miscalibrated, and you have the evidence in hand rather than a vague sense that people are annoyed. An override that is not logged is just a hole, and you will never know how often it is used.
And it means a check can be tuned with data instead of argument. When our override log started filling up, the answer was not to argue about whether the check was too strict. It was to read the overrides, see they clustered on one pattern, and narrow the check to exclude that pattern.
The one that nearly got deleted
We had a check that fired forty times in a single session.
Every firing was correct. The rule was right, the detection was right, and the fix it named was the right fix. It fired forty times because I kept doing the thing anyway – reaching for the quick version of something the check wanted done properly.
The reflex, at firing number thirty, was to delete the check. It was in my way. It was always in my way.
It stayed, and it stayed for a reason that is worth stating: the cost of each denial was one wasted round trip, and the cost of the thing it was preventing was measured in hours. The check was not too strict. I was arguing with a correct check because arguing felt cheaper than changing the habit.
So the last rule is about the person reading the output, not the code:
Before tuning a check that keeps firing, establish whether it is wrong or whether you are. Both feel identical from the inside. The difference is visible in the log – a check that is wrong fires on a variety of innocent things, and a check that is right fires forty times on the same one.
Get the skill
Everything above is generic. None of it is about rats, and none of it is specific to this site. So the rule is also published on its own as a Claude skill: a single Markdown file that an AI coding assistant reads and applies when the situation comes up.
The file: hook-tuning/SKILL.md
Or take the whole set:
git clone https://github.com/blonderoofrat/agent-skills
Installing it in Claude Code. Copy the skill’s folder into one of these, so the file ends up at .../skills/hook-tuning/SKILL.md:
~/.claude/skills/(available in every project on your machine)your-project/.claude/skills/(that one project only)
Claude reads it at the start of the next session and applies it when what you are doing matches the description at the top of the file. You can also ask for it by name.
Using a different assistant? The file is plain Markdown with a two-line header. Paste the body into whatever system prompt, rules file or instructions file your tool uses. Nothing in the rule itself is Claude-specific.
Licence: CC0, public domain. Copy it, adapt it, ship it in commercial work, no attribution required. These are deliberately frozen snapshots rather than a maintained project, so if one is wrong for your situation, change it. That is easier than asking us to.
Part of Notes from building this site: articles about working practices that exist because something here went wrong first. The rule above is also published on its own, as a free public-domain instruction file for AI coding assistants — the hook-tuning skill, in blonderoofrat/agent-skills on GitHub.
Filed under News about this site




