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

CLAUDE.md Advanced Patterns: Monorepos, Hierarchies, and Auto Memory

Advanced CLAUDE.md techniques for large codebases, hierarchical structures, the .claude directory, auto memory management, and patterns for keeping instructions useful over time.

Advanced15 minBy ToolDix Editorial

Learning objectives

  • Design hierarchical CLAUDE.md files for monorepos and large codebases
  • Organize `.claude/rules/` with path-scoped and topic-scoped rules
  • Understand auto memory structure and how to manage it
  • Write rules and instructions that stay useful as code evolves
  • Use the `.claude` directory for skills, hooks, and agents

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.

Hierarchical CLAUDE.md in monorepos

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.

Monorepos and large projects benefit from layered CLAUDE.md files. Each team or subdirectory can maintain its own instructions, while organization-wide standards come from the root.

Directory structure with layered instructions

my-monorepo/
├── CLAUDE.md                    # Organization standards, shared conventions
├── .claude/
│   ├── rules/
│   │   ├── naming.md            # Naming conventions (applies everywhere)
│   │   ├── testing.md           # Testing approach (applies everywhere)
│   │   └── frontend/
│   │       └── react.md         # React-specific (paths: src/web/**)
│   │       └── styling.md       # Styling (paths: src/web/**/styles/**)
│   │   └── backend/
│   │       └── api-design.md    # API conventions (paths: src/api/**)
│   │       └── database.md      # Database patterns (paths: src/db/**)
├── src/
│   ├── web/
│   │   └── CLAUDE.md            # Frontend team instructions
│   │   └── src/
│   │       └── CLAUDE.local.md  # Your personal frontend prefs
│   ├── api/
│   │   └── CLAUDE.md            # Backend team instructions
│   │   └── internal/
│   │       └── CLAUDE.md        # Specific submodule instructions

The load order is: root CLAUDE.md, then user CLAUDE.md, then parent directories walking down. This means:

  1. Organization-wide standards load first
  2. Your personal preferences load second
  3. Each team/subdirectory can override with their own instructions
  4. The most specific instructions (closest to your cwd) load last and take precedence

Excluding irrelevant CLAUDE.md files

In a monorepo, you might load instructions from other teams that aren't relevant to your work. Use claudeMdExcludes in .claude/settings.local.json to skip them:

{
  "claudeMdExcludes": [
    "**/monorepo/CLAUDE.md",
    "*/other-team/.claude/rules/**",
    "*/infrastructure/CLAUDE.md"
  ]
}

Patterns are matched against absolute file paths using glob syntax. Managed policy CLAUDE.md files cannot be excluded.

Path-scoped rules in .claude/rules/

Path-scoped rules load instructions only when Claude reads matching files, reducing noise and saving context.

Directory structure for rules

.claude/rules/
├── code-style.md          # Loads always (no paths field)
├── testing.md             # Loads always
├── security.md            # Loads always
├── frontend/
│   ├── react.md           # Loads when Claude reads src/web/**
│   ├── styling.md         # Loads when Claude reads src/**/*.css
│   └── accessibility.md   # Loads when Claude reads a11y-related files
├── backend/
│   ├── api-design.md      # Loads when Claude reads src/api/**
│   └── database.md        # Loads when Claude reads src/db/**
└── infrastructure/
    ├── terraform.md       # Loads when Claude reads terraform/**
    └── docker.md          # Loads when Claude reads Dockerfile or docker-compose*

Rule file format with path frontmatter

---
paths:
  - "src/web/**/*.tsx"
  - "src/web/**/*.css"
---

# Frontend Development Rules

## React best practices

- Always use functional components with hooks
- Use `useState` for component state, `useContext` for shared state
- Memoize expensive computations with `useMemo`
- Avoid prop drilling; lift state or use context

## CSS guidelines

- Use CSS Modules (`style.module.css`) for component-scoped styles
- Global styles in `src/styles/globals.css` only
- Follow BEM naming: `block__element--modifier`
- Never use `!important`

## Testing

- Test user interactions, not implementation
- Use React Testing Library (`render`, `screen`, `userEvent`)
- Aim for >80% coverage on components

Rules without a paths field load unconditionally and apply globally. Rules with paths trigger only when Claude reads matching files.

The .claude directory structure

The .claude/ directory holds all Claude Code configuration and customization:

.claude/
├── CLAUDE.md                 # Project-level instructions (alt location: ./CLAUDE.md)
├── settings.json             # Shared project settings
├── settings.local.json       # Your personal project settings
├── rules/                    # Path-scoped and topic-scoped rule files
│   ├── code-style.md
│   ├── testing.md
│   └── api/
│       └── conventions.md
├── skills/                   # Reusable task-specific skills
│   ├── run-full-test-suite.md
│   ├── audit-dependencies.md
│   └── prepare-release.md
├── agents/                   # Subagent definitions
│   ├── code-reviewer.md
│   └── infrastructure.md
├── hooks/                    # Lifecycle hooks (bash scripts)
│   ├── pre-commit.sh
│   └── on-error.sh
├── worktrees/                # Git worktree state (auto-managed)
│   └── feature-branch/
├── mcp.json                  # MCP server configuration (if used)
└── claude.json               # Legacy config (for other tools compatibility)

What lives in each subdirectory

rules/ — Markdown files with path-scoped instructions. Load on demand when Claude reads matching files. Organize by domain (frontend, backend, infrastructure).

skills/ — Reusable workflows that Claude activates on demand. One file per skill. Use when a task is multi-step and doesn't need to be in context all the time.

---
name: "Run full test suite"
description: "Run all unit, integration, and e2e tests with coverage report"
---

# Run Full Test Suite

Run:
```bash
npm run test:unit && npm run test:integration && npm run test:e2e
npm run test:coverage
```

Wait for all tests to pass. If any fail, investigate and fix.

agents/ — Subagent definitions. Each file defines a specialized agent for a specific task. See subagents documentation for format.

hooks/ — Shell scripts that run at lifecycle events. Examples:

  • pre-commit.sh — Run lints and tests before Claude commits
  • on-error.sh — Log errors or alert when things fail
  • post-plan.sh — Custom validation after Claude writes a plan

Auto memory structure and management

Auto memory is where Claude saves learnings automatically. It lives in ~/.claude/projects/<project>/memory/:

~/.claude/projects/<project>/memory/
├── MEMORY.md           # Index (first 200 lines or 25KB loaded at start)
├── debugging.md        # Detailed debugging notes
├── api-conventions.md  # API design decisions
├── build-tricks.md     # Build system insights
├── performance.md      # Performance bottlenecks and solutions
└── testing.md          # Test patterns and common failures

MEMORY.md index structure

Keep MEMORY.md concise. It acts as an index. Claude scans it to understand what's stored and where:

# Auto Memory Index

## Build & Environment
- Node 18+ required (see building.md)
- npm workspace monorepo with two main packages
- Build outputs to dist/ via tsup

## API Design
- RESTful endpoints, see api-conventions.md
- Always return 200 or 4xx/5xx, never success with 5xx status
- Standard error shape: `{ error: { code, message, details } }`

## Common Failures
- Auth tests fail if Redis cache isn't flushed before run
- DB migrations must run in order; skipping breaks later ones
- ESM vs CJS mismatch in dependencies causes `__dirname` errors

## Performance
- Image resizing is bottleneck; cache aggressively (see performance.md)
- Database queries N+1 in user list endpoint; needs fix

The first 200 lines or 25KB of MEMORY.md are loaded at session start. Content beyond that threshold is available but not auto-loaded. Detailed notes go in topic files.

Auto memory file limits

When Claude writes to MEMORY.md, Claude Code measures the file. If it's near the 200-line or 25KB limit, Claude Code reminds Claude to shorten it:

  • Keep one line per entry
  • Move detail into topic files
  • Merge or drop stale entries

If MEMORY.md exceeds the limit, the write still succeeds, but Claude Code returns an error telling Claude to rewrite it because everything past the limit won't load next time.

(Requires Claude Code v2.1.210+)

Auditing and editing auto memory

Run /memory in a session to browse auto memory files. You can open and edit them directly. Delete stale entries or files you no longer need. Auto memory is plain markdown; treat it like any other documentation.

Authoring patterns for evergreen instructions

As your codebase evolves, CLAUDE.md and rules can become outdated. Use these patterns to keep them useful:

Write facts, not procedures

Good: "Build system: tsup (see package.json build scripts)" Bad: "To build, open a terminal, type npm run build, wait for it to finish, then check dist/"

Facts are stable across sessions. Procedures need updates every time the process changes.

Instead of duplicating setup steps, reference your real docs:

## Setup

See [CONTRIBUTING.md](CONTRIBUTING.md) for full setup steps. Summary:

- Node 18+ with `nvm install`
- `npm install` to install dependencies
- `.env.example` to `.env` and fill in values

This way, if setup changes, you only edit CONTRIBUTING.md once.

Use @import for evolving docs

Instead of copying and pasting architecture documentation, import it:

# Project Architecture

@docs/architecture.md

## Team-specific tweaks

- Frontend team: never modify cache in src/lib/cache.ts directly

If architecture changes, the imported file is the source of truth.

Mark deprecations with dates

## Authentication (v2 - current)

Use OIDC with Okta. See src/auth/okta.ts.

## Legacy: Session-based auth (deprecated 2024-11, remove 2025-Q2)

Old code using express-session is in src/auth/legacy/. Do not use for new features.

This tells Claude what's deprecated and when it's safe to remove.

Scope instructions to implementation, not goals

Good: "Use the verifyEmail function from src/auth/verify.ts; it's already idempotent and tested." Bad: "Make sure emails are verified" (too vague, Claude might invent a solution)

Point Claude to the actual implementation so it uses what's there.

Advanced example: a real monorepo CLAUDE.md setup

my-platform/
├── CLAUDE.md                    # Root organization standards

Root CLAUDE.md contents:
```markdown
# My Platform — Organization Standards

## Teams and codebases

This monorepo has two main teams:

- **Frontend** (`src/web/`) — React, TypeScript, Vite
- **Backend** (`src/api/`) — Python, FastAPI, SQLAlchemy

Each team has its own CLAUDE.md with specific standards.

## Shared standards

### Git workflow

- Branch naming: `feature/X`, `fix/X`, `refactor/X`
- Commit messages: "Brief summary; more detail if needed"
- Always pull before pushing; never force push
- Small commits (one feature per commit); large commits hard to review

### Testing

- All new code requires tests
- Tests live colocated: `src/feature/feature.test.ts` not in separate `/tests/` folder
- Run `npm run test` before committing

### Code review

- All PRs require review from another team member
- Reviews use our PR template (GitHub will auto-fill)
- Feedback is about code, not the person

├── .claude/ │ ├── rules/ │ │ ├── naming.md # Global naming conventions │ │ ├── error-handling.md # Error handling patterns │ │ ├── frontend/ │ │ │ ├── react.md # React rules (paths: src/web/) │ │ │ └── styling.md # CSS rules (paths: src/web//*.css) │ │ └── backend/ │ │ ├── api.md # API design (paths: src/api/) │ │ └── database.md # DB patterns (paths: src/db/)

├── src/ │ ├── web/ │ │ └── CLAUDE.md # Frontend team: build, test, structure │ ├── api/ │ │ └── CLAUDE.md # Backend team: Python version, dependencies, structure

When Claude Code starts in src/web/, it loads:

  1. Organization standards (root CLAUDE.md)
  2. User preferences (~/.claude/CLAUDE.md)
  3. Frontend team standards (src/web/CLAUDE.md)
  4. Path-scoped rules from .claude/rules/ as it reads files

This setup ensures:
- Organization standards apply everywhere
- Each team has freedom to define its own approach
- Rules load on-demand based on what Claude reads
- No conflicting instructions (the most specific one wins)

## Common mistake

Writing overly detailed "rules" for code style in CLAUDE.md when the codebase already has a linter configured. Linters enforce style automatically; CLAUDE.md should focus on patterns that aren't caught by linters: architectural decisions, naming conventions, when to use which library, common pitfalls. Let the linter handle "use 2-space indents" and use CLAUDE.md for "use React Context, not Redux, for this codebase."

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.