Every Claude Code session starts with amnesia.
Your AI assistant does not remember the build command you corrected three times yesterday. It does not know your team uses 2-space indentation. It has no idea that src/api/handlers/ is where all your API routes live. Every session, you repeat yourself. Every session, you lose context.
CLAUDE.md files fix this. They give Claude Code persistent, structured memory that survives between sessions. Auto memory takes it further: Claude writes its own notes from your corrections, so you stop repeating yourself permanently.
Here are 5 patterns we use daily that turned Claude Code from a forgetful assistant into one that knows our codebase cold.
Pattern 1: The Project Foundation File
Every project needs a root CLAUDE.md. This is the single file Claude Code reads at the start of every session to understand your project.
Create CLAUDE.md in your project root (or .claude/CLAUDE.md if you prefer a cleaner directory):
# Project: my-api
## Build & Test
- Install: `npm install`
- Dev server: `npm run dev` (port 3000)
- Run tests: `npm test`
- Lint: `npm run lint -- --fix`
## Architecture
- API handlers live in `src/api/handlers/`
- Database models in `src/models/`
- Shared utilities in `src/lib/`
- All endpoints return JSON with `{ data, error, meta }` shape
## Coding Standards
- Use 2-space indentation
- Prefer `async/await` over `.then()` chains
- Every function has a JSDoc comment
- No default exports — use named exports only
## Common Workflows
- New endpoint: create handler in `src/api/handlers/`, add route in `src/routes.ts`, add tests in `tests/api/`
- Database migration: `npm run migrate:create <name>`, then `npm run migrate:up`
The key insight: specific beats vague. "Use 2-space indentation" works. "Format code properly" does not. Claude Code treats CLAUDE.md as context, not enforced configuration. The more concrete your instructions, the more consistently Claude follows them.
Run /init in any project and Claude Code analyzes your codebase and generates a starting CLAUDE.md automatically. It discovers build commands, test instructions, and project conventions from your existing code. Refine from there with instructions Claude would not discover on its own.
Keep it under 200 lines. Longer files consume more context tokens and reduce adherence. If your instructions outgrow a single file, Pattern 3 handles that.
Pattern 2: Personal Preferences That Follow You Everywhere
Your project CLAUDE.md covers team standards. But what about your personal workflow?
The user-level CLAUDE.md at ~/.claude/CLAUDE.md applies to every project on your machine. It travels with you across repositories without polluting team configurations.
# My Preferences
## Code Style
- I prefer explicit type annotations over inference
- Use descriptive variable names, not abbreviations
- Comments explain "why", not "what"
## Workflow
- Always show the `git diff` before committing
- Run tests after every file change
- When fixing a bug, write the test first
## Tools
- Use `pnpm` instead of `npm`
- Prefer `vitest` over `jest` for new projects
This file loads before project-level CLAUDE.md, so project rules take precedence when there is a conflict. Your personal preferences fill the gaps where the project does not have opinions.
User-level rules also work in ~/.claude/rules/. Drop markdown files like preferences.md or workflows.md there and they apply to every session, every project.
Pattern 3: Scoped Rules With .claude/rules/
A 200-line CLAUDE.md works for small projects. For larger codebases, you need modular instructions that load only when relevant.
The .claude/rules/ directory lets you split instructions into topic-specific files. Each file covers one concern. Files without path scoping load at every session start. Files with paths frontmatter load on demand when Claude works with matching files.
your-project/
├── .claude/
│ ├── CLAUDE.md # Core project instructions
│ └── rules/
│ ├── code-style.md # Loads every session
│ ├── testing.md # Loads every session
│ ├── api-design.md # Loads when working in src/api/
│ └── security.md # Loads when working with auth files
The power is in path-specific rules. Here is an api-design.md that only activates when Claude touches API files:
---
paths:
- "src/api/**/*.ts"
---
# API Development Rules
- All endpoints must validate input with Zod schemas
- Use the standard error response format from `src/lib/errors.ts`
- Include OpenAPI documentation comments on every handler
- Rate limiting middleware is required for all public endpoints
And a security rule that activates for authentication code:
---
paths:
- "src/auth/**/*"
- "src/middleware/auth*"
---
# Security Rules
- Never log tokens, passwords, or API keys
- All auth tokens expire after 24 hours
- Use `argon2` for password hashing, never `bcrypt`
- Session tokens must be cryptographically random (use `crypto.randomBytes`)
Path patterns use glob syntax. Common patterns:
| Pattern | Matches |
|---|---|
**/*.ts |
All TypeScript files in any directory |
src/**/* |
Everything under src/
|
*.md |
Markdown files in project root only |
src/components/*.tsx |
React components in one directory |
Multiple patterns work with brace expansion: "src/**/*.{ts,tsx}" matches both TypeScript and TSX files.
This pattern keeps your context lean. Claude Code only loads what it needs for the files it is working with. A 50-file rules directory costs zero tokens until Claude opens a matching file.
Pattern 4: Auto Memory — Let Claude Take Its Own Notes
CLAUDE.md files are instructions you write. Auto memory is the complement: notes Claude writes itself based on your corrections and preferences.
When you correct Claude — "use pnpm, not npm" or "the test database runs on port 5433" — Claude saves that to its auto memory directory at ~/.claude/projects/<project>/memory/. Next session, it remembers without you repeating it.
The structure:
~/.claude/projects/<project>/memory/
├── MEMORY.md # Index file, first 200 lines loaded every session
├── debugging.md # Detailed notes on debugging patterns
├── api-conventions.md # API design decisions Claude discovered
└── build-quirks.md # Build system gotchas Claude ran into
MEMORY.md acts as an index. Claude keeps it concise by moving detailed notes into separate topic files. Only the first 200 lines of MEMORY.md load at session start. Topic files load on demand when Claude needs them.
Auto memory requires Claude Code v2.1.59 or later. Check your version:
claude --version
To toggle auto memory, run /memory in any session and use the toggle, or set it in your project settings:
{
"autoMemoryEnabled": true
}
Run /memory any time to browse what Claude has saved. Everything is plain markdown you can read, edit, or delete. If Claude saved something wrong, fix it directly — the files are just text.
Auto memory is machine-local. All worktrees and subdirectories within the same git repository share one auto memory directory. It does not sync across machines.
The combination works: CLAUDE.md files set the rules. Auto memory captures the exceptions and discoveries. You write the standards. Claude learns the quirks.
Pattern 5: Import-Based Architecture for Large Projects
When your project spans multiple services, shared libraries, or complex build systems, a single CLAUDE.md and a rules directory may not be enough. The @import syntax lets you compose instructions from multiple files.
Reference any file using @path/to/file syntax in your CLAUDE.md:
See @README.md for project overview and @package.json for available commands.
# Development Guide
- Git workflow: @docs/git-workflow.md
- API conventions: @docs/api-conventions.md
- Deploy process: @docs/deploy.md
Imported files are expanded and loaded into context alongside the CLAUDE.md that references them. Both relative and absolute paths work. Relative paths resolve from the file containing the import, not the working directory.
Imports can chain recursively, up to 5 levels deep. This lets you build a tree of instructions:
CLAUDE.md
├── @docs/architecture.md
│ └── @docs/patterns/repository.md
├── @docs/api-conventions.md
└── @docs/testing.md
└── @docs/fixtures/README.md
For personal preferences you do not want to check in, import a file from your home directory:
# Team Standards
@docs/coding-standards.md
# My Personal Preferences (not committed)
@~/.claude/my-project-overrides.md
The import goes in the shared CLAUDE.md, but the file it points to stays on your machine. Team members who do not have that file simply skip the import.
For teams in monorepos where other teams' CLAUDE.md files get picked up, the claudeMdExcludes setting filters them out:
{
"claudeMdExcludes": [
"**/other-team/CLAUDE.md",
"/home/user/monorepo/legacy/.claude/rules/**"
]
}
Add this to .claude/settings.local.json so the exclusion stays local to your machine.
Putting It All Together
Here is the complete memory architecture for a production project:
my-project/
├── CLAUDE.md # Pattern 1: project foundation
├── .claude/
│ ├── settings.json # auto memory enabled
│ └── rules/
│ ├── code-style.md # Pattern 3: always loaded
│ ├── testing.md # Pattern 3: always loaded
│ ├── api-design.md # Pattern 3: path-scoped to src/api/
│ └── security.md # Pattern 3: path-scoped to src/auth/
├── docs/
│ ├── architecture.md # Pattern 5: imported by CLAUDE.md
│ └── deploy.md # Pattern 5: imported by CLAUDE.md
~/.claude/
├── CLAUDE.md # Pattern 2: personal preferences
└── rules/
├── preferences.md # Pattern 2: personal rules
└── workflows.md # Pattern 2: personal workflows
~/.claude/projects/<project>/memory/
├── MEMORY.md # Pattern 4: auto memory index
├── debugging.md # Pattern 4: Claude's own notes
└── build-quirks.md # Pattern 4: discovered quirks
The hierarchy resolves in order: managed policy (organization-wide) loads first, then user-level, then project-level. More specific locations take precedence. Path-scoped rules load on demand.
Three things to remember:
Specific instructions work. Vague ones do not. "Run
pytest -xbefore committing" beats "test your changes" every time.Keep CLAUDE.md under 200 lines. Use
.claude/rules/and@importsto split anything larger. Long files waste tokens and reduce adherence.Let auto memory handle the exceptions. You write the rules. Claude learns the quirks. Stop repeating yourself.
Follow @klement_gunndu for more Claude Code content. We're building in public.
Top comments (12)
Great article! Regarding Pattern 4 (Auto Memory), since Claude automatically takes notes based on corrections and debugging sessions, how can we prevent it from accidentally storing sensitive data (like API keys, OSINT targets, or specific environment variables) in the ~/.claude/projects//memory/ directory? Is there a recommended way to sanitize this memory or enforce a strict .claudesignore for the auto-memory feature?
Great question. Auto memory stores plain markdown in ~/.claude/projects//memory/ — you can audit and edit those files anytime via the /memory command. To prevent sensitive data capture, you can disable auto memory entirely with autoMemoryEnabled: false in your project settings (or CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 env var). For a middle ground, use autoMemoryDirectory to redirect storage to a location you audit regularly. There's no .claudeignore yet for auto memory specifically, but combining these settings with careful .gitignore rules keeps secrets out of version control even if they slip into memory files.
Thanks for the transparent and detailed answer! Using the CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 env var is exactly the clean workaround I need for my Linux setup right now. Looking forward to a native .claudeignore feature in the future.
Pattern 3 (scoped rules) is the one that made the biggest difference for me. I run a multilingual programmatic SEO site with 100k+ pages across 12 languages, and the codebase has very different conventions depending on which layer you're touching — the Astro templates, the data pipeline scripts, the content generation modules all have different patterns.
Before scoped rules I had one massive CLAUDE.md that was pushing 400+ lines and adherence was noticeably dropping. Splitting into path-scoped rules meant the content generation code gets its own conventions (output format, tone guidelines, SEO constraints) while the data pipeline gets completely different rules (error handling patterns, API rate limits, retry logic). Context stays lean and relevant.
One thing I'd add: if you're using CLAUDE.md for projects with scheduled tasks or agent-driven workflows, the "decision framework" pattern is incredibly useful. Instead of just listing coding standards, you can encode business logic like scoring criteria or prioritization rules. Claude reads those at session start and makes consistent decisions without you having to re-explain the reasoning every time.
The @import pattern is something I need to adopt though — currently duplicating some shared conventions across multiple rule files. That recursive chaining up to 5 levels deep is exactly what I need for the monorepo-style setup.
Your multilingual SEO setup is a perfect use case for scoped rules -- encoding scoring criteria and prioritization logic as decision frameworks is exactly how we use it too, keeps the agent consistent without re-explaining context every session.
Encoding scoring criteria and prioritization rules into CLAUDE.md is exactly the shift from "style guide" to "operating system" — glad scoped rules cut your 400-line monolith down. The import chaining should clean up those duplicate conventions fast.
Encoding business logic as scoring criteria in CLAUDE.md is effectively turning it into a lightweight policy engine — that's a pattern worth documenting. The @import chaining should clean up that cross-file duplication nicely.
I'm going to try this right now
Start with the role section pattern — takes 30 seconds to set up and the difference in output quality is noticeable right away. The real payoff comes from iterating on it daily: each time Claude misunderstands something, add a line. After a week it becomes a custom interface to how you think. Let me know which patterns click for your workflow.
Start with Pattern 1 (role definition) -- it takes 2 minutes to set up and you'll immediately notice more consistent output from your first prompt.
Start with Pattern 1 (project identity) — even three lines of context cuts the "explain this again" loop dramatically.
Start with Pattern 1 (the identity header) — it takes 30 seconds to add and you'll notice the difference in Claude's responses immediately.