Initialize a project for Claude Code: CLAUDE.md, rules, and memory
PLInitializing a project for Claude Code means committing a short CLAUDE.md that holds the commands, conventions, and pitfalls Claude cannot infer from the code, and moving everything narrower into path-scoped rules under .claude/rules/. The /init command drafts the file. The setup is finished only when /context lists it and a probe prompt returns the exact commands.
You open Claude Code in a TypeScript service and ask for a new endpoint. It installs a package with npm although the repo uses pnpm, writes Jest tests for a Vitest suite, and skips the migration step that every schema change needs. None of that is a model problem: the session started without your project’s context. This page is for the developer setting up Claude Code on an existing repository and for the tech lead who will own the committed instruction files afterwards.
What you get from initializing a project
Section titled “What you get from initializing a project”- A committed
CLAUDE.mdunder 200 lines that lists verified commands and the conventions that differ from tool defaults. - One path-scoped rule in
.claude/rules/generated from code that already exists in the repo. - A clear split between what you write (
CLAUDE.md, rules), what stays personal (CLAUDE.local.md,~/.claude/CLAUDE.md), and what Claude writes itself (auto memory). - A three-check verification you can rerun after every edit:
/context, a probe prompt in a fresh session, and a review gate on the files themselves.
If you are starting a repository from nothing rather than adding Claude Code to one, start a new project from the terminal first, then come back here.
Where does Claude Code read project instructions from?
Section titled “Where does Claude Code read project instructions from?”Claude Code reads instruction files from several scopes. The first rows follow the official memory documentation’s load order, broadest first; rules, subdirectory files and auto memory load as the last column shows:
| Scope | Location | Shared with | When it loads |
|---|---|---|---|
| Managed policy | macOS /Library/Application Support/ClaudeCode/CLAUDE.md, Linux and WSL /etc/claude-code/CLAUDE.md, Windows C:\Program Files\ClaudeCode\CLAUDE.md | Everyone on the machine; users cannot exclude it | At launch |
| User | ~/.claude/CLAUDE.md and ~/.claude/rules/ | Only you, every project | At launch |
| Project | ./CLAUDE.md or ./.claude/CLAUDE.md | The team, through git | At launch |
| Project rules | ./.claude/rules/**/*.md | The team, through git | At launch, or when Claude reads a matching file if the rule has paths |
| Local | ./CLAUDE.local.md | Only you, this project | At launch |
| Subdirectory | ./packages/api/CLAUDE.md and similar | The team | When Claude reads files in that directory |
| Auto memory | ~/.claude/projects/<project>/memory/MEMORY.md | Only you, this machine | At launch: the first 200 lines or 25KB |
Two details in that table change how you write the files:
- Files are concatenated, not overridden. Every file Claude Code finds is added to the context. A project rule does not replace a user rule; the later one is simply read later. When two files contradict each other, Claude may follow either, so the fix for a conflict is to delete one side.
- Instructions are context, not enforcement. Claude reads
CLAUDE.mdand tries to follow it. Anything that must happen every time, such as running the linter after an edit or never touchingmigrations/, belongs in a hook or a permission rule, which the client enforces regardless of what the model decides.
Initialize the project in five steps
Section titled “Initialize the project in five steps”-
Start a session at the repository root. In your terminal, open the repository and launch Claude Code there, because Claude Code loads
CLAUDE.mdfiles from the working directory and every directory above it:Terminal window cd ~/code/orders-apiclaude -
Run
/init. At the Claude Code prompt, type:/initClaude reads the codebase and writes a starting
CLAUDE.mdwith build and test commands and the conventions it detects. If aCLAUDE.mdalready exists,/initsuggests improvements instead of overwriting it. It also folds in.cursor/rules/,.cursorrules, and.github/copilot-instructions.mdif the repository has them. For a guided flow that also proposes skills and hooks and shows a reviewable proposal before writing, setCLAUDE_CODE_NEW_INIT=1in your shell before you startclaude; that flow also readsAGENTS.md,.devin/rules/,.windsurf/rules/or.windsurfrules, and.clinerules. If you are moving from another agent,/import codex,/import cursor, or/import gemini(v2.1.213 or later; v2.1.265 for Cursor; not available on Amazon Bedrock, Google Cloud, Microsoft Foundry, Claude Platform on AWS or through a Claude apps gateway) appends a one-time copy of that tool’s instruction files and carries over its MCP servers, commands, subagents, and skills. -
Cut the draft down to what Claude cannot infer. An
/initdraft tends to describe the directory tree and the dependency list, which Claude can read from the code in any session. Keep the commands, the non-obvious conventions, and the traps. Use the first prompt below to do the cut with evidence. -
Move narrow instructions into a path-scoped rule. A convention that applies only to
src/routes/or only to migrations goes into.claude/rules/with apathsfield, so it loads only when Claude works on those files. The second prompt below writes one from existing code. -
Verify, then commit. Run the three checks in how to prove the setup works, then commit
CLAUDE.mdand.claude/rules/in their own pull request so the team reviews them like code.
What belongs in CLAUDE.md, and what goes somewhere else?
Section titled “What belongs in CLAUDE.md, and what goes somewhere else?”Most instruction files fail by holding too much, not too little. The official guidance targets under 200 lines per CLAUDE.md, because every line costs context in every session and longer files reduce adherence. Use this table to decide where each instruction goes:
| The instruction is… | Put it in | Why |
|---|---|---|
| A command, a project-wide convention, a trap | CLAUDE.md | Needed in every session |
| True only for one directory or file type | .claude/rules/<topic>.md with paths | Loads only when Claude reads matching files |
| A multi-step procedure (release, migration) | A skill or custom command | Loads only when invoked or relevant |
| Something that must happen every time | A hook or permission rule | Enforced by the client, not by the model |
| Your sandbox URL, your preferred test data | CLAUDE.local.md | Personal to this project |
| Your preferences across all repositories | ~/.claude/CLAUDE.md | Personal, every project |
| A correction you gave Claude once | Auto memory (Claude saves it) | Claude decides what is worth keeping |
A CLAUDE.md that follows that split is short. This one is for a TypeScript API on pnpm and Vitest, and every line is something Claude would otherwise get wrong:
# orders-api
## Commands- Install: `pnpm install` (never npm or yarn; the lockfile is pnpm-lock.yaml)- Dev server: `pnpm dev` (port 8080)- All tests: `pnpm test` · one file: `pnpm vitest run src/orders/orders.test.ts`- Type check: `pnpm typecheck` · lint: `pnpm lint`- New migration: `pnpm db:generate`, then `pnpm db:migrate` against the local database
## Conventions that differ from the defaults- Routes use Hono, not Express. Follow src/routes/orders.ts.- Validate every request body with the Zod schema in src/schemas/, never inline.- Money is an integer number of cents. Never use floats for amounts.- Tests use Vitest with the fake clock in tests/setup.ts; do not add Jest.
## Traps- src/db/generated/ is generated by `pnpm db:generate`. Never edit it by hand.- Integration tests need Postgres from `docker compose up db`.- CI runs `pnpm typecheck`; a green `pnpm test` alone does not mean CI passes.
<!-- Owner: platform team. Review changes in PRs like code. -->Block-level HTML comments such as the last line are stripped before the content reaches Claude, so you can leave notes for maintainers at no context cost.
What does a good CLAUDE.md look like in other stacks?
Section titled “What does a good CLAUDE.md look like in other stacks?”The shape stays the same in every stack: commands, the conventions that break the stack’s defaults, and traps. Only the content changes. These two are cut down from typical long templates to the lines that change what Claude does:
# billing-api (Django REST Framework)
## Commands- Env: `uv sync` · tests: `uv run pytest -x` · one test: `uv run pytest billing/tests/test_invoices.py::test_void`- Lint and format: `uv run ruff check --fix . && uv run ruff format .`- Migrations: `uv run python manage.py makemigrations billing`, then `migrate`
## Conventions that differ from the defaults- JSON is camelCase through djangorestframework-camel-case; models stay snake_case.- Serializers own all validation. Views never validate by hand.- Test data comes from factory_boy factories in billing/tests/factories.py.
## Traps- Never edit a migration that has shipped. Add a new one.- Stripe calls are mocked in tests via conftest.py; a real key in .env breaks CI.# platform-infra (Terraform)
## Commands- Format and validate: `terraform fmt -check -recursive && terraform validate`- Security scan: `trivy config .` (CI fails on HIGH)- Plan one environment: `cd environments/staging && terraform plan -out=plan.tfplan`
## Conventions that differ from the defaults- Reusable code lives in modules/; environments/ only wires modules together.- State is in S3 with a DynamoDB lock. Never use local state.
## Traps- Never run `terraform apply`. Production applies go through the CI pipeline after manual approval; you produce a plan and stop.Both files leave out what long templates usually include: a directory tour, the full tech-stack list, generic advice (“use descriptive names”, “write tests”), and sprint goals or known-bug lists. The first three Claude can infer or already does; the last two go stale within weeks and belong in the issue tracker. The Terraform “never apply” line is also a candidate for a permission rule that denies the command, because an instruction alone does not stop it.
Scope instructions to paths with .claude/rules/
Section titled “Scope instructions to paths with .claude/rules/”A rule is a Markdown file under .claude/rules/. Subdirectories are discovered recursively, so frontend/ and backend/ folders work. Without frontmatter, a rule loads at launch like CLAUDE.md. With a paths field, it loads only when Claude reads a file that matches one of the globs:
---paths: - "src/routes/**/*.ts" - "src/schemas/**/*.ts"---
# API route rules
- Parse the body with the matching schema from src/schemas/ before any logic.- Return errors as { error: string, code: string } with an explicit status.- Every new route gets a test in the same folder that covers a 400 response.paths is the only frontmatter field Claude Code reads from a rule. If the YAML does not parse, Claude Code ignores the frontmatter and loads the rule everywhere, so a typo silently turns a scoped rule into a global one. Run claude --debug to see the parse error.
Split a long CLAUDE.md with @path imports
Section titled “Split a long CLAUDE.md with @path imports”CLAUDE.md can pull in other files with @path/to/file. Relative paths resolve from the file that contains the import, imports can nest up to four hops deep, and an @ inside backticks or a fenced code block stays literal:
See @README.md for the product overview and @package.json for scripts.
## Area guides- Payments: @docs/agents/payments.md- Git workflow: @docs/agents/git.mdImports organize a file; they do not shrink the context. Imported files load at launch together with the file that imports them. When the goal is to cut what every session pays for, use path-scoped rules or subdirectory CLAUDE.md files instead, which load only when Claude reads the matching files.
The first time a project imports a file outside the working directory, such as @~/.claude/my-orders-notes.md, Claude Code asks you to approve external imports. If you decline, those imports stay disabled and the dialog does not return. A home-directory import is also the way to share personal notes across git worktrees, because a gitignored CLAUDE.local.md exists only in the worktree where you created it.
Keep personal instructions out of the shared file
Section titled “Keep personal instructions out of the shared file”Two files hold what is true for you and not for the team:
CLAUDE.local.mdin the project root: your local port, your seed data, the flag you pass to end-to-end tests. It loads afterCLAUDE.mdat the same level. The memory documentation (checked 2026-09-26, v2.1.283) tells you to add it to.gitignoreyourself; only the personal option of theCLAUDE_CODE_NEW_INIT=1flow does that for you.~/.claude/CLAUDE.mdand~/.claude/rules/: preferences for every repository, such as “explain the plan before editing more than three files”.
Let auto memory handle corrections
Section titled “Let auto memory handle corrections”Auto memory is on by default. As you work, Claude writes notes for itself about your preferences, corrections you give it, and project context it cannot derive from the code, in ~/.claude/projects/<project>/memory/. All worktrees of one git repository share that directory, and it stays on your machine. MEMORY.md is an index; Claude Code loads its first 200 lines or 25KB at the start of every session and reads the topic files on demand.
The two memory systems take different requests:
- “Remember that the API tests need Redis on port 6379” goes to auto memory, which only you see.
- “Add to CLAUDE.md that the API tests need Redis on port 6379” edits the shared file, which the team reviews.
Put anything a teammate also needs into CLAUDE.md. Run /memory to open any memory file, browse the auto memory folder, or toggle auto memory. To turn it off for one project, set "autoMemoryEnabled": false in that project’s settings; for a whole machine or CI job, set CLAUDE_CODE_DISABLE_AUTO_MEMORY=1.
How do you prove CLAUDE.md works without reading every line?
Section titled “How do you prove CLAUDE.md works without reading every line?”Nobody should re-read a 150-line instruction file after every change. Three checks do the job instead, and the first two take under a minute.
-
Check what loaded. Start a new session and run
/context. YourCLAUDE.md,CLAUDE.local.md, and unscoped rules appear under Memory files. A file missing from that list does not exist for Claude, whatever it says. If a file is over the recommended length, or several files add up past a combined limit, Claude Code also warns at startup and in/status. -
Ask a probe question in a fresh session. A probe is a question whose correct answer exists only in your instruction files. If Claude answers from the file, the instructions work; if it guesses, they do not. Use the prompt below, and keep it in the repository so anyone can rerun it after editing the files.
-
Gate changes to the files. Treat
CLAUDE.mdand.claude/rules/as code: changes land through a pull request, and a named owner, usually the tech lead, approves them through CODEOWNERS. These files steer an agent that runs shell commands, and Phoenix Security’s 2026 supply-chain review (single vendor blog, secondary; read 2026-09-26) counted agent tooling (MCP injection,.cursorrules,CLAUDE.mdand SessionStart hooks) as a delivery mechanism in at least 14 of the 59 campaigns it tracked.
Run the probe in a new session, or after /clear, never in the conversation where you just edited the file: that conversation already contains the answers. Any “not in my instructions” answer is a gap in the file. A confident wrong answer usually means a conflict between two files, or an instruction that lives only in conversation history.
For deeper tracing, a hook on the InstructionsLoaded event, which fires each time a CLAUDE.md or rules file loads, can log which files loaded, when, and why, which helps when a path-scoped rule never seems to apply. The hooks guide shows how to add one.
Maintenance is part of verification. /doctor (v2.1.206 or later) proposes trims for a checked-in CLAUDE.md, cutting content Claude can derive from the code and keeping pitfalls and conventions. From v2.1.283, /doctor prompt-audit audits your CLAUDE.md files, skills, agents and commands for stale paths, stale commands, contradicting instruction files and prompting patterns written for older models. Run one of them before a quarterly review of the files, and read the ablation protocol for pruning context files before you add a rule for every mistake.
Roll out CLAUDE.md to a team
Section titled “Roll out CLAUDE.md to a team”A file that one developer wrote on a Friday afternoon encodes one developer’s habits. For a team, the tech lead makes it a shared artifact:
- Draft it once, together. Run
/initand the tightening prompt, then review the result in one pull request with two or three people who know the repository. Every disputed convention gets settled there, not in later sessions. - Name an owner. Add
CLAUDE.mdand.claude/rules/to CODEOWNERS, so a change to what the agent is told needs the same approval as a change to CI. - Use it for onboarding. A short
CLAUDE.mdthat lists the real commands and traps is also the fastest page a new engineer can read. If a new hire finds it wrong, the agent is wrong too. - Review it quarterly. Run
/doctor, rerun the probe prompt, and delete lines nobody can connect to a real mistake.
Lay out instructions in a monorepo
Section titled “Lay out instructions in a monorepo”In a monorepo, put a short CLAUDE.md at the root with the commands that work everywhere, and one per package for what differs:
repo/├── CLAUDE.md # install, workspace commands, repo-wide traps├── .claude/rules/│ └── migrations.md # paths: ["packages/*/migrations/**"]├── packages/api/CLAUDE.md # loads when Claude reads files in packages/api/└── packages/web/CLAUDE.md # loads when Claude reads files in packages/web/Launching Claude Code in packages/api/ loads that package’s CLAUDE.md and the root one above it. Launching at the root loads the package files only on demand. If another team’s CLAUDE.md keeps loading and does not apply to your work, add its path to claudeMdExcludes in .claude/settings.local.json. A managed policy CLAUDE.md cannot be excluded. The large codebase guide covers navigation at that scale.
When project instructions break
Section titled “When project instructions break”Claude ignores CLAUDE.md. Run /context and look under Memory files. If the file is missing, check that you launched claude in the repository or below it, and that the name is exactly CLAUDE.md. If the file is listed but ignored, the instruction is probably vague (“format nicely”) or contradicted elsewhere. Rewrite it as something checkable (“Use 2-space indentation”). If it must never be skipped, move it to a hook.
Claude follows the wrong one of two instructions. Files are concatenated, so both reach the model. Search ~/.claude/CLAUDE.md, the project file, CLAUDE.local.md, subdirectory files, and .claude/rules/ for the topic, then delete the losing instruction instead of adding an “ALWAYS” to the winner.
A path-scoped rule never applies. Scoped rules trigger when Claude reads a matching file, not on every tool use. Check the glob against a real path, check that the YAML parses (claude --debug), and confirm with an InstructionsLoaded hook.
An instruction disappears after /compact. The project-root CLAUDE.md is re-read from disk after compaction. Subdirectory files and path-scoped rules return only when Claude reads a matching file again. An instruction that existed only in conversation is gone; write it into CLAUDE.md.
AGENTS.md is not being read. Before v2.1.280, /context and /memory did not list an AGENTS.md that Claude read directly, so ask Claude what its project instructions say before assuming it is missing. Otherwise, look for a CLAUDE.md, .claude/CLAUDE.md, or CLAUDE.local.md in the working directory or above it, run claude --version to confirm v2.1.277 or later (v2.1.281 or later on Bedrock, Google Cloud, Foundry, gateways or with telemetry off), and check Project instructions in /config. On any version, @AGENTS.md in a CLAUDE.md works.
An import loads nothing. You may have declined the external-imports dialog, which then stays disabled for that project. Also check that the path resolves from the importing file, not from your working directory, and that the @ is not inside backticks.
The file slowly fills with generic advice. Lines such as “write clean code” or “follow best practices” cost context and change nothing. Run /doctor or the shrink prompt above, and delete any line that would be true in any repository.
Commands in the file go stale. A renamed script makes Claude confidently run a command that no longer exists. Add “update CLAUDE.md if you change package.json scripts or CI” to your pull request template, and rerun the probe prompt when scripts change.
Where to go next after initializing the project
Section titled “Where to go next after initializing the project”The previous step in this quick start is IDE integration. Codex users set up the equivalent file with AGENTS.md setup.
Did this guide help you?
One tap, no sign-in.
What will you do with it?
How did it read?
What got in the way? Pick any that apply
Your role?
Thanks. I read every answer. Michał Jaskólski
Did this guide help?
One tap each. Close whenever you like.
no sign-in