March 20, 202612 min readai-cli-tools

CLAUDE.md Writing Guide: Context Engineering for AI CLI Tools

A step-by-step guide to writing a CLAUDE.md that actually improves AI agent performance. Five sections, real examples, token budgets, and testing strategy.

DH
Danny Huang

Most Context Files Make Things Worse

In February 2026, ETH Zurich published Evaluating AGENTS.md — the first rigorous study on context files for AI coding agents. The finding that matters: LLM-generated context files decreased task success rates by 3% compared to using no context file at all. Human-written files improved success by only 4%, while increasing inference costs by over 20%.

The takeaway is not that context files are useless. It is that most context files are badly written. They are too long, too redundant, and filled with information the agent can already find by reading your code.

This guide shows you how to write a CLAUDE.md from scratch that lands on the right side of that 4% improvement — and avoids the patterns that push you into the negative. If you already have a CLAUDE.md and want to audit it for problems, start with 10 CLAUDE.md Mistakes That Hurt Your AI Agent first.

Prerequisites

Before you start writing:

  • Claude Code installed and working. If not, the First Hour with Claude Code tutorial covers installation.
  • A real project to write for. Do not write a CLAUDE.md in the abstract. Open the project you work on daily.
  • 10 minutes. A good CLAUDE.md is short. If it takes longer than 10 minutes, you are overwriting it.

How Claude Code Reads CLAUDE.md

Understanding the loading mechanism tells you what to put where.

Claude Code reads CLAUDE.md at multiple levels, and they all combine:

  1. Global~/.claude/CLAUDE.md loads for every project. Put your personal coding preferences here (language, communication style, universal constraints).
  2. Project root./CLAUDE.md in the project root loads at session start. This is the main file. Architecture, conventions, commands.
  3. Subdirectories./packages/api/CLAUDE.md loads on demand when Claude accesses files in that directory. Use this for package-specific context in monorepos.
  4. Personal overrides.CLAUDE.local.md is gitignored. Use it for personal preferences that should not be shared with the team.

Levels combine without replacing each other. More specific levels override on conflict. This means your project root CLAUDE.md should not repeat anything from your global file, and subdirectory files should not repeat anything from the root.

Claude also reads ~/.claude/rules/*.md files for modular rule sets. The rules directory is useful for separating concerns — a communication style file, a banned packages file, a workflow file — without cramming everything into one CLAUDE.md.

The Five-Section Template

A good CLAUDE.md has five sections. Not every project needs all five, but this is the structure that covers the full range of what the agent genuinely cannot infer from your code.

Section 1: Architecture

What it is, how it fits together, what decisions the code does not make obvious.

## Architecture
- Next.js 15 App Router, TypeScript strict, Tailwind CSS
- Database: PostgreSQL 16 via Drizzle ORM
- Auth: NextAuth.js v5 (GitHub + Google providers)
- Monorepo: apps/web, apps/api, packages/shared
- API layer: tRPC — all client-server calls go through tRPC routers

This section answers the question an agent asks on cold start: "What kind of project is this?" The code shows individual files. This section shows how they connect.

What not to include: Version numbers for every dependency (the agent reads package.json), framework features you use in standard ways (if you use Next.js App Router like the docs show, the agent knows), or anything a package.json scan reveals.

Section 2: Conventions

Patterns the agent should follow that are not enforced by linters or type checkers.

## Conventions
- Server components by default; 'use client' only for interactivity or browser APIs
- Error handling: Result<T, E> pattern (see src/lib/result.ts)
- Named exports preferred; default exports only for pages/layouts
- Database queries live in src/repositories/ — never in route handlers or components
- All new API endpoints need an integration test in tests/integration/

Each line states a preference and, where useful, the exception. "Prefer X; use Y only when Z" is the right format. Avoid bare "ALWAYS" and "NEVER" — they leave no room for legitimate exceptions and make the agent rigid. See Mistake 5 in the common mistakes guide for detailed examples.

Section 3: Constraints

Hard boundaries. Things the agent must never do, because doing them causes damage that is expensive to fix.

## Constraints
- Never modify files in prisma/migrations/ — generate new migrations instead
- Never change the signature of functions exported from src/api/public/
- Never delete test fixture files in tests/fixtures/ (loaded dynamically by name)
- Never commit .env files or hardcode secrets
- GraphQL schema changes require running pnpm codegen after modification

Conventions are "prefer this." Constraints are "do not touch this, ever." The difference matters. Constraints should be short, specific, and target recoverable-but-costly mistakes. If a constraint is longer than one line, it probably belongs in a skill instead of CLAUDE.md.

Section 4: Commands

How to build, test, lint, and run the project. The agent should never have to guess.

## Commands
- Install: pnpm install
- Dev: pnpm dev (starts all apps)
- Test unit: pnpm test:unit
- Test e2e: pnpm test:e2e (requires running dev server)
- Lint: pnpm lint
- Build: turbo build
- DB migrate: pnpm db:migrate
- DB seed: pnpm db:seed

If your project uses standard npm test and npm run build, you can skip this section — the agent knows the defaults. But the moment you have a monorepo, custom scripts, or non-standard test runners, these commands become the highest-value lines in your file.

Section 5: Patterns (Optional)

Project-specific patterns that recur across tasks. Only include these if the pattern is non-obvious and the agent has gotten it wrong before.

## Patterns
- New pages: create route in app/(dashboard)/[route]/page.tsx, add nav entry in src/config/navigation.ts
- New API endpoint: define tRPC router in src/server/routers/, register in src/server/root.ts
- Feature flags: use src/lib/flags.ts — check with `isEnabled('flag-name')`, never hardcode booleans

This section is optional because many projects do not have recurring patterns complex enough to document. If you find yourself adding more than 5 patterns, move them to skills instead — they are task-specific knowledge that should load on demand, not always-on context. See context engineering with skill layering for the full architecture.

A Complete Example

Here is the full CLAUDE.md for a mid-size Next.js SaaS application, all five sections:

## Architecture
- Next.js 15 App Router, TypeScript strict, Tailwind CSS
- Database: PostgreSQL 16 via Drizzle ORM
- Auth: NextAuth.js v5 (GitHub + Google providers)
- API: tRPC routers in src/server/routers/
- Payments: Stripe SDK, webhooks in src/app/api/webhooks/stripe/

## Conventions
- Server components by default; 'use client' only for interactivity
- Error handling: Result<T, E> pattern (src/lib/result.ts)
- Named exports; default exports only for pages/layouts
- DB queries in src/repositories/, never in handlers or components
- New endpoints need integration tests in tests/integration/

## Constraints
- Never modify files in drizzle/migrations/
- Never change exported function signatures in src/lib/public-api/
- Never delete test fixtures in tests/fixtures/
- All Stripe webhook handlers must verify signature first

## Commands
- Dev: pnpm dev | Test: pnpm test | Lint: pnpm lint
- Build: pnpm build | DB migrate: pnpm db:migrate

## Patterns
- New page: app/(dashboard)/[route]/page.tsx + src/config/nav.ts
- New tRPC router: src/server/routers/ → register in root.ts
- Feature flag: isEnabled('name') from src/lib/flags.ts

That is 28 lines. It covers architecture, conventions, constraints, commands, and patterns. Everything the agent needs to make correct structural decisions on first contact. Everything else — detailed migration workflows, deployment checklists, API documentation — belongs in skills or actual documentation files.

Token Budget: How Big Is Too Big?

Your CLAUDE.md loads into every session. Every token in it competes with the agent's reasoning capacity and the tokens available for your actual task.

The math is straightforward:

File SizeEstimated Tokens% of 200K Context Window
30 lines (lean)~4500.2%
100 lines (max recommended)~1,5000.75%
300 lines (too long)~4,5002.3%
1000 lines (harmful)~15,0007.5%

The ETH Zurich study found that context files increased inference costs by over 20% while providing minimal benefit. The root cause: most of those files were 200-500 lines of mixed-quality content. The 5% rule is a practical ceiling — your always-on context (CLAUDE.md + any global rules) should consume less than 5% of the model's effective context window. For a 200K token model, that is under 10,000 tokens.

At 30-100 lines, a well-written CLAUDE.md stays well under 1% — leaving virtually all the context window for your code and the agent's reasoning.

When to move content to skills: If a section of your CLAUDE.md applies to only one type of task (database migrations, deployment, code review), it belongs in a SKILL.md. Skills load on demand, so they cost zero tokens when unused.

Testing Your CLAUDE.md

Writing the file is half the work. Testing it is the other half.

Step 1: The cold start test. Open a new Claude Code session in your project. Ask the agent to describe your project's architecture. If it correctly identifies your stack, patterns, and constraints without reading additional files, your CLAUDE.md is working.

Step 2: The constraint test. Ask the agent to do something your constraints forbid. "Modify the migration file to fix this column type." If the agent refuses and explains why, the constraint is being read. If it happily modifies the file, something is wrong — either the constraint is buried in too much text, or the wording is ambiguous.

Step 3: The command test. Ask the agent to run your test suite. If it uses the correct command on the first attempt, your commands section is working. If it guesses npm test when you need pnpm test:unit, the commands section is missing or not prominent enough.

Step 4: The convention test. Ask the agent to create a new component or endpoint. Check whether it follows your stated patterns — puts the file in the right directory, uses the right error handling approach, follows your export conventions. If it deviates, your conventions section needs sharper wording.

Step 5: The noise test. Remove a section you suspect might be redundant. Run the same tasks. If agent behavior does not change, that section was wasted tokens. Be aggressive about pruning.

Maintaining Over Time

A CLAUDE.md is a living document, not a write-once artifact. Here is when to add and when to prune.

Add when:

  • The agent makes the same mistake twice. First time is a fluke. Second time means you need a constraint or convention.
  • You introduce a new architectural pattern (new auth provider, new API layer, new database).
  • A new team member joins and the agent gives them wrong guidance — this surfaces gaps.

Prune when:

  • A convention has been followed perfectly for 20+ sessions. The agent may have internalized it from the code itself. Test by removing the line and checking.
  • A tool or pattern is deprecated. Dead constraints about old libraries confuse the agent.
  • The file exceeds 100 lines. Something in there does not need to be always-on.

Review cadence: Check your CLAUDE.md every 2 weeks. Read every line. For each one, ask: "If I remove this, will the agent make a mistake it cannot recover from by reading the code?" If the answer is no, delete it.

CLAUDE.md vs AGENTS.md vs SKILL.md

These three files solve different problems. A quick overview of when to use which:

FilePurposeLoadedBest For
AGENTS.mdCross-tool project contextEvery sessionArchitecture, conventions, constraints (read by all AI CLI tools)
CLAUDE.mdClaude Code-specific contextEvery sessionClaude-specific behavior (compaction, subagents) + reference to AGENTS.md
SKILL.mdTask-specific capabilityOn demandWorkflows, checklists, templates that only apply to specific tasks

If your team uses only Claude Code, you can put everything in CLAUDE.md. The moment anyone uses Codex CLI, Gemini CLI, or Cursor, the portable context should move to AGENTS.md.

For the full comparison with detailed examples, see SKILL.md vs CLAUDE.md vs AGENTS.md. For advanced layering patterns — progressive disclosure, token budgeting across layers, monorepo configuration — see context engineering with skill layering.

The Writing Checklist

Before you commit your CLAUDE.md, verify:

Check
Under 100 lines total
Has Architecture section with non-obvious decisions
Has Constraints section targeting costly mistakes
Has Commands for build/test/lint
No content the agent can find in package.json or tsconfig
No linter rules restated (agent runs the linter)
Conventions use "prefer" with exceptions, not bare ALWAYS/NEVER
Task workflows moved to skills, not inlined
File is committed to version control
Tested with at least 3 representative tasks

If more than 2 items fail, revise before committing. A bad CLAUDE.md is worse than no CLAUDE.md — the ETH Zurich research proved this quantitatively.

When you are testing CLAUDE.md changes iteratively, a multi-panel terminal layout helps — run the agent in one pane, view the CLAUDE.md in another, and compare behavior side by side. Termdock's split-panel workspace makes this workflow fast: modify the file, restart the session in the adjacent pane, test immediately.

Try Termdock Multi Panel works out of the box. Free download →

Start Writing

Open your project. Create a CLAUDE.md at the root. Write the five sections. Keep it under 50 lines on the first draft — you can always add later, but removing is harder than not adding. Test it with three real tasks. Prune anything the agent did not need.

The goal is not a comprehensive document. It is the minimum context the agent needs to make correct decisions from a cold start. Everything beyond that minimum is noise — and noise, as the research shows, makes your agent worse.

For the complete picture of context engineering across all major AI CLI tools, see the AI CLI Tools Guide.

DH
Free Download

Ready to streamline your terminal workflow?

Multi-terminal drag-and-drop layout, workspace Git sync, built-in AI integration, AST code analysis — all in one app.

Download Termdock →
#claude-md#context-engineering#claude-code#workflow#ai-cli#best-practices

Related Posts