How to Write and Organize CLAUDE.md Files for Claude Code
Learn how to write, scope, and verify CLAUDE.md files for Claude Code across user, project, and local scopes, with a hands-on example project.
Every session with an AI coding agent starts from zero. Claude Code, Anthropic’s AI coding agent, does not remember what you told it yesterday, which build command your project uses, or that you prefer tabs over spaces, unless you write it down somewhere Claude reads automatically. That somewhere is a file called CLAUDE.md: a plain markdown file that Claude Code loads at the start of every session so you stop re-explaining the same things. This tutorial focuses on Claude Code’s command-line interface and walks through writing, scoping, and verifying CLAUDE.md files from scratch, including a hands-on example project you can follow along with on your own machine.
Table Of Content
- What CLAUDE.md Is, and What It Is Not
- Prerequisites
- Step 1: Install Claude Code and Confirm the CLI Works
- Step 2: Log In and Start Your First Session
- Step 3: Generate a Starting CLAUDE.md With /init
- Step 4: Understand Where CLAUDE.md Files Can Live
- Hands-On: Build a Small Project Hierarchy
- Step 5: Write a Focused Project CLAUDE.md
- Step 6: Add Personal Notes With CLAUDE.local.md
- Step 7: Pull in Other Files With @imports
- Step 8: Verify What Actually Loaded
- Common Mistakes and How to Catch Them
- Verifying It Works End to End
- Next Steps
- Sources
Every mechanic described here, file locations, load order, the /init and /memory commands, and the @import syntax, is drawn from and cross-checked against Anthropic’s official Claude Code documentation. No prior Claude Code experience is assumed.
What CLAUDE.md Is, and What It Is Not
A session is one continuous conversation with Claude Code, from the moment you run the claude command until you exit. Each session gets a fresh context window, the working memory Claude has available, measured in tokens, for that conversation. A CLAUDE.md file is a set of instructions you write once that gets loaded into that context window automatically at the start of every session, so Claude starts already knowing your build commands, coding conventions, and project layout instead of you typing them in again.
The important nuance, stated directly in Anthropic’s documentation: CLAUDE.md content is delivered as a message Claude reads and tries to follow, not as enforced configuration. Claude treats it as context, the same way it treats anything else you tell it, so there is no hard guarantee it is followed to the letter, especially if an instruction is vague or two files contradict each other. If you need a rule enforced regardless of what Claude decides, such as blocking a command outright, that is a job for a hook (a shell command Claude Code runs automatically at fixed points, covered briefly in Next Steps), not CLAUDE.md. CLAUDE.md is for behavioral guidance: conventions, workflows, and things Claude would otherwise have to guess or rediscover.
Prerequisites
- A terminal on macOS, Linux, WSL, or Windows (PowerShell or CMD).
- A Claude subscription (Pro, Max, Team, or Enterprise), a Claude Console account, or access through a supported enterprise cloud provider (Amazon Bedrock, Google Cloud’s Agent Platform, or Microsoft Foundry). Claude Code will not run without one of these.
- An empty or existing project folder to practice in. This tutorial uses a small Node.js API project as a running example; Node.js 18 or newer is only needed if you want that specific example to actually run, not for Claude Code itself.
- Basic command-line comfort:
cd,mkdir, reading a file withcat. - Git, recommended but not required. One step below shows how CLAUDE.local.md interacts with
.gitignore.
Step 1: Install Claude Code and Confirm the CLI Works
Anthropic’s recommended install path is a native installer script, no Node.js or package manager required for Claude Code itself:
# Context: macOS, Linux, or WSL terminal.
curl -fsSL https://claude.ai/install.sh | bash
On Windows PowerShell, the equivalent is irm https://claude.ai/install.ps1 | iex. Homebrew (brew install --cask claude-code) and WinGet (winget install Anthropic.ClaudeCode) are also officially supported if you already use those package managers; the tradeoff is that native installs auto-update in the background, while Homebrew and WinGet installs need a manual brew upgrade or winget upgrade later.
Confirm the install worked:
# Context: any shell, after installation.
claude --version
What this does and why it matters: per Anthropic’s documentation, this command prints a version number followed by (Claude Code). Running it on the machine used to write this tutorial printed:
2.1.207 (Claude Code)
Your version number will likely differ since native installs update automatically, and that is expected; what matters is that some version string followed by (Claude Code) comes back at all. If you instead see a “command not found” error, the install did not put claude on your PATH, and re-running the installer or opening a new terminal window usually fixes it.
Step 2: Log In and Start Your First Session
Claude Code requires an account before it will do anything. Start it in any project directory:
# Context: inside the project folder you want Claude Code to work in.
cd /path/to/your/project
claude
What this does and why it matters: the first time you run claude, it prompts you to authenticate in your browser against whichever account type you have (Claude subscription, Console, or an enterprise cloud provider). Once you complete that, credentials are stored locally and you will not be asked again. If you ever need to switch accounts, type /login inside a running session; commands that start with / and are typed inside Claude Code, rather than in your regular shell, are called slash commands, and you will use several of them in this tutorial.
Step 3: Generate a Starting CLAUDE.md With /init
You do not have to write a CLAUDE.md entirely by hand. Inside a running session, the fastest starting point is:
/init
What this does and why it matters: /init analyzes your codebase and writes a starter CLAUDE.md containing the build commands, test instructions, and project conventions it can detect on its own, dependency manifests, existing config files, folder structure, and so on. If a CLAUDE.md already exists in the project, /init does not overwrite it; it suggests improvements instead. Treat the result as a first draft, not a finished file: it documents what Claude could discover by reading your repository, but it cannot know your team’s unwritten conventions or the mistakes Claude has made on this project before. Steps 5 through 7 below cover refining it into something more useful.
Newer Claude Code versions also support an enhanced, interactive /init flow that additionally walks through skills and hooks setup, enabled by setting the environment variable CLAUDE_CODE_NEW_INIT=1 before starting a session. That flow is optional; the basic /init is enough for everything in this tutorial.
Step 4: Understand Where CLAUDE.md Files Can Live
Before writing more instructions, it helps to know that CLAUDE.md is not one file. Claude Code recognizes four scopes, listed here from broadest to most specific:
- Managed policy (organization-wide, deployed by IT or DevOps):
/etc/claude-code/CLAUDE.mdon Linux and WSL,/Library/Application Support/ClaudeCode/CLAUDE.mdon macOS,C:\Program Files\ClaudeCode\CLAUDE.mdon Windows. Applies to every user on the machine and cannot be excluded by individual settings. Most individual developers will never create this file themselves. - User instructions (your personal defaults across every project):
~/.claude/CLAUDE.md. Good for things like your own code-styling preferences or personal tooling shortcuts that have nothing to do with any one project. - Project instructions (shared with your team via version control):
./CLAUDE.mdor./.claude/CLAUDE.mdat the project root. This is the one most tutorials, including this one, focus on: architecture notes, coding standards, and common workflows that everyone on the project benefits from. - Local instructions (your own preferences for one specific project, never committed):
./CLAUDE.local.md. Covered in Step 6.
Here is the part that trips people up: these files are not overridden by one another the way a more specific configuration file usually overrides a general one. Anthropic’s documentation is explicit that all discovered CLAUDE.md files are concatenated into context, not layered so one replaces another. What changes is the order: broader-scope files are read first, project-specific ones last, so an instruction closer to where you launched Claude effectively has the last word in context if two files genuinely disagree.
There is a second, separate rule for files inside subdirectories of your project. Claude Code walks up the directory tree from your current working directory at launch and loads every CLAUDE.md and CLAUDE.local.md it finds along that upward path immediately. But CLAUDE.md files sitting in subdirectories below where you started are not loaded at launch; they are picked up on demand, only when Claude actually reads a file in that subdirectory. That distinction matters for the hands-on example below.
Hands-On: Build a Small Project Hierarchy
To make this concrete, here is a real project structure with CLAUDE.md files at two different levels, built and verified with plain shell commands so you can reproduce every step:
# Context: any Linux, macOS, or WSL shell with git installed.
mkdir -p claude-md-demo/src/api && cd claude-md-demo
git init -q
echo "console.log('hello');" > src/api/server.js
echo "node_modules/" > .gitignore
git add .gitignore src && git commit -q -m "initial commit"
Now add a project-root CLAUDE.md and a second, narrower one inside src/api/:
# Context: claude-md-demo/CLAUDE.md, project root.
# Project Instructions
## Build and test
- Install dependencies: `npm install`
- Run the dev server: `npm run dev`
- Run tests: `npm test`
## Conventions
- Use 2-space indentation
- API handlers live in `src/api/`
- Prefer `async/await` over `.then()` chains
See @README.md for a project overview.
# Context: claude-md-demo/src/api/CLAUDE.md, nested subdirectory.
# API-specific rules
- Every handler must validate its input before touching the database
- Return errors as `{ "error": "message" }` JSON, never a bare string
Listing the resulting tree confirms the layout:
$ find . -not -path './.git*' | sort
.
./CLAUDE.md
./README.md
./src
./src/api
./src/api/CLAUDE.md
./src/api/server.js
What this does and why it matters: if you now start claude from the claude-md-demo root, the project-root CLAUDE.md loads immediately at launch. The narrower src/api/CLAUDE.md does not load yet, exactly as the docs describe, because it is a subdirectory file; it only enters context the moment Claude reads or edits something inside src/api/, at which point its input-validation and error-format rules apply on top of the project-wide ones. This is how a large project keeps its root CLAUDE.md short while still giving specific areas of the codebase their own rules, without paying the context cost of loading every subdirectory’s instructions on every single session.
Step 5: Write a Focused Project CLAUDE.md
The project-root CLAUDE.md above is deliberately specific rather than vague, and that is not an accident. Anthropic’s own guidance contrasts instructions like these directly:
- “Use 2-space indentation” instead of “Format code properly”.
- “Run
npm testbefore committing” instead of “Test your changes”. - “API handlers live in
src/api/handlers/” instead of “Keep files organized”.
The left-hand versions are concrete enough that you, or Claude, can check whether they were followed. The right-hand versions sound reasonable but give Claude nothing to actually verify against, so they get followed inconsistently. When you refine the file /init generated for you, this is the single highest-value edit: replace anything that sounds like general advice with a specific, checkable rule.
Size matters too. Anthropic’s documentation recommends keeping each CLAUDE.md file under roughly 200 lines; longer files consume more of the context window and, per their own testing, reduce how consistently Claude follows the instructions in them. If a project genuinely needs more than that, the documented answer is not one giant file. It is either path-scoped rules in a .claude/rules/ directory (instructions that only load when Claude touches matching files, using a paths frontmatter field) or splitting by subdirectory the way Step 4’s src/api/CLAUDE.md already does. Both are worth knowing exist even if this tutorial does not build one; see Next Steps.
Step 6: Add Personal Notes With CLAUDE.local.md
Project CLAUDE.md is shared with your whole team through version control, so it should only contain things that are true for everyone. Your own local Postgres port, personal test shortcuts, or sandbox URLs do not belong there. That is what CLAUDE.local.md is for: same format, same loading behavior, but scoped to you and this one project, and explicitly meant to be gitignored.
# Context: claude-md-demo/CLAUDE.local.md, project root.
# Personal notes (not committed)
- My local Postgres runs on port 5433, not the default 5432
- Skip the slow integration suite locally: `npm test -- --fast`
# Context: same project root, add it to .gitignore immediately.
echo "CLAUDE.local.md" >> .gitignore
git add .gitignore
git check-ignore -v CLAUDE.local.md
Running that check on this exact demo project confirmed it is correctly ignored:
.gitignore:2:CLAUDE.local.md CLAUDE.local.md
What this does and why it matters: git check-ignore -v prints the exact .gitignore line responsible for ignoring a file, or nothing at all if the file would still be committed. Running it right after adding the entry is a cheap, immediate way to confirm you did not typo the filename, before you accidentally commit a file full of your personal sandbox details. One more thing worth knowing before you rely on this file: if you work across multiple git worktrees of the same repository, a gitignored CLAUDE.local.md only exists in the worktree where you created it, since it is never committed anywhere for other worktrees to see. Anthropic’s documentation covers sharing personal preferences across worktrees by importing a file from your home directory instead, which leads directly into the next step.
Step 7: Pull in Other Files With @imports
Notice the project CLAUDE.md from Step 5 ended with See @README.md for a project overview. The @path syntax imports another file’s contents directly into context alongside the CLAUDE.md that references it, so you do not have to duplicate information that already lives elsewhere:
See @README.md for project overview and @package.json for available npm commands.
# Individual Preferences
- @~/.claude/my-project-instructions.md
What this does and why it matters: both relative and absolute paths work; relative paths resolve relative to the file doing the importing, not your current directory, and imported files can themselves import further files, up to four hops deep. That last example, importing a file from your home directory, is the documented fix for the worktree limitation from Step 6: a plain CLAUDE.local.md is per-worktree, but a file under ~/.claude/ that you import from a tracked CLAUDE.md is available in every worktree of every project. Two details worth knowing before you rely on this: Claude Code shows a one-time approval dialog listing the files the first time it encounters external imports in a project, and if you decline, imports stay disabled for that project without asking again; and if you want to mention a path in a CLAUDE.md without triggering an import, wrapping it in backticks, like `@README`, keeps it literal text instead.
Step 8: Verify What Actually Loaded
Writing instructions is only half the job; confirming Claude Code actually saw them is what turns “I think this works” into something you can trust. Two slash commands cover this:
/context
What this does and why it matters: shows what is actually loaded into the current session’s context window. If a CLAUDE.md file you expected to be active is missing from that breakdown, Claude genuinely cannot see it, usually because it is not in a location that gets loaded for your current session (revisit the scopes in Step 4).
/memory
What this does and why it matters: lists every CLAUDE.md and CLAUDE.local.md location Claude Code knows about across user and project scopes, lets you toggle the separate auto memory system on or off, and opens any of these files directly in your editor when you select one. When you are not sure whether an instruction is being followed, /memory is the fastest way to jump straight to the file and check the wording, rather than guessing.
Common Mistakes and How to Catch Them
- Treating CLAUDE.md as an enforced rule instead of context. An instruction like “never touch the production database” in CLAUDE.md is a strong nudge, not a hard block; Claude can still misjudge a situation. If a rule must never be violated regardless of Claude’s judgment, that requirement belongs in a hook, not a markdown file.
- Letting the file grow past roughly 200 lines. It keeps working, but adherence quietly gets worse as the file grows, per Anthropic’s own guidance. Move detail that only matters for part of the codebase into
.claude/rules/or a subdirectory CLAUDE.md instead of piling everything into one file. - Writing instructions that cannot be checked. “Keep the code clean” gives Claude nothing to verify against. “Run
npm run lintbefore committing” does. - Forgetting to gitignore CLAUDE.local.md before the first commit. Run
git check-ignore -v CLAUDE.local.mdimmediately after creating it, as in Step 6, rather than trusting that you remembered to add the line. - Contradicting yourself across nested CLAUDE.md files. If the project root says one thing and a subdirectory file says the opposite, Claude may pick either one arbitrarily. Periodically skim nested files for conflicts, especially after a project reorganization.
- Assuming a subdirectory’s CLAUDE.md is active the moment a session starts. As Step 4 demonstrated, it only loads once Claude reads a file in that subdirectory, not at launch. Do not be surprised if a rule scoped to
src/api/seems to be ignored before Claude has touched anything in that folder.
Verifying It Works End to End
claude --versionreturns a version number followed by(Claude Code), confirming the install.- Starting
claudein your project and running/contextshows your project CLAUDE.md (and CLAUDE.local.md, if present) actually loaded. - Add one deliberately specific, easy-to-observe instruction, for example “always use
npm test -- --fastfor this project instead of the full suite”, start a fresh session, and ask Claude to run the tests. Confirm it uses the command you specified rather than a default. /memorylists the files you expect, at the scopes you expect, and opens correctly when selected.- For a nested rule, edit a file inside that subdirectory and confirm (again via
/contextor by observing Claude’s behavior) that the subdirectory’s CLAUDE.md has now joined the session.
If all five check out, you have a working CLAUDE.md hierarchy: instructions that load automatically, at the scope you intended, that you can prove are actually reaching Claude rather than just hoping they are.
Next Steps
CLAUDE.md is one of several ways to shape Claude Code’s behavior, and knowing where its job ends is as useful as knowing how to write one. For hard rules that must never be skipped regardless of Claude’s judgment, such as blocking a command outright, look at hooks: shell commands Claude Code runs automatically at fixed lifecycle events. For instructions that should only load when Claude works with a specific part of a large codebase, without paying the context cost every session, look at path-scoped rules in .claude/rules/. And separate from anything you write by hand, Claude Code also maintains auto memory, notes Claude writes for itself based on your corrections, stored per repository and reviewable through the same /memory command used in Step 8. If your team already maintains an AGENTS.md for other coding agents, Claude Code reads CLAUDE.md specifically, but a one-line @AGENTS.md import at the top of your CLAUDE.md lets both tools share the same source of truth instead of maintaining two files by hand.
Sources
- Claude Code Documentation: How Claude Remembers Your Project (CLAUDE.md and auto memory)
- Claude Code Documentation: Quickstart (installation and first session)
- Claude Code Documentation: Slash Commands Reference
- Featured image source: Shixart1985, Wikimedia Commons
Image credit: Photo by Shixart1985, licensed CC BY 2.0 via Wikimedia Commons; cropped, resized, and converted to WebP for sxz.io.








No Comment! Be the first one.