Why it happens, and why it is not a bug
A model answers using what is in its context window — the working set assembled for that request. Whatever is not in it may as well not exist, however clearly you explained it before. That is the whole mechanism, and it is worth separating from three things people assume are the same:
- Conversation history — the transcript. Depending on the tool it may be kept and partly re-fed into the window, summarised, truncated, or dropped when you open a new chat. It records what was said, not what is currently true.
- Memory features — where a product offers them, these persist across conversations. They are generally aimed at preferences and recurring details about you.
- Project files and instructions — where the platform supports them, files the assistant reads as part of the work. This is the only one of the three you can review, diff and correct.
What people describe as forgetting is usually the first of those wearing out. A long transcript gets summarised or truncated and a decision you explained in week one quietly stops being visible — or you start a new chat and it is gone outright. Nothing broke. The transcript was never meant to be the project's source of truth.
That rules out the fixes people try first. Repeating yourself more carefully does not help, because the explanation was never the unclear part. A larger context window helps within one long session, not next month. What survives a session boundary is something written down where the assistant will read it again.
The fix: write the context into the project
If context has to live in a file for the assistant to read it, the obvious place to put that file is the project it describes. Not in a notes app, not in a saved prompt, not in a chat you scroll back through — in the repository or folder you are already working in, next to the work.
This has a property that nothing else on the list has: it stays true. When the project changes, you are already in the folder changing it. Context stored anywhere else is context you have to remember to go and update somewhere else, which is the same as context that will be wrong by November.
What that folder needs is three layers. They are worth naming separately because most attempts at this build one of them and stall.
Layer 1 — structure
A folder tree that mirrors how the work actually happens. Not a generic docs/ dump — categories that match the real shape of the project, so that the question "where does this go?" has an obvious answer and the assistant can infer meaning from location alone.
project/ ├── Project/ what this is, current state, what's next ├── Docs/ architecture decisions and why they were made ├── Conventions/ naming, structure, error handling, testing ├── Prompts/ repeatable tasks: review, debug, refactor └── AGENTS.md the map and the standing rules
company/ ├── Company/ what we do, positioning, current priorities ├── Product/ what exists, what's shipping, what's parked ├── Customers/ research, interviews, recurring complaints ├── Meetings/ decisions, dated, with the reasoning └── AI Instructions/ the map and the standing rules
The trees differ because the work differs. What they share is that a file's location already tells you most of what it is — and an assistant reading the tree gets the same signal without opening anything.
Layer 2 — content
Markdown documents holding the facts that stay true across sessions. This is the layer people either skip or overdo, and overdoing it is the more common failure: forty pages of documentation that nobody maintains is worse than one page that is correct, because the assistant will cite the stale forty with complete confidence.
The test for whether something belongs is simple. If you have explained it to the assistant more than twice, write it down. If you have never needed to explain it, do not.
In practice, the minimum that earns its place:
- What this project is, in three sentences — the thing you type at the start of every new chat.
- Current state: what works, what is half-built, what is deliberately not being done yet.
- Decisions and their reasons. The reason matters more than the decision — without it, an assistant will cheerfully undo a choice you made for a good reason it cannot see.
- Conventions: how things are named, structured and organised here, as opposed to how they are named in general.
- Constraints: what must not change, and why. Budgets, compliance, a client's hard requirement, a dependency you cannot drop.
Layer 3 — instructions
One file that tells the assistant how to use the other two: what lives where, which conventions apply, what good output looks like here, and what it should never do without asking.
Without this layer, structure and content are a filing cabinet with no index. The assistant can read any file you point it at, but it does not know which ones matter, which are current, or that Conventions/ is binding rather than aspirational.
Where this file goes depends on your tool, and the answer has converged recently. Many coding agents now read an AGENTS.md from the repository root — an open format listing support from Cursor, VS Code, GitHub Copilot, Codex, Aider and others. Claude Code reads CLAUDE.md, and reads AGENTS.md when no CLAUDE.md sits in the working directory or above it. Where an assistant works from uploads rather than the filesystem — a ChatGPT Project, for instance — the same file becomes project context by being uploaded rather than read from disk. Check what your own tool supports; this is the part that changes fastest.
The content is the same in every case. Only the filename and the delivery change.
# Project context A scheduling tool for independent clinics. Next.js, Postgres, deployed on Fly. Booking works, billing is half-built, notifications are not started. ## Where things live - `Project/` — what we're building and what state it's in - `Docs/` — architecture decisions, each with the reasoning - `Conventions/` — naming, error handling, testing ## Standing rules - Read `Conventions/` before writing code. They override general best practice here. - Never change anything under `Docs/decisions/` without asking — those record why, and rewriting one loses it. - If a decision looks wrong, say so before working around it. ## Before you finish Run `npm test`. Don't report work as done if it fails.
What changes in practice
The difference shows up in the first message of a session rather than gradually.
Before, asking for a new endpoint produces working code in a style that belongs to no particular project — a plausible average of every codebase the model has seen. It invents an error format, picks a folder, names things reasonably, and none of it matches what is already there. You spend the review explaining conventions you have explained before, and next session it happens again.
After, the same request produces code in your error format, in the folder your structure implies, with your naming — because all of that was read before the first line was written. Review becomes review rather than archaeology.
The second-order effect is larger and takes a week to notice: you stop pre-loading requests. "Add rate limiting to the booking endpoint" replaces three paragraphs of preamble, because the preamble is already on disk.
That prompt is also the test. Run it in a fresh session: if the answer cites your actual documents, the layers are working. If it is vague or generic, the instruction file is not pointing at the right things — which is a much easier problem to fix than the one you started with.
Keeping it current
Written context decays, and stale context is worse than none — an assistant working from a document that was true in March will make confident, well-reasoned, wrong decisions, and it will cite your own file as justification.
Two habits keep it honest, and neither is a process:
- 01Update the context in the same change as the work. If a pull request changes how errors are handled, it also changes Conventions/. Keeping them in the same diff means review catches drift, rather than a quarterly audit that never happens.
- 02When you catch the assistant being wrong about the project, fix the file rather than the reply. A correction typed into a chat lasts one session. The same correction written into the instruction file is the last time you have to make it.
The second habit is the one that compounds. Every wrong answer becomes a permanent improvement instead of a repeated annoyance, which means the setup gets better through use rather than decaying through it.
Common questions
Is this the same as using an assistant's memory feature?
No. Memory features store facts about you across conversations — preferences, working style, recurring details — and they are good at that. Project context is different: it changes as the project changes, it needs to be correct rather than merely remembered, and other people need to see and edit it. A file in the repository can be reviewed, diffed and corrected. A memory cannot.
How long should the instruction file be?
Shorter than you expect. One page that is accurate beats ten that are aspirational, because everything in the file competes for attention and the stale parts actively mislead. Start with the three sentences you type at the beginning of every new chat — that is the highest-value content you own — and add only what you find yourself explaining repeatedly.
Does this work outside coding tools?
Where the platform supports project files or custom instructions, yes — with a difference in delivery. A coding agent reads the files from disk as it works, so an edit takes effect on the next request. An assistant working from an uploaded snapshot, such as a ChatGPT Project, holds the version you gave it, so you re-upload after substantial changes. The files themselves are identical either way: plain Markdown, no tool-specific format. If a tool offers neither project files nor custom instructions, this approach has nothing to attach to.
My project changes constantly. Is it worth documenting?
Yes, but document the stable layer rather than the moving one. What the project is, why the main decisions were made and which conventions apply change far more slowly than the work itself. Skip anything that would need editing weekly — a current-state file is useful; a task list duplicated from wherever you already track tasks is not.