A couple of days ago I ran ls on a directory I had never opened. It lives at ~/.claude/projects/, one folder per project, and inside the folder for this repo were twenty-nine Markdown files. Claude Code had written every one of them. About me. About how I work, which corrections I had made, which mistakes it did not want to repeat.
I hadn't asked for any of it. Auto-memory had started writing to that folder a couple of weeks earlier (the oldest file is dated May 14) while I worked. Twenty-nine here, thirty-five across all four of my projects on the machine, by the time I went looking.
Here is the part that should bother you. A third-party plugin that bolts a memory system onto Claude Code has tens of thousands of stars on GitHub. People are installing extra tooling to manage something the tool already does natively, and writes to plain files you can open in any editor. The feature is not the gap. The gap is that, in most of the discussion I have seen, almost no one has read what it writes.
So I read all of it.
Open a thread about Claude Code's memory and you land in one of two camps. The first treats it as a black box that quietly learns you, a tiny local fine-tune, and trusts it on that basis. The second read one leaked source-map breakdown, decided it was grep over a capped text file, and switched off. Both camps make the same error. They skip the step where you open the files and look.
As an agent memory layer, auto-memory isn't a brain that learns you, and it isn't a gimmick to disable. It is a context layer you govern, and how hard you govern it should scale with how much damage a wrong line can do. The blast radius sets the discipline. That is the whole argument of this post, and the best evidence for it is sitting in a folder on your own machine right now.
What auto-memory is, and where it lives
You cannot govern a layer you have not looked at, so start with what it is and where it physically sits. Auto-memory is Claude Code's answer to a problem the agentic development starter guide names directly: agents do not have perfect memory across long sessions. Context windows end. Start a new session tomorrow and yesterday's hard-won correction is gone, unless something wrote it down. Auto-memory is the something.
It shipped quietly, in two steps. Auto-memory behavior arrived in v2.1.32, whose changelog reads "Claude now automatically records and recalls memories as it works." The supported way to manage it came three weeks later in v2.1.59, the release that added the /memory command ("Claude automatically saves useful context to auto-memory. Manage with /memory"). There was no launch post on anthropic.com for either. At publication, in late May 2026, the current release was v2.1.157, and the version moves most days. A feature this load-bearing went in through the changelog and stayed there.
The mechanism is plain. Each project gets a directory at ~/.claude/projects/<project>/memory/. Inside sit two kinds of file: a single MEMORY.md index, and a set of per-topic Markdown files, one fact per file. Claude writes both. At the start of every session it loads the index back in. The model decides what goes in. Anthropic's memory documentation puts the trigger plainly: "Claude doesn't save something every session. It decides what's worth remembering based on whether the information would be useful in a future conversation."
The path matters more than it looks. It is derived from the git repository, so every worktree and subdirectory of the same repo shares one memory directory. The memory documentation is blunt about the boundary: "Auto memory is machine-local. All worktrees and subdirectories within the same git repository share one auto memory directory. Files are not shared across machines or cloud environments." Read "machine-local" as local to wherever Claude Code is executing: on your laptop that is the laptop, but for Claude Code on the web it is the session's cloud execution environment, not your machine at all. Your teammate on another laptop has their own separate folder, writing its own separate notes. Hold that thought. It decides half of what governance can and cannot do later.
If you have read the post on where each rule belongs in Claude Code, auto-memory is the surface that decision tree did not yet have a row for. It is not CLAUDE.md, which you write and commit. It is not a hook, which fires deterministically. It sits between them: written by the model, loaded like configuration, enforced like nothing. The same post on creating skills draws the line that ambient context belongs in configuration, not procedure. Auto-memory is a third ambient layer alongside CLAUDE.md and hooks, and it is the only one Claude maintains without you.
Reading the files Claude wrote about me
The thing nobody tells you is how legible it all is. These are not embeddings or a binary store. Each topic file is Markdown with a YAML frontmatter block, and the frontmatter is richer than the docs let on. Here is a real one from my own directory, a memory about a preference I had stated:
---name: feedback-brevity-over-verbositydescription: User prefers brass-tacks brevity over technical verbositymetadata: node_type: memory type: feedback originSessionId: fea5ce5f-56ce-4707-989f-f3cbe294f4c6---Three of those fields are absent from Anthropic's public memory docs, as far as I could find, and the descriptions below come from reading my own files. node_type is literally the string memory on all thirty-five files. originSessionId is a UUID, and it is the interesting one: it points back to the exact session that wrote the memory. That is provenance. You can grep your memory directory for a session ID and reconstruct which conversation taught Claude a given lesson. Anthropic's own docs do not mention the field; a few third-party write-ups have started to, but you do not have to take anyone's word for it, because the file is right there to open.
Then there is type. The system instructions that drive memory writing define four categories: user (who you are and how you work), feedback (corrections and confirmed approaches), project (time-bound facts about ongoing work), and reference (pointers to external sources). Those four are not enumerated in Anthropic's public docs. You confirm them the only honest way, by reading the files. One command does it:
grep '^ type:' ~/.claude/projects/*/memory/*.md | sort | uniq -cAcross my thirty-five files: twenty-five feedback, eight project, one user, one reference. Four values, no fifth. I mention the count because a pre-built research note I was handed claimed a fifth, undocumented workflow type, sourced to a file named workflow_kb_maintenance_via_blog_subagents.md. I opened that file. Its metadata.type is feedback. The workflow_ in the filename is just the start of its slug, because the memory happens to be about a workflow. The filename prefix is decoration; the type field is the truth. That distinction is worth internalizing before you trust any tool, including a research assistant, to tell you what your own files contain.
Two more details from the read-through. The files cross-link each other with wiki-style [[slug]] references, which act as navigational hints the model can follow toward a related memory rather than a guarantee of deterministic traversal. And the filenames are not enforced: in this project, twenty-one files carry a typed prefix like feedback_ and eight are bare slugs. The convention is cosmetic. The frontmatter is canonical.
The most pointed thing I found was a memory overriding a built-in default. One file records that I prefer brevity, and its body states, in plain text, that this "overrides the 'Depth Over Economy' directive." That directive is part of my project configuration. A memory Claude wrote is, by its own description, countermanding a rule I wrote. That's not a bug. It is the risk advisory context carries, showing up exactly where the design says it can, and it is precisely why you cannot treat this directory as write-only.
What triggers a save, and the staleness flag the docs skip
So what makes Claude write a memory rather than let a detail evaporate? The decision rule is the one quoted above: the model asks whether a fact would help a future conversation. In practice that means corrections survive ("never commit directly to main here"), durable preferences survive ("default to worktrees"), and one-off context does not. The model is the gatekeeper, not you. Worth sitting with, because it means the contents of that folder are a record of the model's judgment about what mattered, which is not always the same as what mattered in practice.
Here is the finding I have not seen in Anthropic's documentation. When Claude Code reads a memory file that has aged, it injects a warning ahead of the content. Open a file a few days old and this appears first:
This memory is 3 days old. Memories are point-in-time observations, not live state, so claims about code behavior or file:line citations may be outdated. Verify against current code before asserting as fact.
I reproduced this across files of different ages. It fired on a file three days old, one six days old, one fifteen days old, each time reporting the exact age. Three days is the youngest I could test, because nothing newer than that had aged enough to check. The number in the warning counts up as the file sits there.
Read that warning again, because it is the tool telling on itself. Claude Code already knows memory goes stale. It already knows a point-in-time note can drift out of sync with the code it describes. It is loud about this internally, to itself, on every read. And it documents none of it to you. The staleness governance exists; the burden of acting on it is handed to you silently. The model-level substrate underneath all of this, the file-system memory tool, is something I traced in the Opus 4.7 deep dive; the staleness behavior is the layer Claude Code wraps around it, and it is the strongest argument in the whole feature for reading your files on a schedule rather than assuming they stay true.
The line that tells you everything
If you read one sentence of the official documentation, read this one. It is in the memory documentation, and it is the keystone the rest of this post hangs on:
Claude treats them as context, not enforced configuration. To block an action regardless of what Claude decides, use a PreToolUse hook instead.
Memory is advisory. A line in a memory file is a suggestion the model reads and usually follows, with no guarantee. This is the same shape of truth the rule-routing post makes about CLAUDE.md, and I am not going to relitigate the advisory-versus-enforcement argument here. The memory-specific consequence is what matters: the contents of that folder steer the model without ever being checked by anything except the model. There is no validation step between what gets written and what gets loaded back in.
Two things follow. The first is mechanical. Only the first 200 lines or 25KB of MEMORY.md load at session start; the docs are explicit that "content beyond that threshold is not loaded at session start." An index left to grow unbounded silently drops its tail. The stuff you assumed was active context is sitting below the waterline, doing nothing. The cap is not a limitation to resent. It is a forcing function: it makes you triage what earns a place in the index, the same way a tight word budget makes prose better.
The second consequence is adversarial. If memory steers the model and nothing validates it, memory is an attack surface. This is not hypothetical hand-waving. The OWASP Top 10 for Agentic Applications, published in December 2025, lists "Memory & Context Poisoning" as a named threat class, ASI06, describing attacks where poisoned memory reshapes behavior long after the initial interaction. A persistent, model-trusted, unvalidated store that the model loads on every session, that nothing validates, maps squarely onto that threat class. How does a line get poisoned in practice? Any path that can write to that directory will do it, which is why Anthropic restricts where memory can be redirected, a control I come back to below. You do not have to be paranoid. You do have to know the surface exists.
Governing it: steer, audit, and when to switch it off
Here is where the blast-radius rule earns its keep. Govern auto-memory in proportion to what a wrong line can cost, and the controls Claude Code already ships map cleanly onto that scale.
At the light end, you read and steer. Run /memory to browse and open the files; the command also toggles auto-memory and links straight to the folder. When you find a memory that is wrong, stale, or overreaching, you do not file a ticket or run a special command. You open the file and edit it, or delete it. It is Markdown. The file is the interface, which is the entire reason reading the directory is the load-bearing skill and not an optional nicety.
At the firm end, you switch it off, and Claude Code gives you three switches plus a CI mode:
| Layer | CLAUDE.md | Auto-memory | Subagent memory |
|---|---|---|---|
| Who writes it | You | Claude, automatically | The subagent, automatically |
| Where it lives | Your repo | memory/ (local) | agent-memory/ dirs (3 scopes) |
| Scope | Committed, shared | Machine-local, per repo | Per agent: user, project, or local |
| Loaded into | Every session | Session (200 lines / 25KB) | Subagent prompt (same cap) |
| How to control | Edit and commit | /memory, settings, env var | Per-agent config |
| Enforcement | Advisory | Advisory | Advisory |
The settings key autoMemoryEnabled: false turns it off for a project or your user profile. The environment variable CLAUDE_CODE_DISABLE_AUTO_MEMORY set to 1 does the same, and set to 0 it forces memory back on even when other settings would suppress it, which is the escape hatch for a context that disabled it upstream. And the --bare flag skips auto-memory entirely along with hooks, skills, plugins, MCP servers, and CLAUDE.md, for scripted runs that should start clean, unless you explicitly override it with CLAUDE_CODE_DISABLE_AUTO_MEMORY=0, which forces memory on even under --bare. That last one is the tell. The vendor ships a one-flag way to start with no memory at all, which says it does not treat memory as something to trust in every context. Neither should you.
There is a security control here too. The autoMemoryDirectory setting, which relocates where memory is written, is read from any settings scope, but when it comes from a project's .claude/settings.json or .claude/settings.local.json it is honored only after you accept the workspace trust dialog for that folder, the same gate that governs hooks. Read that as a worked example of the threat model. Someone thought about a cloned repo redirecting a memory path somewhere it should not write, and put it behind the trust prompt. Apply the same suspicion to the contents.
Two contexts move the dial hard toward "off." The first is anything regulated, and here it pays to separate two concerns the controls keep separate. Disabling auto-memory stops Claude from writing memory files; it does nothing about session transcripts. The data usage documentation notes that Claude Code "store[s] session transcripts locally in plaintext under ~/.claude/projects/ for 30 days by default," and that retention is governed by its own switches: cleanupPeriodDays shortens the window, CLAUDE_CODE_SKIP_PROMPT_HISTORY stops transcript writes entirely, and --no-session-persistence does the same for a single print-mode run. If you operate under HIPAA, a BAA, or a zero-data-retention agreement, plaintext local persistence is a fact you account for on both fronts, and turning off auto-memory alone is not enough; the conservative call disables memory and addresses transcript retention together. The second is multi-agent work. Subagents have their own separate memory layer, documented in the subagents reference, with the same index and the same cap. Unlike auto-memory it is not uniformly machine-local: the recommended default scope (project) writes to .claude/agent-memory/<name>/ inside the repo and is shareable through version control, with user (~/.claude/agent-memory/<name>/) and local as the alternatives. More agents writing memory, some of it committable, means more surfaces to govern, not one.
Worth saying plainly, because it is the honest objection: if you have to review and prune every write, are you not just maintaining CLAUDE.md by hand with extra steps? You would be, if governance meant inspecting every line before every session. It doesn't. Governance proportional to blast radius means a low-stakes solo project earns a glance at the folder every couple of weeks, and a shared repo where a poisoned line could misroute an agent earns a real review cadence. The parallel is code review. Running CI does not mean you stop writing tests; it means you verify before you ship. The docs' own pitch, that memory lets Claude "accumulate knowledge across sessions without you writing anything," describes the accumulation, not the permanence. The model writes; you decide what stays.
This is the same posture I argued for with the /advisor tool: a powerful Claude Code mechanism that rewards knowing exactly where it helps and where it is blind, rather than trusting it by default. It is also why the compatibility scanner I built audits five configuration layers and yet memory is the sixth surface it does not check, an honest gap I am now staring at. Wiring this kind of governance into a team's setup, where the memory directory, the review cadence, and the kill switches are part of the standard, is exactly the Claude Code infrastructure work I do; the broader pattern of advisory-versus-deterministic control across a whole practice is the subject of the production engineering practice guide.
FAQ
Where does Claude Code store its auto-memory files? In a per-project directory at ~/.claude/projects/<project>/memory/, on your local machine. The path is derived from the git repository, so every worktree and subdirectory of the same repo shares one memory directory. Files are not synced to the cloud and not shared across machines.
How do I turn auto-memory off? Three ways. Run /memory in a session and toggle it. Set autoMemoryEnabled to false in settings. Or set CLAUDE_CODE_DISABLE_AUTO_MEMORY=1. For scripted -p runs, --bare skips auto-memory along with hooks, skills, plugins, MCP servers, and CLAUDE.md.
Is auto-memory shared with my team or synced to the cloud? No. It is machine-local. A teammate on another laptop has a separate memory directory. Sharing requires a layer the feature does not provide, such as committing curated notes to CLAUDE.md instead.
What is the difference between CLAUDE.md and MEMORY.md? You write CLAUDE.md and commit it. Claude writes MEMORY.md and the topic files automatically, to a local directory. Both load as context every session, and both are advisory. Neither blocks an action on its own.
How do I fix or stop a bad memory? Open the file and edit or delete it. Entries are plain Markdown with YAML frontmatter, so the file is the interface. Run /memory to find them. There is no special correction command, because there does not need to be one.
The folder is already there
The strongest thing I can tell you about Claude Code's auto-memory is also the simplest: there is a folder on your machine, right now, full of things the model decided to remember about your work, and you can open it. Most of the confusion about this feature dissolves the moment you do.
It isn't a learning system to trust and it isn't noise to silence. It is a context layer you govern, and the right amount of governance is set by what a wrong line would cost. For a weekend project, that is a glance now and then. For a shared repo where Claude is shipping changes, it is a review you run, not one you keep meaning to. Either way the first move is the same. Run grep '^ type:' ~/.claude/projects/*/memory/*.md, read what comes back, and decide for yourself whether the model got it right.
If you want this wired into how a team runs Claude Code, with the kill switches, the review cadence, and the directory treated as a real surface rather than a black box, that is the kind of setup work I do. The fastest way to start is a short call: book fifteen minutes and bring the output of that grep.