Unwait

Claude Code memory: CLAUDE.md, rules, and the notes Claude keeps on you

· 8 min read claude code memory claude.md rules workflow

Most people know CLAUDE.md and stop there. The memory system has three layers, and the two you are probably ignoring are the ones that fix a bloated CLAUDE.md and explain why your instructions get followed only sometimes. Load order, path-scoped rules, auto memory, and what actually enforces anything.

Every Claude Code session starts with an empty context window, so everything the agent knows about your project on turn one came from a file. Most developers know one of those files. There are three layers, and the two people skip are the ones that solve the problems they complain about most: a CLAUDE.md that has grown too big to be followed, and instructions that get obeyed only sometimes.

Here is the whole map, with the operating advice that comes from running these files daily rather than from reading the reference once.

The three layers

  1. CLAUDE.md files: instructions you write, loaded into every session.
  2. .claude/rules/: instructions you write that load only when Claude touches matching files.
  3. Auto memory: notes Claude writes about your corrections and preferences, saved between sessions.

The first is context you always pay for. The second is context you pay for only when it is relevant. The third is written by the agent, not you, and most people have never opened it.

Layer 1: CLAUDE.md and where it lives

Four locations, listed broadest to most specific, which is also load order:

Scope Path For
Managed policy /Library/Application Support/ClaudeCode/CLAUDE.md (macOS), /etc/claude-code/CLAUDE.md (Linux, WSL) Org-wide rules, cannot be excluded by users
User ~/.claude/CLAUDE.md You, across all projects
Project ./CLAUDE.md or ./.claude/CLAUDE.md The team, via version control
Local ./CLAUDE.local.md You, this project only. Gitignore it

They concatenate, they do not override. Claude Code loads every CLAUDE.md from the filesystem root down to your working directory, so a parent directory's file appears before the one where you launched, and within a directory CLAUDE.local.md is appended after CLAUDE.md. Files in subdirectories below your working directory are different: they load on demand, when Claude reads a file in that directory. That is what makes per-package instructions work in a monorepo.

To check what actually loaded, run /context and look under Memory files. If a file is not in that list, Claude cannot see it, and no amount of rewording will help.

What earns a line

The test we use: facts go in CLAUDE.md, procedures go in a skill. "The dev bundle id is com.example.dev" is a fact the agent needs every session. "How we publish a release" is a nine-step procedure that matters twice a month, and it belongs in a skill that loads only when invoked.

Beyond that, the guidance that matches our experience:

/init generates a starting file by reading your codebase, and /doctor will propose trims, cutting the parts Claude can derive from the code (directory layouts, dependency lists) and keeping the pitfalls and conventions it cannot.

Imports, and the trap in them

CLAUDE.md can pull in other files with @path/to/file, relative to the file doing the importing, recursively up to four hops. Two things to know:

Imports do not save context. Everything imported loads at launch, same as if you pasted it. Splitting a 400-line file into four imports organizes it and changes nothing about the token cost. The thing that actually reduces context is layer 2 below.

To mention a path without importing it, wrap it in backticks. Import parsing skips code spans and fenced blocks, so `@README` stays literal while @README pulls the file in.

Two practical uses. If your repo already has AGENTS.md for other agents, do not duplicate it: a CLAUDE.md containing @AGENTS.md plus any Claude-specific lines keeps one source of truth. And if you work in git worktrees, remember that a gitignored CLAUDE.local.md exists only in the worktree where you made it; import @~/.claude/my-project-instructions.md instead so your personal notes follow you across all of them. Note that a project file importing something outside the working directory triggers a one-time approval dialog, which exists because a shared repo can otherwise point at files you never reviewed.

Layer 2: .claude/rules/, the fix for a bloated CLAUDE.md

This is the underused one. Put markdown files in .claude/rules/, one topic each, discovered recursively. Rules without frontmatter load at launch like project CLAUDE.md. Rules with a paths field load only when Claude works with matching files:

---
paths:
  - "src/api/**/*.ts"
---

# API rules

- Every endpoint validates input before touching the database.
- Errors use the standard error envelope, never a bare string.

That is the answer to "my CLAUDE.md is too long". Your API conventions do not need to sit in context while you edit CSS. Brace expansion works (src/**/*.{ts,tsx}), and there is a budget of 1,000 expanded patterns per rule, which you will not hit unless you write something pathological.

~/.claude/rules/ gives you the same thing at the personal level across every project, loaded before project rules so project rules win. And in a monorepo where other teams' files keep getting picked up, claudeMdExcludes in .claude/settings.local.json skips them by glob.

Layer 3: auto memory, the notes Claude keeps

Auto memory is on by default, and it is the layer most people have never looked at. As you work, Claude saves four kinds of note for itself:

It deliberately skips anything derivable from the codebase and anything your CLAUDE.md already says. Storage is ~/.claude/projects/<project>/memory/, keyed off the git repository, so every worktree of a repo shares one memory directory. It is machine-local and never synced.

The mechanics that matter:

Worth doing once: open that folder and read what has accumulated. In ours, the entries that earn their place are the ones no code could have told the agent, like a pricing change and a correction about verifying claims before publishing them. The entries that age badly are the ones naming a specific file or flag, because those get stale silently. When you audit, delete anything that reads like documentation and keep anything that reads like a lesson.

If you want something remembered right now, say so in the session ("remember that the API tests need a local Redis"); it lands in auto memory. If it belongs in the shared, committed rules instead, say "add this to CLAUDE.md" explicitly, because those are different destinations with different audiences.

The part that explains the frustration

CLAUDE.md is context, not enforcement. It arrives as a user message after the system prompt, and Claude tries to follow it with no guarantee of strict compliance. That single fact explains most "why does it ignore my rules" complaints, and it points at the fix:

Related, and reassuring: project-root CLAUDE.md survives /compact, because it gets re-read from disk and re-injected. If an instruction vanished after compaction, it was given only in conversation, which is the argument for writing it down in the first place.

Debugging checklist

  1. /context and read Memory files. Not listed, not loaded.
  2. /memory to open any of them, including files that do not exist yet.
  3. Look for a parent directory's CLAUDE.md contradicting your local one, and for a stale auto memory saying the opposite of a fresh rule.
  4. Over 200 lines? Move path-specific content into .claude/rules/ with paths, procedures into skills, and delete anything derivable from the code.
  5. Still not obeyed, and it must be? It is a hook, not a memory file.
  6. For deep debugging, the InstructionsLoaded hook logs exactly which instruction files loaded and when.

Our setup, for what it is worth

The user-level ~/.claude/CLAUDE.md holds one hard rule (never implement without explicit approval) and one standing exception for a toggle we run constantly. The project CLAUDE.md holds the things no one could derive: which build produces the dev instance and why testing with the real one corrupted real data, the pipeline's routing table, and the deploy rule. Procedures live in skills. Auto memory holds corrections we gave once and would rather not give again.

The result is boring, which is the point. Between them, a fresh session knows what a new teammate would need on day one, and nothing else.

Worth noticing, though: the agent now has a system for accumulating what it learns across sessions, and you probably do not. The stack you are working in changes monthly, and the things you look up for the fifth time are still going into a browser tab instead of anywhere durable. That asymmetry is why we build Unwait, which puts one flashcard in the gap while the agent works. The agent takes notes on you; it seems fair to take some back.

Unwait does this for you

A macOS menu bar app that watches your Claude Code and Codex sessions, shows a short card while they work, and puts a strip on screen the moment one finishes. Free for two weeks, no card and no sign up.

Try for free
← All posts