MVP Factory
ai startup development

CLAUDE.md best practices: 8 patterns that work

KW
Krystian Wiewiór · · 7 min read

Meta description: 8 patterns for structuring CLAUDE.md files so Claude Code actually understands your codebase — from skills and hooks to progressive disclosure.

TL;DR

Your CLAUDE.md is not a README. It’s a short, high-signal repo memory that tells Claude Code how to work in your codebase — not everything about it. After applying these patterns across multiple production repositories, I’ve landed on 8 that reliably make a difference: concise root files, reusable skills, deterministic hooks, progressive disclosure via ADRs, local context in sensitive directories, lean project structure, minimal skill definitions, and documenting architectural why. Get these right, and Claude stops fighting your architecture and starts extending it.


The problem: knowledge dump vs. repo memory

Most teams treat CLAUDE.md like onboarding docs — they dump everything in. Architecture diagrams, coding standards, deployment procedures, team conventions. The result is a 2,000-line file where the stuff Claude actually needs gets buried.

The thing people miss: Claude Code doesn’t need to know everything. It needs the right things at the right time.

The 8 patterns

1. CLAUDE.md as short, high-signal repo memory

Your root CLAUDE.md should be a concise cheat sheet, not a knowledge base. Think sticky notes on a senior engineer’s monitor — build commands, critical invariants, the one thing that breaks if you forget it.

ApproachToken costSignal qualityResult
Full knowledge dump (2,000+ lines)HighLow — buried in noiseClaude ignores critical rules
Concise repo memory (50-150 lines)LowHigh — every line mattersClaude follows conventions reliably

Keep it under 200 lines. If you need more, you need pattern #4.

2. Skills for repeated workflows

Skills encapsulate repeated workflows — code reviews, release prep, debugging runbooks. Instead of re-explaining your release process every session, define it once as a skill that Claude can invoke consistently.

# Example skill: /release
1. Run `./scripts/version-bump.sh`
2. Update CHANGELOG.md with conventional commits since last tag
3. Create PR targeting main with title "release: vX.Y.Z"

Short, declarative skills outperform verbose ones. A 10-line skill that says what to do beats a 50-line skill that explains how each step works internally. Say what you want done; trust Claude to figure out the mechanics.

3. Hooks over memory for deterministic actions

If an action must always happen — formatting on save, running tests before commit, blocking edits to sensitive folders — don’t put it in CLAUDE.md. Use hooks. Memory is probabilistic; hooks are deterministic.

Claude Code hooks live in .claude/settings.json under event matchers like PreToolUse and PostToolUse:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit",
        "command": "echo 'Editing file: $CLAUDE_FILE'"
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write",
        "command": "npx prettier --write $CLAUDE_FILE"
      }
    ]
  }
}

Hook schemas evolve — check the official Claude Code docs for the current configuration format.

A line in CLAUDE.md saying “always run prettier” will be forgotten halfway through a long session. A hook won’t.

4. Progressive disclosure — point, don’t dump

Instead of inlining your entire authentication architecture into CLAUDE.md, point to it:

## Architecture decisions
- Auth flow: see docs/adr/003-auth-strategy.md
- Database sharding: see docs/adr/007-sharding.md
- API versioning: see docs/adr/012-api-versions.md

Claude reads these files when it needs them. Your root context stays lean while deep knowledge remains accessible on demand.

5. Local CLAUDE.md in sensitive directories

Place local CLAUDE.md files in directories that need special treatment — auth/, db/migrations/, infra/. These override or extend the root file with context that only matters in that scope.

# infra/CLAUDE.md
- NEVER modify terraform state files directly
- All changes require plan output review before apply
- Cost tags are mandatory on every resource

I’ve found this especially useful in codebases where different directories play by fundamentally different rules. The auth module almost always needs stricter guardrails than the rest of the app.

6. Keep context lean and navigable

Every token in your CLAUDE.md that doesn’t directly change Claude’s behavior is wasted context. The same idea behind .editorconfig, ESLint configs, and Git hooks applies here: surface the minimum viable signal at the exact point of action.

This extends to project structure too. Clear folder names, consistent naming, and explicit ownership boundaries help Claude navigate your repo the same way they help a new hire. If a human would be confused by your project layout, Claude will be too.

# Before: unclear structure
src/
  mod1/
    hlpr.ts
    svc.ts
    u.ts
  mod2/
    stuff.ts

# After: navigable structure
src/
  payments/
    payment-validator.ts
    payment-service.ts
    payment-utils.ts
  notifications/
    notification-sender.ts

When Claude sees payments/payment-service.ts, it already knows scope, responsibility, and where related code lives — before reading a single line.

7. Version your CLAUDE.md alongside code

Treat CLAUDE.md as a living artifact that evolves with your codebase. Check it into version control, review changes in PRs, and update it when architecture shifts. A stale CLAUDE.md is worse than none — it actively misleads.

PracticeOutcome
CLAUDE.md updated in same PR as arch changesClaude stays aligned with current architecture
CLAUDE.md reviewed separately, months laterDrift accumulates; Claude follows outdated rules
CLAUDE.md never updated after initial creationClaude fights new patterns, enforces deprecated ones

The teams I’ve seen get the best results add “update CLAUDE.md” to their PR checklist, right next to “update tests.” It sounds like a small thing, but the compound effect is real.

8. Document the WHY in ADRs

When Claude hits an architectural decision it doesn’t understand — say, why you chose gRPC over REST for internal services — it will try to “fix” it. ADRs (Architecture Decision Records) that explain the why prevent Claude from second-guessing your architecture.

# ADR-005: gRPC for internal services
## Status: Accepted
## Context: Inter-service latency exceeded 200ms p99 under load
## Decision: Migrate internal APIs from REST to gRPC
## Consequence: Significant throughput improvement measured in load tests, but added protobuf compilation step

Without this, Claude sees gRPC and may suggest REST “for simplicity.” With the ADR in place, it respects the decision and works within the constraint.

Pattern comparison

PatternTypeWhen to use
Root CLAUDE.mdStatic contextAlways — every repo needs one
SkillsReusable workflowsRepeated multi-step tasks
HooksDeterministic enforcementActions that must never be skipped
Progressive disclosureOn-demand contextComplex architectures with deep docs
Local CLAUDE.mdScoped rulesSensitive or special-case directories
Lean and navigableStructural disciplineAll repos — reduce noise everywhere
Versioned CLAUDE.mdChange managementAny repo under active development
ADRsArchitectural rationaleAny non-obvious design decision

3 takeaways you can act on today

  1. Audit your CLAUDE.md. If it’s over 200 lines, extract detail into ADRs and local context files. Keep the root file high-signal.

  2. Convert your top 3 repeated workflows into skills. Release, review, and debug are good starting candidates. Keep each under 15 lines.

  3. Replace every “always do X” instruction with a hook. If it must happen every time, it belongs in deterministic automation, not probabilistic memory.


TAGS: architecture, devops, cleanarchitecture, api, productengineering


Share: Twitter LinkedIn