Growing CLAUDE.md — Three Months of Evolving an AI Collaboration Config File
Go deeper on this topic
Claude Code Workflow
Large-scale refactoring, CLAUDE.md design, and session management with Claude Code
Article 2 of 4 in this series.
Next reads
One Session, One Task — The Principle I Learned from Claude Code Context Management
While developing 203 components with Claude Code, "one session, one task" proved to be the most impactful productivity principle. Real examples of context exhaustion and countermeasures.
How to Guarantee Quality When AI Mass-Produces Your Code — The 4-Layer Gate System Behind 200 Components
The real quality machinery behind ~200 AI-built interactive components: four pre-commit hooks, data invariant tests, real-browser pixel smoke tests, and a quality-score + PR-proposal pipeline — documented down to the file names.
Bulk-Fixing 200 Components with Claude Code — The Full Pipeline of Classification, Fixing, and Verification
A practical record of bulk-fixing bugs across 203 interactive components with Claude Code in 6 commits and 100+ files. The entire process of classification, templating, and verification.
Use the topic hub as a map, then continue to the next article in the series. New here? Start at the home hub →
What is CLAUDE.md?
When you launch Claude Code, the first thing it reads is CLAUDE.md at the project root. The contents become the "background knowledge" for the entire session. Tech stack, coding conventions, folder structure, things not to do — it's a configuration file for conveying project context to AI.
In a nutshell, it's an "instruction manual for AI." The same concept as giving onboarding materials to a new human team member — you give AI project-specific knowledge too.
I've been continuously updating CLAUDE.md for this portfolio site (with 211 interactive components) for 3 months. After 323 commits, I've gained clarity on what works and what doesn't. This article is a record of that evolution.
Early Stage (Around January 2026): Tech Stack Listing Phase
The first CLAUDE.md I wrote was a list of the tech stack.
- Framework: TanStack Start (React 19)
- Styling: Tailwind CSS v4
- Animation: Motion (motion/react)
- Package Manager: bun
- Linter: BiomeI also carefully documented commands. bun run dev starts the dev server, bun run build builds, bun run check runs lint.
This had almost no effect.
The reason is simple: AI can determine the tech stack by reading package.json and tsconfig.json. If .ts files are present, it knows it's TypeScript. If tailwind.config exists, it knows Tailwind is used. Even without writing "use TypeScript," AI judges from the project structure.
Writing obvious things only consumes the context window. What CLAUDE.md should contain is "things you can't tell just by looking at files."
However, there was one exception. Biome's format settings (single quotes, 2 spaces, 100 width, semicolons asNeeded) were worth explicitly stating. While this can be determined from biome.json, it saves AI the trip of checking the config file each time. Frequently referenced information is worth inlining.
Middle Stage (February 2026): Workflow Rules Phase
Reflecting on January, February shifted focus to "points where AI tends to make mistakes."
Project-Specific Traps
This project has several "traps" that can't be discerned just by looking at files.
- Vite plugin order:
cloudflaremust be placed beforetanstackStartor the build breaks - motion import path: Use
motion/reactnotframer-motion(the package was renamed) - No ServerFn: Doesn't work due to a known Cloudflare Pages bug. All data is static TypeScript constants
- routeTree.gen.ts: Auto-generated by TanStack Router. Must not be edited
These are "landmines you'll definitely step on if you don't know about them." The Vite plugin order in particular is hard to diagnose from error messages alone. Writing them in CLAUDE.md let AI avoid landmines before stepping on them.
Workflow Definition
Around the same time, takt workflows were defined. A table for automatically selecting work flows based on task size.
| Condition | Selection |
|---|---|
| Typo fix, 1-line change | Implement directly |
| Bug fix, 3 files or fewer | quick-fix |
| New feature, multiple files | plan-implement-review |
| Major feature, architecture change | spec-then-build |
Explicitly stating decision criteria in table format enabled AI to autonomously judge "should I plan first, or implement immediately?" Tables with conditions are more clearly communicated to AI than ambiguous instructions.
The Rule Bloat Problem
However, by late February, rules had grown too numerous. Git commit message conventions, detailed folder structure explanations, Canvas vs. DOM selection criteria, physics engine design principles... CLAUDE.md ballooned to hundreds of lines, and the problem of "consuming context just to read it" became apparent.
AI's context window is finite. When CLAUDE.md is too long, less context is available for actual tasks. I faced the tradeoff between rule quantity and precision.
Current State (March 2026): Decision Criteria and Fallback Phase
In March, I significantly changed the CLAUDE.md philosophy. Reduced "what to do" rules and focused on "how to decide" meta-rules.
Meta-Rules: Decision Criteria for Decisions
The most effective elements in the current CLAUDE.md are meta-rules like these.
- "Same problem fails twice →
/clear": Judge that context is contaminated and reset the session - "Give validation means first → 2-3x quality": Passing tests or expected output first enables AI's self-correction loop
- "One session, one task": Context is the scarcest resource, don't cram
- "First try deleting rules that don't work": Define rule pruning itself as a meta-rule
These aren't "specific actions" but "decision frameworks." AI applies these criteria as situations arise. Ten decision criteria are more effective than a hundred specific rules.
Explicit Fallbacks
Another change was making fallbacks explicit.
When in doubt, choose quick-fix (guarantees minimum review)This single line prevents AI "freezing." When encountering edge cases that don't match any decision criteria, AI can safely fall back. Same concept as defining a default value.
Top 5 Rules That Worked
Five rules that proved especially effective over 3 months of operation.
1. Vite Plugin Order
tailwindcss → tsConfigPaths → cloudflare → tanstackStart → react
Cloudflare must be placed before TanStack Start.This was the most "glad I wrote it" rule. Plugin order bugs are extremely difficult to diagnose from error messages. When AI hits this trap, it burns dozens of turns just investigating the cause. A single line of warning completely prevents it.
2. motion Import Path
motion imports use motion/react (not framer-motion)When Framer Motion was rebranded to Motion, the import path changed. Online information still predominantly shows framer-motion, so AI gets pulled toward outdated information. Making it explicit meant the correct path was used every time.
3. routeTree.gen.ts is Auto-Generated
src/routeTree.gen.ts is auto-generated. Don't edit it, don't commit itAI sometimes recognizes a file's existence and treats it as "an editable file." Explicitly marking auto-generated files prevents accidental editing.
4. No ServerFn
ServerFn not used: known CF Pages bug workaround. All data is static TypeScript constants in src/data/TanStack Start has ServerFn (server functions) as a standard feature. AI tries to use it when adding new features, but it doesn't work on Cloudflare Pages yet. Writing "don't use it" paired with "the reason" enabled AI to autonomously choose alternative approaches. Prohibition rules without reasons tend to be ignored.
5. takt Workflow Auto-Selection Table
Condition-based tables communicate more precisely to AI than natural language. "Make a plan before implementing large changes" is less clear than a matrix of conditions and choices — AI has less room for interpretation.
Top 3 Rules That Didn't Work
Conversely, rules that had no effect even when written.
1. "Write Comments in Code"
Unless explicitly instructed "write a comment for this function," AI doesn't spontaneously write comments. Writing "leave appropriate comments" in CLAUDE.md was almost entirely ignored. A typical example of CLAUDE.md being "advisory."
2. "Always Include Error Handling"
Too abstract to function. The scope of "error handling" is too broad for AI to judge what level of defensive code to write. In the end, I had to bulk-add AudioContext error handling across 200 components retroactively.
What worked instead was presenting specific patterns. Instructions like "wrap new AudioContext() in try-catch and continue operating without sound on failure" — when broken down to specific code patterns, AI follows them.
3. "Write Tests Before Code"
Writing TDD as a workflow in CLAUDE.md didn't work — AI never wrote tests first unless explicitly told "write the test." Controlling workflow order through CLAUDE.md alone is difficult.
Solving this requires combining it with workflow definitions like takt: "list test items in the plan phase → write tests first in the implement phase" with clearly defined steps.
"Advisory" vs. "Deterministic"
The most important lesson from 3 months of operation: CLAUDE.md is advisory, not mandatory.
hooks are deterministic, CLAUDE.md is advisoryThis line is currently in the CLAUDE.md.
- CLAUDE.md = Advisory. AI judges contextually and decides whether to follow
- pre-commit hooks = Deterministic. If conditions aren't met, commits are physically impossible
For example, if you truly want to enforce "passing Biome lint," writing it in CLAUDE.md isn't enough. Running bun run check in a pre-commit hook ensures code with lint errors absolutely cannot be committed.
Once this distinction became clear, what gets written in CLAUDE.md changed.
- Rules that must be enforced → Write in hooks (deterministically enforced)
- Preferences → Write in CLAUDE.md (presented as advice)
- Decision criteria → Write in CLAUDE.md (support AI's autonomous judgment)
Writing "absolutely" or "always" in CLAUDE.md is merely emphasizing advice. If enforcement is needed, guarantee it through mechanisms.
User-Level vs. Project-Level
CLAUDE.md has two layers.
~/.claude/CLAUDE.md (User-Level)
Where rules common to all projects are written. In my case:
- Prefer
bunxovernpx - Design principles (invest in DB design, loosely coupled module design)
- Common workflow rules (fail twice → /clear, one session one task)
- AI utilization tips (give validation means first)
These are rules I want applied regardless of project.
project/CLAUDE.md (Project-Level)
Where repository-specific information is written:
- Tech stack details (TanStack Start v1.x, Tailwind CSS v4)
- Architecture decisions (Canvas vs. DOM selection criteria, why ServerFn isn't used)
- Vite plugin order
- Folder structure
The Effect of Separation
Initially, everything was packed into the project's CLAUDE.md. Separating user-level settings allowed the project CLAUDE.md to focus on project-specific information.
Additionally, when starting a new project, user-level rules apply automatically. No need to write "use bunx" every time.
Quantitative Changes
Recording the changes felt before and after CLAUDE.md improvements.
- Vite build error investigation time: Previously consumed 5-10 turns on plugin order issues → Zero after adding the note
- motion import corrections: Previously used
framer-motionabout 30% of the time when creating new components → Zero after explicit documentation - takt workflow application rate: After switching to table format, the probability of selecting the appropriate workflow improved dramatically in practice
These aren't precise quantitative data, but a characteristic of CLAUDE.md is that you can tell "whether the effect is zero or one" the moment you write it. Effective rules work 100% from the moment they're written. Ineffective rules don't work no matter how many times you rewrite them.
Summary: CLAUDE.md is Something You Grow
A summary of what I learned from 3 months of continuous CLAUDE.md updates.
CLAUDE.md won't be perfect from the start. As the project progresses, you see the landmines AI steps on, and rules to prevent them accumulate. Conversely, ineffective rules get deleted.
What effective rules have in common:
- Specific ("wrap AudioContext in try-catch" not "add error handling")
- Include decision criteria (condition tables, fallback definitions)
- Information not discernible from files alone (plugin order, deprecated API alternatives)
What ineffective rules have in common:
- Abstract ("write appropriate comments," "always add error handling")
- Things discernible from files ("use TypeScript," "use React")
- Things requiring enforcement (if you truly want compliance, enforce via hooks)
Periodic pruning is necessary. Like code, CLAUDE.md rots without maintenance. Actively delete unused rules, ineffective rules, and outdated information. "First try deleting rules that don't work" — this meta-rule itself may be the most important lesson from 3 months of operation.
CLAUDE.md isn't a "contract" for collaboration with AI. It's a "record of a growing relationship."