Skip to content
sessionsv1.21.0

Local-first recall for AI coding agents

Four agent CLIs.
One searchable memory.

Every AI coding session leaves a transcript behind, and every one of them is effectively write-only. sessions builds one full-text index over Claude Code, Codex, Pi, and OpenCode — then hands it to your agents over MCP, so the next one starts out knowing what the last one already decided.

$brew install nicknisi/formulae/sessions$sessions setup

Standalone binary · no runtime · sessions setup wires up every agent CLI it finds

agent CLIs, one index
4agent CLIs, one index
MCP tools, all read-only
8MCP tools, all read-only
skills that compose them
6skills that compose them
bytes that leave your machine
0bytes that leave your machine

What is already on your disk

Four tools, four layouts, one timeline. This is the list sessions pipes into fzf when you run it with no arguments.

mar 3
authkit-webclaudeRefactor the auth middleware to use JWT
apr 22
api-servercodexAdd rate limiting to the /api/v2 endpoints
jun 8
sessionspiWhy is the FTS5 index rebuilding every run?
jul 14
authkit-webopencodePort the session store to the new schema

1,847 more, indexed message by message — sample data, invented for this page

today

MCPreaches back along the spine

Your agent asks the question for you.

The point is not that you can search your history. It is that the agent does it unprompted — before re-deriving a decision, when a why-question is not answered by the code, when you say “didn’t we already fix this”.

  1. mar 3
    authkit-webclaudeRefactor the auth middleware to use JWT
  2. mar 9
    authkit-webpiHelp me debug the flaky integration test
  3. apr 22
    api-servercodexAdd rate limiting to the /api/v2 endpoints

reached back 4 months, unprompted

agent · you asked why refresh tokens rotate here
search_sessions({ query: "jwt refresh rotation" })
3 sessions · best hitauthkit-web, mar 3, msg#41
get_session_digest(mar 3) → the whole arc, ~2k tokens

8 tools, grouped by what you are trying to do

Find it

Two ways in, and the difference matters: one ranks, one is exhaustive.

  • search_sessions

    Ranked search across every session, message-granular. Returns the matching messages, not just the sessions — and a ready-to-run resume command. Top-k, so it is fast and not exhaustive.

  • grep_sessions

    Every message matching a literal string or regex, with a true total. This is the one for "how many times did I say that" — ranked search would quietly miss some.

Read it

Expand only the part that matters. Neither of these pages a full transcript.

  • get_session_digest

    One session's whole arc in a single bounded call, around 2k tokens: every real turn you took, paired with the reply that closed it. Long sessions elide the middle, never the ends.

  • get_session_messages

    The exact exchange a search matched — pass the hit index straight through as the offset. Ask for tool calls too and you see what the agent actually did, which the prose usually leaves out.

Know where you are

The two calls worth making before writing any code in a repo you have been away from.

  • get_context_primer

    Where you left off here: recent sessions in detail, older ones as headlines, the branch you were on, and the last thing each one said.

  • get_memory

    The standing instructions you have already given — build conventions, tooling constraints, rules you should not have to restate. Scoped to this repo, its project group, and your cross-repo workflow rules.

Account for it

Time-scoped rather than topic-scoped, for recaps and for knowing where the money went.

  • get_activity_digest

    A date range grouped by day and project. This is what a weekly summary or a standup is built from.

  • get_session_metrics

    Tool and project breakdown, daily activity, and the hours you are actually working.

…and 6 skills that compose them

A skill is the workflow, not the tool: /recall searches by topic, digests the best candidates, and expands only the exchanges that matched. Say any of the phrases below and it fires.

  • /contextoptional repo path

    Prior decisions, dead ends, and the thread you left open.

    “what was I doing here”“catch me up on this repo”“context primer”“what's the open thread”

  • /recallproject name or path

    The reasoning behind one past decision, without paging a transcript.

    “what did I do on [project]”“recall [topic]”“history of [project]”“when did I last work on [thing]”

  • /standup

    Yesterday and today as terse bullets you can paste into Slack.

    “standup”“what did I do yesterday”“daily summary”“what have I been working on”

  • /weekly-summary

    A structured week, then a nudge toward any new memory worth keeping.

    “weekly summary”“what did I do this week”“summarize my week”“weekly recap”

  • /session-metricstime period (e.g., "past week", "may", "past month")

    Which tool you actually use, and the hours you actually work.

    “how much have I been coding”“session stats”“show me metrics”“tool usage”

  • /memoryrepo path (optional, defaults to current repo)

    A mined batch clustered and triaged — approve, reject, or snooze each one.

    “triage memory”“review memory”“mine memory”“/memory”

And the half that outlives any one session

Search answers “what happened”. Memory answers “what am I not supposed to have to say again” — build conventions, tooling constraints, the rules you have already stated. Candidates are mined from your own transcripts; nothing becomes memory until you say so.

  1. 01mine

    Durable facts pulled out of past sessions as candidates.

  2. 02triage

    Approve, reject, or snooze each one. Paraphrases merge into a single fact.

  3. 03scope

    Bound to this repo, a project group, or every repo you work in.

Approve with --always-on and a fact is returned for every topic, first — so an agent that truncates drops the conditional tail, never the invariants.

may 1–31

Reportbrackets a span of the spine

Where the money actually went.

sessions report reads the same four transcript sources and writes a self-contained HTML dashboard — cost, tokens, cache savings, and breakdowns by tool, provider, model, project, and subagent. Roughly half of a heavy Task user’s tokens land in subagents; this is the view that says which ones.

sessionsmay 1 – may 31 · all tools
$412.68
estimated cost
1.24B
tokens
184
sessions
11
day streak

Cost per week

apr 28
may 5
may 12
may 19
may 26

By subagent$285.70 of $412.68

general-purpose$148.20
code-reviewer$86.40
Explore$51.10

Active hourspeak 10:00

0006121823
Sample figures, invented for this page. In a real report the cost is estimated from LiteLLM pricing data — the product never claims it is a bill.

Every number explains itself

In the HTML, each stat, heading, and column says on hover what is counted, what is excluded, and what the cost is an estimate of.

Bounded periods get a pace

Spend per active day, a straight-line projection to the end of the period, and the equally long window immediately before it.

Incremental by default

Parsed transcripts are cached against mtime and size, so a second run re-reads only what changed.

$sessions report --this-month
$sessions report --format text --today
$sessions report --days 30 --tool claude
the year

Wrappedcollapses the whole spine

The year, as a deck you scroll.

sessions wrapped turns the same index into a scroll-through story: tokens at human scale, the receipt, streaks, a rhythm heatmap, your most significant session — and a set of stats mined from what you and your agents actually said to each other.

Tokens

1.24billiontokens

that's the Voyager 1 record, transmitted 380 times

across claude · codex · pi · opencode

The receipt

$412.68at APIrates

about 68 oat-milk lattes

estimated from LiteLLM pricing · not a bill

Most said

“You'reabsolutelyright”

47 times · your record was 6 in one session

mined from what you actually said to each other

Your type

Thenightrefactorer

nocturnal · high-interrupt · one-repo-at-a-time

built from three behavioural axes, evidence on the card

Sample cards, invented for this page · the real deck picks its slides from your data

The slides are chosen, not fixed

Every candidate stat is scored for how notable it is in your data, and only the top ones render. A daylight coder never sees a 3 AM slide.

It ends with a reveal

A coding personality built from three behavioural axes, with the evidence printed on the card — then a shareable image at 1200×630 or 1080×1920.

Roast mode is opt-in

Hands your stats to an agent CLI you already have and asks it to improvise. Only stats are sent, never transcripts, and it fails open.

Token and cost math match sessions report exactly. Because AI tools prune old transcripts, the page discloses when its data actually starts if that is later than January 1.

How it works

Four layouts in, one index, three ways out.

The index is SQLite with FTS5, built on first use and updated incrementally by modification time. Hits are message-granular, so a match localizes to the exact message rather than the session that contained it.

  • Claude Code
    ~/.claude/projects/
  • Codex
    ~/.codex/sessions/
  • Pi
    ~/.pi/agent/sessions/
  • OpenCode
    ~/.local/share/opencode/
One index
~/.cache/sessions/index.db
SQLite + FTS5 · message-granular · incremental
  • MCP server
    8 read-only tools
  • sessions report
    usage dashboard
  • sessions wrapped
    the year, as a deck

Constraints

What it will not do.

These are load-bearing. Recall over your own transcripts is only worth having if the boundaries are boring and checkable.

  • Nothing is uploaded

    Every transcript searched is already on your disk, the index is a local SQLite file, and the report and wrapped are HTML written to your machine and opened from it. There is no account and no server. The one seam that talks to anything is --roast, which hands your computed stats — counts and project names, never transcript text — to an agent CLI you already have installed.

  • Every MCP tool is read-only

    All eight are annotated read-only and none of them writes. Memory is the only thing that persists a decision, and it changes only when you triage a candidate yourself. A store nobody curates is just a log.

  • Estimates say they are estimates

    Cost is estimated from LiteLLM pricing, cached daily with an offline snapshot. A model with no published price is billed at its family’s newest rate and flagged; one in no known family counts as $0, loudly. Roast slides are stamped “improvised by <tool>” so a generated line can never read as a counted one.

  • Auto-injection is off until you ask

    A session-start hook can drop a small primer into every new Claude Code session — three recent sessions for the current repo. It is opt-in, because it costs tokens every single time, and this is your budget rather than a default worth taking on your behalf.

now

Install

Two commands, then stop thinking about it.

The Homebrew build is a standalone binary with no runtime. sessions setup detects the agent CLIs you have, writes the MCP config for each, and registers the skills. Run it again after an upgrade.

$brew install nicknisi/formulae/sessions$sessions setup

fzf is optional — without it you get a numbered list instead. Removing everything the installer wrote is sessions uninstall; your triage decisions survive it.

Full reference