CLAUDE.md Best Practices

  • Tuesday

CLAUDE.md Best Practices: The 7 Files That Run 14 Products Without Drifting

CLAUDE.md best practices from a solo founder running 14 products: file hierarchy, what to include, why Claude ignores rules, and how to test yours.

I run about 14 launched products on Supabase and Vercel, three SEO blogs, and a set of scheduled marketing routines, all by myself, mostly through Claude Code. The thing that keeps that from turning into a mess is not a clever prompt. It is seven plain markdown files: one global CLAUDE.md in my home folder and six project-level ones, written on July 6, 2026, and edited most weeks since.

Almost every guide to CLAUDE.md best practices you will find is a list of sections to include. That is the easy part. The hard part is the stuff nobody writes down: where the files load from, what happens when two of them disagree, which rules belong in a file at all versus somewhere with teeth, and how you find out whether the file is being followed instead of quietly skipped.

This is what I actually run, what broke before I ran it, and how I test it.

What is a CLAUDE.md file, and when does Claude Code read it?

A CLAUDE.md file is a plain markdown file that Claude Code loads at the start of every session. There is no schema and no required format. You write the rules in sentences and Claude reads them before it touches anything.

Two details matter more than the contents, and most posts skip both.

First, it is context, not configuration. Per the official memory documentation, CLAUDE.md content is delivered as a user message after the system prompt. Claude reads it and tries to follow it. There is no guarantee of compliance. That single fact explains most of the frustration people have with these files, and it is the reason the last third of this article is about enforcement.

Second, the files stack. Claude Code walks up the directory tree from wherever you launched it and loads every CLAUDE.md and CLAUDE.local.md it finds along the way. They are concatenated, not overridden, ordered from the filesystem root down to your working directory. Files in subdirectories below you are not loaded at launch. They load on demand, when Claude reads a file in that directory.

So a rule you wrote three folders up is still in play, and a rule you wrote in a subfolder may not be. If you have ever watched an agent do something that no file in front of you permitted, that is usually why.

To see exactly what loaded in a session, run /context and look under Memory files. If your file is not on that list, Claude cannot see it, and no amount of rewording will help.

Where should your CLAUDE.md files live?

There are four scopes, in load order from broadest to most specific:

  • Managed policy, at C:\Program Files\ClaudeCodCLAUDE.md on Windows, /etc/claude-code/CLAUDE.md on Linux and WSL, or the equivalent Application Support path on macOS. Deployed by IT, cannot be excluded by individual settings. Most solo builders will never touch this.

  • User instructions, at ~/.claude/CLAUDE.md. Applies to every project on the machine.

  • Project instructions, at ./CLAUDE.md or ./.claude/CLAUDE.md. Committed to git, shared with anyone else on the repo.

  • Local instructions, at ./CLAUDE.local.md. Personal, project-specific, gitignored.

My layout is deliberately lopsided. The global file at ~/.claude/CLAUDE.md is the shortest one I own and holds only two kinds of thing: who I am and what I am building (so an agent does not invent a biography for me), and the facts about my products that would cause real damage if an agent got them wrong. Everything technical lives in the project files.

That split exists because the global file is loaded into literally every session, including sessions that have nothing to do with the product in question. Pricing rules for one marketplace do not belong in a session where I am debugging a Stripe webhook for something else, unless getting them wrong would end up in public.

One more location worth knowing: the .claude/rules/ directory. Rules are markdown files that can carry a paths field in YAML frontmatter, so they load only when Claude reads a matching file. A rule scoped to the TypeScript files under src/api costs nothing in context until Claude opens an API handler. For anything that only applies to part of a codebase, that is a better home than the root CLAUDE.md.

What belongs in a CLAUDE.md, and what does not

The documented target is under 200 lines per file. Longer files consume more context and reduce adherence, and the Claude Code best practices guide is blunt about the failure mode: bloated CLAUDE.md files cause Claude to ignore your actual instructions.

My test for every line is the one from that guide. Would removing this cause a mistake? If not, it comes out. In practice, four categories survive that test.

Commands Claude cannot guess. The exact typecheck command, the build command, which package manager. In my files this is usually two lines: npx tsc --noEmit or npm run build must pass before anything is called done.

Invariants that cost money or credibility if broken. Not style preferences. Things like: secrets for this product live in the Supabase dashboard and Vault, not in .env files, and Vercel environment variables are set separately in the Vercel dashboard, so three places have to stay in sync. That is not something Claude can read off the codebase, and getting it wrong means a deploy that silently fails in production.

Gotchas with a reason attached. The reason is the part people skip, and it is what makes a rule generalize. "Never rotate the encryption key" is a rule an agent can rationalize its way around when it is trying to fix an auth bug. "Never rotate the encryption key without checking what is encrypted with it first, because user-stored credentials are encrypted with it and rotation destroys them" survives contact with an edge case, because now the agent knows what the rule is protecting.

Pointers, not content. My project files say which docs are authoritative and that the docs win when they conflict with the agent's instinct. The docs themselves stay in the repo where they belong. Imports with @path syntax pull other files in, but be clear on what that buys you: imported files still load into context at launch, so imports are for organization, not for saving tokens. Recursion is capped at four hops.

What comes out: anything Claude can derive by reading the code, standard language conventions, directory listings, dependency lists, and anything a linter already enforces. If you are on Claude Code v2.1.206 or later, /doctor will propose exactly these trims for a checked-in file.

The brand-invariant pattern, or how to stop an agent publishing something false

This is the section I have not seen in any of the CLAUDE.md guides currently ranking, and it is the one that has saved me the most.

Most CLAUDE.md advice assumes the agent is writing code, where mistakes surface as failing tests. Mine mostly write and publish marketing: blog posts, social drafts, outreach. There is no test suite for a false claim. The mistake ships.

Here is my honest admission. Earlier this year, one of my publishing routines described me as a former domain broker. I was a domain reseller and a blogger. Never a broker. Nobody prompted for it; the model had a plausible-sounding gap in a biography and filled it, and that draft went into a queue for a live property. Nothing catastrophic happened, but the fix was not a better prompt. The fix was a line near the top of the global file stating what I was and what I was never, plus a matching line in the blog repo's editorial doc.

The pattern generalizes to anything with public consequences:

  • State the fact and the anti-fact together. Not "Mark was a reseller" but "Mark was a reseller and blogger, never a broker; never invent biographical stories or credentials." The negation is doing the work, because the failure mode is invention, not contradiction.

  • Write the exact number or phrase, never the approximation. One of my products has a tiered price ladder and a variable seller payout. The file carries the real numbers and the exact framing, and explicitly forbids the flattened version an agent naturally reaches for when it wants a snappier sentence.

  • Say what the damage is. "Violating these damages live marketing" is a header in my global file. An agent weighing a tradeoff needs to know which rules are load-bearing.

  • Name the canonical URL form. Mine is www or nothing. That one line has prevented a lot of dead links.

If you are pointing agents at anything customer-facing, this category of rule earns its context budget several times over. It is also why my global file is small: brand invariants are the only thing allowed to be global, because they are the only rules where the cost of a violation does not depend on which project you are in.

Why does Claude ignore my CLAUDE.md, and what should I do about it?

Four causes, in the order I check them.

  1. It never loaded. Run /context and check Memory files. Subdirectory files load lazily. Nested files are also not re-injected after /compact, though a project-root CLAUDE.md is re-read from disk and re-injected.

  2. It is too long. Rules get lost in noise. Cut, or move to path-scoped rules.

  3. Two rules contradict each other. When they do, Claude may pick one arbitrarily. This is the sneaky one in a multi-file setup, because the contradiction lives across two files you never read side by side. I re-read my global file against a project file whenever a rule "stops working."

  4. It is vague. "Format code properly" is not verifiable. "Use 2-space indentation" is. The same applies to content rules: "write in my voice" does nothing, while "no hashtags, no hype words, one small ask" is checkable.

But there is a fifth case, and it is the important one: some instructions should never have been in a markdown file at all. CLAUDE.md is advisory. If a thing must happen every single time, it needs a mechanism with teeth.

Here is how I route a rule now:

  • CLAUDE.md for facts and conventions that apply to every session in a project.

  • .claude/rules/ with a paths field for instructions that only apply to certain files, so they cost nothing until they are relevant.

  • Skills for multi-step procedures that only matter sometimes. They load on demand instead of sitting in every conversation. My publishing routines are skills for exactly this reason.

  • Hooks for anything that must happen with zero exceptions. Hooks are shell commands that run at fixed lifecycle events and execute regardless of what the model decides. A PreToolUse hook can block an action outright. A Stop hook can refuse to end the turn until your check passes. This is the difference between asking and enforcing.

  • Auto memory for the things you would otherwise have to keep telling it. Claude writes these itself, into a per-repository folder under ~/.claude/projects/, with a MEMORY.md index of which only the first 200 lines or 25KB load per session.

The rule of thumb I use: if the consequence of skipping it is "the output is a bit worse," it belongs in CLAUDE.md. If the consequence is "something broke or something false got published," it belongs in a hook. I moved my pre-publish checks in that direction after the broker incident, and the file got shorter as a result.

If you are already running multiple agents against the same repos, the same routing question applies one level up, which I wrote about in more detail in how I run a team of Claude Code subagents across 14 products.

How do I know my CLAUDE.md is working?

Most guides stop before this, which is strange, because it is the only part that tells you whether any of the advice worked.

I use three signals, none of them sophisticated.

Corrections per session. If I type the same correction twice in a week, that is the trigger to write it down. The docs frame it the same way: add to CLAUDE.md when Claude makes the same mistake a second time, or when you type the same clarification you typed last session. I treat the second correction as a bug report against the file, not against the model.

A check the agent can run. The single highest-leverage line in my project files is the one that says run the typecheck or the build and do not report done until it passes. It converts "looks finished" into a pass or fail the agent can read and iterate against, without me in the loop. If your project has no such command, creating one is worth more than another 50 lines of instructions.

Deleting a rule and watching. If I suspect a line is dead weight, I remove it and see whether the behavior changes. Usually it does not, which means the model already did the right thing and I was spending context to tell it something it knew. This is how my files got from long to short.

There is no dashboard for this. It is closer to pruning than to configuration, and treating the file as living documentation rather than a one-time setup task is the actual best practice hiding under all the others.

I built the publishing side of this on top of the same idea. The routines that write and publish my posts are a set of instructions plus a state file plus a schedule, which is a different thing from a prompt you paste in each time. That distinction is the whole argument in AI prompts vs systems.

A five-step way to rewrite your CLAUDE.md this week

  1. Run /context in a live session and write down every memory file that actually loaded. Most people discover a file they forgot they wrote, or one they thought was loading and is not.

  2. Open the longest one and delete every line describing something Claude could learn by reading the code. Directory layouts, dependency lists, architecture summaries. On v2.1.206 or later, let /doctor propose the cuts.

  3. For every surviving rule, add the reason in the same sentence. If you cannot state a reason, that is a strong hint the rule is a preference rather than a constraint, and preferences are what get dropped first when context fills.

  4. Move anything that only applies to part of the codebase into .claude/rules/ with a paths field, and anything multi-step into a skill.

  5. Pick the one rule you would be most upset to see violated in public. Convert it into a hook. That is your enforcement layer, and it is the only one that does not depend on the model's judgment.

Run that loop once and your file will get noticeably shorter. Mine did, and adherence went up, which is the counterintuitive part: the fewer instructions you give, the more reliably each one lands.

Want to see the whole system running?

I walked through the marketing side of this end to end in a live session, Turn Claude Code Into Your Marketing Team. The full replay is available instantly, along with all three workflow repos, ready to install and yours to keep. If you want to see how these instruction files sit inside real running routines rather than in isolation, that is the fastest path.

The Reinventing AI Accelerator membership includes that session plus the rest of the live trainings and the vault of AI apps, tools, and agents I build for members. If you are building with Claude Code and would rather start from something that already works than assemble it yourself, take a look. One small ask: if you only do one thing from this article, run /context today and see what your agent is really reading.

Frequently asked questions

How long should a CLAUDE.md file be?

Target under 200 lines. That is the documented guidance, and it matches what I see in practice. Unlike auto memory's MEMORY.md, which loads only its first 200 lines or 25KB, CLAUDE.md files are loaded in full no matter how long they are. Length does not get truncated, it gets ignored. A 600-line file is not six times as instructive as a 100-line one, it is a 100-line file with 500 lines of noise burying the rules you care about.

Should I commit CLAUDE.md to git?

Yes for project files. They are team-shared context and they compound in value as people add the things Claude got wrong. Keep personal preferences and machine-specific details in CLAUDE.local.md and add that to .gitignore. One caveat worth knowing if you use git worktrees: a gitignored CLAUDE.local.md only exists in the worktree where you made it, so for preferences you want everywhere, import a file from your home directory instead.

Is /init good enough, or should I write CLAUDE.md by hand?

Use /init for the skeleton and then do the real work by hand. It analyzes your codebase and detects build systems, test frameworks, and conventions, which is a fine starting point and saves twenty minutes. But by definition it can only write down what it can discover by reading your repo, and the whole value of a CLAUDE.md is the things it cannot discover: why a decision was made, which gotcha bit you last month, what is authoritative when two docs disagree. If a CLAUDE.md already exists, /init suggests improvements rather than overwriting it.

What is the difference between CLAUDE.md and auto memory?

You write CLAUDE.md; Claude writes auto memory. CLAUDE.md holds instructions and rules and is scoped to a project, a user, or an organization. Auto memory holds learnings Claude picks up from your corrections, stored per repository in a folder under ~/.claude/projects/, and it is machine-local rather than shared. They are complementary. I use CLAUDE.md for the things that must be true and let auto memory accumulate the operational trivia I would otherwise have to keep repeating.

Does CLAUDE.md work with other AI coding tools?

Claude Code reads CLAUDE.md, not AGENTS.md. If your repo already has an AGENTS.md for other agents, do not duplicate it. Create a CLAUDE.md whose first line imports it with @AGENTS.md, then add Claude-specific instructions below. Both tools then read one source of truth. A symlink works too, though on Windows that needs Administrator privileges or Developer Mode, so the import is the easier path there.

My CLAUDE.md rule keeps getting ignored. Is the model broken?

Almost certainly not. Check, in order: did the file load (/context), is it too long, does another file contradict it, and is the rule specific enough to verify. If all four check out and it still gets skipped, you have found a rule that does not belong in a markdown file. Instructions are advisory by design. Move it to a hook, where it runs as a shell command at a fixed point in the lifecycle and does not depend on the model choosing to comply.

Subscribe Now for More AI Insights

Subscribe for Updates from Reinventing AI

Stay current on the most cutting-edge AI solutions for ambitious entrepreneurs and marketers!

Get weekly AI training announcements, AI resources and insights.

0 comments

Joinor login to leave a comment