Your CLAUDE.md Gets Ignored Mid-Session. Here's What to Put in It
You wrote a CLAUDE.md. The first twenty minutes look great. Then Claude invents an API that already exists, runs npm in a pnpm repo, and “improves” a file nobody asked about.
The file is still on disk. The session just stopped treating it as load-bearing.
That is not a model failure. It is a context file doing the job of a README, a wiki, and a style guide at the same time — then losing the fight as the window fills.
What is actually happening
Each Claude Code session starts with a fresh context window. CLAUDE.md is how you re-brief the new hire. Anthropic’s memory docs are explicit about the mechanism: the file is injected as a user message after the system prompt, not as enforced configuration. Claude tries to follow it. There is no guarantee of strict compliance, especially when the instructions are vague or they contradict each other.
Three things make that worse mid-session.
The window fills. Tool output, file reads, and your back-and-forth crowd the briefing you wrote. A 400-line CLAUDE.md that restates package.json is the first thing to get soft.
Compaction is selective. After /compact, Claude re-reads the project-root CLAUDE.md from disk and puts it back. Nested CLAUDE.md files in subdirectories, and path-scoped rules with paths: frontmatter, do not come back automatically. They reload the next time Claude reads a matching file. If the instruction you cared about lived only in src/app/CLAUDE.md, compaction just ate it.
Several files concatenate. They do not override. Claude walks from the filesystem root down to the working directory and stitches every CLAUDE.md and CLAUDE.local.md it finds. Instructions closer to where you launched are read last. A leftover ~/.claude/CLAUDE.md that says “always use npm” will sit in the same prompt as the project file that says pnpm. Claude picks one.
Official guidance is to keep each file under 200 lines. Longer files consume more context and reduce adherence. /doctor will even propose trims: cut the directory tree Claude can see for itself, keep the pitfalls it cannot.
Write the file that survives the session
Do this in order. The first check is the cheapest.
1. Confirm the file loaded
Do not reason about it. Look at it.
/contextUnder Memory files you should see your project CLAUDE.md. If it is missing, Claude cannot see it. /memory lists the paths Claude will consider and opens the one you pick.
The project file belongs at ./CLAUDE.md or ./.claude/CLAUDE.md. Personal overrides that must not be committed go in ./CLAUDE.local.md (gitignored). Preferences that follow you across every repo go in ~/.claude/CLAUDE.md — and nowhere else.
If /context does not list the file, stop editing prose. You are debugging placement, not wording.
2. Cut what Claude can derive
Before you write a better file, delete the parts of the current one that are just a tour of the repo.
Cut:
- A directory tree Claude can
ls - A dependency list that already lives in
package.json - “Write clean code” and “follow best practices”
- A pasted README
- Every
@importyou added “for organization” — imported files still load at launch, so they do not save context - Empty headings. They cost tokens and teach nothing
Keep:
- The one-paragraph product brief a new senior engineer would need on day one
- Exact commands, including the package manager
- Boundaries: what must never import what
- The gotcha that has already burned someone
- How Claude should behave when a requirement is ambiguous
If a section is a multi-step procedure, or only matters for one folder, it does not belong in the root file. That is a skill or a path-scoped rule in .claude/rules/.
3. Put the sections in an order that still works at minute forty
Claude scans structure the way you do: headings, then bullets. Order is not decoration. The top of the file is what you need in every turn. The bottom is what you need when the task matches.
Use this order:
- Project context — what this is, who it is for, the stack, the package manager
- Workflow commands — a table, not a paragraph
- Architecture — where things live, and what must never live there
- Coding standards — only the rules that differ from the tool defaults
- Agent behavior — how to work in this repo
- Gotchas and out of scope — the landmines
Do not lead with a 60-line style guide. By the time Claude is writing a route handler, the window is already full of the file it just read. The stack and the commands have to still be in reach.
4. Drop in a finished file for a Next.js App Router app
This is the file, not a description of a file. Swap the product paragraph and the gotchas for yours. Delete any section that does not apply.
## Project Context
B2B SaaS dashboard. Teams manage projects, members, and billing.Breaking auth or billing is worse than shipping a late feature.
- **Stack**: TypeScript, React 19, Next.js 15 App Router, Tailwind CSS 4, PostgreSQL, Prisma- **Package manager**: pnpm — never npm or yarn- **Node**: 24 LTS- **Deploy**: Vercel, production deploys on merge to `main`
### Constraints
- Server Components by default. Add `"use client"` only for state, effects, or browser APIs.- Do not set `runtime = 'edge'` unless a route specifically needs it. Node.js (Fluid Compute) is the default and keeps the full Node API.- No new dependency without asking.
## Workflow Commands
| Task | Command || ------------------ | ---------------------------------- || Install | `pnpm install` || Dev server | `pnpm dev` || Build | `pnpm build` || Unit tests | `pnpm test` || Test a single file | `pnpm test path/to/file.test.ts` || Typecheck | `pnpm typecheck` || Lint | `pnpm lint` || E2E | `pnpm test:e2e` |
Before calling a change done: `pnpm typecheck && pnpm test`.
## Architecture
src/ app/ # routes, layouts, route handlers — no domain logic components/ # UI only. No Prisma. No process.env lib/ # server utilities, db client, auth lib/billing/ # Stripe and plan logic. Do not import this from client components
Key boundaries:
- Domain logic does not import from `next/headers` or `next/navigation`.- All database access goes through `src/lib/db.ts`. No `new PrismaClient()` in a route file.- Route handlers in `src/app/api/` stay thin: parse, call `lib/`, return.
## Coding Standards
- TypeScript `strict` is on. Never use `any` — use `unknown` and narrow it.- No `as` casts to silence the compiler. If the type is wrong, fix the type.- Named exports. Default exports only where the App Router requires them (`page.tsx`, `layout.tsx`, `error.tsx`).- Server Actions that mutate data revalidate the tag they touch. Do not sprinkle `revalidatePath('/')`.- Comments explain WHY. Delete a comment that restates the code.
## Agent Behavior
- Read the existing pattern in the nearest files and match it. Consistency beats preference.- Ask when the requirement is ambiguous. A wrong assumption implemented well is still wrong.- Change the minimum. Do not refactor unrelated code or reformat untouched files.- Never invent a library API. Check the installed version, or the docs, first.- Run typecheck and tests before saying it works. If they fail, paste the output.- Never commit or push unless asked.
## Gotchas
- `NEXT_PUBLIC_` env vars are baked in at build time. A missing Stripe publishable key looks like "checkout is broken," not like a config error.- `src/lib/db.ts` must stay a singleton. Instantiating Prisma in a Server Action will exhaust connections in dev.- Do not edit `src/generated/`. Run `pnpm prisma generate`.
## Out of Scope
- `src/generated/` — regenerate, do not patch- `.next/` — build outputThat file is specific enough to verify. “Use 2-space indentation” beats “format code properly.” “Run pnpm test before calling it done” beats “test your changes.”
A Django app gets the same shape: product paragraph, exact commands (ruff, pytest, the settings module), the boundary between views and domain, the gotcha that only exists in that repo. The stack changes. The job of the file does not.
5. Restart, then judge
Some of what you just changed is read once, at session start. Edit the file, start a new session, run /context again, and only then decide whether the wording works.
If an instruction must run at a fixed moment — before every commit, after every edit — it is a hook, not a sentence in CLAUDE.md. Hooks execute. The markdown file asks.
Common mistakes
Pasting the README. Claude can read README.md when it needs it. Putting it in CLAUDE.md means it is in every turn, including the ones where you are renaming a variable.
Editing ~/.claude/CLAUDE.md to fix one project. That file follows you into the next repo. Project rules belong in the project file.
Using @imports to “keep the root file short.” The root looks clean. The context window still pays for every imported file at launch. Split with .claude/rules/ and paths: frontmatter if the instruction is only for src/app/api/**/*.ts.
Leaving a nested CLAUDE.md as the only copy of a rule. It will vanish after compaction until Claude happens to read that folder again. If the rule matters in every session, it belongs at the project root.
Contradicting yourself. A user file that says npm and a project file that says pnpm is not “coverage.” It is a coin flip. /memory lists every file in play — read them as a set.
Treating the file as a lock. CLAUDE.md is context. Settings and hooks are enforcement. If “never run rm -rf” has to be true regardless of what Claude decides, it does not go in markdown.
Trusting the file over the session. The file is what you wrote. /context is what was loaded. When they disagree, the session is right.
Checklist
-
/contextlists the projectCLAUDE.mdunder Memory files - The file is at
./CLAUDE.mdor./.claude/CLAUDE.md, not only in your home directory -
CLAUDE.local.mdis gitignored if you use one - The file is under 200 lines and has no empty headings
- Package manager, Node version, and verify commands are exact
- Architecture says what must not live in a folder, not just what does
- Agent behavior tells Claude when to ask instead of guess
- Gotchas are things that have already happened, not generic advice
- Path-specific rules live in
.claude/rules/withpaths:frontmatter - Nothing in the file contradicts
~/.claude/CLAUDE.mdor a leftover nested file - You restarted the session after the last edit and checked
/contextagain
Build the file for your repo
If you want a starting point instead of a blank page, use the CLAUDE.md Workflow Builder. Pick the project type and stack, then replace the product paragraph and the gotchas with the ones only you know.
The builder will not know that Prisma in a Server Action exhausts connections in your app. That line is the whole reason the file exists.
For how the rest of a ClaudeFlow project is wired — dropping the kit into a repo you already have — start at the getting started guide. If Claude is ignoring instructions and you are not sure the file is even the layer that is broken, diagnose by symptom in troubleshooting Claude Code.
Written by
Marco Elizalde
ClaudeFlow Team
