Yesterday's session ruled out one library, agreed where a folder of shared code should live, and left a database change half finished. Today Claude Code opens cold. It proposes the ruled-out library, creates a second folder for the same thing, and cannot say which half of the change exists.

None of that was an accident or a bug. Those three decisions only ever existed inside a conversation, and a conversation is not a place things are kept.

The idea

A session's is assembled fresh every time, so whatever the next session needs to know has to be readable from disk. Durable project memory is a small set of plain files that answer four questions: how this project works, what was decided and why, what is true right now, and what to do first on resuming. Everything else stays in the conversation and is allowed to disappear.

MemoryThe question it answersWritten byShape that works
InstructionsHow does this project work?You, deliberatelyShort, specific, verifiable rules
DecisionsWhy is it this way?You, when a choice sticksDate, choice, consequence
ProgressWhat is true right now?Whoever finishes a sessionDone, active, next
HandoffWhere do I start?The session that stopsEntry file plus the check to run

How it works

The instruction file is the one every tool has. Claude Code reads CLAUDE.md at the start of every session; Cursor and several other agents read an equivalent, commonly AGENTS.md. Anthropic's memory documentation describes two systems: instruction files you write, and an automatic memory Claude Code keeps from your corrections and preferences. Your instruction file loads at the start of the session along with a short index of that automatic memory; the memory's detail is filed by topic and fetched only when the topic comes up. Nothing here remembers you. Something loads a file.

Loaded and obeyed are different states. The same documentation says these files are context rather than enforced configuration, with no guarantee of strict compliance, and that two contradicting instructions may be resolved arbitrarily. For something that must happen at a fixed moment every time, the documented answer is a that runs as a script.

Length is the failure everyone walks into. Anthropic targets under 200 lines per instruction file and offers a test worth stealing for each line: would removing it cause a mistake? If not, cut it. That rules out anything the model can work out by reading the code.

One fact needs one owner. If the active task appears in a plan, a progress file and a README, the copies drift and a cold session cannot tell which is current.

What to do

  1. Move a rule into CLAUDE.md the second time you type it into chat, and delete one whenever you add one past about thirty lines. The file only works while it is short, so treat it as a fixed budget rather than a growing pile. A real one is smaller than people expect:

    markdown
    # CLAUDE.md
    
    Next.js 15 app, Postgres via Supabase. Run everything with pnpm.
    
    - Check: `pnpm build` and `pnpm test` before saying anything is done.
    - Money is stored in integer cents. Never floats.
    - Server-only code goes in src/server/. Never import it from a component.
    - Migrations are forward-only. Do not edit one that already ran.
  2. Record a decision when it changes what the next session should do, one file per decision under docs/decisions/, named so the order is obvious (0007-email-provider.md). Write the consequence, not only the conclusion: "Chose Resend over SES, 2026-03-04. No AWS account needed. The free tier caps at 3,000 a month, so a launch spike will bill."

  3. Keep one file answering "what is true right now" and "where do I start", in the four lines the previous section showed. The discipline is writing them at the end of a session, while you still know them, rather than reconstructing them at the start of the next one.

Where it breaks

Written memory is a second project, and it rots. A stale file does more damage than a missing one, because it is read with the same trust as a true one. Do not keep routine conversation, raw command output, or facts the code already states. If you cannot name a decision the file would change, it is notes rather than memory.

Files also do not enforce anything. A rule in CLAUDE.md changes the odds, which is why anything that has to be true every single time belongs in a hook, where it runs as a script instead of being read as advice.