byldr
ryan@cwynar:~
> cat ./writing/the-context-file.json

The context file: stop re-explaining your codebase every morning

2026-08-14 · 3 min read

Open a new session, and the model knows your code but not your decisions. So you explain: we use this ORM, migrations go here, do not touch that legacy module, tests run with this command, money is stored in cents. Ten minutes later you get to the actual task. Tomorrow you do it again, slightly differently, and get slightly different architecture.

That re-explanation is the single most automatable thing in an AI-assisted workflow, and the fix is a file in the repository.

> the contents

Conventions, commands, and landmines

A context file is not documentation. Documentation explains the system to a newcomer; this explains the rules to a capable contributor who can read the code perfectly well but has no idea what you have already decided. Three categories earn their place:

  • <strong>Commands</strong> — how to install, run, test, lint, migrate, and deploy. Exact invocations, not descriptions of them.
  • <strong>Conventions</strong> — the choices that are already made. Where new code goes, how errors are handled, what money and dates look like, which patterns you have deliberately rejected.
  • <strong>Landmines</strong> — the things that look wrong and are load-bearing, the module being replaced, the generated file that must never be hand-edited, the endpoint with an external contract.
CLAUDE.md · markdown
# Working in this repo

## Commands
npm run dev            # local server, port 3000
npm test -- --run      # unit tests, no watch mode
npm run typecheck      # must pass before any commit
npm run db:migrate     # applies pending migrations

## Conventions
- Money is integer cents. Never a float, never a string.
- Timestamps are UTC in the DB, formatted at the edge only.
- New API routes go in app/api/<name>/route.ts and validate input
  with a zod schema in lib/api/schemas.ts. No exceptions.
- Errors bubble to the route handler. Do not catch and log locally.

## Landmines
- lib/legacy/billing.ts is being replaced. Do not add to it.
- lib/db/schema/ is the source of truth; migrations are generated
  from it, never written by hand.
- /api/webhooks/stripe has an external contract. Changing the
  response shape breaks production.

That is most of the value, and it took one sitting to write. Note what is absent: no architecture diagrams, no history, no explanation of what the product does. The model can read the code. What it cannot read is which of the four patterns in your codebase is the one you want next.

> the failure mode

Short, or it starts lying

Every context file dies the same way: it grows, then some of it becomes false, then nobody trusts any of it. A stale rule is worse than a missing one — a missing rule gets asked about, a stale rule gets followed.

  • Keep it to the length someone will actually re-read. A page or two, not a wiki.
  • Write rules, not narration. “Money is integer cents” survives a refactor; “the billing module currently handles three plan types” does not.
  • Update it in the same commit that breaks it. If the test command changes, the file changes in that PR or the rule is now a lie.
  • Delete aggressively. Anything you would not stop a human colleague over does not belong.
> in practice

What changes once it exists

Three things, in increasing order of value.

What you get back
  1. 01
    Sessions start productive.

    The first message is the task, not the orientation. Over a week of sessions that is real time, but it is the least interesting benefit.

  2. 02
    Output stops drifting.

    Two sessions on the same codebase produce code that looks like it came from the same team, because both read the same rules. Consistency was the thing you were spending review cycles on.

  3. 03
    The rules become reviewable.

    This is the one that matters. A convention in your head cannot be argued with; a convention in a file can be changed in a pull request, by a colleague, with a reason attached. Writing it down converts habit into a decision.

That third point is why this is worth doing even on a solo project. The file is where you find out that two of your conventions contradict each other, and that one of them exists only because of a library you stopped using last year.

> the extension

Then let the repo carry the rest

Once the context file is habit, the same instinct applies to everything else that currently lives in your head:

  • A README that starts with how to run the thing, not what it aspires to be.
  • Test names that state the rule rather than the mechanism — <code>rejects a duplicate external_id</code>, not <code>test upsert 2</code>.
  • The acceptance criteria for each task in the issue, not the chat.
  • A short note in the PR about why, since the diff already covers what.

All of it is the same move: move the knowledge from a conversation into the repository, where it is versioned, reviewable, and available to every session and every colleague, including the version of you that comes back to this project in March.

Anything you explain twice should be a file. Anything you explain three times is costing you more than the file would have.
The rule
Want this set up properly?

Five days of senior engineering on your bottleneck — and the conventions, commands and landmines written down while we work. Code in your repo by Friday.

See how the free week works
More writing