Projects

Retro Agent

2026 · Kusha Sahu

What it is

Claude Code deletes your session transcripts after thirty days by default. I found out the way you would expect, which is by going looking for one. Twenty-six sessions at the start of an afternoon, eight by the end of it, and nothing older than a month left on disk.

That is annoying on its own. The more interesting problem is that even when the transcripts are there, none of the usage dashboards tell you the thing you actually want to know. They report tokens, and token volume is equally consistent with a productive session and a session spent going in circles. In my own history, cached context replay outnumbered generated tokens 296 to 1, so the headline number was mostly the model re-reading its own context.

retro is a CLI that reads what the agents already leave on disk and answers two questions instead. Where did I have to say it twice, and can this session be shown to anyone else. It runs entirely locally. There are no network calls anywhere in it.

How it works

Three agents, three completely different stores. Claude Code writes one JSONL file per session under ~/.claude/projects. Codex writes date-partitioned JSONL under ~/.codex/sessions. Cursor keeps everything in a SQLite key-value table inside its editor state, 145 conversations and nineteen thousand message rows in my case.

An adapter per agent normalises all of it into one representation whose load-bearing field is what a tool call did, not what it was called. Claude Code names its tools, so an edit is an Edit. Codex pushes almost everything through a shell, so an edit is an apply_patch or a sed -i buried in a command string. Cursor names them again but differently. Every metric above that line sees only edit, verify, read, shell, and never touches an agent-specific string.

Then the measurements, all of them deterministic. No model is involved and none is wanted: a score meant to be comparable cannot change between runs, and transcripts hold credentials and other people's correspondence, so nothing should leave the machine. The headline number is verification runs per file edit. The one I like most is churn:

for i in range(len(poss) - 2):
    a, b = poss[i], poss[i + 2]
    if b - a <= 10 and not any(a < v < b for v in verify_pos):
        churn.append((basename(fp), len(poss)))

Three edits to the same file inside a ten-call window with no verification call between the first and the third. It makes no judgement about whether the edits were good. It only observes that nothing was checked in between. On my own worst session that fired on a file edited twenty-six times with zero test runs, which is not a number anyone would defend out loud.

The hard part is comparison, not parsing

Once three adapters existed, the obvious next move was to compare agents. That turns out to be a trap. Each adapter is blind in a different place, and a coverage gap looks exactly like a behavioural difference. Cursor supplies a usable timestamp for nine per cent of sessions and no token counts at all, so a naive read makes it look dramatically cheaper and faster than it is.

So there is a parity command whose only job is to report what each adapter can actually observe, and to refuse a cross-agent comparison of any metric whose inputs are not covered on both sides. It caught two of my own bugs before I could publish numbers based on them, including one where I had filled a timestamp field without making it meaningful and my own coverage check happily reported a hundred per cent.

The part I did not expect

Archiving turns data your agent deletes on a schedule into data that lives forever, and that thirty-day cleanup had been acting as a security control nobody meant to rely on. The first version of the archive was a faithful copy, which meant it was also a permanent store of 366 database connection strings, 133 key-shaped strings and 220 email addresses belonging to other people, sitting unencrypted in my home directory.

So the tool asks before it stores anything, strips credentials on the way in rather than on the way out, leaves Cursor's verbatim before-and-after source code behind by default, encrypts on request, and has a forget command. Sanitising a session for sharing is a separate step that fails closed: anything that looks like a secret is masked, and everything masked is listed for you to read before you send it anywhere.

That last part has a real limit worth stating. Pattern matching catches secrets, paths and addresses. It does not catch context that has no shape. A bundle that came back clean on every rule still contained a job-board URL with posting IDs in it, which tells a reader something no regex was ever going to flag.

Numbers

Measured on a 163-session corpus across three agents.

  • 296 to 1 cached context replay against generated tokens, which is why volume is not the metric
  • 0.12 verification runs per file edit, roughly one check per eight edits
  • Credentials in the archive: 366 connection strings to zero, every JWT to zero, verified by re-running the scan that found them
  • 32,984 blocks of verbatim source code omitted from Cursor sessions rather than stored
  • A year of prompt history recoverable where only thirty days of transcripts survived: 133 active days against 34

It is a working prototype rather than a finished tool, and its gaps are written down in the README rather than left for you to discover. There are no tests. Roughly 47 per cent of my own edits are invisible to the activity heatmap because most Cursor sessions carry no usable date, and the tool says so instead of printing a confident number.