Stop copy-pasting project context: 4 stages of CLAUDE.md evolution

Dev.to / 4/18/2026

💬 OpinionDeveloper Stack & InfrastructureIdeas & Deep AnalysisTools & Practical Usage

Key Points

  • The article argues that CLAUDE.md guides should focus not only on what information to include, but on when to add it as a project evolves.
  • It claims many teams make a mistake by copying large CLAUDE.md templates on day one, causing Claude to follow rules that no longer match the project.
  • In Stage 1 (prototype), the recommendation is to keep CLAUDE.md minimal—record what exists (stack and basic rules) rather than over-documenting rationale.
  • In Stage 2 (MVP), as decisions accumulate, the guidance shifts toward documenting explicit architecture decisions and especially what was intentionally rejected.
  • The overall message is that CLAUDE.md should grow from an empty file into a fuller “harness” as the app matures, ensuring the AI stays aligned with current production realities.

Last Tuesday I pasted the same 15 lines of project context into Claude -- for the 47th time. Stack, conventions, database schema, the "don't use localStorage for JWT" rule. Every. Single. Session.

That's when it hit me: my CLAUDE.md was frozen in time, written for a prototype that had become a production app six months ago.

Sound familiar?

Most CLAUDE.md guides tell you what to put in the file. This article is about something different: when to put it there. Your CLAUDE.md should grow with your project. Here are 4 stages, from empty file to enterprise harness.

Stage 1: The blank canvas (prototype)

When you mkdir a new project, you don't need a 200-line CLAUDE.md. You need 10 lines.

# CLAUDE.md

## Project
Name: TaskFlow (working title)
Purpose: Team task management system

## Stack
- Frontend: React + TypeScript
- Backend: Node.js + Express
- Database: PostgreSQL

## Rules
- TypeScript strict mode
- Conventional Commits

That's it. At this stage, record what is, not why. You haven't made enough decisions to document reasoning yet. The prototype will pivot three times before lunch.

The mistake I see most often: copying someone else's 150-line CLAUDE.md template on day one. Claude dutifully follows rules written for a different project, a different team, a different architecture. Start small. Grow intentionally.

Stage 2: The MVP harness

Your prototype survived. Users exist. Now decisions start accumulating, and the most valuable thing you can document is what you chose NOT to use.

## Architecture decisions

### Frontend
- React 18 + TypeScript 5.0
- State: Zustand (Redux was overkill for our scale)
- UI: Material-UI (minimizing custom design work)
- Routing: React Router v6

### Backend
- Node.js 18 + Express 4
- API: REST (GraphQL postponed -- added complexity,
  no consumer demand yet)
- Auth: JWT + refresh token
- DB: PostgreSQL 15

### Rejected alternatives (and why)
- Vue.js: team has deeper React experience
- GraphQL: REST covers current use cases, less overhead
- MongoDB: relational data model fits better

The "rejected alternatives" section is the hidden gem. Without it, every new team member (and every new Claude session) will suggest the same alternatives you already evaluated. You'll waste tokens re-litigating decisions that were settled months ago.

I learned this the hard way. Claude kept suggesting GraphQL migrations in code reviews until I added one line: GraphQL: postponed -- REST covers current needs. That single line saved dozens of conversations.

This stage is also where you start recording architecture decisions as they happen. Every time you pick a library, reject an approach, or settle a debate in a PR review -- add it to CLAUDE.md. Future-you and future-Claude will thank present-you. The cost is one line per decision. The payoff is every session after that starts with shared context instead of a blank slate.

Stage 3: The production rulebook

Your app is live. Users are paying. Now the stakes are higher, and the most important section becomes the one most teams skip: "never do this".

## Coding standards

### TypeScript
- Interface names: PascalCase, no I prefix
- Prefer undefined over null (API consistency)
- Shared types in types/, component-local types inline

### React
- Functional components only (no class components)
- Custom hooks: use- prefix required
- Props: destructure when 3+ properties

## Never do this

### Security
- Never store JWT in localStorage -> use httpOnly cookies
- Never embed API keys in frontend code
- Never build SQL with string concatenation -> parameterized queries only

### Performance
- Never skip useEffect dependency arrays (infinite loop risk)
- Never use key={index} on dynamic lists
- Never render images without optimization (use next/image)

### Operations
- Never push directly to production branch
- Never run migrations without backup
- Never rollback without checking logs first

(Yes, I stored JWT in localStorage once. No, I don't want to talk about it.)

The "never do this" section works because Claude treats it as a hard constraint. When you ask Claude to implement auth, it won't even suggest localStorage -- the option is pre-eliminated. That's Context Engineering at its core: shaping the solution space before the question is asked -- or, more practically, you write rules in a text file and Claude stops arguing about things you've already decided.

This is also where security constraints belong. If your CLAUDE.md says "parameterized queries only", Claude will generate parameterized queries by default. No reminder needed. No code review catch needed. The context does the work.

Stage 4: The enterprise harness

Your team grew to 12 people. Your monolith split into 6 services. Your CLAUDE.md is now 300 lines long and eating your context window.

Time to split it up.

project/
├── CLAUDE.md                  # Core rules only (~50 lines)
├── docs/
│   ├── ARCHITECTURE.md        # System design details
│   ├── API-DESIGN.md          # API design guide
│   └── SECURITY.md            # Security requirements
└── .claude/
    └── agents/
        ├── frontend.md        # Frontend specialist
        ├── backend.md         # Backend specialist
        └── devops.md          # DevOps specialist

The parent CLAUDE.md stays lean -- project overview, shared rules, and a map of where specialist knowledge lives. Each sub-agent file contains domain-specific context that only loads when relevant.

The real power comes from hooks that auto-inject context based on what you're working on:

#!/bin/bash
# .claude/hooks/user-prompt-submit.sh

PROMPT="$1"

if echo "$PROMPT" | grep -qi "react\|component\|hook\|frontend"; then
    cat .claude/agents/frontend.md
fi

if echo "$PROMPT" | grep -qi "api\|database\|auth\|backend"; then
    cat .claude/agents/backend.md
fi

# Security context always loads for auth-related work
if echo "$PROMPT" | grep -qi "auth\|token\|security"; then
    cat docs/SECURITY.md
fi

This is the same pattern that large codebases use for CI/CD: don't run everything every time. Load what's relevant. Your context window is a budget -- spend it wisely.

What this looks like in practice

On my team, the split reduced our average context consumption by roughly 40%. Before the split, every Claude session loaded 300+ lines of rules regardless of the task. After: a frontend bug fix loads ~80 lines (core + frontend.md), a database migration loads ~90 lines (core + backend.md), and a deployment task loads ~70 lines (core + devops.md).

The unexpected benefit was consistency. When the frontend specialist context is loaded, Claude doesn't suggest backend patterns for UI problems. When the DevOps context is active, it doesn't recommend application-level fixes for infrastructure issues. Each sub-agent stays in its lane -- not because you told it to, but because the loaded context naturally constrains the solution space.

One gotcha: keep the core CLAUDE.md under 50 lines. The moment it creeps past 100, you're back to the same bloat problem. I review ours monthly and push anything domain-specific into the specialist files.

graph TD
    A[CLAUDE.md<br/>Core rules ~50 lines] --> B[frontend.md<br/>React, UI, hooks]
    A --> C[backend.md<br/>API, DB, auth]
    A --> D[devops.md<br/>Infra, CI/CD, monitoring]
    E[Hook: prompt analysis] --> |"react, component"| B
    E --> |"api, database"| C
    E --> |"deploy, docker"| D
    F[SECURITY.md] -.-> |"always loads for auth"| C

CLAUDE.md vs AGENTS.md: different philosophies

If you've used OpenAI's Codex, you've seen AGENTS.md. Both files configure AI behavior, but their design philosophies differ:

Aspect AGENTS.md (OpenAI) CLAUDE.md (Anthropic)
Focus AI's role and persona Project situation and constraints
Length Concise (500-1,000 chars) Detailed (2,000-5,000 chars)
Updates Rarely (initial setup) Frequently (evolves with project)
Scope Code generation Entire project lifecycle
Team sharing Limited Git-managed, everyone shares

AGENTS.md tells the AI what to be. CLAUDE.md tells the AI where it is. In practice, you can combine both approaches:

# CLAUDE.md

## AI Configuration
You are a senior full-stack engineer for TaskFlow.
Prioritize maintainability and security in all suggestions.

## Project Context
[Detailed project information -- the CLAUDE.md way]

## Standards
[Team conventions and constraints]

The hybrid approach gives Claude both identity and context. I've found this combination produces the most consistent results across sessions.

Your move

Here's what to do this week:

  • [ ] Check which stage your current CLAUDE.md is at (1-4)
  • [ ] Add the section you're missing -- especially "never do this"
  • [ ] If your file is over 100 lines, start splitting into sub-agent files

Which stage is your CLAUDE.md at right now? Drop a comment -- I'm genuinely curious how many of us are stuck at Stage 1 with a template we copied six months ago and never touched.

If you want to go deeper
Practical Claude Code -- Context Engineering for Modern Development covers CLAUDE.md patterns, sub-agent design, hooks, and the full context engineering workflow in detail. The 4-stage evolution in this article is one chapter of a larger system.