Memory — Stop Repeating Yourself
Cross-session context without re-explaining
Count how many times this week you explained something to Claude that you've explained before. "Our auth works like this…" "Billing is separate from users because…" "That legacy folder doesn't match the rest of the codebase — don't touch it…" Every one of those is an annoyance tax you pay for not having wired up.
Memory is a folder in your repo (memory/) plus a convention for writing per-feature notes that Claude reads on its own when it notices the matching feature. This chapter wires it up in 15 minutes and saves you hours per week forever.
You'll have a memory/ directory in your repo, an index file, and at least one project_<feature>.md memo for the ONE feature you re-explain to Claude most often. CLAUDE.md will be wired to point at it. Then you'll cold-start a session and watch Claude pick up the context without you saying a word.
Memory is the WHY behind your code
tells Claude what rules to follow. tells Claude what history to respect. When a repo has weird-looking code that's weird for a good reason — because of an incident you had, a compliance requirement, a bug Stripe has that you work around — memory is where that story lives.
The pattern is a memory/ directory with two kinds of files. One is a MEMORY.md index — a table of contents that tells Claude what memos exist. The rest are project_<feature>.md files — one memo per feature, each capturing status, invariants, key files, and gotchas.
With memory wired up, Claude stops asking you "wait, how does X work?" and starts saying "I see from memory/project_X.md that you soft-delete — I'll do the same." That's the whole payoff.
Three steps. Create the folder, write an index, write your first memo. It takes about 10 minutes if you already know the feature you're documenting.
Create memory/ at your repo root
mkdir memory
Write an index file at memory/MEMORY.md
The index is a table of contents. One line per memo. The index doesn't carry the detail — it just helps Claude (and you) find the right memo fast.
# MEMORY.md Index of per-feature memory files. Each memo below captures architectural decisions, invariants, gotchas, and the WHY behind non-obvious code in that feature. READ the relevant memo before touching its feature directory. ## Features - [project_auth.md](./project_auth.md) — magic-link auth, session handling, Supabase RLS gotchas - [project_billing.md](./project_billing.md) — Stripe subscriptions, tier downgrades, proration, webhook ordering - [project_ai_pipeline.md](./project_ai_pipeline.md) — prompt loading, retry logic, cost tracking, cached system prompts ## Cross-cutting - [architecture.md](./architecture.md) — repo structure, folder responsibilities, why things live where they do - [deployment.md](./deployment.md) — CI/CD, rollback, on-call runbook
Don't worry if not every memo exists yet — an index entry is a promise, not a requirement. Write the memos as you need them.
Write your first project_<feature>.md
Here's the skeleton every feature memo should follow. Five sections, no exceptions. Consistency matters — Claude reads fastest when every memo looks the same.
# project_<feature>.md ## Status <one line — e.g. "in production since 2025-11", "in progress D3/5", "deprecated — being replaced by X"> ## Why this feature exists <1–3 sentences. The business or technical need. Not "what it does" — "what would be broken if we didn't have this".> ## Core invariants What must ALWAYS be true about this feature, regardless of how the code evolves: - <invariant 1 — e.g. "a cancelled subscription can never lose user data"> - <invariant 2> - <invariant 3> ## Key files - `src/<path>` — <one line on what lives here> - `src/<path>` — <...> - `src/<path>` — <...> ## Known gotchas Non-obvious things that bit us once. If Claude trips on these, the fix is to update this section — not to add a code comment. - <gotcha 1 — e.g. "Stripe webhooks arrive out of order; we reconcile by event timestamp, not arrival order"> - <gotcha 2> ## Related features - See also: [project_<other-feature>.md](./project_<other-feature>.md)
Here's the auth memo filled in for a typical -backed app. Notice how every gotcha is something that cost real debugging time — not hypothetical "maybe this could happen" musings. That's the bar.
# project_auth.md ## Status Shipped 2025-09. ~8k monthly active users. ## Why this feature exists Magic-link auth (not password) because our audience is non-technical creators and password friction measurably tanked activation by 40% in early testing. ## Core invariants - A session must never outlive 30 days. Refresh or re-auth. - Failed login attempts are never user-visible as distinct errors — always "invalid link" to prevent enumeration. - Admin users have a separate auth path; never mix with public auth. ## Key files - `src/lib/auth/client.ts` — Supabase auth client (singleton) - `src/app/auth/callback/route.ts` — magic-link callback handler - `src/middleware.ts` — session check on every request - `supabase/migrations/*_auth_*.sql` — RLS policies ## Known gotchas - Session cookies are SET on /auth/callback but READ via middleware. If middleware config excludes /auth/callback, you get a login loop. - Supabase RLS on `public.profiles` uses `auth.uid()`. We mirror new users into `profiles` via a trigger — if the trigger fails silently, users appear logged in but have no profile row. - Magic-link tokens expire in 15 min server-side but the UI doesn't know. Resend button shows even when already valid. ## Related features - See also: [project_billing.md](./project_billing.md) — billing identity is linked to auth user id; deletion cascades.
Memory files are useless if Claude doesn't know to read them. Add a pointer in your — a short section telling Claude to check memory before touching feature code.
## Memory See `memory/MEMORY.md` for per-feature context. READ the matching `project_<feature>.md` before touching a feature directory — architectural invariants and known gotchas live there.
Now test it. Close any open Claude session, cdinto a directory related to the feature you wrote a memo for, and ask Claude to make a small change there. You'll see it reference specifics from your memo — the invariants, the gotchas, the file-by-file map — without you typing any of it. That's the payoff.
From information to enforcement
You now have four of the five primitives wired up: rules (CLAUDE.md), recipes (skills), rituals (commands), and history (memory). Between them, they cover everything Claude should know.
Chapter 7 is the last of the five: . Unlike everything we've done so far, hooks aren't suggestions Claude might follow — they're hard walls at the operating-system level. If a hook says "no writes to migrations/without confirmation," Claude literally cannot do that write, no matter what you or it ask for. That's the chapter where you stop trusting Claude's good intentions and start putting guardrails around the filesystem.