Use case · software development

Stop re-deriving your own codebase, every session.

Your agent already reads the code — that part it's good at. What it can't recover is the why: why the retry lives in the gateway, why that "obviously better" refactor was reverted last month, which cache is secretly single-threaded. The code, git blame, and the issue tracker don't hold it. PriorStates does — recall before you change, record the decision as you go — and shares it across Claude Code, Codex, Cursor and Copilot.

The code is the what. The expensive part is the why.

Everything an agent needs splits in two. One half the repo answers perfectly. The other half it can't answer at all — by construction.

📄

The repo already has this

File layout, function signatures, what changed and when. Your agent reads it, git grep finds it, the type checker enforces it. Don't put it in memory — that just adds noise.

🧭

Nothing has this

Why the interface is shaped this way and the three alternatives you rejected. Why a workaround exists and the upstream bug it dances around. The convention no linter enforces. This is what PriorStates holds.

The loop, in five moves

Most sessions only do steps 2–3. PriorStates is steps 1, 4, 5 — the brackets that make a change build on the last one instead of starting cold.

  1. 1

    Recall first

    Before touching the subsystem, ask what's already known. A journal_search on the area surfaces the prior losers, decisions and landmines; a memory_search recalls your standing conventions. The mistakes you won't repeat are free.

  2. 2

    Plan the change

    Recall shapes the plan. With the dead ends ruled out and the invariants known, scope one change that respects them — not one that compiles and quietly breaks a rule nobody wrote down.

  3. 3

    Edit & verify

    Make the change and prove it: the test suite passes, the build is green, the repro no longer reproduces. The step ends with something you can stand behind.

  4. 4

    Record the decision

    The change isn't done when it's green — it's done when the next session can find why you made it. One journal_add (winner / loser / decision / gotcha) plus a memory_add for any durable convention. Store the invariant, never the line number.

  5. 5

    Recall again — in any tool

    Tomorrow's session re-runs step 1 and your decision is waiting — whether it's you in Claude Code, a teammate in Cursor, or a different agent entirely. One store, every tool.

Watch the loop close

Same search, two sessions apart, on a migration off a deprecated client library. The recall that starts today's work already carries what last week learned — and tomorrow it carries today's too.

Step 1 — recall before you start. Three prior findings appear before you write a line of code:

$ journal_search topic=client-migration

 outcome   title                                            TL;DR
 ───────   ──────────────────────────────────────────────  ─────────────────────────────
 gotcha    legacy client retried on 409, new one doesn't    callers must add explicit retry
 decision  Migrate call sites leaf-first, not the wrapper   wrapper-first broke 6 services
 loser     Moving retries into the SDK broke idempotency    reverted in #4412

You now know — for free — to go leaf-first, to add the 409 retry at each call site, and not to push retries into the SDK. Three traps you won't fall into this iteration.

Step 5 — record, then recall again. You migrated billing and inventory, all green, and journaled it. The same search now returns four:

$ journal_search topic=client-migration

 outcome   title                                            TL;DR
 ───────   ──────────────────────────────────────────────  ─────────────────────────────
 gotcha    legacy client retried on 409, new one doesn't    callers must add explicit retry
 decision  Migrate call sites leaf-first, not the wrapper   wrapper-first broke 6 services
 loser     Moving retries into the SDK broke idempotency    reverted in #4412
 winner    billing + inventory migrated (wrap + retry-409)  pattern proven, 2 of 9 services

The list grew. A fresh session — you tomorrow, a teammate, a different agent in a different editor — picks up at service 3 instead of a blank page.

Four kinds of finding worth keeping

Each entry is a plain Markdown file on your disk, semantically searchable, with a one-line TL;DR and a pointer to the PR or commit it came from.

🏆

Winner

What worked, with the pattern. “Migrate with wrap + retry-409, leaf-first.” The next service starts from it.

🪦

Loser

The dead end, so no agent re-walks it. “Retries in the SDK broke idempotency, reverted in #4412.” The single most expensive thing to rediscover — because losers never get committed.

⚖️

Decision

A standing choice, with its rejected alternatives. “Auth is validated in the gateway, never in services.” Stops every new session from re-litigating it.

⚠️

Gotcha

A landmine that bit you once. “OrderCache is not thread-safe — IO thread only.” Catches the bug before it ships, not in the incident channel after.

“Don't I already have CLAUDE.md and Cursor rules?”

You do — and they solve a different problem. Rule files are per-tool and injected into every session, so they don't scale and they don't travel.

🔁

One store, every tool

A fact you teach Claude Code is recalled in Codex, Cursor and Copilot too. A rule file is locked to one tool; PriorStates is the layer they all share.

🎯

Recalled, not pinned

Fifty standing instructions in a rule file drown the few that matter for this task. PriorStates surfaces the handful of relevant facts by meaning, on demand.

🌱

It grows with the work

A rule file is something you maintain. The journal accumulates as a side effect of doing the work — record-as-you-go, not a doc you keep forgetting to update.

You don't run any of this by hand

Once installed, your agents do it on their own.

priorstates init gives a repo its own memory and journal, and wires a short protocol block into Claude Code, Codex, Gemini, Copilot and Cursor: recall before you change, record durable decisions as you go. The agent calls journal_search / journal_add the same way it decides to read a file — no background process, nothing scraped silently, every entry a file you can read, edit or delete. It stays on your machine.

One rule keeps it a memory and not a junk drawer:

Store the why, never the what. If git grep could answer it, it's a comment, not a memory. If only the author's intent could answer it — the rejected alternative, the landmine, the unenforced convention — that's what goes in. And store the invariant (“writes are single-threaded”), not the coordinate (“line 412”), so a rename can't make your memory lie.

Give your codebase a memory.

Free, open source, and yours to run.