<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: rulereceipt</title>
    <description>The latest articles on DEV Community by rulereceipt (@rulereceipt).</description>
    <link>https://dev.to/rulereceipt</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4105436%2F5dae1080-1e49-4757-a56d-11e965055dbb.png</url>
      <title>DEV Community: rulereceipt</title>
      <link>https://dev.to/rulereceipt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rulereceipt"/>
    <language>en</language>
    <item>
      <title>My AI rule-checker was wrong about 1 in 6 times. Fixing that was the whole project.</title>
      <dc:creator>rulereceipt</dc:creator>
      <pubDate>Mon, 21 Sep 2026 13:50:21 +0000</pubDate>
      <link>https://dev.to/rulereceipt/i-measured-whether-claude-code-actually-follows-my-claudemd-25ao</link>
      <guid>https://dev.to/rulereceipt/i-measured-whether-claude-code-actually-follows-my-claudemd-25ao</guid>
      <description>&lt;p&gt;I've been building a small thing that reads a Claude Code session afterward and checks it against your rules file — did it follow "ask before deleting," "run the tests before claiming done," that kind of thing.&lt;/p&gt;

&lt;p&gt;Simple idea. The naive version took an afternoon.&lt;/p&gt;

&lt;p&gt;Then I ran it against real data and it was a liar.&lt;/p&gt;

&lt;p&gt;Not a little. Here's the number that mattered: I ran 559 real rules files against 5 real session transcripts — about 2,795 reports, ~18,000 individual verdicts. The stat I cared about was "what fraction of reports show the user at least one FAIL," because that's what a person actually sees on one run.&lt;/p&gt;

&lt;p&gt;15.8% of reports had at least one FAIL.&lt;/p&gt;

&lt;p&gt;If one in six runs accuses you of breaking a rule you didn't break, nobody trusts the tool again. It's worse than useless — it's a smoke alarm that goes off when you make toast. So I spent the bulk of the work not on catching more, but on catching wrongly less. It's now at 2.9%, and the bugs I found getting there are more interesting than the tool.&lt;/p&gt;

&lt;p&gt;A comma is not a rule. One rules file listed , as a forbidden pattern. My matcher dutifully flagged every file that contained a comma.&lt;/p&gt;

&lt;p&gt;rm fired inside "performance". My pattern matcher had a word boundary on the end but not the start, so the rule "don't run rm" matched the letters r-m sitting inside the word performance. Every session that used the word got accused of running a delete command.&lt;/p&gt;

&lt;p&gt;The worst one: guessing, and always guessing guilty. When my classifier couldn't tell which direction a rule pointed — "you must do X" or "you must never do X" — it defaulted to the accusing direction, and I'd justified that as "preserving existing behavior." It then failed a real session for following a rule that said "update the closest CLAUDE.md," because the session had updated one. It saw the right thing happen and called it a violation.&lt;/p&gt;

&lt;p&gt;The fix that stuck wasn't a smarter heuristic. It was making the bad case impossible to build: a FAIL verdict can now only be constructed through one function that requires the rule's direction to be typed as"forbid." Code that's checking a "you must do X" rule literally cannot emit an accusation — the build fails if it tries.&lt;/p&gt;

&lt;p&gt;The general lesson, if there is one: for anything that judges other work — a linter, a test oracle, an AI-output checker — a false positive costs far more than a miss, because it spends the user's trust, and trust doesn't refill.&lt;/p&gt;

&lt;p&gt;The tool is RuleReceipt (&lt;a href="https://rulereceipt.dev" rel="noopener noreferrer"&gt;https://rulereceipt.dev&lt;/a&gt;) if you want the shape of it (npx rulereceipt check, runs locally, no account) — but honestly I mostly wanted to write down the toast-alarm bugs, because I suspect anyone who's built something that grades other things has their own version of the comma.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>devtools</category>
      <category>showdev</category>
    </item>
    <item>
      <title>I parsed 559 public CLAUDE.md files. Most of what's in them isn't rules.</title>
      <dc:creator>rulereceipt</dc:creator>
      <pubDate>Wed, 02 Sep 2026 05:11:55 +0000</pubDate>
      <link>https://dev.to/rulereceipt/i-parsed-559-public-claudemd-files-most-of-whats-in-them-isnt-rules-3flo</link>
      <guid>https://dev.to/rulereceipt/i-parsed-559-public-claudemd-files-most-of-whats-in-them-isnt-rules-3flo</guid>
      <description>&lt;p&gt;I've been building a tool that checks whether Claude Code actually followed the rules in your CLAUDE.md. Early on I realised I was testing it against one file: my own. So I went and got 559 real ones.&lt;/p&gt;

&lt;p&gt;CLAUDE.md, AGENTS.md, .cursorrules, Copilot instructions, Windsurf, Gemini — from PyTorch, Kubernetes, Elasticsearch and a few hundred smaller repos. 21,986 items parsed out of them, no crashes.&lt;/p&gt;

&lt;p&gt;Two things came out of it that I didn't expect.&lt;/p&gt;

&lt;p&gt;63.4% of a rules file isn't a rule&lt;/p&gt;

&lt;p&gt;Directory listings. Reference tables. Import examples. Architecture notes. Glob syntax cheatsheets.&lt;/p&gt;

&lt;p&gt;All useful documentation. None of it is telling the agent to do anything. And it's sitting in the same file as the actual rules, competing for the same attention.&lt;/p&gt;

&lt;p&gt;So when someone says their CLAUDE.md is 400 lines, it's usually closer to 150 lines of rules with 250 lines of README stapled on.&lt;/p&gt;

&lt;p&gt;That reframes the "my CLAUDE.md is too long" problem. It's often not too many rules. It's rules buried in documentation.&lt;/p&gt;

&lt;p&gt;Of the real rules, only 44.2% can be checked mechanically&lt;/p&gt;

&lt;p&gt;Here's the split that surprised me more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Checkable:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Never commit directly to main" — you can look at what git actually ran&lt;/li&gt;
&lt;li&gt;"No console.log in committed code" — you can look at what was written to files&lt;/li&gt;
&lt;li&gt;"Run the test suite before pushing" — either the command ran or it didn't&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Not checkable by any tool, ever:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Surface bad news first"&lt;/li&gt;
&lt;li&gt;"Explain the trade-off before choosing an approach"
&lt;/li&gt;
&lt;li&gt;"Keep changes reviewable"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's no command to inspect for the second group. It's not a limitation of my parser — the information isn't in the transcript. A person has to read it and decide.&lt;/p&gt;

&lt;p&gt;55.8% of the rules people actually write fall in that second group.                                                                                                                                     &lt;/p&gt;

&lt;p&gt;The distribution barely moved as the corpus grew&lt;/p&gt;

&lt;p&gt;I started with 40 files: 65.4% non-instructions.&lt;br&gt;
  At 559 files: 63.4%.&lt;/p&gt;

&lt;p&gt;Between those two points I added formats the parser had never been tuned on. It moved 2.0 percentage points.                                                                                            &lt;/p&gt;

&lt;p&gt;That's the part I'd actually stand behind. It suggests "is this a directive?" is a property of language, not of file format — which matters, because the alternative approach (recognising every way people format&lt;br&gt;
  rules) is an infinite list.&lt;/p&gt;

&lt;p&gt;What I don't know&lt;/p&gt;

&lt;p&gt;I don't have a controlled experiment showing longer files perform worse. That's the obvious next question and I haven't run it.                                             &lt;/p&gt;

&lt;p&gt;But if a model is budgeting attention across a long file, it seems worth knowing that most of that file was never telling it to do anything.&lt;/p&gt;

&lt;p&gt;The tool&lt;/p&gt;

&lt;p&gt;It's called RuleReceipt. Free, runs locally, no account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  npx rulereceipt check
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also published the part where it got things badly wrong — it reported 10 violations on a real session of mine and every single one was false. That write-up is at &lt;a href="https://rulereceipt.dev/postmortem" rel="noopener noreferrer"&gt;https://rulereceipt.dev/postmortem&lt;/a&gt;, including the wrong turn I took while fixing it.&lt;/p&gt;

&lt;p&gt;Happy to answer anything about the method. The corpus was public files only, and the classifier is in the repo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update, 4 September.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Two bugs in my own parser moved these numbers after publishing, so I'm correcting them in place rather than leaving them wrong. The parser had no concept of fenced code blocks, so a shell comment starting with # or a YAML item starting with - was read as a rule boundary — 588 rules were being cut mid-block, and 1,718 items (7.2% of everything extracted) were lines lifted out of code samples that had never been rules at all. &lt;/p&gt;

&lt;p&gt;Separately, command documentation was being counted as rules. Corrected: 21,986 items, 63.4% non-instructions, 44.2% of real rules checkable. The 40-file sample moved 2.0 points rather than 2.5, which if anything strengthens the stability point. &lt;/p&gt;

&lt;p&gt;Full history of every figure and what changed it: &lt;a href="https://rulereceipt.dev/postmortem#history" rel="noopener noreferrer"&gt;https://rulereceipt.dev/postmortem#history&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devtools</category>
      <category>claude</category>
      <category>cursor</category>
    </item>
  </channel>
</rss>
