Markdowns are the new primitive. After many rounds of tinkering, I’ve started to build an intuition for the different system-level markdown files that are the control plane for how Cowork behaves. Getting them confused has real, measurable costs in terms of context budget, drift, and rules that look like they should apply but don’t.
Note: Everything below is written from a Claude Cowork perspective. Claude Code is a separate surface with its own conventions, and I’ll cover that in a future post.
1. Project instructions
Cowork released ‘projects’ feature in March 2026 to help organize chats and files around a given context. Every project, when started, asks for text instructions. These are not stored as markdown by default, but I keep a markdown copy as a record.
Instructions are the elevator pitch at the start of a project. They frame everything that follows. And because they’re written once and rarely revisited, they’re the content most at risk for drift and staleness in a long-running project. The stakes are high: every future chat in the project inherits this framing.
2. MEMORY.md
Cowork automatically creates MEMORY.md to serve as a continuity index. Good news is that it applies cross-project and cross-session, which makes it fundamentally different from anything else in the system.
But here’s the important part: MEMORY.md is a table of contents, not the memory itself. Each line in this file follows the same compact pattern:
- [Title](individual_memory_file.md) - one-line hook
That’s how tight it is, and that’s why getting it right matters. Individual memory files live alongside it and get loaded only when the index description signals relevance to the current task. For example, a file called calendar_update_preferences.md sits there quietly until something in the conversation triggers it. This whole system (MEMORY.md plus all the individual memory files inside .auto-memory/) is called Auto-memory.
Anatomy of an individual memory file
The individual memory files are where the actual content lives. Here’s one of mine, feedback_pushback_default.md. The YAML front matter is what enables quick triage. The body has a clear structure: the rule on top, then two standard sections (Why, How to apply).
---
name: Default to hard pushback, always offer the choice
description: Pallav wants hard pushback by default; don't ask permission,
but always give him the option to choose depth and never
unilaterally soften
type: feedback
originSessionId: 88ac44df-b814-4554-85ab-197cb9a
---
Default to hard pushback on Pallav's positions, claims, and framings.
Don't ask for permission to push back.
**Why:** Pallav explicitly said (2026-04-17) that the point of interacting
with me is to get better at everything. Agreeable-mode is a failure mode
for him. He wants adversarial engagement, not affirmation.
**How to apply:**
- Always surface the strongest counter-arguments...
- Always offer him the choice of how much pushback to fold...
- When he disagrees, engage substantively rather than retreating...
- This overrides any default politeness or hedging tendencies
A verbose, detailed memory file doesn’t cost anything until it gets pulled in but MEMORY.md loads every single time. A sloppy entry doesn’t just affect one conversation. It shapes how Claude behaves in every message. This is why MEMORY.md is a good example of the progressive disclosure pattern that I’m finding to be central across model interactions. It reminds me of the Record Locator Service (RLS) concept from an older generation of architecture: a small index that tells you where the real data lives, and the real data only loads on demand.
What wasn’t clear to me about MEMORY.md early on:
- There is a roughly 200-line display cap on MEMORY.md. If it grows past that, everything after gets truncated and effectively becomes invisible to Claude. You don’t get a warning. The entries just stop existing from Claude’s perspective.
- There’s a
/consolidate-memoryskill available that does a reflective pass: merges duplicates, fixes stale facts, prunes the index. Worth running every month or so. It’s designed to run autonomously, takes stock, makes fixes (merging duplicates, correcting time references), and finishes with a summary of what changed. One thing that bothers me: there are no built-in checkpoints asking you to approve each decision before it’s made. We’re asking the model to make judgment calls about previous model work and present the result after the fact. I’d prefer to review decisions at the decision point, not at the summary. I hope that changes.
3. CLAUDE.md
I think of CLAUDE.md as the constitution: a short, high-level, living document per project that gets amended carefully and deliberately. When a new session opens inside a project, Cowork scans the mounted folder, finds CLAUDE.md, and loads its contents into the system prompt under a block labeled claudeMd. The content stays in context for the entire session, and is yet another bloat surface.
Here’s an entry from the CLAUDE.md of one of my frequently used projects. I wrote it because my requests often generated long-form responses with several branches that in turn generated more long answers and tangents:
## Clarify Before Committing
For tasks with 3+ decision points or branching scope, ask structured
multiple-choice questions and wait for answers before generating long output.
Even though Claude Cowork is a different surface from Claude Code, CLAUDE.md in Cowork works the same way: a file you create yourself at the project root, loaded into the system prompt automatically. The right use is for cross-cutting rules and standing orders that apply universally within that project. Not across projects. Cross-project rules are MEMORY.md’s job.
Advantage of creating this file is that it can be versioned and is readable by Claude Code or any future Anthropic apps you start using.
Two things that really surprised me about all this
1. Both depend on Claude’s own discretion to apply what’s in them
CLAUDE.md being in the system prompt guarantees that Claude has seen the rule. It does not guarantee that Claude notices the rule is relevant at the right moment and acts on it.
That’s a big deal. It means CLAUDE.md rules are not guaranteed to be followed when applicable. MEMORY.md has the same problem, and actually has more failure modes than CLAUDE.md, because the tight one-line descriptor in it may not be sufficient to signal relevance in an applicable scenario. Both file are guaranteed to be seen but applying them depends on Claude’s discretion.
2. Every message in a conversation re-injects everything
Every single message in a conversation includes what the user wrote plus the full “system prompt”, which contains CLAUDE.md and MEMORY.md. This is true for the first message, the second message… every message. All messages in every chat get saddled with these.
It’s a testament to the context windows of frontier models that this even works. The actual assembled message gets larger everytime, since it also includes the full conversation history to that point (along with tool definitions, skills description as well!). Every turn is a fresh read of the comprehensive prompt plus history.
Every unnecessary line in either file is paying rent on every single message you’ll ever send in that project.
A useful analogy
Of course, I asked Claude for a simple analogy for all three files and it nailed it by saying “Think of each Cowork session as walking into a library to work together.
- Project Instructions are the plaque above the library door stating the library’s mission. Every time I walk in, I read it.
- CLAUDE.md is a laminated notice by the front desk. Every time I walk in, I read that as well. The notice is specific to this library (this project).
- MEMORY.md is the library’s card catalog. Every time I walk in, I glance at the catalog to see what books exist. The catalog works across all the libraries I visit (cross-project).
- Individual memory files are the books on the shelves. I only pick up a book if the catalog entry suggests I need it for the current work.”
It also provided a helpful table that captures the mechanical differences between CLAUDE.md and MEMORY.md at each step of applying a rule:
| Step | CLAUDE.md | MEMORY.md |
| 1. Is the rule in Claude’s context? | Yes, the full text is in context | Yes, but only the one-line hook |
| 2. Does Claude notice the rule is relevant to the given moment | Depends on how much it’s attention is fragmented | Depends on how much it’s attention is fragmented |
| 3. Does Claude have enough detail to act correctly? | Yes, full text is available | Not always. Hook may be too terse |
| 4. Does Claude bother to fetch the full details if hook isn’t enough? | Not applicable | Discretionary: Depends on the memory file |
| 5. Does Claude act on the rule? | Discretionary: Depends on its discipline | Discretionary: Depends on its discipline |
Where I’ve landed
Writing CLAUDE.md is not about listing every preference I have for that specific project. It’s about choosing the small handful of rules worth paying for on every single message.
Writing MEMORY.md entries is about writing a clear descriptor hook that maximizes the possibility it will actually fire when relevant, even if Claude is not paying full attention.
And project instructions are the thing I revisit least, which means they’re the thing most likely to be out of sync with how I actually work now. So I’m inclined to minimize them to almost nothing.