Every repository we work in has a CLAUDE.md, and most of the work in them is done by an AI agent. At first we wrote that file the way you'd write onboarding docs for a new hire: what the project is, the stack, a tour of the folders, the coding conventions. Thorough and welcoming.

The agent ignored roughly half of it. So we wrote more rules, the file got longer, and compliance got worse.

The problem wasn't the amount of documentation. It was the kind. We had written a README; what the job needed was a contract.

1. Don't Write Down What the Agent Already Does

The early version contained lines like these.

- Keep functions small and focused on one thing - Use descriptive variable names - Prefer named constants over magic numbers - Write commit messages that explain what changed and why

All true. All unnecessary. An agent does these without being asked — they're general good practice, already baked in.

And they aren't free. A long file buries the rules that matter. If 27 lines out of 30 are things anyone would do anyway, the other three read like more of the same.

The test: without this line, would the agent do the opposite?

If no, delete it. What survives is the things this repository does differently — which is the only reason the file exists.

2. Keep Only the Judgment Calls

After the cut, the surviving rules mostly looked like this.

11ty only processes .njk as templates. Every other .html is copied through byte for byte — which is why the inline styles and deep-link scripts on those pages are untouched by the build. The landing and lab pages stay self-contained with an inline <style> block. That's the existing approach; do not extract it to a CSS file. Blog posts use the shared posts.css. Do not add per-post styles.

The second rule is the interesting one. General good practice says "move inline styles into a stylesheet." Here the opposite is correct. Leave it unwritten and the agent helpfully refactors — pulling the inline styles out of a passthrough-copied page and quietly breaking something.

The third rule points the other way, in the same repository. Policy splits by page type. Nothing in the code tells you whether that split is intentional or an accident.

So there are three kinds of rule worth writing down:

  • Things that contradict general practice — otherwise the agent will "fix" them.
  • Things that split within one repository — otherwise it generalizes from the first example it sees.
  • Things that leave no trace in the code — external systems, deploy procedures, agreements with other repos.

3. Every Prohibition Needs a Reason

Bare prohibitions hold poorly. A prohibition with a reason generalizes to adjacent cases.

No reason — covers exactly this one file Don't touch the search engine verification files. With a reason — now it's a judgment the agent can apply Don't change the name or contents of the search engine verification files (google*.html, naver*.html). The filename itself is the verification token, so renaming one revokes site ownership.

An agent that read the second version makes the same call later when it meets app-ads.txt or a .well-known domain-verification file. The first version says nothing about those.

For the same reason, "do X" beats "don't do Y." A prohibition with no alternative just sends the agent looking for a way around it. "Write vanilla JS; don't introduce a new client framework" held up far better than "don't use React."

4. Spell Out How to Verify

This section had the largest effect of anything we added. It defines what "done" means.

## Verification npm run build # A failing build is a failing deploy. It must pass. npm run dev # Check the actual render locally What the build catches: locale symmetry, date agreement, links between posts, template syntax errors, broken references. What the build does NOT catch — check these yourself: - Whether layout and links survive in a browser - Whether relative paths in passthrough .html match directory depth - Deep link fallback behavior (needs a real device) - Never claim you verified links you didn't open.

The second half matters far more than the first. The default assumption is that a green build means the work is done; this states explicitly what the build cannot see.

That last line earns its place surprisingly often. It's a one-sentence rule against reporting a check that never happened.

5. Rules a Document Can't Enforce Belong in Code

This is the real conclusion. The more important a rule is, the less it belongs in the document.

Every post on this site has to exist in Korean and English. Originally that was just a bold line in the rules file — and posts still shipped in one locale only. A document can go unread, and even when read it fades partway through a long task.

So we moved it into a build hook. Add a post in one locale now and the build fails.

Error: ko/en posts are not symmetric. missing en: neat-daily-activity-guide

The difference is categorical. A documented rule is something it would be good to follow; a build rule is something you cannot proceed without. An agent can skim past a paragraph. It cannot skim past a failing build.

When you find yourself bolding a rule for the third time, that's the signal to move it into code.

Needing emphasis means the rule gets broken often, and rules that get broken often keep getting broken no matter how much you emphasize them.

Not everything can move, of course. "Translations shouldn't read like machine translation" has no automated check. Leave that class of rule in the document and migrate everything that a check can express.

6. Reporting Rules — Say What Must Be Said

The last section we added, and one we're glad we did.

## Reporting - If you added, moved, or deleted a page, state whether you also updated the sitemap and the redirects. - If you worked in only one locale, say so and name the one left. - If you changed the deep link scheme, call out the iOS/Android work it requires.

The real risk with agent work isn't a wrong thing reported as right — that gets caught in review. It's half the work reported as all of it, which doesn't. Deciding in advance what must always be mentioned closes a good deal of that gap.

7. In Summary

The file ended up less than half its original length, and compliance clearly improved. The principles:

  • Don't write what would happen anyway. It buries what wouldn't.
  • Keep only genuine judgment calls — against general practice, split within the repo, or invisible in the code.
  • Attach a reason to every prohibition. Reasons generalize; bare rules don't.
  • State how to verify, especially what the build misses.
  • Move checkable rules into code. The document is the fallback, not the mechanism.
  • Say what must be reported. It exposes half-finished work.

If your CLAUDE.md reads like a README, take another look at it. The reader isn't someone new to the project — it's a collaborator who already knows every general convention and none of your exceptions. The file only needs to carry the difference.