You're explaining the same thing to Claude every single session. Your project structure. Your error handling pattern. The fact that you never use default exports. The fact that src/migrations/ is sacred ground and nothing in there gets touched without a dry run.
Every time. From scratch. Like the last conversation never happened.
That's not a Claude problem. That's a CLAUDE.md problem — specifically, not having one that actually does anything.
The File Most People Get Wrong
Here's what most CLAUDE.md files look like in the wild:
This is a Next.js 14 app using TypeScript and Tailwind.
We use Prisma for the database. Follow clean code principles.
That's a context dump. It's better than nothing. It's also burning most of the file's real potential.
CLAUDE.md isn't a README for Claude. It's an instruction set. The difference matters because Claude doesn't just read it — it shapes how Claude behaves for every prompt that follows. Everything you define there runs implicitly, in the background, without you asking.
Think about what that actually means. You can encode a full pre-commit workflow and have it trigger automatically. You can define conditional behavior based on branch name, file path, annotation tags. You can build macros — two-word commands that kick off four operations and hand you back a consolidated status report.
Most people use 5% of that surface. This is the other 95%.
Two things to know before you start: the file lives in your project root, and you can also have a global one at ~/.claude/CLAUDE.md that applies across every project. Local overrides global where they conflict. Claude reads the whole file every session but weights the top more heavily as context compresses in long runs — so put the critical stuff first, not buried at the bottom after your stack overview.
Encoding Workflows That Run Themselves
Pick the task you repeat most. The one where you open a new Claude session, type out the same three-step process, watch it execute, and think: I've done this exact thing forty times this month.
That task belongs in CLAUDE.md as a standing instruction.
Say your commit cycle always hits the same sequence: lint, type-check, coverage check, changelog entry. Instead of narrating it every time:
## Pre-Commit Workflow
Before finalizing any code change:
1. Run `npm run lint --fix` and surface errors that couldn't be auto-fixed
2. Run `npx tsc --noEmit` and report type errors
3. Run `jest --coverage --testPathPattern=<modified_file>` — flag if coverage drops below 80%
4. Append a one-line entry to CHANGELOG.md under today's date
Do not prompt me to confirm each step. Run sequentially and report results together.
You've removed four context-switches from your commit cycle. Claude runs the sequence, hands you one consolidated status block, and you make a call. No back-and-forth. No "should I proceed with step 2?" interruptions mid-flow.
That last line — "do not prompt me to confirm each step" — is load-bearing. Without it, Claude asks permission at every stage. Sometimes that's what you want. If you trust the sequence, skip the ceremony.
Making Claude Understand Your Architecture, Not Just Your Stack
There's a version of this that goes deeper than workflow. Your codebase has conventions — accumulated decisions that reflect how your team actually thinks about structure. Claude defaults to what "most projects" do. That's often wrong for you specifically.
Stop re-explaining it:
## Code Generation Standards
- Named exports only. Never default exports.
- Error handling: Result<T, E> pattern from `~/lib/result.ts`. Never throw.
- Database queries live in `~/server/db/queries/`. Never inline SQL in route handlers.
- API responses must match the schema in `~/types/api.ts` — reference it before generating any response shape.
- One component per file. Filename matches component name exactly.
Now you're not just telling Claude what framework you're using. You're handing it a mental model of how your codebase is organized and what rules are non-negotiable. When it generates a new route handler or a database query, it follows your architecture because your architecture is in the file.
The specificity of these rules scales directly with how much you can trust the output without review. Loose rules, more review. Tight rules, faster merge. Write them the way you'd write them for a sharp junior engineer who needed the reasoning, not just the rule.
Documentation That Doesn't Rot
Documentation maintenance is one of those tasks everyone agrees is important and nobody wants to do. The docs drift. Behavior changes, comments don't. Six months later someone is reading a JSDoc that describes a function that no longer exists in the form it describes.
The fix isn't a documentation sprint. It's making docs a mandatory side effect of code changes:
## Documentation Policy
When modifying any exported function, class, or type:
- Update the JSDoc comment to reflect current behavior
- If the function appears in docs/api.md, update that entry
- If the change is breaking, add a deprecation notice before implementing
When adding a new environment variable:
- Add it to .env.example with a descriptive comment
- Add it to the "Environment Variables" section of README.md
The shift here is subtle but significant. You're not scheduling documentation — you're building it into the cost of every change. The docs stay accurate because they're maintained incrementally, at the same moment the code changes, by the same process that changes the code.
No deferred cleanup sprint. No "we'll fix the docs later" that never happens.
Protecting the Parts of the Codebase That Deserve It
Some directories are not like the others. Auth logic, database migrations, payment processing — these are the areas where a casual refactor or a misunderstood instruction can cause damage that's genuinely hard to undo.
You can encode that sensitivity directly:
## File-Specific Rules
`src/auth/`: Treat all changes here as security-sensitive. Flag anything that:
- Modifies token generation or validation logic
- Changes session duration or cookie attributes
- Adds or removes permission checks
Flag before implementing. Do not proceed without explicit confirmation.
`src/migrations/`: Never modify existing migration files. New migrations only.
Always run `npx prisma migrate dev --dry-run` before proposing any migration and include the full output.
The auth block adds a friction layer that makes you stop and think before a change goes through — which is the actual goal. The migrations block encodes a hard rule that eliminates a class of mistakes completely. Both of these things used to live in your head, in a wiki page nobody reads, or in a PR review comment that comes too late.
Two-Word Macros for Multi-Step Operations
Claude Code runs shell commands. Your CLAUDE.md can tell it exactly when and which ones — and you can give that sequence a name.
## External Tool Integration
After modifying any Python file:
- Run `black <file>` and `isort <file>` before presenting changes
- Run `mypy <file>` — include any type errors in your response
When I say "full sync":
- Run `git fetch --all`
- Run `pip install -r requirements.txt`
- Run `alembic upgrade head`
- Run `pytest -x -q`
- Report the state of each step in sequence
"Full sync" is a macro. Two words in, four operations out, one status report back. If you've got a Raspberry Pi 5 [AFFILIATE: Raspberry Pi 5] sitting on your desk as a local dev server, this kind of CLAUDE.md setup is what separates it from being a novelty to being something that actually runs your environment for you.
The pattern generalizes. Name any multi-step operation you run more than twice a week and give Claude a trigger phrase for it. You'll find yourself reaching for those phrases more than you expect.
Conditional Behavior: Claude That Reads the Room
Static instructions are powerful. Conditional instructions are smarter.
## Context-Aware Behavior
If I'm working in a branch prefixed with `hotfix/`:
- Skip style enforcement
- Skip changelog updates
- Prioritize correctness and minimal diff over everything else
If the file contains `// @legacy`:
- Do not refactor without explicit request
- Do not apply modern patterns
- Preserve existing logic structure exactly
The hotfix rule exists because production is down and nobody cares about your naming conventions right now. Fast and correct is the only thing that matters. The legacy annotation is a signal that the code is old on purpose — there's context around why it is the way it is, and Claude shouldn't helpfully modernize it because you didn't ask.
Both rules encode judgment calls you were already making manually. Writing them into the file means Claude makes them with you, automatically.
The CLAUDE.md That Maintains Itself
This one takes a minute to click, but it's the most interesting pattern on the list.
## Self-Maintenance
If I ask you to "remember" something during a session:
- Add it to the appropriate section of this CLAUDE.md file
- Tell me what you added and where
If you notice a convention I'm using consistently that isn't in this file:
- Flag it at the end of the session and suggest how to document it
What you've built here is a file that learns. You make a decision mid-session — "actually, let's always use zod for runtime validation from this point forward" — and instead of that preference evaporating when the session ends, it gets written into the file. Next session, it's already there.
Claude also starts surfacing its own observations. You'll get notes like: "I noticed you consistently name your custom hooks use[Resource]State — want me to add that to the conventions section?" You can ignore it or accept it. Either way, the option exists.
Over time the file gets more accurate, not less. That's the opposite of what happens with documentation you maintain manually.
Global vs Local: Where the Rule Actually Belongs
One last thing that trips people up.
~/.claude/CLAUDE.md is for you — communication style, verbosity preference, output formatting, code standards you apply everywhere regardless of project. The stuff you'd have to re-explain to any tool, on any codebase, forever.
./CLAUDE.md (in the project root) is for the project — architecture rules, team conventions, file-specific behavior, external tool chains, project macros. The stuff that's specific to this repo and this context.
If you're working across six repos with six different stacks, the global file handles your personal preferences. Each project file handles what makes that project different from every other one you work on.
Start with the global. One good global CLAUDE.md immediately makes every project session better before you've written a single project-specific rule.
The honest version of this: most Claude Code power users have a CLAUDE.md that's doing real work. Most casual users don't. That gap shows up in output quality, review overhead, and how often they're re-explaining things they've explained before.
Pick one workflow. Encode it. See what changes.
The full methodology for building out your CLAUDE.md as a persistent AI second brain — session design, memory architecture, the patterns that hold under real project pressure — is at [claude.md] Masterclass: Build Your Own Persistent AI Brain.
If you want the broader Claude Code playbook alongside it, Claude Code for Developers: 21 Productivity Tricks That Save Hours covers 21 techniques the official docs skip over — context management, tool chaining, multi-agent setup.
Top comments (0)