/t · guide · audit

The CLAUDE.md owner audit: who added this line, and is it still true?

M
Matthew Diakonov
7 min read

A CLAUDE.md has no CODEOWNERS file. It has no review gate, no test that fails when a line goes wrong, and no owner of record. It grows the way scar tissue grows: every engineer appends a rule, nobody deletes one, and after a few months the file is a sediment of decisions that made sense on the day they were written. The lines still fire. They are still billed on every turn. But nobody can tell you, line by line, which ones are still true.

An owner audit fixes that. It is not a vibe check and it is not a prompt you paste into the same model that has been ignoring half the file. It is two deterministic passes stacked together: git blame for the human owner, and a line-level analyzer for the patterns stale lines leave in the text. This page walks the audit end to end on a small example file, and shows the exact part ccmd.dev automates.

How a line goes stale

No line is born stale. Staleness happens to a line, slowly, while the repo moves and the file does not.

One line, four months

01 / 04

A line is added

An engineer commits 'Run npm run seed:staging before the test suite.' to CLAUDE.md. It is correct. It has an author, a date, and a reason.

The line never broke a build. No tool went red. It just quietly stopped being true, and kept getting paid for. That is the failure mode an owner audit is built to catch.

The file under audit

Thirteen lines from a small payments repo. It reads fine. It is not. Three of these lines are stale and one is a duplicate, and you cannot see which from the text alone.

CLAUDE.md

Pass 1: establish ownership with git blame

The file itself has no ownership metadata. Git does. One command turns the anonymous file into an annotated one: every line gets the commit, the author, and the date it last changed.

terminal

Read the dates, not the rules. Today is 2026-05-18. The seed:staging line is from Priya in August 2025, untouched for nine months. The old-billing-client prohibition is from the same commit, equally cold. And look at the last line: an intern re-added the seed:staging rule in February 2026, a verbatim copy of Priya's line from six months earlier. Two authors, same rule, neither aware of the other. That is the concatenation scar of a file with no owner.

Sort the blame output by date. Anything that has not been touched in roughly six months is not automatically stale, but it is stale-suspect: no one has re-confirmed it in a long time, and the repo has shipped a lot since.

Pass 2: flag the text fingerprints with ccmd

Stale lines leave marks in the text itself, and three of them are detectable without ever seeing the repo. Paste the file into the analyzer on ccmd.dev. It runs entirely in the browser, no upload, and reports them in roughly a fifth of a second.

ccmd · analyze

Three of the seven finding kinds in src/lib/analyzer.ts are staleness fingerprints, and this file trips all three:

  • cache_bust on L12. The check at analyzer.ts line 194 scans the first 20 lines for an ISO date or the words today, this session, right now. Today we are mid-migration is a fact with an expiry date. It is the highest-severity finding because it is both stale and it voids the prompt cache every session.
  • duplicate on L13. The check at analyzer.ts line 207 lowercases every non-trivial line and flags the second occurrence. It is the exact detector for the two-authors-one-rule pattern that git blame just exposed.
  • missing_why on L8 and L9. The check at analyzer.ts line 227 flags a prohibition whose next four lines contain no because, why, reason, or incident. A rule with no recorded reason cannot be judged stale. You can only guess. That is the worst possible state for an owner audit.

The bundled sample in the same analyzer file makes the point against itself: its final line (analyzer.ts:321) reads Today is 2026-05-17 and we are mid-sprint on the subscriptions rewrite. A line accurate for exactly one calendar day, shipped inside the tool that flags it.

Pass 3: cross-check named artifacts against the repo

ccmd cannot see your repository, and that is by design: nothing leaves your browser. So the analyzer cannot tell you that a script a line names was deleted. This pass is yours. For every line that names a script, a path, a file, or an env var, ask the repo whether it still exists.

terminal · cross-check

Two greps settle it. The seed:staging script is not in package.json, so the L4 and L13 rules instruct the agent to run a command that will fail. The old billing client cannot even be grepped, because the rule never named a path, only a vague "old billing client". That vagueness is itself a finding: a line you cannot mechanically check is a line that will outlive its own truth.

Pass 4: give every survivor an owner and a reason

Deleting the dead lines is the easy part. The pass that makes the next audit possible is rewriting the survivors so they carry their own evidence. A line that records who, why, and when can be judged stale in five seconds next quarter. A line that records nothing can only be argued about.

The same rule, before and after the audit

- Never import from the old billing client.

  • No author on record without running git blame
  • No reason recorded, so nobody can judge if it still holds
  • Names a "client" too vaguely to grep, so it can never be checked

After the four passes the example file drops from thirteen lines to eight, the two dead rules are gone, the duplicate is gone, and every remaining line either names something the repo still has or records why it is kept. The token saving is real but it is the smaller win. The bigger one is that the file is now something a person can stand behind, line by line.

The audit, as a pipeline

Three inputs feed one judgement and produce three actions. No step replaces another. git blame answers who, the analyzer answers what the text shows, and the grep answers what the repo still has.

The owner audit

git blame CLAUDE.md
ccmd analyzer
repo grep
Owner audit
Stale lines deleted
Survivors get a Why
New lines gated
0
of ccmd's finding kinds are staleness fingerprints
0
finding kinds total, all deterministic regex
0
formats audited: CLAUDE.md, AGENTS.md, .cursorrules, .grokrules

Why not just run an audit prompt?

The most common advice online is to invoke an audit skill: a prompt file that asks Claude to read its own config and report what looks stale. It is better than nothing. It is also the same model that has been ignoring half the file, now grading the file. Here is what an owner audit gives you that a judgement prompt cannot.

FeatureLLM audit promptOwner audit (git blame + ccmd)
Same file scores the same way twiceno, the verdict drifts run to runyes, deterministic regex and git
Names the human who added each linenoyes, git blame author and date
Catches a stale timestamp as a priced findingsometimes, if the model noticesalways, cache_bust, high severity
Catches a verbatim duplicate ruleunreliable across a long fileyes, exact-match check
Runs without sending the file to a modelno, the file is the promptyes, pure client-side
Proves a named script is goneno, the model cannot see the repoyes, one grep against the repo
Runs unattended in a pull requestnot without a model call per PRyes, on the paid tier

Making the audit continuous

A one-time audit decays. The file was clean the day you ran it and starts collecting orphan lines the next morning. The free analyzer on ccmd.dev is the one-shot pass. The paid tier, 9 to 19 dollars a month solo and 49 for a team, closes the loop so the file cannot rot silently between audits.

  • Pull request diff comments. When a PR adds or changes a CLAUDE.md line, ccmd comments inline. The new line gets a reviewer and a recorded reason at the moment it lands, which is the only moment the author still remembers why.
  • Weekly drift email. A scheduled re-run that surfaces lines that have aged past your threshold or whose token weight has crept up since the last audit.
  • Per-engineer attribution. For a shared file, the report ties each line, and its token cost, back to the engineer who added it. The owner question stops being a git blame you run by hand.

Want us to run the owner audit on your file live?

15 minutes, free. Paste your CLAUDE.md, we walk the four passes together, you leave with a delete list and a rewrite list.

Frequently asked questions

What is a CLAUDE.md owner audit?

It is the practice of asking three questions of every line in your agent config file: who added this, why, and is it still true. A CLAUDE.md has no CODEOWNERS file and no review gate. Lines accumulate by concatenation, each engineer appends, nobody removes, and after a few months no single person can vouch for the whole file. An owner audit restores that accountability. It pairs git blame (the only ownership record the file actually has) with a line-level analyzer that flags the text patterns stale lines leave behind. The output is a list of lines to delete, lines to rewrite, and lines that survive with a recorded reason.

Is there a tool that audits my CLAUDE.md for stale lines automatically?

No single tool does the whole job, and any page that claims otherwise is overselling. Staleness has two halves. The first half is text patterns inside the file: a stale timestamp, a duplicate rule, a prohibition with no recorded reason. ccmd.dev flags those for free, in the browser, deterministically. The second half is whether a line still matches the repo it describes, for example whether the script it names is still in package.json. That check needs your actual repository, so it is a git blame plus a grep you run locally. ccmd is the analyzer half. The paid tier makes the whole loop continuous by commenting on CLAUDE.md changes inside pull requests.

Why git blame instead of one of the audit prompt skills going around?

The audit skills that circulate, the audit-prompt files and setup-audit gists, are LLM-judgment passes. You invoke a prompt and the same model that has been ignoring your lines is asked to grade them. That has two problems. It is not reproducible, run it twice and you get two different verdicts, and it never tells you who added a line, so you cannot go ask the one person who knows if a constraint still holds. git blame is deterministic and it names the human. ccmd's analyzer is also deterministic, it is plain regex in src/lib/analyzer.ts, so the same file scores the same way every time. An audit you cannot reproduce is not an audit.

What actually counts as a stale line?

A stale line is one whose content has stopped being true while the line keeps firing. Three common shapes. A dated fact: 'Today we are mid-migration' was accurate the day it was written and wrong every day after. A dead reference: 'run npm run seed:staging' points at a script someone removed from package.json six weeks ago. An orphan rule: 'never import from the old billing client' refers to code that no longer exists, so the prohibition guards nothing. All three still get concatenated into the system prompt and billed on every turn. The agent reads instructions about a project that has moved on.

How does ccmd flag a stale timestamp specifically?

The cache_bust check at src/lib/analyzer.ts line 194 scans the first 20 lines for an ISO date or one of the phrases 'today', 'this session', 'right now'. It is marked high severity, the highest of the seven finding kinds, because it does double damage. The line is factually stale, and because it changes between sessions it also voids the prompt cache, so every turn re-bills the full file at full input cost instead of the cached rate. ccmd's own bundled sample file ships with exactly this mistake on its last line, 'Today is 2026-05-17 and we are mid-sprint on the subscriptions rewrite'. A line accurate for one calendar day.

Does an owner audit work for AGENTS.md, .cursorrules, and .grokrules?

Yes, and nothing changes. git blame works on any text file, so the ownership half is identical. ccmd's analyzer detects the format by content rather than filename and runs the same seven checks on AGENTS.md, .cursorrules, and .grokrules. The repo cross-check is also the same: every named script, path, or env var either still exists or it does not. The reason staleness is universal is that every one of these files is injected verbatim into a system prompt, so a wrong line costs the same regardless of which CLI shipped it.

How do I stop new lines from going stale in the first place?

Two layers. The cheap one is a discipline: every line you add gets a one-line Why with a date, because a line with a recorded reason can be judged stale later and a line without one can only be guessed at. The continuous one is the ccmd paid tier, 9 to 19 dollars a month solo and 49 for a team. It comments on CLAUDE.md changes inside pull requests, so a new line gets a reviewer and a reason at the moment it lands, and it sends a weekly drift email so the file never silently rots between audits.

How did this page land for you?

React to reveal totals

Comments ()

Leave a comment to see what others are saying.

Public and anonymous. No signup.