AXME Code · 5 min read

CLAUDE.md Is a Read-Only File. Your Coding Agent Needs Writable Memory.

Everyone puts project context in CLAUDE.md. It's static, it grows, nobody maintains it, and it becomes a graveyard of stale rules. Writable memory with an audit trail is a different shape of solution.

CLAUDE.md is the standard place to give Claude Code project context. A markdown file at the root of your repo, read by the agent on session start, containing things you want the agent to know. Most teams use it. Most teams also, after a few weeks, realize it has a ceiling.

The ceiling is structural. It is not a matter of writing a better CLAUDE.md. It is that CLAUDE.md, by its shape, is the wrong tool for the job it is being asked to do.

Let me explain what I mean.

What CLAUDE.md does well

CLAUDE.md is a static document. You write it once, check it into the repo, and it’s loaded automatically at the start of every session. For simple cases, this is perfect:

  • Stack: “We use TypeScript, Postgres, Astro.”
  • Entry points: “Main server is in server/index.ts.”
  • Test command: “Run tests with npm test.”
  • Deploy: “Deploy via GitHub Actions, never direct.”

These are facts about your project that don’t change often. A static file is a fine place for them. The agent reads the file, learns the facts, applies them during the session.

This works for about two weeks.

What breaks

After two weeks of real use, CLAUDE.md starts to rot. Here is the sequence.

Week 1: 10 lines. Clean. Everything relevant is there.

Week 2: 25 lines. You add your naming conventions, the fact that you use pnpm not npm, the three deprecated files nobody should touch. Still fine.

Week 3: 60 lines. You add a section on the new auth refactor. You add a note that Joi was replaced with Zod (but the old Joi types are still referenced in two places, so it’s complicated). You add that feature flags live in config/flags.ts unless they’re UI flags in which case they live in frontend/flags.ts.

Week 5: 120 lines. You notice that the agent is ignoring half of CLAUDE.md because the file is so long that the most important rules are buried. You reorganize with headings. You add a “TL;DR” at the top. You add a warning that some sections are outdated (you don’t remember which).

Week 8: 200+ lines. Multiple sections contradict each other. The “use Zod not Joi” rule is there, but so is a section written three weeks earlier about how to extend the legacy Joi schemas. Neither is wrong in isolation. Together they confuse the agent, which picks one at random on any given session.

This is the structural problem. CLAUDE.md is append-only in practice, but mutable in intent. You keep adding to it, but you don’t remove old stuff because you’re not sure if it’s still relevant, and you don’t edit old stuff because that requires re-reading and thinking carefully. Entropy wins.

The missing half: writable memory

The fix is not a better CLAUDE.md. The fix is to add a second thing alongside it, which is writable memory.

Writable memory means a store that the agent updates as the session goes, not just reads. Not “you wrote rules, the agent obeys them,” but “during the session, the agent writes new facts and the next session reads them.” The direction of writing is reversed.

Here’s what goes in writable memory:

  • Patterns the agent discovered: you corrected it, the correction becomes a memory. “User prefers async def over def for any handler that makes IO calls.”
  • Things you told it: you said “never use httpx.Client inside async handlers, it blocks the event loop.” That becomes a memory with a reason.
  • Observations about the codebase: the agent noticed that user_service.py and users.py both exist and users.py is legacy. That becomes a memory.
  • State from the previous session: you stopped mid-refactor. The handoff note lives in memory.

Writable memory is append-only, but with structure. Every entry has a timestamp and a source (session that created it). When an entry becomes wrong, you mark it obsolete, you don’t edit it. The history is preserved.

This is different from CLAUDE.md in three ways:

  1. Direction: agent writes, not just reads.
  2. Structure: each entry has metadata, so you can filter, expire, audit.
  3. Growth shape: memory grows by accretion of observations, not by accretion of hand-typed rules.

Why this is actually different

“Writable memory” could sound like just a fancy CLAUDE.md. It is not. Here is the test.

Imagine you finish a session. During the session, you corrected the agent five times. With CLAUDE.md, those corrections are gone the moment the session ends. To preserve them, you have to switch to another editor, open CLAUDE.md, remember what you said, write it down, save, commit. Five times.

Nobody does this. I tried. After a week I was editing CLAUDE.md once a day and it was still drifting from reality.

With writable memory, the corrections get captured automatically. An audit agent runs after the session ends, reads the transcript, extracts the corrections, writes them to a memory file. You do nothing. The next session starts with those corrections already loaded.

The difference is who is doing the writing. CLAUDE.md is written by you. Memory is written by the session itself. That is the structural difference, and it is the difference that makes maintenance feasible.

Decisions are their own category

There’s a subtle third thing that CLAUDE.md conflates, which is decisions.

A memory is an observation. “The user prefers Zod.” A decision is a commitment with a reason. “We decided to use Zod instead of Joi because Zod composes better with TypeScript types, 2025-09-12.”

Decisions deserve their own store. They have metadata that memories don’t: an enforce level (required vs advisory), a date, a rationale. When a decision is superseded, you mark it superseded, you don’t delete it. The history of “what did we decide and why” becomes a browseable log, not a tangle of lines in CLAUDE.md.

I wrote a whole separate post on this, so I won’t belabor it here. The key point: when you treat decisions as a separate data type, you can enforce them (“this command violates a required decision, refuse it”) in ways you can’t with a flat doc.

The minimum practical version

If you want to try this without installing anything, here is the minimal version:

  1. Create .memory/ in your repo root. Gitignored, or not, your call.
  2. After each session, spend one minute writing one line of what you learned: a correction, a pattern, a decision, a state note.
  3. At the start of the next session, tell the agent to read .memory/.
  4. Repeat for two weeks.

You will discover this is enough structure to beat CLAUDE.md for things that change. And then you will want automation for the “after each session” step, because you will forget to do it.

That automation is what AXME Code provides. It’s an MCP plugin that runs an audit agent at session close, extracts memories and decisions and safety rules from the transcript, and writes them to .axme-code/ in your repo. Next session, they’re loaded automatically.

But the tool is the implementation detail. The insight is the shape: static files don’t scale because they are read-only. Writable memory scales because the agent maintains it.

If you only take one thing from this post, take that.

More on AXME Code