If you use Claude Code, you probably know the feeling: you ask it to fix a small bug and it rewrites half your codebase, adds docstrings everywhere, and creates three new abstraction layers you never asked for. The solution? A .CLAUDE.md file ā a set of instructions that Claude reads at the start of every conversation.
Here's a deep dive into mine and why each section exists.
What is CLAUDE.md?
Claude Code looks for CLAUDE.md files in your project root and in ~/.claude/CLAUDE.md globally. Think of it as a persistent system prompt that shapes how the AI collaborates with you. My global one applies to every project I work on ā it encodes the coding philosophy I've built over years of professional development.
The Persona
You are a senior full-stack developer ā one of those rare 10x developers
with incredible knowledge.
Simple but effective. This sets the baseline expectation: don't explain obvious things, don't be overly cautious, and bring real engineering judgment to the conversation.
General Principles
- Focus on simplicity, readability, performance, maintainability,
testability, and reusability.
- Less code is better. Lines of code = debt.
- Write correct, DRY code. Prefer functional, immutable style unless
it adds significant verbosity.
- Let tests drive design.
The key line here is "Lines of code = debt." Without this, AI assistants tend to be verbose ā adding defensive checks, exhaustive error handling, and helper functions for things that happen once. Every line of code is a line that needs to be maintained, understood, and potentially debugged.
TDD: Red, Green, Refactor
This is the heart of the file. I enforce strict TDD discipline:
1. Red ā Write a small failing test that specifies the next behavior.
2. Green ā Write the minimum code to pass. Ugly is fine.
3. Refactor ā Clean up under green tests. No new behavior.
I also explicitly define when TDD is required and when it's optional:
- Always TDD: business logic, transformations, validators, parsers, state machines, API handlers, complex hooks
- TDD optional: thin glue code, layout-only components, one-off scripts, spikes
- Bug fixes: reproduce with a failing test first, then fix
Without these boundaries, you either get an AI that writes tests for every CSS class or one that skips tests entirely when they matter most.
Test Quality
- Name tests as behavior specs: `rejects expired tokens with 401`,
not `test token`.
- Test behavior, not implementation.
- No shared mutable state between tests.
The naming convention alone transformed how Claude writes tests for me. Instead of generic test_create_user names, I get descriptive specs like creates user with valid email and returns 201 ā tests that serve as living documentation.
Tidying Moves
This section is directly inspired by Kent Beck's "Tidy First?" and gives Claude a vocabulary for structural improvements:
- One pile: scattered logic? Inline it back together first, then split along real seams
- Explaining variables: extract complex expressions into named constants
- Guard clauses: early returns upfront, happy path at top indentation
- Normalize symmetries: make parallel cases structurally identical
- Dead code removal: delete it, don't comment it out
The key rule: each tidy is a single, small, committable structural change ā never mixed with behavior changes. This prevents the classic AI antipattern of "fixing" your code while also adding the feature you asked for, making the diff impossible to review.
Naming and Functions
- Names reveal intent, not implementation. If you struggle to name it,
it does too much.
- One function, one responsibility. If you need "and" to describe it,
split it.
- Hard to test in isolation ā doing too much.
These rules give Claude clear heuristics for decomposition. The "and" test is particularly powerful ā if you catch yourself writing validateAndSaveUser, that's two functions.
What to Avoid
This section exists because AI assistants have specific failure modes:
- Gold plating: don't build for imagined requirements.
- Premature abstraction: don't extract until the pattern appears twice.
- Over-engineering: simplest working solution wins.
- Afterthought tests: writing all code first then "adding tests later"
kills the design feedback loop.
"Don't extract until the pattern appears twice" is the single most impactful rule. Without it, Claude will create a utils/formatters.ts file the first time it needs to format a date. With it, duplication is tolerated until a real pattern emerges.
Does It Actually Work?
Yes. The difference between Claude Code with and without a well-crafted CLAUDE.md is night and day. With mine:
- It writes a failing test before touching production code
- It keeps diffs small and focused
- It resists the urge to "improve" unrelated code
- It names things well and uses guard clauses naturally
- It asks "what tidy would make this easier?" when stuck
The file has evolved over months of daily use. Every rule exists because I hit a pain point ā Claude doing something I had to undo or correct. It's a living document that encodes my collaboration preferences, and I'd recommend every Claude Code user invest time in writing their own.
The full file is about 100 lines of Markdown. That's it ā 100 lines that fundamentally change how an AI writes code with you.
Claude Code, CLAUDE.md, TDD, Clean Code, Refactoring
Inspired by: Kent Beck's "Tidy First?", Martin Fowler's Refactoring, Test-Driven Development by Example