↓Skip to main content

The Power of CLAUDE.md

·8 mins

Without a CLAUDE.md, Claude is left to guess. In a large repository, the code that should serve as the example for what you’re writing may not be anywhere near it, so the agent may never see it. There are also patterns a senior developer gravitates toward that a junior developer may never have heard of, and an agent left to its own resources doesn’t know to reach for them either.

How much that matters varies heavily by model. Opus is great at research and Sonnet is great at coding, and when Sonnet is all you have, it leans on what it’s told and does much less research into the patterns around it. AI is a pattern matching system (an oversimplification, I know), so telling it which patterns to match goes a long way.

When I say CLAUDE.md, I mean the markdown file in the root of a repository that Claude Code reads at the start of every session.1 It’s where you tell the agent the things it can’t work out from reading your code: how to build and test the project, where things live, and which conventions matter. Other tools have their own version, like AGENTS.md, .github/copilot-instructions.md, or Junie’s guidelines. They aren’t interchangeable, and a tool won’t necessarily read another tool’s file, so check what yours actually loads. Everything below applies to any of them.

A CLAUDE.md steers the agent toward the patterns that matter, but only while it stays accurate, and a file that has drifted from the code does more harm than none at all.

Where to Start #

I’ve been a senior developer for many years, luckily well before AI gained traction. Once AI started to show how good it could be at coding, I used it as a better auto-complete, and Copilot was the early bread and butter for that. Eventually Copilot CLI came out and I started using a CLI to generate code. It became apparent quickly that a senior developer with AI was significantly better than a junior developer with AI, and we needed a way to unify them. I found rule files early, so by the time I adopted Claude Code I already had a solid set of Copilot rules, and I had Claude itself import them.

If you don’t have that background, run /init inside Claude Code. It looks through the repository and writes a first draft for you. It’s incredibly important to remember that it’s a starting point, not an end. There isn’t an end, in my opinion. The rules in a CLAUDE.md will keep growing and evolving along with the industry. As we adopt new best practices, the rules for the AI tools we use should follow. I like to adopt industry best practices over time, like the testing pyramid or the repository pattern for abstracting database queries, among many others. They come out of my history with certain patterns, and I tell Claude to add the rule along with a way to adopt the pattern.

Existing coding standards are another good place to start. At work we had a lot of them for new developers, and I adopted those into our first set of AI instructions.

Whichever way you start, focus it on what the agent can’t reliably figure out on its own:

  • The commands that actually work for building, testing, and previewing the project.
  • Where the important things live.
  • The conventions that matter in this repository.
  • Which files are generated and where their source lives.

It doesn’t need to describe your whole architecture, because the agent can read the code. If a line wouldn’t change what the agent does, it’s probably just noise. AI docs tend to be wordy, and humans aren’t necessarily the target audience, so a CLAUDE.md doesn’t have to read like something you’d hand a teammate. Everything in it loads into context every session, though, so I keep it to the generic rules. Anything specific to one part of the codebase goes in a rules file with paths frontmatter, which only loads when Claude works on matching files.1

When I’m not sure where a rule belongs, I ask Claude where it should go and why. The why is important to me. I want a reason for the placement, not a guess.

I like to tell Claude what to do, not what not to do. Documenting the negative has become noise, in a repo and in a CLAUDE.md alike. Keep each rule simple and concise, and say what you want. “Edit the source in content/” says more than “Don’t touch public/.”

Sometimes, though, you do need to say what’s not allowed. Those boundaries, or anti-patterns, can go in their own section. Never logging secrets is a good example.

Why It Goes Stale #

An out-of-date README is annoying, but a person usually notices when something doesn’t work and starts asking questions. An agent takes the file at its word, and I’ve seen one follow both an out-of-date rule and a bad one. Say the file lists a test command that was renamed a few months ago. The agent runs it, hits an error, and spends its time working around it. The worse case is a rule that nobody wrote down after the code changed, so the agent makes a reasonable-looking change that breaks it.

It also compounds. A good correction helps every session after it, and a wrong line gets repeated every session until somebody catches it.

I’ve seen a bad rule sneak in and lead to some bad decisions. Say a rule tells the agent to edit the title of a PR when taking it out of draft, and I wrote that title by hand. I don’t want that to happen. Change these quickly, as they’re found. An active bug in a CLAUDE.md affects every developer in the repo (and every non-technical user), not just the end users of the app, so I treat those almost as sev1 issues for myself.

I want to be fair here, because you can overdo it. A new rule after every mistake piles up quickly, and adding a rule is rarely the fix on its own.

Keeping It Current #

First, change it in the same pull request as the thing it describes. If you rename the test command, swap out a package, or add a step to a migration, update the CLAUDE.md in that same change. It’s the cheapest time to do it, because you already know what changed.

Second, review the reviews. I review a lot of code, both by hand and with custom skills I’ve written over time, and much of it now was written with AI. When a reviewer points out a mistake, I treat it as evidence that the agent’s guidance fell short somewhere. CLAUDE.md is maybe the most important file in the repo, and reviews are how I find the missing rules, like “look in utils/ before inventing a util” or “don’t invent a pattern to match the test.”

I tell Claude to read the reviews from other reviewers (mine included), use that data to analyze the CLAUDE.md, and fill in the gaps. One great thing about AI is that you can be somewhat vague about the wording, tell it to optimize the file, and it does a pretty good job.

I still treat what it proposes as a starting point and read it before it goes in. A review comment can be specific to one situation and not a reusable rule, and AI is better at producing code that looks right than at knowing whether it’s right for this system. So I decide whether the cause was missing context, a gap in the tests or tooling, or just a one-off judgment call. The absence of review comments is a win, but it doesn’t prove the instructions are correct, since a quiet review can also mean nobody noticed the problem.

The rules that come out of this are probably 50/50 between anti-patterns and positive rules. Another trend that came up in my reviews is globals getting created all over the place. Instead of banning them, I’d write the replacement: “when groups of global variables or constants are grouped naturally (or by some other similarity), consider using an enum instead.” Reviews are good at finding what went wrong, and the useful part is turning that into a rule that says what to do.

Third, test it. Ask the agent for a small task, like making a content edit and previewing it, or finding the test command for a component you just touched, and watch what it does. If it keeps guessing wrong, the instruction may be missing, vague, or not loaded by that tool at all. Fix that before adding another paragraph.

Fourth, prune it. Delete duplicates and advice that stopped being true. Asking Claude to optimize the file works well for this too.

Finally, don’t ask the file to do a job something else does better. “Do not expose secrets” is a fine thing to write down, but it isn’t a security control, and secrets shouldn’t be available to an agent that doesn’t need them. “Run the tests” doesn’t replace CI running them independently. If a rule really matters, back it with a linter, a permission, or a check, and keep the sentence in the file so the agent knows why.

Where That Leaves Us #

A CLAUDE.md is part of how your repository gets worked on now, whether the work comes from you, your teammates, or somebody’s agent. If you don’t have one, run /init, cut it down to what the agent can’t figure out itself, and commit it. If you do have one, open it this week and check that every command in it still runs. After that, update it in the same change as the code, and let your code reviews tell you what’s missing.


  1. How Claude remembers your project, Claude Code Docs. It covers where CLAUDE.md files can live, how they’re loaded, @ imports, and path-scoped rules in .claude/rules/. ↩︎ ↩︎