CLAUDE.md Mastery: Writing Project Instructions That Claude Actually Follows
CLAUDE.md Mastery: Writing Project Instructions That Claude Actually Follows Every Claude Code session loads a single CLAUDE.md file into the context window.
Primary Focus
ai developmentAI Tools Covered
What You'll Learn
- ✓The Three Failure Modes
- ✓Specific > General
- ✓The Verification Command Pattern
- ✓Patterns 1–3: Negative Examples, Absolute Constraints, and Path-Scoped Rules
- ✓Patterns 4–7: Enforcement Gates, Dependency Chains, Escape Hatches, Living Updates
- ✓The Cost of Bloat and How to Fix It
Guide Curriculum
Why Most CLAUDE.md Files Don't Work
Learn key concepts
- •The Three Failure Modes10m
- •Specific > General10m
- •The Verification Command Pattern10m
The 7 Patterns That Make Instructions Stick
Learn key concepts
- •Patterns 1–3: Negative Examples, Absolute Constraints, and Path-Scoped Rules10m
- •Patterns 4–7: Enforcement Gates, Dependency Chains, Escape Hatches, Living Updates10m
Maintaining CLAUDE.md Over Time: Bloat, Drift, and Pruning
Learn key concepts
- •The Cost of Bloat and How to Fix It10m
- •Structure for Scanning10m
- •Adding New Fields10m
- •Deleting Fields10m
- •Pruning Without Losing Context10m
Preview: First Lesson
Why Most CLAUDE.md Files Don't Work
The Three Failure Modes
Why Most CLAUDE.md Files Don't Work
The most common CLAUDE.md mistakes fall into three categories: vagueness, breadth, and aspirational-only content.
Vagueness sounds like: "Always be careful when modifying the database." Claude will nod along, but what does "careful" mean? Don't modify production? Don't drop tables? Don't change schemas? Vague rules create uncertainty, and Claude errs on the side of asking for permission rather than acting confidently.
Breadth is when you dump everything you wish Claude knew into CLAUDE.md. "Here's our testing philosophy, our git workflow, our deployment procedure, our code style, our API design patterns..." This creates a 50KB wall of text that gets truncated or ignored.
Aspirational-only content is the biggest trap. Rules like "Always write unit tests for new functions" sound good, but they don't include the verification command. How does Claude know if the rule was followed? Without a self-check mechanism, Claude will write the tests, then forget they exist and move on.
The fix is specificity, scoping, and verification.
Start learning with this comprehensive guide
This guide includes:
About the Author
Hiram Clark is the founder and managing editor of vybecoding.ai and sets editorial direction for the guides and news published here. Articles are drafted with AI assistance and edited before publication. He works hands-on with the AI development tools, workflows, and infrastructure covered on the site.
Full Guide Content
Complete lesson text — start the interactive course above for exercises and progress tracking.
Module 1Why Most CLAUDE.md Files Don't Work
1.1The Three Failure Modes
Why Most CLAUDE.md Files Don't Work
The most common CLAUDE.md mistakes fall into three categories: vagueness, breadth, and aspirational-only content.
Vagueness sounds like: "Always be careful when modifying the database." Claude will nod along, but what does "careful" mean? Don't modify production? Don't drop tables? Don't change schemas? Vague rules create uncertainty, and Claude errs on the side of asking for permission rather than acting confidently. Breadth is when you dump everything you wish Claude knew into CLAUDE.md. "Here's our testing philosophy, our git workflow, our deployment procedure, our code style, our API design patterns..." This creates a 50KB wall of text that gets truncated or ignored. Aspirational-only content is the biggest trap. Rules like "Always write unit tests for new functions" sound good, but they don't include the verification command. How does Claude know if the rule was followed? Without a self-check mechanism, Claude will write the tests, then forget they exist and move on.The fix is specificity, scoping, and verification.
1.2Specific > General
Replace every generic rule with a concrete command or constraint.
Bad: "Be mindful of database performance." Good: "Before running migrations on the prod database, usenpx convex run verifyMigration --prod to check for full-table scans."
Bad: "Follow the project's code style."
Good: "Use the ESLint config in .eslintrc.json. Run npm run lint:fix before committing."
Bad: "Test your changes."
Good: "Run npm test -- --coverage and ensure coverage is ≥85%. Commit only if all tests pass."
Specific rules are verifiable. Vague rules are not.
1.3The Verification Command Pattern
Every rule should have a built-in self-check. This is how Claude confirms compliance without asking you.
Example:
## Database Migrations
When modifying the schema:
1. Create a migration file in convex/schema.ts
2. Run: npx convex run verifyMigration --dev
3. Check the output for warnings. Do not proceed if you see "FULL_TABLE_SCAN"
4. Test locally: npm test
5. Verification: npm run schema:validate (should output "✓ Schema valid")
The npm run schema:validate command is your verification gate. Claude can run it, see the output, and know whether the rule was followed.
Without this, Claude might write the code and trust that it works. With verification, Claude knows.
Module 2The 7 Patterns That Make Instructions Stick
2.1Patterns 1–3: Negative Examples, Absolute Constraints, and Path-Scoped Rules
The 7 Patterns That Make Instructions Stick
Pattern 1: Negative Examples are more powerful than positive ones.## DO NOT delete database records via direct mutation
❌ WRONG:
db.patch(docId, { deleted: true }) // silent corruption
✓ RIGHT:
await ctx.db.patch(docId, { isDeleted: true, deletedAt: Date.now() })
// soft delete with timestamp
Negative examples stick because Claude sees the failure case first.
Pattern 2: Absolute Constraints prevent entire categories of mistakes.## Convex Production Database
- NEVER use --prod flag unless explicitly instructed
- NEVER run destructive commands (delete, patch batch) without --dry-run first
- ALWAYS verify output before applying changes
Absolute rules are black-and-white. No gray area, no interpretation needed.
Pattern 3: Path-Scoped Rules avoid applying all rules to all files.## Rules for convex/schema.ts
When modifying convex/schema.ts:
- Never add a required field to an existing table without a default value
- Run: npx convex codegen after any schema change
- Verification: git diff should show no breaking changes
## Rules for src/components/
- Use React hooks, not class components
- Every component ≥200 LOC must have TypeScript types
- Verification: npm run type-check should pass
This keeps rules focused. Rules for the database schema don't clutter rules for React components.
2.2Patterns 4–7: Enforcement Gates, Dependency Chains, Escape Hatches, Living Updates
## Before committing:
1. npm run lint:fix (must pass)
2. npm test (must pass with coverage ≥80%)
3. npm run type-check (must pass)
ONLY commit after all three gates pass.
Claude will follow this sequentially because it's a clear chain.
Pattern 5: Dependency Chains tell Claude the order of operations.## Creating a new feature:
1. Update convex/schema.ts with new tables/fields
2. Run: npx convex codegen (depends on step 1)
3. Create API function in convex/myfeature.ts (depends on step 2)
4. Create React hook in src/hooks/useMyFeature.ts (depends on step 3)
5. Create component in src/components/MyFeature.tsx (depends on step 4)
6. Test in src/__tests__/MyFeature.test.tsx (depends on step 5)
Each step depends on the previous one — this isn't arbitrary.
Pattern 6: Escape Hatches acknowledge that rules will sometimes need to be broken.## DO NOT modify production data
EXCEPTION: If you have explicit permission from the on-call engineer,
use convex run --prod --dry-run first, show output, wait for approval.
This prevents Claude from getting stuck when rules conflict with real-world needs.
Pattern 7: Living Updates means CLAUDE.md changes as your project evolves.Every sprint, review CLAUDE.md: remove rules that no longer apply, add rules for new failure modes, update verification commands as your CI/CD pipeline changes. Old CLAUDE.md files are worse than no CLAUDE.md because Claude follows outdated rules.
Module 3Maintaining CLAUDE.md Over Time: Bloat, Drift, and Pruning
3.1The Cost of Bloat and How to Fix It
Maintaining CLAUDE.md Over Time
CLAUDE.md is loaded into every context window. If it's 10KB, that's ~2,500 tokens. If it's 50KB, that's ~12,500 tokens. You're paying that cost on every single conversation.
Bloat sources:- Aspirational content ("Here's our dream architecture...")
- Outdated rules from 6 months ago
- Overly detailed philosophy paragraphs
- Duplicate rules in different sections
- Rules that duplicate project documentation
- Is this rule referenced in the codebase (via comments or convention)?
- Does this rule prevent a real failure mode Claude has hit before?
- Could this rule live in project docs instead?
- Is this rule still true today?
If you answer "no" to any of these, consider removing it.
3.2Structure for Scanning
Claude scans CLAUDE.md quickly. Structure it for skim-reading, not deep study.
Use:
- Clear headings (## Section, ### Category)
- Bullet points for lists
- Code blocks for commands
- Bolded key terms
Avoid:
- Long paragraphs without headings
- Narrative prose (save that for your project wiki)
- Rules buried in explanatory text
```
Convex Database
3.3Adding New Fields
- Never add required fields without defaults
- Command: npx convex codegen
- Verification: npm run type-check
3.4Deleting Fields
- Never delete in place; use soft-delete pattern
- Add _isDeleted: Boolean, _deletedAt: Number fields
- Command: npx convex run migrateData
```
3.5Pruning Without Losing Context
Once a quarter:
- List all rules in CLAUDE.md
- Check git history: how often was each rule relevant?
- Ask: "If we removed this rule, would Claude break the project?"
- If the answer is "probably not," move it to project docs or remove it
- Architecture overview (too large for CLAUDE.md)
- Historical context ("We used to do X, now we do Y")
- Philosophy and rationale (useful for onboarding, not daily work)
- Immediate constraints and failure modes
- Verification commands
- "Never do this" rules
- Path-scoped guardrails