Model or dataset
raiyanyahya/recall avatar
raiyanyahya/recall

Recall: offline session memory for Claude Code, summarised without a model call

Stop wasting tokens and re-explaining your project every session. Recall gives Claude Code , Opencode durable memory — entirely offline.

752 stars42 forksPythonMIT

At a glance

What is it?
Recall is an MIT-licensed Python plugin that logs Claude Code sessions to .recall/history.md and condenses them into context.md using a vendored TF-IDF plus TextRank summarizer. The judgement: it is a good fit if you want a diffable resume point without spending tokens on memory, and a poor fit if you expect semantic recall or run on Windows.
Who is it for?
Adopt Recall if you run Claude Code locally on a subscription, want a plaintext resume point in .recall/context.md, and are willing to run /recall:save or set auto_save_context to on_end. Do not adopt it if you want semantic retrieval across months of work, if your sessions are mostly tool output rather than prose, or if you need Windows support, since the README documents POSIX shell commands and a .sh installer.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 8 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The cold start problem Recall is built around

Claude Code begins each session with no knowledge of the previous one. The README states the problem directly: "Claude Code starts every session cold." The practical cost is that you re-explain the project, the current goal and where you stopped, and that explanation is paid for in tokens every time.

Recall targets people running Claude Code locally on a subscription. The README is explicit that the only AI in the loop is Claude Code itself, and that summarisation is done by a classical Python summarizer. That framing matters because it sets the cost model. Capturing and updating memory spends zero model tokens, and resuming from a compact context.md of roughly 1 to 2K tokens is cheaper than replaying a transcript or retyping context.

The project also draws a boundary against the built-in options. CLAUDE.md is hand-written memory that Claude treats as instructions. The --continue and --resume flags replay a prior conversation in full. Context compaction works inside a session and does not produce a record you reopen days later. Recall positions itself between those: an automatic log of what happened, condensed into a resume point, stored as plaintext in .recall/.

Two files, two different lifecycles

Recall writes into .recall/ inside your project. The README describes exactly two files, and their behaviour differs in a way that matters for anyone who wants to version or diff them.

history.md is the log. It is append-only, and every session is captured as it happens: your prompts, Claude's replies, the files touched and the commands run. Because it only grows, it is the durable record and the thing you would commit or inspect if you wanted to audit what happened.

context.md is the summary. It is overwritten by the local summarizer each time you run /recall:save, or automatically when auto_save_context is set to on_end. It contains the goal, a summary, next steps and open threads, files touched, and where you left off. Because it is overwritten rather than appended, its git history is where the interesting changes live. A single diff of context.md between two commits shows what the summarizer considered worth carrying forward.

Both are plaintext Markdown, which the README calls out as diffable and shareable. That is the main architectural decision here: memory is a file in your repository, not a database behind a service.

The mechanism: hooks capture, TextRank condenses

Capture runs through Claude Code hooks. The README lists Stop and SessionEnd as the hooks that append new activity to .recall/history.md, and notes that capture is incremental, meaning only new turns are written. SessionStart does the opposite direction: it surfaces context.md and has Claude ask you two questions, whether to resume from the saved context and whether to keep logging the session. That prompt is a deliberate choice. Recall does not silently inject memory; it asks first.

The summarizer lives in scripts/summarizer.py and is extractive, not generative. The README describes four steps: TF-IDF sentence vectors, a cosine-similarity graph between sentences, TextRank (PageRank power iteration over that graph) to score sentences, and finally the top N sentences kept in their original order. Nothing is rewritten. Sentences are selected.

context.md then wraps that selection with what the README calls deterministic facts pulled straight from the transcript and git: the goal taken from your first ask, files touched, commands run, where you left off, and git diff --stat. So the file is part extractive summary, part structured metadata.

The dependency story is unusual. The whole TF-IDF and TextRank implementation is vendored in summarizer.py, so no pip install is needed. If numpy is importable it is used to vectorise the math and the README says this is faster on big sessions; if not, an identical pure-Python TextRank runs instead. The README claims the same algorithm and same result, and says the save output reports which path ran. That last detail is the one to check if you care about reproducibility across machines.

Getting it running and the config keys that change behaviour

Recall is distributed as a Claude Code plugin, and the README's framing is that it starts working the moment the plugin loads. The repository layout includes .claude-plugin/plugin.json, commands/, hooks/, scripts/ and recall.config.json, which is where the slash commands and hook wiring are defined.

Installation is a Claude Code plugin install rather than a pip install. The README's installation section shows a bash one-liner using curl and sh, and a manual install that clones the repository into ~/.claude/plugins/recall and makes the shell scripts executable with chmod +x. Both routes are POSIX shell, which is worth noting for Windows users.

Once loaded, three commands are documented. /recall:save runs the local summarizer and overwrites context.md. /recall:show prints context.md. /recall:log tails history.md.

Configuration is a recall.config.json file in your project root. Four keys are documented in the README table. output_dir defaults to ".recall" and controls where history.md and context.md live. capture_history defaults to true and controls whether session activity is appended to history.md. auto_save_context defaults to "off" and accepts "off" or "on_end"; setting it to on_end regenerates context.md every time a session ends, removing the need to run /recall:save manually. The fourth key, summarizer, is cut off in the material available to me, so I cannot describe its accepted values.

Where the design costs you something

The summarizer is extractive, and that is a real constraint rather than an implementation detail. TextRank selects sentences that are central to the session text. It cannot synthesise a status you never wrote down. If the important decision happened in a tool call whose output was terse, or if the reasoning lived in Claude's replies rather than your prompts, the ranking may not surface it. The README's own description of context.md includes next steps, which implies those next steps exist in the transcript for the summarizer to find. Sessions that end mid-thought will produce a context.md that reflects the mid-thought state.

There is also a signal-to-noise question. history.md captures prompts, replies, files and commands. A session dominated by long command output gives TF-IDF a lot of low-value text to rank. The README does not describe any filtering, chunking or weighting by turn type, so the same scoring applies to a stack trace and to a design decision.

The hook dependency is the other failure mode. If the Stop and SessionEnd hooks do not fire, history.md stops growing and context.md summarises stale material. The README does not document hook diagnostics or a verification command, so the practical check is to look at whether .recall/history.md changed after a session. auto_save_context set to on_end also means context.md is rewritten at every session end, including short throwaway sessions, which will churn the file in git.

Finally, recall is per-project, living in .recall/ inside the repository. If you work across several repositories that share context, there is nothing in the README about a shared store or cross-project memory.

How it compares to mem0 and similar memory layers

The obvious comparison is a memory layer such as mem0, which extracts and stores facts about you and your project and retrieves them by semantic similarity, usually backed by a vector store and an embedding model. The difference in approach is fundamental. mem0 decides what is worth remembering using a model, which means the extraction step costs tokens or an API call and the retrieval step depends on embeddings. Recall does not decide anything semantically. It logs everything to history.md and then ranks sentences by graph centrality using TF-IDF and TextRank, entirely offline.

That trade is legible. Recall gives you a deterministic, inspectable artefact: you can open context.md, see the exact sentences that were selected, and diff it against yesterday's version. A vector-store memory gives you fuzzy retrieval across a long horizon but hides the selection behind a similarity score. Recall's README also argues the privacy point sharply, noting that most memory tools pipe context to a model endpoint while Recall sends nothing.

The cost of Recall's approach is recall in the other sense: it will not connect a note you made three months ago to a task today unless that note is still in the summarised window. It has no cross-session semantic index. If your need is "find everything I ever said about the auth refactor", Recall is the wrong tool. If your need is "tell me where we stopped yesterday without burning tokens", it is aimed exactly at that.

Maintenance, licence and what to watch on upgrade

The repository is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is a permissive licence and it is compatible with vendoring the summarizer into your own tooling, which the project already does internally. I am not a lawyer and this is not legal advice; if you plan to redistribute Recall inside a product, read the LICENSE file in the repository.

Release cadence, based on the tags supplied, has been steady: v0.3.5 in June 2026, v0.3.6 later that month, and v0.4.0 in July 2026, which the release notes title "OpenCode support (opt-in)". The opt-in label matters because the README's badge also marks OpenCode as opt-in, so the default path remains Claude Code. If you are on OpenCode, check the release notes for v0.4.0 rather than assuming parity.

Upgrade cost is low in the normal case, because your data lives in .recall/ as plaintext and the plugin is a directory under ~/.claude/plugins/. The thing to re-check after an upgrade is the hook wiring in hooks/ and the config schema in recall.config.json, since a new or renamed key would change behaviour silently. Because the summarizer is vendored rather than pulled from PyPI, upgrading the plugin is also how you get algorithm changes; there is no separate summarizer version to pin.

The project also carries CI and CodeQL workflow badges and a Codecov badge in the README, which indicates automated testing and static analysis are configured. I have not run the test suite and cannot speak to its coverage.

Editorial conclusion

Adopt Recall if you run Claude Code locally on a subscription, want a plaintext resume point in .recall/context.md, and are willing to run /recall:save or set auto_save_context to on_end. Do not adopt it if you want semantic retrieval across months of work, if your sessions are mostly tool output rather than prose, or if you need Windows support, since the README documents POSIX shell commands and a .sh installer. Verify two things before trusting it: that the hooks fire in your Claude Code version by checking that .recall/history.md grows after a session, and that context.md actually contains the next steps and git diff --stat you expect, because the summarizer is extractive and will drop anything it did not rank highly.

Official sources

  1. License: MIT
  2. Project website
  3. raiyanyahya/recall on GitHub
  4. README
  5. Releases
Community notes

Community notes