Rule audit
Skill xniperbuilds/rule-audit
Find out which of your Claude Code rules are actually enforced and which are just hope. Audits CLAUDE.md, classifies every rule, and converts the enforceable ones into hooks and permissions.
npx -y skills add xniperbuilds/rule-auditAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 12 days oldThe repository was created 12 days ago. New is not bad, but a brand new repository carrying a familiar-sounding name is the shape a typosquat arrives in, and there has been no time for anyone else to find a problem with it.
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Find out which of your agent rules are actually enforced and which are only hope — then convert the ones that matter into deterministic enforcement. Use whenever the user says Claude ignored my rules, it pushed to main again, it keeps forgetting my instructions, my CLAUDE.md isn't working, "same mistake again", "I told it not to", "rule follow nahi karta", "phir wahi ghalti" — or asks to add a hook, block a command, enforce a convention, run something automatically after edits, review their CLAUDE.md, or make an instruction actually stick. Also use before writing a new rule, to decide whether it belongs in prose or in the harness, and when a CLAUDE.md has grown long enough that compliance is degrading. It inventories every rule you have, classifies each as enforceable or advisory, generates the hook or permission config for the enforceable ones, tells you plainly which rules can never be enforced, and prunes the rest so the remaining instructions actually get followed.
SKILL.md
11.7 KB, ~2.5k tokens by cl100k_base, as published. Nobody here has run it
Rule Audit
An instruction is a request. A hook is a guarantee. Rules that must never break do not belong in prose. They belong in the harness.
The problem this exists for
Writing a rule in CLAUDE.md feels like fixing the problem. It isn't — it's asking for the problem to be fixed, on every future turn, forever, under context pressure.
What is actually measured:
- CLAUDE.md rules are followed roughly 70% of the time — meaning a "never push to main" rule is a production incident on a schedule.
- Instruction compliance decreases as instruction count increases. Adding a rule to fix a violation makes every other rule slightly less likely to be followed. This is the trap: the natural response to a broken rule is to write another rule, which makes it worse.
- Long sessions, ambiguity, and content pulled in from files all push compliance down further.
- Users have asked Anthropic directly for this (
anthropics/claude-codeissue #32163 — "Hard-enforce CLAUDE.md rules via code — rules marked CRITICAL should trigger hooks, not just prompts"). Hooks exist; the conversion of your prose rules into them does not.
(Figures are from secondary sources; the mechanism facts in references/hook-reference.md were verified against the official reference and a working config on 2026-07-26. See "Sourcing" at the end.)
So the core move is not "write better rules". It is: decide which rules must be mechanical, make those mechanical, and delete enough of the rest that the remainder gets read.
The classification — the heart of this skill
Every rule you have is exactly one of these. Classify before doing anything.
| Class | Meaning | Mechanism |
|---|---|---|
| BLOCK | Must never happen | permissions.deny, or PreToolUse → exit 2 / permissionDecision: "deny" |
| GATE | Allowed, but a human must approve | permissions.ask, or PreToolUse → permissionDecision: "ask" |
| REWRITE | Should happen a different way | PreToolUse → updatedInput (silently corrects instead of blocking) |
| AUTO | Must always happen after something | PostToolUse (format, backup, lint, regenerate) |
| INJECT | Context that must be present, not remembered | SessionStart / UserPromptSubmit → additionalContext |
| DETECT | Cannot be prevented, can be caught | PostToolUse → decision: "block" + reason (Claude sees it and fixes) |
| FINISH | Must be done before the turn ends | Stop → decision: "block" + reason |
| ADVISORY | Requires taste or judgment; no mechanical test exists | Stays in CLAUDE.md — and must be short |
| DEAD | Obsolete, contradictory, unverifiable, or never once mattered | Delete |
The classification test
Ask one question about the rule:
Can a script decide this from the tool name, the tool input, and the files on disk — with no judgment?
- Yes → it is mechanical. Pick the class above by when it must act (before / instead of / after / at end).
- No → it is ADVISORY. Accept that it will be followed ~70% of the time, keep it to one line, and stop adding paragraphs to compensate.
- "Sort of" → usually DETECT: you cannot prevent it, but you can catch it immediately and let Claude self-correct, which in practice is nearly as good and far simpler.
Being honest at this step is the whole value. A rule like "write clean, idiomatic code" can never be a hook. Saying so out loud is more useful than pretending a longer paragraph will help.
Simplest mechanism first
Reach for the lowest rung that works. Most rule-enforcement advice jumps straight to writing scripts; most rules don't need one.
- Permissions (
deny/askin settings.json) — no code, no process, no timeout, cannot crash. If the rule is "never run X" or "always ask before X", stop here. - The
iffield on a hook entry — filters by tool pattern without a script ("if": "Bash(git push *)"). - A command hook script — when you need to inspect the input, check the filesystem, or decide.
- A prompt/agent hook — only when the decision genuinely needs judgment; it costs a model call on every matching event.
Every rung up costs latency on every matching tool call and adds something that can break. A hook that errors on every Edit is worse than the rule it replaced.
Workflow
1. Inventory
Find every rule source: ~/.claude/CLAUDE.md, project CLAUDE.md(s), .claude/rules/*.md, @-imported files, settings.json + settings.local.json (existing permissions and hooks), and installed skills that carry standing instructions.
Run assets/rule_audit.py for a first pass — it extracts candidate rules, counts the instruction load, inventories existing hooks and permissions, and flags hard rules (never / always / must) that have no mechanical backing.
2. Classify
Put every rule in exactly one class. Do this with the user for anything ambiguous — they know which violations actually hurt. Present it as a table; do not start writing config yet.
3. Rank by cost of violation
Not every mechanical rule is worth a hook. Ask: what does one violation actually cost? A destroyed database, a force-push, a leaked secret — enforce. A missing blank line — don't; that's what a formatter is for, and a hook that fires constantly for trivia trains the user to ignore hook output.
4. Convert
Write the config for the top rules only. Use references/rule-patterns.md for ready-made patterns and references/hook-reference.md for exact syntax. Show the user the config and the diff before writing anything to settings.json — see Safety.
5. Test — not optional
An untested hook is worse than no hook, because it converts a known-unreliable rule into a believed-reliable one. For each hook: trigger the exact situation it guards, confirm it fires, and confirm it does not fire on a near-miss it shouldn't catch. A matcher typo fails silently and forever.
6. Prune
Now delete. Every rule that became a hook should be removed from CLAUDE.md — keeping both is pure instruction-budget waste for zero gain. Delete DEAD rules. Compress ADVISORY rules to one line each. The goal is a CLAUDE.md short enough that all of it is actually operative.
Instruction budget
Compliance falls as instruction count rises, which means your rules compete with each other. Treat the rule list as a fixed budget, not a growing document.
Symptoms of an over-budget file: rules that contradict each other, rules nobody remembers writing, rules for one-off situations from months ago, multiple paragraphs restating the same rule with more emphasis, and ALL-CAPS escalation (a reliable sign that a previous version of the rule wasn't working — escalating the font never fixes it; changing the mechanism does).
The counterintuitive fix that actually works: delete rules to make the remaining ones stick. When the user resists, ask which three rules they'd keep if they could only have three. Those are the ones that should have been hooks all along.
Also check for conflicts — two rules that cannot both be satisfied. Nothing flags these automatically; whichever sits closer in context tends to win, which looks random from the outside and destroys trust in the whole file.
Safety
Hooks execute with your full user permissions, automatically, on every matching event. Treat writing one with the same care as adding something to a shell profile.
- Never write to
settings.jsonwithout showing the exact change and getting explicit approval. Back up the file first. - Validate the JSON before and after. A malformed settings file can break the session.
- Always set a
timeout. A hanging hook hangs every matching tool call. - Beware blocking hooks that always block. A
Stophook that unconditionally returnsdecision: "block"puts the agent in a loop it cannot exit. Every blocking hook needs a condition that is definitely reachable. - Fail open on anything non-critical. If the hook script itself errors, prefer allowing the action over halting all work — unless the rule is a genuine safety rule, in which case fail closed and say so.
- Never put secrets in hook config; use environment variables.
- Hooks read tool input that may contain untrusted content. A hook that passes tool input into a shell without quoting is a command-injection hole you installed yourself.
Output shape
RULE INVENTORY N rules across M files; existing: X permissions, Y hooks
CLASSIFICATION table: rule | class | mechanism | cost of violation
CONVERT (top N) the exact config, ready to paste, one per rule
CANNOT BE ENFORCED the advisory list, stated plainly — with why
PRUNE delete these (dead/duplicated/now-a-hook)
TEST PLAN how to verify each new hook actually fires
BUDGET before → after rule count
Lead with the number that lands: "You have 47 rules. 6 of them can be guaranteed. 9 are dead. The other 32 are hope — and they're the reason the 6 that matter get ignored."
Known limits
- Only mechanical rules become guarantees. Most rules about quality, style, judgment, and taste cannot be enforced by any mechanism. This skill makes that boundary explicit; it does not move it.
- Hooks are a Claude Code mechanism. The classification method transfers to any agent with lifecycle hooks or permission systems, but the exact JSON here does not.
- Hook APIs change. The reference file is dated. Verify against the current official docs before relying on an exotic event or field.
- A hook cannot read intent. It sees a tool call. Rules that depend on why something is being done are advisory, no matter how important they are.
- This skill cannot make your rules correct — only enforceable. An enforced wrong rule is worse than an ignored one.
Files
| File | Contents |
|---|---|
references/hook-reference.md | Verified: all 30 events, matcher rules per event, exit-code semantics per event, input fields, every JSON output shape, gotchas |
references/rule-patterns.md | Cookbook — common real rules mapped to ready-to-paste config, including the no-script options |
assets/rule_audit.py | Zero-dependency: inventories rules across CLAUDE.md files + settings, counts the instruction budget, flags hard rules with no mechanical backing, lists existing hooks/permissions |
Sourcing
Mechanism facts (events, matchers, exit codes, JSON shapes) were taken from the official Claude Code hooks reference and cross-checked against a working settings.json on a live machine, both on 2026-07-26. Compliance percentages and the instruction-count finding come from secondary reporting and are labelled as such rather than presented as measured here. The feature request cited is anthropics/claude-code issue #32163.