CLAUDE.md Best Practices: A Working Template for Claude Code
Write a useful CLAUDE.md with a concise template, three workflows, a working checker, and fixes for common mistakes.
Your pull request comes back with the same review comment for the third time. Claude Code changed the right feature, but missed the repository’s test command, edited a migration that was out of scope, or forgot the mobile check. Repeating a longer prompt in every session does not fix that operating problem.
A useful CLAUDE.md gives Claude Code a short set of durable decisions before work starts. It does not need to explain the whole company or reproduce the README. This guide shows what belongs in the file, what must be enforced elsewhere, and how to test the result with a working Node.js checker.
The short answer
The CLAUDE.md file should contain commands, edit boundaries, and review gates that apply to most tasks in its scope. Keep these five rules in mind:
- CLAUDE.md is persistent guidance for Claude Code, not an access-control system.
- Put shared rules at the repository root, personal notes in
CLAUDE.local.md, and path-specific rules in.claude/rules/. - Keep it under roughly 200 lines. Prefer file paths, commands, and pass conditions over background prose.
- Enforce security restrictions with permissions and hooks instead of trusting a written warning.
- Test a new instruction on a real, small task before treating it as a team rule.
Do not try to design the perfect file on day one. List the review comments that appeared in the last three pull requests, then keep only the decisions that will matter again.
What Claude Code can do and what a human must decide
A repository file and a permission boundary solve different problems. Claude Code can inspect existing code, make a scoped change, run named checks, and summarize the diff. A human still owns product policy, production approval, and decisions involving customers, money, privacy, or legal obligations.
| Decision | Delegate to Claude Code | Keep with a human |
|---|---|---|
| Investigation | Find related files, patterns, and tests | Decide whether customer or contract data may be inspected |
| Implementation | Change code and tests inside the named scope | Approve pricing, authorization, legal, and customer-facing policy changes |
| Verification | Run lint, type checks, tests, and builds | Decide whether acceptance criteria are met and release is approved |
| Maintenance | Report changed files and unresolved risks | Add or remove permanent repository rules |
CLAUDE.md says, in effect, “check these things in this order.” It cannot guarantee that a destructive command will never run. Use permission deny rules or a PreToolUse hook when git push --force, production database access, or secret-bearing files must be physically blocked. The Claude Code permissions guide covers that enforcement layer separately.
Choose the correct scope before writing
File placement controls where the guidance applies. A root CLAUDE.md is appropriate for shared project rules. ~/.claude/CLAUDE.md applies to the user’s projects. CLAUDE.local.md is suited to private machine-specific notes and should be gitignored. Nested files and path-scoped rules keep large repositories from loading irrelevant instructions.
repo/
CLAUDE.md # short rules shared by the team
CLAUDE.local.md # personal notes; add to .gitignore
.claude/
rules/
api.md # rules needed only for API files
packages/
admin/
CLAUDE.md # added when Claude reads this subtree
At launch, Claude Code reads applicable files in the current directory and its ancestors. A nested CLAUDE.md is loaded when Claude reads files in that subtree. That behavior is the reason to place package rules near the package instead of putting every instruction at the root.
An import such as @docs/project-map.md can make instructions easier to organize, but it does not save context. Imported content is still loaded at launch. Keep the always-needed decision in CLAUDE.md and point to detailed material for on-demand reading. On Windows, Claude Code reads CLAUDE.md rather than AGENTS.md, so an explicit @AGENTS.md import is more reliable than depending on a symlink.
Start with this CLAUDE.md template
Commands and change rules should fit on one screen. The template below avoids vague advice such as “write clean code.” It names the paths, checks, exclusions, and final report expected from the agent.
# Project Instructions
## Project map
- App: Next.js 15 + TypeScript
- API: src/app/api/**
- Database schema: prisma/schema.prisma
- Tests: Vitest for units, Playwright for checkout
## Commands
- Install: npm ci
- Type check: npm run typecheck
- Unit tests: npm test
- Lint: npm run lint
- Build: npm run build
## Change rules
- Follow nearby code before adding a new abstraction.
- Do not change auth, billing, or migrations unless the task names them.
- When an API handler changes, update validation and tests together.
- Never place secrets in code, fixtures, logs, or screenshots.
## Review checklist
- Run the checks related to the changed files.
- Test an error path as well as the happy path.
- Report changed files, commands run, and skipped checks.
The file can be written in the language your team uses. Precision matters more than language. Replace “test appropriately” with npm test. Replace “follow the architecture” with a concrete rule such as “API responses use src/lib/api-response.ts.” A reviewer should be able to tell whether the instruction was followed without guessing what it means.
Three real-world use cases
These workflows separate input, output, and human review. Before adding any lesson to the permanent file, run a small task and check whether the instruction changes observable behavior.
Use case 1: reduce repeated agency review comments
A web agency may use different CSS conventions, image sizes, and browser targets in each client repository. Copying the entire agency handbook into every project makes the useful rules hard to find. Keep the three to five checks that apply to this client and this codebase.
Input: The last three review threads, the files in scope, and the existing lint and build commands.
Output: A diff report naming reused components, changed pages, commands run, and browser conditions that remain unchecked.
Human review: Design intent, image rights, CTA wording, and the final mobile layout. Compare review-return counts across ten tasks before and after the change; that is a better signal than the raw length of CLAUDE.md.
Use case 2: change a SaaS contact form safely
A form can look correct while server validation, notification email, or error handling remains broken. The project guidance should name the files and checks that move together whenever the form changes.
Input: The form component, validation schema, API handler, email template, and existing tests.
Output: Happy-path and invalid-input tests, user-facing errors, and a list of settings changed. The final report should also confirm that personal data was not written to logs.
Human review: The data fields collected, retention policy, notification recipients, and production release. Track failed submissions and support time as well as conversion rate.
Use case 3: prevent incomplete content releases
An MDX page may contain correct prose but still ship without a description, internal link, hero image, or usable mobile code block. A short publishing checklist gives the agent an observable finish line.
Input: The MDX file, frontmatter schema, internal-link targets, build command, and production URL.
Output: Description length, broken-link result, code-block check, build status, and URLs inspected in a browser.
Human review: Factual accuracy, search intent, ad placement, readability, and release approval. Review search clicks, engaged reading, and CTA clicks weekly instead of judging success from page views alone.
Run this CLAUDE.md checker
The following Node.js script checks line count, required headings, and a few high-signal secret patterns. Save it as check-claude-md.mjs and run it with Node.js 20 or newer.
import { readFile } from "node:fs/promises";
const filePath = process.argv[2] ?? "CLAUDE.md";
const text = await readFile(filePath, "utf8");
const lines = text.split(/\r?\n/);
const lineCount = text.endsWith("\n") ? lines.length - 1 : lines.length;
// Pass localized H2 names as the third argument, separated by "|".
const requiredHeadings = (
process.argv[3] ?? "Commands|Change rules|Review checklist"
)
.split("|")
.map((heading) => heading.trim())
.filter(Boolean);
const h2Headings = new Set();
let fenceMarker = null;
for (const line of lines) {
const fenceMatch = line.match(/^\s*(`{3,}|~{3,})/);
if (fenceMatch) {
const marker = fenceMatch[1];
if (fenceMarker === null) fenceMarker = marker;
else if (marker[0] === fenceMarker[0] && marker.length >= fenceMarker.length) fenceMarker = null;
continue;
}
if (fenceMarker !== null) continue;
const heading = line.match(/^##\s+(.+?)\s*$/)?.[1];
if (heading) h2Headings.add(heading);
}
const secretPatterns = [
["AWS access key", /AKIA[0-9A-Z]{16}/],
["GitHub token", /gh[pousr]_[A-Za-z0-9]{20,}/],
["assigned secret", /\b(api[_-]?key|password|token)\s*[:=]\s*["'][^"'\n]{8,}["']/i],
];
const failures = [];
if (lineCount > 200) failures.push(`too many lines: ${lineCount} (max 200)`);
if (requiredHeadings.length === 0) failures.push("required heading list is empty");
for (const heading of requiredHeadings) {
if (!h2Headings.has(heading)) failures.push(`missing h2: ${heading}`);
}
for (const [label, pattern] of secretPatterns) {
if (pattern.test(text)) failures.push(`possible secret: ${label}`);
}
if (failures.length > 0) {
console.table(failures.map((problem) => ({ problem })));
process.exitCode = 1;
} else {
console.log(`CLAUDE.md check passed: ${lineCount} lines`);
}
The command is intentionally simple enough to run locally and in CI:
node check-claude-md.mjs CLAUDE.md
# When your team uses different H2 names
node check-claude-md.mjs CLAUDE.md "Build commands|Change policy|Release checklist"
This checker is not a complete secret scanner. Pair it with GitHub secret scanning or a dedicated scanner. If a credential is detected, remove it from history where necessary and revoke it; deleting the visible line is not sufficient.
Pitfalls and concrete fixes
Pitfall 1: the file grows after every review. The cause is turning every comment into a permanent rule before checking whether it will recur. Fix it by adding only repeated decisions, deleting stale commands first, and moving package-specific detail closer to the package.
Pitfall 2: instructions cannot be verified. “Maintain quality” and “follow the existing design” do not define a pass condition. Replace them with a target path, command, expected exit status, browser width, or named test. A new teammate should reach the same conclusion as the original author.
Pitfall 3: security depends on prose. Writing “never touch production” does not create a barrier. Put dangerous command patterns in permission deny rules and use a PreToolUse hook when an operation must stop deterministically. Keep the reason and approved alternative in CLAUDE.md.
Pitfall 4: imports become a hidden knowledge dump. The cause is assuming imported files are free context. They are loaded at startup. Keep a short decision rule in the root file and provide a path or URL for details that Claude can read only when the task requires them.
Maintenance without documentation drift
Treat a CLAUDE.md change like a code change. Open the diff, run the checker, and test one representative task. Remove a rule when the command, path, or architecture it describes no longer exists.
A lightweight monthly review can use four questions:
- Which review comment appeared more than once?
- Which instruction was ignored or interpreted in two different ways?
- Which command or path has become stale?
- Which warning should be enforced by permissions or a hook?
The useful metric is not token count or document length. Track review-return count, failed checks caught before merge, and minutes spent re-explaining repository basics. If those numbers do not improve, rewrite or delete the rule.
Frequently asked questions
How long should CLAUDE.md be?
There is no hard content limit, but the official guidance recommends targeting fewer than 200 lines. Starting near 100 lines leaves room for a project map, commands, boundaries, and review gates. Move package-only material to nested files or .claude/rules/.
Does the file survive /compact?
The root CLAUDE.md is re-injected after compaction. Nested and path-scoped instructions are loaded again when Claude reads matching files. Put durable decisions in files rather than relying on a conversation that may be compacted.
How is auto memory different?
CLAUDE.md contains instructions that people write and maintain. Auto memory contains local notes Claude records from experience, such as debugging discoveries and preferences. Shared commands and boundaries belong in CLAUDE.md; local discoveries belong in auto memory unless a human promotes them to a team rule.
What should the first version contain?
Start with install, test, and build commands; one list of protected areas; and the required final report. Run a real task, then add only the missing decision that caused observable rework.
Build your project template from the course materials
Writing CLAUDE.md is only one part of a reliable workflow. Permissions, tests, handoff, and review still need to agree with it. The ClaudeCodeLab product catalog collects reusable checklists and exercises for turning these pieces into a project-specific operating template.
What was actually tested
On July 22, 2026, the check-claude-md.mjs code in this article was run against two temporary fixtures. A valid 10-line sample returned exit code 0 and the pass message. A negative sample with one missing heading and a test token returned exit code 1 and reported three findings: the missing heading plus two matching secret patterns.
The article review also checked JavaScript syntax, official-source URLs, internal links, frontmatter, the final results section, and the presence of one primary commercial CTA. Start by running the checker against your own CLAUDE.md, then fix the first reported issue. Product behavior was cross-checked against the official Claude Code documentation for memory, context windows, settings, and hooks.
Related Posts
Claude Code Permission Receipt Pattern: Record Scope, Proof, and Rollback
A permission receipt pattern for Claude Code: allowed actions, approval boundaries, proof commands, rollback, and revenue CTA checks.
Claude Code CLAUDE.md Permission Recipe: Reduce Repeated Context and Risky Access
A beginner-friendly recipe for combining CLAUDE.md rules with permission boundaries and proof commands.
Claude Code Session Handoff Template: Preserve Context for the Next Human or Agent
A practical Claude Code handoff template for context, verification, risks, and next prompts across sessions.
Free PDF: Claude Code Cheatsheet
Enter your email and download the one-page Claude Code cheatsheet for commands, review habits, and safe workflows.
We handle your data with care and never send spam.
Level up your Claude Code workflow
Start with the free PDF, use Gumroad guides when you need repeatable workflows, and book consultation when rollout or revenue paths need human judgment.
About the Author
Masa
Engineer focused on practical Claude Code workflows. Runs claudecode-lab.com, a 10-language technical media site.
Related Products
The Complete Claude Code Setup & Configuration Guide
From install to team-ready workflow.
A practical guide to installation, CLAUDE.md, hooks, MCP servers, permissions, IDE setup, and CI/CD workflows.
50 Battle-Tested Claude Code Prompt Templates
Copy, paste, ship. 50 production-ready prompts.
Use proven prompts for code review, refactoring, testing, documentation, debugging, architecture, and incident response.