Skip to main content
Claude Code Tutorial: From First Command to Custom Workflows

CLAUDE.md Fundamentals: Project Memory and Context

CLAUDE.md is a standing instruction file that gives Claude Code persistent context about your project. This lesson covers the file format, exact load order, @import syntax, and how context is injected at session start.

Intermediate14 minBy ToolDix Editorial

Learning objectives

  • Understand what CLAUDE.md is and when to use it
  • Identify the exact file lookup order and where files are read from
  • Use @import syntax to include external files
  • Recognize how context is injected and its token cost
  • Debug when CLAUDE.md is not being loaded or followed

ToolDix original visual

Claude Code Tutorial practice loop
1

Frame

Name the outcome and constraints.

2

Build

Try one bounded workflow.

3

Review

Keep evidence, revise, and share.

What is CLAUDE.md?

CLAUDE.md is a markdown file you create to give Claude Code persistent instructions for a project. Unlike chat messages, which expire when a session ends, CLAUDE.md is loaded at the start of every session. It's the place to write things you would otherwise re-explain: build commands, coding standards, project layout, architectural decisions, naming conventions, and common workflows.

ToolDix original diagram
CLAUDE.md: Standing context for every session
In CLAUDE.md
Architecture overview
Code standards
How to run tests
File boundaries
Key conventions
Result
No repeated context-setting
Consistent decisions
Faster sessions
Fewer mistakes
Claude Code reads CLAUDE.md at the start of every session, eliminating repetition and keeping decisions consistent.

CLAUDE.md is context, not enforcement. Claude Code reads it and tries to follow it, but there's no guarantee of strict compliance, especially for vague or conflicting instructions. To block an action regardless of what Claude decides, use a permission rule instead. To require a hook to run at a specific lifecycle event, use a PreToolUse hook.

When to add to CLAUDE.md

Add an entry when:

  • Claude makes the same mistake a second time
  • A code review catches something Claude should have known about the codebase
  • You type the same correction or clarification multiple times
  • A new teammate would need the same context to be productive

Keep entries factual and specific: "Use 2-space indentation" works better than "format code nicely."

When NOT to use CLAUDE.md

  • Task-specific instructions: don't put these in CLAUDE.md; use them in your prompt for that session only
  • Multi-step procedures: use a skill instead; skills load on demand and don't consume context all the time
  • Path-scoped rules: use .claude/rules/ with frontmatter; these load only when Claude reads matching files

The exact file lookup order

Claude Code reads CLAUDE.md files by walking up the directory tree from your working directory, then loading managed policy files. The order is:

Organization-wide (managed policy):

  1. macOS: /Library/Application Support/ClaudeCode/CLAUDE.md
  2. Linux/WSL: /etc/claude-code/CLAUDE.md
  3. Windows: C:\Program Files\ClaudeCode\CLAUDE.md

User-level: 4. ~/.claude/CLAUDE.md

Project-level (walking up from working directory): 5. Parent directories up to filesystem root: ./CLAUDE.md and ./CLAUDE.local.md at each level 6. Current working directory: ./CLAUDE.md and ./CLAUDE.local.md 7. Alternative project location: ./.claude/CLAUDE.md and ./.claude/CLAUDE.local.md

Files are concatenated in order, so content from organization-wide applies first, then user, then parent directories (from root down to your cwd), then your cwd. Within each directory, CLAUDE.md loads before CLAUDE.local.md.

Important: Files in subdirectories below your cwd are not loaded at startup. They load on demand when Claude reads files in those directories.

Scopes and purposes

| Scope | Files | Purpose | Shared with | |:---|:---|:---|:---| | Managed policy | /Library/Application Support/ (macOS), /etc/claude-code/ (Linux), C:\Program Files\ (Windows) | Organization-wide standing instructions | All users in org | | User | ~/.claude/CLAUDE.md | Personal preferences for all projects | Just you (all projects) | | Project | ./CLAUDE.md or ./.claude/CLAUDE.md | Team-shared standing instructions | Team members via git | | Local | ./CLAUDE.local.md | Personal project-specific preferences | Just you (add to .gitignore) |

Which file to edit for which use case

  • Coding standards for your org: /Library/Application Support/ClaudeCode/CLAUDE.md (managed by IT)
  • Your personal preferences (all projects): ~/.claude/CLAUDE.md (your machine only)
  • Project architecture and conventions: ./CLAUDE.md or ./.claude/CLAUDE.md (committed to git)
  • Your sandbox URLs or test data: ./CLAUDE.local.md (add to .gitignore)

Creating your first project CLAUDE.md

Create either ./CLAUDE.md or ./.claude/CLAUDE.md in your project root. Claude Code treats both the same; the difference is organizational. Use ./CLAUDE.md if you want to track the file visibly in your editor; use ./.claude/CLAUDE.md if you want to keep it alongside other project config.

What to include:

# MyProject CLAUDE.md

## Build and test

- Build: `npm run build` (produces dist/)
- Test: `npm run test` (uses Jest, requires Node 18+)
- Dev server: `npm run dev` (localhost:3000)

## Project layout

- `src/` — Application code
- `src/components/` — React components
- `src/api/` — API client code
- `tests/` — Test files (colocated with source)
- `docs/` — User documentation

## Code standards

- Use 2-space indentation
- Function names in camelCase, constants in UPPER_SNAKE_CASE
- All functions have JSDoc comments
- Imports organized: React, then dependencies, then local code

## Git workflow

- Never commit directly to main; always use a feature branch
- Prefix branch names: `feature/`, `fix/`, `refactor/`
- Run `npm run test` and `npm run lint` before committing
- Pull request title format: [TYPE] Brief description (e.g., [FEATURE] Add user auth)

## Important constraints

- Never remove the error boundary in src/components/ErrorBoundary.tsx
- Config files in src/config are controlled by ops; don't edit without checking the wiki
- The cache in src/lib/cache.ts is shared across routes; invalidate with care

Run /init to auto-generate a starting CLAUDE.md. Claude Code analyzes your codebase and creates a file with build commands, test instructions, and conventions it discovers. Refine it from there.

The @import syntax

CLAUDE.md files can import external files using @path/to/file syntax. Imported files are expanded and loaded into context at launch.

Basic import

# Project Instructions

## Git workflow

@docs/git-workflow.md

## API conventions

@docs/api-standards.md

The paths are relative to the file containing the import. Relative paths like @./docs/file or @../shared/file work, as do absolute paths like @~/.claude/my-preferences.md.

Import limit and recursion

  • Maximum import depth: 4 hops (A imports B imports C imports D imports E is too deep)
  • Circular imports are detected and handled gracefully
  • Import parsing skips Markdown code spans and fenced code blocks

To mention a path without importing it, wrap it in backticks: `@README` is treated as literal text, not an import.

Practical examples

Pull in a README and build instructions:

@README.md
@docs/BUILD.md

Share instructions across git worktrees:

# Local preferences (different for each worktree)
@~/.claude/my-worktree-settings.md

Conditional imports in a monorepo:

Each team's project root has its own CLAUDE.md:

monorepo/
├── CLAUDE.md            # organization-wide standards
├── api/
│   └── CLAUDE.md        # API team standards
├── web/
│   └── CLAUDE.md        # Web team standards

How context is injected at session start

Claude Code injects CLAUDE.md as a user message after the system prompt but before your conversation. This means:

  1. The system prompt sets Claude's base instructions
  2. CLAUDE.md is loaded and delivered as context (appears in the transcript)
  3. Your first message in the session arrives

The order matters: CLAUDE.md is read last among all context, so instructions closer to your working directory override those from parent directories and from user-level CLAUDE.md.

Token cost

CLAUDE.md consumes tokens from your context window. The context window visualization shows where CLAUDE.md loads relative to your conversation. Keep CLAUDE.md files to under 200 lines to minimize context usage while maintaining adherence.

If your CLAUDE.md grows large, use path-scoped rules in .claude/rules/ to load instructions only when Claude works with matching files.

What survives context compaction

If you run /compact to clear context, project-root CLAUDE.md is re-read and re-injected automatically. Nested CLAUDE.md files in subdirectories (those that load on demand) are not re-injected; they reload the next time Claude reads a file in that subdirectory.

If instructions disappear after compaction, they were either:

  • Given only in conversation (add them to CLAUDE.md permanently)
  • In a nested CLAUDE.md that hasn't reloaded yet

Debugging CLAUDE.md issues

Check which files loaded

Run /context in a session and look under Memory files. This lists all CLAUDE.md and CLAUDE.local.md files discovered.

Claude isn't following CLAUDE.md

  • Check /context to confirm the file loaded
  • Check the file location (make sure it's in one of the recognized paths)
  • Make instructions more specific: "Use 2-space indentation" is more effective than "format code nicely"
  • Look for conflicting instructions: if two CLAUDE.md files give different guidance, Claude may pick one arbitrarily
  • Use /memory to edit the file if you find errors

My CLAUDE.md is too large

  • Target under 200 lines per file
  • Use path-scoped rules in .claude/rules/ to load instructions only for specific file patterns
  • Remove entries that are discoverable from the codebase itself (directory listings, dependency lists)
  • Keep pitfalls, rationale, and conventions that differ from tool defaults

The /doctor checkup can suggest trims (Claude Code v2.1.206+).

Worked example: setting up CLAUDE.md for a backend API project

---
---

# TemplateAPI CLAUDE.md

## Build and runtime

- **Language:** Python 3.11+
- **Package manager:** uv (`uv sync` to install, `uv pip list` to verify)
- **Framework:** FastAPI with Pydantic v2
- **Database:** PostgreSQL via SQLAlchemy ORM
- **Test framework:** pytest

Build and run:
```bash
uv run uvicorn app.main:app --reload  # dev server on localhost:8000
uv run pytest                          # run all tests
uv run pytest -xvs tests/test_auth.py # run one test file

Project structure

app/
├── main.py           # Application entry point, route registration
├── models/           # SQLAlchemy ORM models
├── schemas/          # Pydantic request/response models
├── routers/          # Route handlers organized by domain
├── middleware/       # Custom middleware (auth, logging, etc.)
├── db/               # Database setup and utilities
└── config.py         # Configuration (environment-based)

tests/
├── conftest.py       # pytest fixtures and setup
├── test_auth.py
├── test_api.py
└── test_db.py

Code standards

  • Type hints: All functions have type hints, including return types
  • Docstrings: Use Google-style docstrings for all public functions
  • Error handling: Raise HTTPException for API errors with status and detail
  • Database: Always use async context managers for sessions; never commit directly

Example function:

async def create_user(name: str, email: str) -> UserSchema:
    """Create a new user and return the created record.

    Args:
        name: User's full name
        email: User's email address

    Returns:
        UserSchema with the created user data

    Raises:
        HTTPException(400) if email already exists
    """

Common operations

  • Run migrations: alembic upgrade head
  • Create migration: alembic revision --autogenerate -m "message"
  • Reset test DB: uv run pytest --resetdb
  • Check types: uv run mypy app/

Important: Do not edit

  • alembic/versions/ — Migration files are version-controlled and immutable
  • pyproject.toml — Dependency list managed by ops team; propose changes in #infra

When to call Claude in this project

  1. Bug fix: Describe the error and expected behavior. Claude will debug and fix.
  2. New API endpoint: Describe the request/response shape and business logic. Claude will implement with full test coverage.
  3. Refactoring: Point out the code and the goal. Claude will refactor and re-run tests to verify.

This CLAUDE.md is dense with factual, actionable information. When Claude starts working on this codebase, it knows the exact build commands, project structure, coding standards, and constraints without asking.

## Common mistake

Writing too much procedural detail in CLAUDE.md. CLAUDE.md is for standing facts and conventions, not step-by-step guides. If you find yourself writing numbered multi-step procedures, move that to a skill or a docs file instead. CLAUDE.md should be scannable and quick to reference, not a manual.

Sources and license context

These references informed the lesson. ToolDix adds its own explanation, workflow, and practice rather than reproducing source material. Every link below leaves ToolDix and opens the publisher's own site in a new tab.

Keep going

Read these next on ToolDix.

Original lessons that build on what you just read.