Your CLAUDE.md started at 40 lines. "Here's what this project is. Here's the stack. Here are some conventions." Clean.
Three months later it is 3000 lines and Claude Code is drifting more, not less. Every time Claude did something you didn't want, you added a paragraph to CLAUDE.md: “When reviewing PRs, also check for X.” “When writing tests, remember Y.” “Do not forget Z.”
The file grew. The drift got worse.
Here is why that happens, and what actually fixes it.
Why longer CLAUDE.md makes drift worse
Three compounding mechanisms:
1. Instruction dilution. Claude reads the whole CLAUDE.md every session. When your file has 40 lines of real instruction, each instruction gets meaningful weight. When it has 3000 lines — 80% of which are aspirational fluff, mission statements, and duplicated paragraphs — the real instructions get buried. Claude’s attention mechanism does attend to everything, but when everything is screaming, nothing is heard distinctly.
2. Recency bias hits early instructions hardest. If a 3000-line CLAUDE.md says "always check for N+1 queries" on line 400, and then 800 lines later you’re asking Claude to implement a new feature, the N+1 rule is ambient but not salient. The later context dominates. The earlier rule gets skipped.
3. Interpretive freedom compounds. Every CLAUDE.md paragraph is prose. Prose is interpreted fresh each session. You wrote "review PRs for security issues" — Claude interprets that differently depending on what else is in the context. One session it checks OWASP top 10. Next session it just checks for hardcoded secrets. You can’t tell why. The instruction is unstructured; the behavior drifts.
The problem isn’t that Claude ignores CLAUDE.md. The problem is that long-form prose instructions are inherently re-interpretable, and every session starts fresh. Length doesn’t make instructions more durable. It makes them noisier.
The first symptom: you start writing the same paragraph twice
At some point you notice you’ve written “review this PR for X” in three different sections of CLAUDE.md, each slightly different. You’re solving the same drift problem three different ways.
This is the signal that the instruction should not be in CLAUDE.md at all. It should be a skill.
What a skill is (and why it stops drift)
A skill lives in ~/.claude/skills/{name}/SKILL.md. Claude Code loads it automatically. Invoked explicitly by name:
use the pr-review-comprehensive skill on the current branch
A skill file is not prose. It enforces:
- Scope: exactly which files the skill touches, and which it refuses to.
- Output shape: predictable formatting.
[severity] file:line — finding + suggested action. Every invocation, same shape. Greppable. - Constraints: explicit “refuses to” rules. “Refuses to approve without citing 3+ verified items.” “Refuses to propose a fix before a repro is verified.”
- Sequence: ordered steps. No skipping when context is long.
The key distinction: prose in CLAUDE.md gets re-interpreted each session. A skill file declares rules that fire during execution, not rules that get merged into a free-form context window. Same structure every time.
The migration path
Three steps:
1. Run an audit. Paste your CLAUDE.md into the free client-side tool at septimlabs.com/tools/claude-md-analyzer. It flags length, instruction-vs-aspirational ratio, corporate-speak terms, and recurring-instruction patterns that should be skills.
2. Extract the top 5 recurring instructions. For every section of CLAUDE.md that tells Claude "when you do X, check for Y," move the how-to into ~/.claude/skills/{x}/SKILL.md. Format:
--- name: x description: Short description of when to invoke this. --- # Skill body ## Inputs - What the skill expects ## Steps 1. Ordered step with explicit constraints 2. Another step 3. ... ## Output format Structured output spec ## Refuses to - Specific things the skill will not do
3. Delete the extracted instructions from CLAUDE.md. This is the step most people skip. You write the skill file and leave the original CLAUDE.md paragraph in place. That defeats the purpose — now you have the instruction in two places, with two different interpretations. Remove it from CLAUDE.md. The skill is the source of truth.
What CLAUDE.md should contain after the migration
Project-specific context only. About 5 sections:
- What this project is. 3-5 lines. Not a mission statement.
- Stack + deploy target. Bulleted, factual.
- Project-specific conventions. Naming, testing framework, commit style, env var locations.
- Gotchas. 5-15 specific traps the project has hit. “The Stripe webhook needs raw body.” “Supabase RLS is on.” This section is where CLAUDE.md earns its keep.
- What not to touch. Paths, files, patterns Claude should refuse.
Target length: under 400 lines. Ideally under 200. If it’s longer, you still have reusable instructions that should be extracted.
A concrete before / after
Before (excerpt from a 2400-line CLAUDE.md):
## Instructions for Claude When reviewing my pull requests, please check for: - Code quality - Tests - Security issues - Performance problems - Breaking API changes Please write code that is well-tested, maintainable, and scalable. Aim for best-in-class quality that our customers will love. Follow SOLID principles and clean architecture. When reviewing, also make sure to consider edge cases, error handling, and that the code follows our team’s conventions. We value excellence and we want all code to meet our highest standards.
After (the relevant skill file, at ~/.claude/skills/pr-review-comprehensive/SKILL.md):
--- name: pr-review-comprehensive description: Run a 7-lens review on a pending PR. --- Run seven review lenses against the diff, in order: 1. Intent drift (does diff match description) 2. Logic correctness (walk every non-trivial branch) 3. Test gaps (every added function has a test) 4. Security (OWASP top-10 class scan) 5. Performance (N+1, unbounded, blocking sync) 6. API surface (breaking change check) 7. Rollback safety (revert cleanly if needed) Output format: - [severity] file:line — one-sentence finding + suggested action Severities: blocker, major, minor, nit. End with verdict: APPROVE / APPROVE with comments / REQUEST CHANGES / BLOCK. Refuses to: - Approve without citing 3+ verified items. - Speculate about files outside the diff. - Mark security issues without file:line reference.
The skill file is shorter AND more deterministic. CLAUDE.md shrinks by 300 lines. Claude’s review output stops drifting.
The skills you’ll probably need
Across 3 months of production Claude Code use, the recurring instruction patterns that almost always should be skills:
- Review — PR review, test gaps, migration safety, security triage, performance smell
- Refactor — extract shared logic, dead-code sweep, type tightening, error boundaries, env audit
- Documentation — README sync, API docs, changelog, commit quality, onboarding
- Ops — dependency triage, CI audit, bug reproduce, postmortem, deprecation plan
- Launch — HN post, X thread, release notes, spec-to-plan, effort estimate
If your CLAUDE.md currently has instructions in more than 2-3 of those categories, it’s doing the work of a skill directory, badly.
A real session, with numbers
Here is what a production CLAUDE.md audit actually looked like. The project: a Next.js 14 + Supabase SaaS with 11 months of Claude Code sessions behind it. The CLAUDE.md: 2,841 lines.
We ran a content classification pass across the file and bucketed every line:
CLAUDE.md content audit — 2,841 lines
---------------------------------------
Project context (stack, conventions, gotchas) 214 lines 7.5%
Aspirational statements ("aim for quality") 380 lines 13.4%
Duplicated instructions (same intent, 3+ times) 611 lines 21.5%
Category: Review instructions 442 lines 15.6%
Category: Refactor instructions 318 lines 11.2%
Category: Documentation instructions 279 lines 9.8%
Category: Ops / CI instructions 388 lines 13.7%
Category: Launch / shipping instructions 209 lines 7.4%
---------------------------------------
Lines that belong in CLAUDE.md: 214 (7.5%)
Lines that should be skills: 2,427 (85.4%)
Lines that should be deleted: 200 (7.0%)
After the migration: CLAUDE.md compressed to 198 lines. Eight skill files created, totalling 712 lines of structured enforcement that ran identically every invocation. The two-hour session that previously produced drift on the N+1 query check now caught every instance — because the skill file had the specific rule, not a general aspiration.
The "aspirational statements" bucket is worth calling out specifically. Lines like "Write code that you’d be proud to show a senior engineer" and "Strive for test coverage that gives us confidence" are not instructions. They are feelings. They consume context without doing any work.
Common mistakes when doing the migration
Mistake 1: Writing the skill file and keeping the CLAUDE.md paragraph. You end up with the same instruction in two places, interpreted differently in each location. One wins per session, non-deterministically. Delete from CLAUDE.md the moment you extract to a skill.
Mistake 2: Writing skill files that are too broad. A skill called code-quality that covers "review, refactor, and documentation" is just a smaller CLAUDE.md. Skills compound best when they have one job. pr-review-security is a skill. code-quality is a category.
Mistake 3: Not defining the "Refuses to" section. This is the most important section of a skill file and the most skipped. Without explicit refusals, Claude will fill gaps with reasonable-seeming behavior that differs from session to session. A PR review skill that "refuses to approve without citing 3+ verified findings" will not approve based on a general feeling of quality. That is the determinism you want.
Mistake 4: Forgetting to invoke. Skills are not loaded automatically like CLAUDE.md. If you write a pr-review-comprehensive skill but never type the invocation, it does nothing. Put a note in your PR-open checklist: run /pr-review-comprehensive before pushing.
Step-by-step checklist
- Run a line-count on your CLAUDE.md:
wc -l CLAUDE.md. If it’s over 400, continue. - Classify every section manually or with Claude: project context, aspirational, duplicated, or "should be skill."
- Delete all aspirational statements. They do no work.
- Pick the 3 most duplicated instruction patterns. Each becomes one skill file.
- Write the skill file per the template above. Include: name, description, inputs, ordered steps, output format, refuses-to rules.
- Delete the corresponding lines from CLAUDE.md.
- Test: invoke the skill explicitly on a real task. Compare output structure to previous sessions. It should be identical in shape.
- Repeat for the next 2-3 instruction categories over the following week.
- Target CLAUDE.md length: 150-300 lines. If it creeps back above 400, stop adding prose and add a skill instead.
When this approach doesn’t apply
Short CLAUDE.md files — under 200 lines — are usually fine as prose. The drift problem is a large-file problem. A 120-line CLAUDE.md with a clear structure and no aspirational filler is unlikely to cause meaningful drift. Don’t prematurely optimize.
The org-chart alternative: some teams use multiple sub-agents instead of skills, where each agent has a narrow CLAUDE.md focused only on its domain. A pr-reviewer agent with a 40-line CLAUDE.md that covers only review concerns. A refactor-agent with its own 40-line context. This is structurally equivalent to skills — the key is the same: narrow scope, structured output, explicit refusals. The mechanism (skill files vs. dedicated agents) is secondary to the discipline.
25 pre-built skills, ready to drop in.
Septim Drills is the pack above, shipped. 25 production Claude Code skills across review, refactor, docs, ops, and launch — each with a scoped input, structured output format, and refuses-to rules defined. Drop into ~/.claude/skills/ and invoke by name. $29 lifetime, private GitHub repo, free updates. Three sample skills are free at github.com/septimlabs-code/septim-drills-samples.
The last thing
The CLAUDE.md problem isn’t actually about CLAUDE.md. It’s about what happens when you try to solve drift with more prose. Prose doesn’t enforce; prose interprets. Every added paragraph is another interpretation surface.
The fix is structural: move enforcement out of prose and into a format that runs the same way every time. That’s what skills are. CLAUDE.md becomes what it should have been all along — a small, boring, factual context file about this project. Skills become the reusable enforcement layer that works regardless of how long the context window has grown.
Start with the line count. If it’s over 400: audit, extract, delete. If it’s under 200: leave it alone and spend the time on something that matters more.
— The Septim Labs team