Chat history is a poor place to keep decisions. It is long, unstructured, full of things you tried and abandoned, and it disappears the moment you start a new session.
The usual symptom is a second session that quietly contradicts the first. A convention you settled on Tuesday is gone by Thursday. A rule you agreed — dates stored in one format, one component owning the styling — is followed for a while and then not. Nothing announces the change; the code simply starts disagreeing with itself.
It is tempting to treat this as a memory problem to be solved with longer context windows or better tooling. It is more usefully treated as a record-keeping problem, because the thing that was lost was never really in the conversation. It was a decision you made and never wrote down anywhere durable.
What is actually worth preserving
Very little of a session deserves to survive it. Four things generally do.
Accepted behaviour. What the software is supposed to do, in plain observable terms. Not what you hoped, not what you discussed — what you settled on. This is the thing everything else is checked against, and it is the most expensive to reconstruct from memory.
Decisions that closed off alternatives. Every project accumulates small rulings: duplicates are allowed, deleting asks first, times are stored in UTC and shown in local time, the reference number is generated on save rather than on submit. Individually trivial; collectively they are the difference between a coherent system and one that behaves differently depending on which day each part was built.
Constraints that still apply. "The reporting module is not to be touched." "No new dependencies." "The public API response shape is fixed." These have a habit of being stated once, early, and then silently expiring — usually at the point they matter most.
Current state. Which increments are finished and verified, which are in progress, and what the last version you trust actually is. This is the smallest of the four and the one that saves the most time when you come back after a fortnight.
What is not worth preserving
Almost everything else, and this matters — a record nobody maintains is worse than none, because it is trusted while being wrong.
Do not keep the reasoning that led to a decision unless the reasoning is likely to be re-litigated. Keep the decision. Do not keep rejected options, failed attempts or the shape of the discussion. Do not keep anything already visible in the code: the code is the authority on what exists, and a written description of it will drift within days.
The test is whether losing it would cost you something. If the answer is "I could work it out again in a minute by looking", leave it out.
Where to keep it
Somewhere that lives with the project rather than with the tool. A plain file in the repository is entirely sufficient — a short document that states the current accepted behaviour, the standing decisions, the active constraints and where you got to.
The reason to prefer this over assistant-specific memory features is not that those features are bad. It is that decisions about your software should outlive your choice of assistant, and should be readable by a person. If you change tools, or someone else picks the project up, or you return in six months, a file in the repository still works.
This is also what makes changing tools cheap rather than disruptive, which is part of why the tool matters less than how you direct it.
Keep it short enough that you will actually update it. A page is plenty for most projects. If it grows past a few pages, it has probably started duplicating the code.
Opening a new session
Give the assistant the durable record, not a summary of the last conversation.
In practice that means starting with the current accepted behaviour and standing decisions relevant to what you are about to do, the constraints that apply, and then the specific piece of work. It reads as slightly laborious and takes under a minute, and it replaces the far longer ritual of discovering mid-session that an earlier agreement has evaporated.
One thing worth being deliberate about: state the decisions as settled, not as background. "Duplicates are allowed" is an instruction. "We discussed whether duplicates should be allowed" is an invitation to reopen it.
A worked example
Suppose you are building a support ticket tool and pick it up again after a week. The durable record might be about this long:
Accepted so far: staff can raise a ticket with a title, description and priority; tickets appear on a list, newest first; a ticket can be assigned to one person.
Standing decisions: priority is one of Low, Normal, High and cannot be blank; tickets are never deleted, only closed; the assignee list is loaded from the existing staff table, not a new one.
Constraints: do not alter the staff table or the existing login flow; no new dependencies.
State: assignment was finished and checked on Friday. Nothing since. Closing a ticket is next.
Four short paragraphs, and the next session starts from a shared understanding instead of an archaeology exercise. Note that it says nothing about how any of it is implemented — that is the code's job, and writing it down here would only create something to keep in step.
Why this is worth the effort
A contradiction introduced because the assistant did not know about an earlier decision is not obviously a fault. Everything runs. It looks deliberate. It is usually found much later, once a good deal of other work is resting on it.
That is the same mechanism, arriving by a different route, as the way AI projects drift — change accumulating faster than understanding. Keeping a durable record is one of the cheaper defences against it, and unlike most process advice it takes minutes rather than discipline.
Session Compaction Can Leave You Unable to Retrieve Code an Agent Ran
Writing down context between sessions assumes you can still retrieve what the agent actually did if you need to inspect it later. One recent ChatGPT Work example shows why that is worth checking rather than assuming.
Simon Willison asked ChatGPT Work, using GPT-6 Astra, to generate running routes from his address using OpenStreetMap data. The agent worked for 27 minutes and produced a visualisation, a GPX file and a GeoJSON file. When he later asked how the routes had been created, it described tools including Nominatim and Overpass. But when he asked for the actual Python code it had run, ChatGPT was unable to provide it. Willison wrote that this appeared to be because the thread had been compacted.
That is one observed case, not evidence that every agent, platform or compacted session behaves the same way. Willison nevertheless argues that systems using compaction should preserve the pre-compaction content and make it retrievable through tool calls. That is his proposed design improvement, not a documented product feature.
The practical lesson is simple: if an agent generates code, commands or other execution details that you may need for debugging, verification or reuse, save them while they are available. Do not assume that everything visible or executed during a long session will necessarily remain retrievable later.
This is especially relevant during the Test & Correct and Commit & Maintain phases. A working output tells you what was produced, but later investigation may require the exact code or commands that produced it. Keep important execution details alongside the project evidence rather than relying on the conversation history as the only record.
If you are also finding that decisions were never made clearly in the first place, the earlier problem is worth solving first: how to plan an app before you ask AI to build it.