Last week you and your assistant spent an hour comparing two ways to handle background jobs. You picked one, for good reasons. Today a new session looks at the same code and suggests the other one, with a tidy explanation of its benefits. You spend twenty minutes remembering why you said no.

Every new assistant session starts without last week's reasoning. The code shows what you chose. It does not show what you rejected, or why. Without a written record, each fresh session is free to reopen the question, and so is every new teammate.

Decision records fix this. This guide gives you a format short enough to actually write, a list of moments that call for one, and a way to make your assistant read them before it proposes changes.

Why AI-assisted projects need them more

Decision records are an old idea. Architecture decision records, popularised by Michael Nygard, capture one decision per short document: the context, the decision, and its consequences. Teams have used them for years to explain their systems to future members.

With AI assistants, the need grows for three reasons:

  • Every session is a new team member. It knows the code but none of the history.
  • Assistants suggest alternatives readily. That is useful, until they keep suggesting the same rejected one.
  • Decisions happen faster. You may make several real choices in one session. Without a habit of writing them down, the reasons stay inside a transcript you will never reopen.

A decision record turns a conversation into a fact the next session can read.

The smallest useful record

Heavy templates do not get used. Start with five fields:

# 2026-09-18 Use a database-backed job queue, not a message broker

Status: accepted

Context:
Jobs are low volume and must survive restarts. We already run one
database. Adding a broker means one more service to deploy and watch.

Decision:
Store jobs in a table and poll it with a single worker.

Rejected:
- Message broker: more moving parts than the volume justifies.
- In-memory queue: loses jobs on restart.

Consequences:
Revisit if job volume grows enough to strain the database.
Worker code lives in `src/jobs/worker.ts`.

Notice the Rejected section. Classic templates often fold alternatives into the context. For AI-assisted work, list them on their own. It is the part that stops a session from proposing the same option again.

Keep records short. If it takes more than ten minutes to write, it is probably a design document, and the record should link to it.

When to write one

You do not need a record for every choice. Write one when any of these is true:

  • You rejected a reasonable alternative. If a smart newcomer would suggest it, write down why not.
  • The choice is hard to reverse. Data formats, public APIs, storage, authentication.
  • You chose something unusual on purpose. A pinned old version, a skipped test, a slower but simpler algorithm.
  • You had to look something up to decide. The research will not be in the code.
  • An assistant proposed something you said no to twice. That is a clear signal.
  • A teammate asked "why is it done this way?" Answer once, in a file.

A useful habit: at the end of a session where you made a real choice, ask the assistant to draft the record from the conversation. Then edit it. The draft saves time, but you own the reasoning, so read it before saving.

Where to keep them and how to name them

Keep records in the project, next to the code they describe. A layout that stays readable as it grows:

.prjcontext/
  memory/
    decisions/
      README.md
      2026-06-10-retry-jobs-twice.md
      2026-08-02-keep-rest-api-v1.md
      2026-09-18-db-job-queue.md

Naming tips:

  • Start with the date. Files sort in order, and you see at a glance how old a decision is.
  • Use a short slug that states the decision, not the topic. db-job-queue is better than queues.
  • Keep an index. decisions/README.md lists each record with its status in one line. It is the file an assistant reads first.
# Decisions

- 2026-06-10 Retry failed jobs at most twice (accepted)
- 2026-08-02 Keep REST API v1 until mobile app update (accepted)
- 2026-09-18 Database-backed job queue (accepted)

Make your assistant read them

Records only help if the session sees them. Point to them from your project instructions. Claude Code reads CLAUDE.md files, and many other coding agents read AGENTS.md, so add a short rule to whichever you use:

## Decisions
Before proposing a new library, a structural change, or a change to
how jobs, storage or the API work, read
`.prjcontext/memory/decisions/README.md` and any related record.
If your proposal goes against an accepted decision, say so and explain
what has changed since it was made.

The last sentence matters. You do not want the assistant to treat records as untouchable. You want it to argue with them openly instead of ignoring them.

Before and after

Here is the difference in practice. Without a record, a new session reviewing the job worker might say:

The polling worker is inefficient. I suggest moving jobs to a
message broker for better scalability.

With the index and the rule above, the same session is more likely to say:

Decision 2026-09-18 chose a database-backed queue over a broker
because of low volume. Job volume looks unchanged, so I will keep
the current design and only fix the retry bug you asked about.

The second answer saves you the re-explaining. It also tells you when a decision might need revisiting, because the assistant names what would have to change.

Close the loop at the end of a session

Add one more line to your instructions, so new decisions get captured while the reasoning is fresh:

At the end of a session where we chose between real alternatives,
offer to draft a decision record in `.prjcontext/memory/decisions/`.

The article on writing CLAUDE.md and AGENTS.md covers how to keep that file short. For the wider picture of what belongs in memory, see project memory for AI coding.

Replace decisions, do not rewrite them

Decisions change. When one does, do not edit the old record to say something new. Write a new record and mark the old one:

Status: superseded by 2026-11-03-move-jobs-to-broker.md

This keeps the history honest. Six months later, you can see that you used a table-based queue, why, and what changed. An assistant reading the index sees the current answer and the path to it.

Keep the status values few: proposed, accepted, superseded. More states tend to go stale.

How PrjLab handles this

We built PrjLab to keep project memory next to the code it explains. Put your records in .prjcontext/memory/decisions/ and they are captured as project memory, not mixed in with source files. Each prj push creates an immutable version with a list of changes and a line diff, so you can see when a decision was added or superseded. Teammates you share the repository with, as readers or writers, get the records when they run prj clone, together with your instructions and saved sessions. If you make the repository public, the memory is public too, so review it first. The getting-started guide shows the setup.

Frequently asked questions

Is this the same as an ADR? It is a light version of one. The main addition is a separate "Rejected" list, because that is what stops an assistant from proposing the same option again.

Should I put decisions in CLAUDE.md or AGENTS.md directly? Only a one-line pointer. Instructions files work best short. Keep the records in their own folder and let the instructions tell the assistant where to look.

Can the assistant write records for me? It can draft them from the session. Always read and correct the draft, since the reasoning is yours and a wrong record is worse than none.

What about small projects? Small projects benefit most, because there is no teammate to ask. Even three records save you from re-explaining your own choices.

To keep decision records with your project across machines and teammates, start with the getting-started guide.