DEV Community

Olivia Craft
Olivia Craft

Posted on

The CLAUDE.md Structure That Makes Claude Code Actually Listen

The CLAUDE.md Structure That Makes Claude Code Actually Listen

I've shipped CLAUDE.md files across 35 projects in the last six months — TypeScript monorepos, Python ML pipelines, Go backends, mobile apps, infrastructure repos. Same agent. Wildly different results.

The difference wasn't the model. It was the file.

A bad CLAUDE.md gets ignored after the third tool call. A good one keeps Claude Code on rails for 200 turns. Here's the structure I've converged on, why it works, and how to adapt it to your stack.

Why most CLAUDE.md files fail

The default instinct is to write CLAUDE.md like a README. It's not a README. A README explains a project to a human who will read it once. CLAUDE.md is a system prompt that gets loaded into every interaction — and it competes for attention with tool results, file contents, and the user's actual request.

The three failure modes I see constantly:

  1. Wall of prose. Five paragraphs about "our philosophy of clean code." The agent skims it and forgets. Rules need to be scannable.
  2. No hierarchy. Setup, conventions, gotchas, deployment — all jumbled together. The agent can't tell what's load-bearing.
  3. Aspirational, not enforced. "We prefer functional patterns" with zero examples. Without a concrete rule, the agent reverts to its priors.

The fix is structural. Write CLAUDE.md the way you'd write a checklist, not an essay.

The five components that actually work

After 35 projects I always include the same five sections, in this order:

1. Identity & boundaries (3–5 lines)

Top of file. What is this project, what's the working directory, what should never be touched.

# CLAUDE.md — payments-api

Go service handling card auth + settlement. Runs on K8s, talks to Stripe.
Working dir: /Users/me/work/payments-api

DO NOT modify: migrations/*.sql (use `make migration` instead), .env.production
Enter fullscreen mode Exit fullscreen mode

This is the agent's first impression. Make it count.

2. Hard rules (numbered list, no fluff)

Numbered, imperative, falsifiable. Not "write good code" — "every exported function has a _test.go counterpart."

## Rules
1. No `any` in TypeScript. Use `unknown` and narrow.
2. All async errors caught at the route handler, not the service layer.
3. Tests live next to source: `foo.ts``foo.test.ts`.
4. Run `pnpm typecheck && pnpm test` before declaring done.
Enter fullscreen mode Exit fullscreen mode

If you can't write the rule as a sentence Claude could verify against a diff, it's not a rule — it's a vibe.

3. Commands cheat sheet

The exact shell commands. Not "run the tests" — pnpm test:integration -- --coverage.

This is the highest-leverage section. The agent will copy these verbatim into Bash calls. Wrong command here = wasted minutes per turn.

4. Architecture map (one paragraph max)

Where things live, in 4–6 lines. Not a tree dump. Not the full ADR.

## Layout
- `src/api/` — HTTP handlers (thin, route → service → repo)
- `src/services/` — business logic, no HTTP, no DB drivers
- `src/repos/` — Postgres only, returns domain types
- `src/lib/` — shared, no domain knowledge
Enter fullscreen mode Exit fullscreen mode

The agent uses this to decide where new code goes. Skip it and you'll get handlers with SQL inlined.

5. Anti-patterns (the "do not do this" list)

This is the secret weapon. List the things you've watched the agent do wrong before.

## Anti-patterns
- Don't add `try/except Exception` — let errors propagate to the FastAPI handler.
- Don't `pip install` — use `uv add`.
- Don't create new files at repo root. Everything goes in `src/` or `tests/`.
Enter fullscreen mode Exit fullscreen mode

Every project accumulates these. Write them down the first time, never repeat them.

Real stacks, real differences

The skeleton is the same. The contents shift hard by stack.

TypeScript / Next.js: Lean heavy on the Rules section. Ban any, ban default exports for components, specify which router (App vs Pages), pin the package manager. Add a "Server vs Client component" note — Claude defaults to client when unspecified.

Python / FastAPI: Commands section dominates. uv vs pip, pytest invocation, ruff config, alembic migration command. Add a Pydantic v1-vs-v2 note if relevant — the agent's prior is unreliable here.

Go: Minimum file. Go's conventions are tight enough that 80% of the work is done by gofmt and the standard library. Focus your rules on project-specific things: error wrapping style, context propagation, your logger of choice.

The pattern: rules expand where the language is permissive, contract where it's strict.

Solo vs team usage

Solo, your CLAUDE.md is a personal contract — it can be opinionated, terse, full of shorthand only you understand. Iterate it weekly.

Team usage changes the game:

  • Commit it. Review changes to it like code.
  • Add a "Decisions" section: "We chose Drizzle over Prisma because [link to ADR]." Stops the agent from "improving" past decisions.
  • Keep a per-developer override at ~/.claude/CLAUDE.md for personal preferences. Project file = team rules. User file = your habits.
  • When onboarding, the CLAUDE.md is the first doc new humans should read too. If it's not useful to a junior dev, it's not useful to Claude.

The teams I've seen succeed treat CLAUDE.md as living infrastructure. The teams that fail write it once and never touch it.

Stop reinventing this

I built 35+ pre-built CLAUDE.md editions — one per stack — using the exact structure above. TypeScript + Next.js, Python + FastAPI, Go + Echo, Rails, Django, Laravel, Flutter, Kotlin, Scala, and 25 more. Every one battle-tested across real projects.

If you've ever stared at an empty CLAUDE.md wondering what to write, skip the trial-and-error: CLAUDE.md Rules Pack — drop the right edition into your repo and ship.

Your agent only listens when you tell it what to listen for. Tell it well.

Top comments (0)