The Persistence of Memory

Agent memory files are configuration, not notes — and for the first time, the configuration writes itself.

I was working on a startup MVP I’m building with Claude, and we had drifted into a steady rhythm: Claude proposed a numbered backlog, I picked a task, and we worked through it. Halfway through, I typed “F14 — let’s generalize.” In my head, this was an invitation: which one next, and tell me how you’d approach it. Claude, with its usual eagerness, took it as a green light and started coding.

I interrupted, mildly annoyed. In the same chat, for a different feature, I had written “F3b — show me the current uses again before you start.” Claude had handled F3b correctly: surveyed the call sites, showed me the result, waited. For F14, it had jumped straight to code. Two requests, structurally the same intent — pause, produce non-code output, wait for me to say go — but only one of the two phrasings was explicit enough for Claude to catch it. It had understood “Let’s X” as “go.” What I had been pushing for all that week was a more deliberate sequence — state the choice, ask for the approach, wait for the go-ahead. Claude had pattern-matched the wrong way.

After the correction, Claude wrote a memory file — one of the small markdown files that Claude Code keeps in a per-project directory — titled “‘Let’s X’ is a direction, not a go-signal.” The body explained the rule, the reasoning, and the kinds of phrases that are go-signals — “do it”, “proceed”, “go ahead”. I had never asked it to do this. The next time I typed “let’s”, Claude paused and asked, and the rule has held for months.

It took me a moment to register how strange this was. I had been working with LLMs the way we always worked with compilers, and not much better than folks used to work with punch cards: issue an instruction, watch the output, retype if it came out wrong. The corrections were a per-turn cost, paid every time. I had seen Claude’s memory files before, but had taken them for the agent’s own housekeeping — not appreciated, until this moment, that they were where my corrections were being quietly preserved, with surprising leverage.

Claude Code’s memory works in the plainest possible way. As you work, the agent writes markdown files — one for each useful thing it has learned: something about you (your role, what you find irritating), something about the project (which test command to use, which packages live where), or, most importantly, a correction you handed it earlier and would prefer not to hand it again. Each file has a name, a one-line description, and a few paragraphs of prose. They persist across sessions, loading themselves into the agent’s context the next time you start a session.

The natural reaction, when you first notice these files, is to read them as notes — the agent’s journal of what it learned that day. That’s not wrong, but it misses what these files really are. They are configuration, not notes. When you correct the agent once, and the correction is quietly written to memory, it becomes a standing rule that applies on its own the next time around. It’s more like writing a config file than chatting with the agent.

The F14 correction was a particularly successful example. The rule eventually graduated: it became one line in my project’s CLAUDE.md, and from there into my /start-task slash command — the one I described in The Slash Command That Knew Too Much. What started as a midstream correction became part of the standing protocol for every new session.

Few rules graduate that far; most are smaller, and over time, the memory directory becomes a roadmap to where I’ve been sloppy in my instructions to the LLM.

Looking through one project’s memory directory, here is a sampling. One file came from the day I watched the agent run make lint five times in a debugging loop, and captures the rule: redirect the lint output to a file once, then grep the file. Another, “Don’t patch the environment to work around dependency issues,” was written after I caught the agent typing “uv pip install babel” to recover from a failed import. (“What are you doing? Why are you installing new tooling?” was my line that ended that approach.) A third is just a one-liner: the backend auto-restarts on file changes, so the agent should not restart it manually.

Not every correction belongs in a memory. The test I’ve settled on, after some misfires, is whether I would want the rule to apply in future sessions, in different code on a different day — if yes, it is configuration; if not, it belongs in the conversation and nowhere else.

There’s one failure mode worth flagging. The agent writes most of these files unbidden, which is most of the magic — but also a small risk. One time, the agent slipped in a constraint I had never actually requested into a planning document: a defensive-sounding bit of privacy posturing that looked like my policy, but that Claude had invented while drafting. I caught the constraint before it steered any real decision, but only just barely.

The memory file is yours. The agent helps you write it, but every once in a while, you should read it like a config file you actually own.

Configuration itself is not a novel idea. Over the years, I’ve written many thousands of lines of configuration files: dotfiles, batch files, yaml manifests, Makefiles, JSON configs, and a dozen other formats that I’ve since forgotten. A few of them have gotten complicated enough that I’ve even started using LLM tools to clear out the detritus, but that’s a story for another post. The habit underneath is the same one every programmer learns early: you notice you’re typing the same mini-task every morning. So, you write it once into the appropriate config file, and never think about it again — a small, lasting joy. Carpenters measure twice and cut once. Programmers type twice and configure once.

There is one thing here that is truly new and worth emphasizing. My shell never decided, on its own, to add an alias because it noticed I kept typing one. My editor never wrote a new keybinding into its init file because I’d had to reach for the same command three times that morning. Claude does. The configuration target — the agent — is also the one writing the configuration, in response to me, while I work. I’m not yet certain of all the implications of what this means in the long run. But it’s clear that the analogies to older tools only reach so far.

What I have now, written in plain English in a simple markdown file, is a quiet but real shift in what configuration means for programmers. The instinct is old. The partner is new.

Also on Medium·All essays

Contact

Tell me what you’re building.

deg@degel.com