AI Development

Write a CLAUDE.md That Actually Works

Aditya Kumar JhaAditya Kumar JhaLinkedIn·June 12, 2026·10 min read

CLAUDE.md best practices: keep it under ~200 lines, pair every prohibition with a direction, cut generic advice, and let it evolve.

Adding more rules to your CLAUDE.md can make Claude follow fewer of them. That is the counterintuitive heart of the CLAUDE.md best practices that work: the file is loaded into context at the start of every session, and a bloated one makes Claude ignore your actual instructions because the important rules get lost in the noise. A file that works is short, project-specific, and directive. It holds only the facts Claude Code cannot infer from your code, and it pairs every prohibition with a clear instruction about what to do instead.

Most teams get this backwards. They treat CLAUDE.md like a wiki or a dumping ground for everything a new hire might want to know, and the result is a long file that the model skims and half-applies. This post is about that single file: the one that gives the agent persistent memory of your project.

What CLAUDE.md actually is

CLAUDE.md is a plain markdown file that Claude Code reads at the start of every conversation, giving it persistent context it cannot get from reading code alone. It is not enforced configuration. The official memory documentation is explicit: CLAUDE.md content is delivered as a user message after the system prompt, so Claude reads it and tries to follow it, but there is no guarantee of strict compliance. If you need an action to happen every time with zero exceptions, that belongs in a hook, not a memory file.

The file lives in a few standard places, loaded broadest scope first. A managed policy file applies org-wide. A file at ~/.claude/CLAUDE.md applies to all your projects. A project file at ./CLAUDE.md or ./.claude/CLAUDE.md is checked into git and shared with your team. A gitignored CLAUDE.local.md holds personal project notes like sandbox URLs. In a monorepo, Claude walks up the directory tree and concatenates every CLAUDE.md it finds, ordered from the filesystem root down to your working directory.

Insight

A widely repeated number is wrong: CLAUDE.md files are loaded in full regardless of length. The 200-line and 25KB limits you may have read about apply to the auto-memory MEMORY.md index, not to CLAUDE.md. Your file is never truncated, which is why a long one costs you adherence on every turn.

Rule 1: Keep it short, and treat every line as a cost

Target under 200 lines, and aim far lower if you can. The documentation states that longer files consume more context and reduce adherence, and one cited heuristic from practitioners is that some experienced teams run successfully with fewer than 60 lines. The reason is mechanical: Claude's performance degrades as its context window fills, and CLAUDE.md pays that tax on every message of every session.

Insight

Here is what most explainers will not tell you: you are not writing for unlimited attention, you are spending a fixed instruction budget, and Claude Code's own startup already spent some of it. The DataCamp guide puts numbers on it. Claude Code's system prompt consumes roughly 50 instructions before your session begins, and research on frontier LLMs (the IFScale study, Jaroslawicz et al., 2025) finds instruction-following starts to degrade somewhere around 150 to 200 total instructions. That leaves you roughly 100 to 150 slots for everything your project needs Claude to know. A wiki-length CLAUDE.md does not just waste tokens; it spends slots you do not have.

One test prunes a file faster than any other. For each line, ask: would removing this cause Claude to make a mistake? If not, cut it. This single question kills most of the bloat, because most lines in an overgrown CLAUDE.md describe behavior the model already does correctly on its own.

Pro Tip

If Claude keeps doing something despite a rule against it, the file is probably too long and the rule is getting lost. The fix is rarely a louder rule. It is a shorter file.

Rule 2: Every 'never' needs a 'do this instead'

A bare prohibition leaves the agent stuck: it tells the model what road is closed without showing it any open road, so the model stalls or improvises. Most files break this rule. Pair every 'never X' with a 'do Y instead.' The DataCamp tutorial illustrates this with force-pushing: 'Never force push. This rewrites shared history and is unrecoverable for collaborators' beats a bare 'Never force push' because the rationale lets Claude generalize the principle to related situations.

A negation-only rule reads 'Never use --legacy-peer-deps.' When Claude hits a peer-dependency conflict, it knows one thing not to do and nothing to do instead, so it improvises. The directive version reads 'Never use --legacy-peer-deps; resolve conflicts by updating the package to a compatible version.' Now the model has a destination, not just a wall.

Before and after

  • Before: "Don't put business logic in components." After: "Keep components presentational; put business logic in hooks under src/hooks/ and call them from the component."
  • Before: "Never edit files in generated/." After: "Files in generated/ are produced by `npm run codegen`; change the source schema in schema/ and regenerate instead of editing them by hand."
  • Before: "Avoid global state." After: "Share state through the existing AppContext provider; do not add new top-level stores."

Rule 3: Strip anything the model already knows

Documenting that Claude should 'write clean code' is like leaving a note telling water to be wet. Claude already knows TypeScript patterns, Python idioms, and what 'clean code' means, so documenting them wastes context budget. The official include/exclude split is the cleanest mental model here: include things Claude cannot guess, and exclude things it can derive from reading the repo or from general knowledge.

  • Include: bash commands Claude cannot guess, like the real test or build command for your repo.
  • Include: code-style rules that differ from defaults, plus repository etiquette like branch naming and PR conventions.
  • Include: architectural decisions specific to your project and developer-environment quirks, like a required env var.
  • Include: common gotchas and non-obvious behaviors that bite anyone new to the codebase.
  • Exclude: anything Claude can figure out by reading the code, and standard language conventions it already knows.
  • Exclude: detailed API docs (link to them instead), information that changes frequently, and self-evident advice like 'write clean code.'

A related trap is enforcing things a tool already enforces. Formatting, indentation, and import ordering are deterministic problems with deterministic solutions; a linter and formatter handle them faster, cheaper, and with full consistency. If a rule can be a hook or a pre-commit check, make it one. CLAUDE.md is for behavioral guidance the model has to reason about, not for mechanical rules a script can guarantee.

Rule 4: Be specific enough to verify

Write instructions concrete enough that you could check whether they were followed. 'Use 2-space indentation' is verifiable; 'format code properly' is not. 'Run npm test before committing' beats 'test your changes.' 'API handlers live in src/api/handlers/' beats 'keep files organized.' Vague phrasing is the other half of the adherence problem: the docs note that if Claude asks you questions already answered in CLAUDE.md, the wording is probably ambiguous.

Structure helps adherence too. Use markdown headers and bullets to group related rules, because Claude scans structure the way a human reader does, and organized sections beat dense paragraphs. You can add emphasis like 'IMPORTANT' or 'YOU MUST' to push compliance on the few rules that genuinely matter, but if every line shouts, none of them land. Reserve the emphasis for the rule you would be upset to see broken.

Here is what the same rule looks like before and after. Screenshot this table if nothing else.

PatternWeak versionStrong version
Constraint shape"Never use raw SQL.""Never write raw SQL; use the query builder in src/db/query.ts."
Style rule"Format code properly.""Use 2-space indentation, single quotes, no semicolons."
Command"Test your changes.""Run `pnpm test` before committing; prefer single tests over the full suite."
Layout"Keep files organized.""API handlers live in src/api/handlers/; shared types in src/types/."
Generic advice"Write clean, maintainable code."(cut it: the model already knows this)

Rule 5: Treat it as a living file that captures corrections

The best CLAUDE.md is not written once; it accumulates from the corrections you make. The official guidance gives clear triggers for when to add a line: when Claude makes the same mistake a second time, when a code review catches something the agent should have known about your codebase, when you type the same correction you typed last session, or when a new teammate would need the same context to be productive. Each of those is a signal to write the rule down once instead of repeating it.

Start the file with /init, which analyzes your codebase and detects build systems, test frameworks, and patterns to give you a foundation. Then refine. Treat CLAUDE.md like code: check it into git so the team contributes, review it when behavior goes wrong, and prune it regularly. If two rules contradict each other, Claude may pick one arbitrarily, so periodic cleanup matters as much as periodic addition.

Insight

When the file outgrows a single screen, do not stretch it. Split topic-specific rules into .claude/rules/ files with path globs in YAML frontmatter, so a rule loads only when Claude touches matching files. Move multi-step procedures that only matter sometimes into skills, which load on demand instead of taxing every session.

A small CLAUDE.md that works

Here is the shape, not a template to copy wholesale. Every line earns its place because removing it would change Claude's behavior on this specific project.

  • Project: payments API, Node 20 + Fastify + Postgres. Money is stored as integer cents, never floats.
  • Commands: `pnpm dev` runs the server; `pnpm test` runs Vitest; prefer single test files for speed.
  • Database: all queries go through src/db/query.ts; never write raw SQL in handlers.
  • Migrations: add a file in migrations/ and run `pnpm migrate`; never edit an applied migration, write a new one.
  • Errors: return the standard shape from src/lib/httpError.ts; do not throw bare strings.
  • Commits: Conventional Commits; branch as feat/<ticket> or fix/<ticket>.
  • Quirk: STRIPE_WEBHOOK_SECRET must be set locally or webhook tests fail silently; copy it from .env.example.

Notice what is absent: no 'write clean code,' no TypeScript tutorial, no formatting rules a linter owns. Each prohibition carries a direction. The 'never raw SQL' rule points at the query builder; the migration rule points at writing a new file. That pairing is what keeps the agent moving.

Where a separate memory layer fits

CLAUDE.md is project memory for one coding agent. It does not follow you to a chat assistant, a research tool, or another model, and it is not meant to. For memory that spans tools and conversations, MemX (memx.app) is an external AI memory layer that stores personal context you can carry across assistants instead of re-explaining it each time. It is private by architecture, with per-user isolation, encryption at rest, and on-device options. Keep project rules in CLAUDE.md; use a memory layer for the durable personal context that outlives any single repo or session.

Frequently Asked Questions
01How long should a CLAUDE.md file be?

Aim for under 200 lines, and shorter is better. CLAUDE.md loads in full on every session, and longer files reduce how reliably Claude follows your instructions. A useful test: remove any line that would not cause a mistake if deleted.

02Why is Claude ignoring my CLAUDE.md?

Usually the file is too long, so the rule gets lost, or the instruction is too vague. CLAUDE.md is advisory context, not enforced. Make rules specific and prune the file. The fix is rarely a louder rule. It is a shorter file.

03Where should I put my CLAUDE.md file?

Put project rules in ./CLAUDE.md (checked into git), personal cross-project preferences in ~/.claude/CLAUDE.md, and private project notes in a gitignored CLAUDE.local.md. Claude loads all of them, ordered from broadest to most specific scope.

04Should CLAUDE.md include code style rules?

Only rules that differ from defaults and that a tool cannot enforce. Formatting, indentation, and import order belong in a linter or formatter, which is faster and fully consistent. Reserve CLAUDE.md for behavioral guidance the model has to reason about.

05How do I add a memory while working in Claude Code?

Ask Claude directly, like 'add this to CLAUDE.md,' or run /memory to list the loaded files and open one in your editor. Add a rule when Claude repeats a mistake, when a review catches something it should have known, or when you retype the same correction.

Read Next

Or try MemX to access 40+ AI models in one place — including Claude Sonnet 4.6 and GPT-5.4 — and get your questions answered today.

Was this article helpful?

Found this useful? Share it with someone who needs it.

Free · iOS, Android & WhatsApp

Stop losing what you save.
Let MemX remember it for you.

Every screenshot, photo, PDF and voice note — captured, encrypted, and instantly searchable. Ask in plain English, get the answer in seconds.

  • Reads text inside images and handwriting
  • Private and encrypted by default
  • Free to start, no credit card

Takes under a minute to set up. Your data stays yours.

Aditya Kumar Jha
Written by
Aditya Kumar JhaLinkedIn

Core software engineer at MemX, where he builds the website, backend, and data systems. Also a published author of six books on Amazon KDP, writing on AI, memory, and behavior.

Keep reading

More guides for AI-powered students.