Your assistant was doing fine an hour ago. It knew the project used the repository pattern, it knew you had rejected the third-party queue, it knew the test command. Now it is suggesting the queue again, writing code in a style you corrected twice, and asking which database you use. Nothing broke. You hit the edge of the context window.

This is the context window explained as a mechanism rather than a complaint: what it is, why it fills up so fast when you are coding, and what the "the assistant forgot" moment actually looks like from the inside. It is the one piece of vocabulary that makes most AI-coding frustrations legible.

After reading, you will be able to tell the difference between two problems people constantly merge — a full context window in this session, and missing project knowledge across all sessions — and you will know which fix applies to which. The fixes themselves live in other articles; this one makes sure you pick the right one.

Context window explained: what it actually is

A language model does not have a memory in the everyday sense. Every time it produces a response, it reads one long block of text and predicts what comes next. That block is the context window: the maximum amount of text the model can look at in a single pass.

Everything the model "knows" about your situation has to be inside that block:

  • the system prompt your tool sends (rules about tool use, formatting, safety)
  • your project instructions, if the tool loaded them — CLAUDE.md for Claude Code, AGENTS.md for Codex and many other agents
  • every message you have typed in this session
  • every reply the assistant has produced
  • the contents of every file it read
  • the output of every command it ran

Size is measured in tokens. A token is a chunk of text — often a short word or part of a longer one, so a line of code is several tokens. The exact window size depends on the model and changes with every release, so read your tool's own documentation rather than trusting a number you remember from a blog post.

Two consequences follow, and they are the whole article:

  1. The window is a budget, not a filing cabinet. Text does not get stored; it gets carried along, and it competes for space.
  2. The window is per session. Close the terminal and it is gone. Nothing you said is written anywhere unless you or your tool wrote it to a file.

Why it fills faster than you would expect

Reading the list above, you might assume conversation is the main cost. It is usually the smallest part. Coding work is unusually expensive per turn, for four reasons.

Files are big. Ask "why does auth fail on refresh?" and the assistant may read a route handler, a middleware file, a token helper and two tests. That is a few hundred lines of code you never see in the chat, all of it now sitting in the window.

Tool output is bigger. A failing test suite prints stack traces. A grep across the repo returns forty matches with surrounding lines. npm install prints a wall of warnings. Build logs are the single most effective way to fill a context window by accident.

Everything accumulates. Turn twelve still carries the file the assistant read at turn two, even though you refactored it since. Old versions of code and stale command output stay in the window alongside the current ones.

Long agentic runs multiply all of it. When an assistant works autonomously — read, edit, run tests, read the failure, edit again — each loop adds another round of file contents and output. A ten-minute autonomous run can consume more of the window than an hour of you asking questions.

The practical result: sessions that start crisp get muddy, and they get muddy in the middle of the task you cared about, because that is when the most files have been read.

What happens when it runs out

Different tools handle the limit differently, but you will meet some combination of these three behaviours.

Truncation and compaction

When the window is full, something has to go. Some tools drop the oldest messages. Some summarise the earlier conversation into a shorter note and continue with that — often called compaction. Either way, detail is lost, and the lost detail is disproportionately your early instructions, because they were at the top.

This is why the assistant re-suggests the library you rejected. You rejected it in message four. Message four no longer exists, or exists as one line in a summary that reads "discussed queue options."

Drift

Before anything is dropped, quality usually sags. A crowded window contains multiple versions of the same file, contradictory instructions from different points in the conversation, and a lot of irrelevant log noise. The model is working from a messier description of reality, so you get answers that are plausible for some state of the project, just not the current one.

Confident-sounding mistakes

The failure mode that costs real time: nothing announces itself. The assistant does not say "I no longer have the constraint you gave me." It writes code in the style it infers from whatever is still in front of it, and explains it convincingly. This is exactly why reviewing what your assistant changed before you commit is not optional paranoia — a truncated window produces diffs that look reasonable and quietly violate a decision from last Tuesday.

Context window vs. project memory: two problems, two fixes

Here is the distinction most people skip, and it determines which fix helps you.

Context windowProject memory
ScopeOne sessionEvery session, forever
LimitFixed size, fills upOnly your discipline
Lives inThe model's input for this turnFiles in the repository
Symptom when brokenForgets things you said an hour agoNever knew things you decided last month
FixManage the budget: fresh sessions, narrower tasks, less noiseWrite it down where an assistant will read it

A full context window is a capacity problem. You cannot write your way out of it; you manage it, the way you manage a small disk.

Missing project memory is a persistence problem. A bigger window would not help at all, because the knowledge was never written down anywhere. Ten times the capacity, and a brand-new session still cannot know why you chose SQLite over Postgres for the desktop build.

Most days you have both. The tell: if the assistant knew something earlier today and lost it, that is the window. If it has never known it in any session, that is memory.

What you can move outside the context window for good

You cannot make the window bigger. You can stop wasting it on things that should be written down once and re-read cheaply.

Three kinds of context are worth moving out of the conversation and into files:

Standing rules → instruction file. Anything you would type at the start of every session belongs in CLAUDE.md or AGENTS.md: the test command, the package manager, the conventions you actually enforce, the directories to leave alone.

## Commands
- Install: `pnpm install`
- Test: `pnpm test` (run before proposing a commit)

## Conventions
- No new dependencies without asking.
- Data access goes through `src/db/`, never inline SQL in routes.

Keep it short. An instruction file is charged against the window on every session, so a bloated one costs you the thing you are trying to protect. The guide on writing project instructions your assistant follows covers what earns its place.

Decisions and state → memory files. Short, dated entries: what you chose, why, what you rejected, where you are. These are cheap to read and they are the entries that stop a fresh session from re-litigating settled questions. Project memory for AI coding has templates for each type of entry.

The reasoning behind hard problems → saved sessions. Occasionally the transcript itself is the artefact: the two-hour conversation where a migration strategy got worked out. You do not feed that back into a window; you keep it so a human — or a future session, pointed at a specific part — can reconstruct the thinking. Which AI coding sessions are worth keeping is about picking the few that matter.

A layout that works with plain files:

your-project/
  CLAUDE.md                     # standing rules
  .prjcontext/
    memory/
      decisions.md              # dated choices + reasons
      state.md                  # where we are, what's open
    sessions/
      2026-09-14-migration.md   # the one long conversation worth keeping

A mental model for managing context day to day

Treat the window as a workbench, not a warehouse. A few habits follow from that.

Start fresh on purpose. A new session with a good instruction file beats a three-hour session running on fumes. Ending a session is not losing progress if the progress is in files.

One task per session. Debugging auth and refactoring the build in the same window means each one is paying for the other's file reads.

Point at files, don't paste them. "Read src/auth/refresh.ts" is cheaper and more current than pasting a copy that goes stale the moment you edit.

Watch for the noisy command. A full build log or an unfiltered repo-wide search can cost more window than the last twenty minutes of conversation. Narrow the command, or pipe it to the relevant lines.

Notice the tell and stop. When the assistant starts asking questions it already had answers to, or re-proposes a rejected approach, do not argue with it. That is a capacity signal. Write anything new and worth keeping into memory, start a clean session, and continue.

Write at the end, not the beginning. The moment you learn something — a decision, a dead end, a gotcha — is the moment it is cheapest to record. Three days later you will remember the conclusion and not the reason.

How PrjLab handles this

We built PrjLab because the fix for lost context is files, and files that only exist on one laptop are not much of a fix. A PrjLab repository holds your source files plus three kinds of context with explicit types: .prjcontext/instructions/ (project instructions; CLAUDE.md and AGENTS.md at the project root are recognised too), .prjcontext/memory/ (decisions, notes) and .prjcontext/sessions/ (the conversations you chose to keep).

You push with the prj CLI — prj init, prj status to see what would be captured, prj push — and every push creates an immutable version you can open in the browser with a list of changes and a line diff. On another machine, prj clone brings the whole picture down, so a fresh session starts with the same instructions and the same memory you had yesterday. prj pull never overwrites local edits; conflicting files are reported instead of replaced. Repositories are private by default, and the CLI skips .env files, key files and anything in .gitignore or .prjignore — a safety net, not a complete secret scanner, so review prj status before you push. PrjLab sits beside git; it does not replace it. The docs walk through the first push.

Frequently asked questions

Does a bigger context window solve the forgetting problem? It delays it. A bigger window lets one session run longer before truncation, but it is still per session — close the terminal and the knowledge is gone. Anything you want in next week's session has to be in a file.

Is compaction the same as memory? No. Compaction is lossy summarisation of the current conversation to buy room in the same window. Memory is text you wrote deliberately, stored outside any session, and re-readable in full whenever you want it.

Can I just paste my memory files into every session? You can, and for a small project that is fine. The problem is discipline and cost: you will forget, and pasting everything every time spends window on things the assistant does not need for today's task. Files in the repository let you — or the tool — load only what is relevant.

How long should my instruction file be? Short enough that you would not mind re-reading it. It is loaded into every session, so it competes with the actual work for space. If a rule has not changed anyone's behaviour, cut it and put project state in memory instead.

If you want your instructions, decisions and kept sessions to survive the next fresh window, start with the getting-started guide.