crispy-recall
v0.4.0
Published
Local session transcript memory for Claude Code and Codex — search past sessions with FTS5 + semantic vectors.
Maintainers
Readme
crispy-recall
Let your agents search your past conversations.
Recall lets Claude Code and Codex look up your past conversations, so you can start a new session whenever you want. Close a long chat to save tokens without writing a handoff or worrying about losing what you worked through. Your next session can retrieve just what it needs.
Just ask: “Recall where we left off,” “Recall why we chose this approach,” or even “Recall <session ID> and continue.” Your conversations are saved automatically, so your agent can find the relevant discussion or pick up a specific session. Continuing an old, uncached session this way can also save tokens: Recall brings back the conversation without all the background activity that filled the original chat.
Under the hood, Recall indexes the JSONL conversation logs that Claude Code and Codex already generate in a local SQLite database, with vector embeddings generated by the open-source Nomic Embed Text v1.5 model running on your machine. A small skill teaches your agent to retrieve relevant passages using hybrid keyword and semantic search—local RAG over your conversation history, guided by what your agent needs right now.
Quick start (single machine)
Use Node.js 24 (or Node.js 22.16+) and install in the environment where you run Claude Code. This installs the stable single-machine release:
npm install -g crispy-recall
recall installIt picks up the conversation history already on your machine, so you can ask it to recall something straight away. The installer sets up the local embedding model, lifecycle hooks, and recall skill for Claude Code, with the same integration for Codex when detected.
More than one machine (experimental)
Keep your coding history on one hub. Each satellite uploads its transcripts and searches the hub, without running its own database or embedding model. Install Recall under the same account and in the same environment as your coding agent. WSL is optional; install separately in Windows and WSL if you use both.
Use Node.js 24 and a private network, such as your LAN or Tailscale. Recall does not configure Tailscale or SSH; remote access is separate from shared memory.
Satellite mode is experimental. On every machine (the hub and each satellite), install Recall first:
npm install -g crispy-recallOn the hub, initialize Recall, create a token for one satellite, and start listening on the hub's private IP:
recall install
recall hub token --host laptop
recall hub serve --bind <hub-private-ip> --port 7877 --detachSave the token shown. Use your hub's private IP below even if the generated
example shows 127.0.0.1. Give each satellite a different host name; issuing a
new token for the same name replaces its old token.
On the satellite, enter that token and connect to the hub. These commands read it interactively and pass it through stdin, keeping it out of shell history.
Bash:
read -r -s -p 'Hub token: ' recall_token; printf '\n'
printf '%s\n' "$recall_token" | recall install --hub http://<hub-private-ip>:7877 --token -
unset recall_tokenPowerShell:
$recallToken = Read-Host 'Hub token'
$recallToken | recall install --hub http://<hub-private-ip>:7877 --token -
Remove-Variable recallTokenInstallation starts uploading existing transcripts; new turns follow automatically. Check the connection and search shared history:
recall doctor
recall --all "a conversation from another machine"Keep the hub running and reachable. --detach does not configure startup after
reboot. On Linux, stop the detached hub before running recall hub install-service,
which starts and enables the systemd service; follow any printed linger instructions.
Windows and macOS need their own startup configuration. Live platform and reboot
acceptance for this prerelease is still pending.
Only connect trusted users: satellites upload raw transcripts, and every hub token can search the entire hub history. See Privacy and data.
How to use recall
Ask your agent
Ask about what you worked through, or give your agent a session ID and continue from there:
| Say this | What your agent can recover |
|---|---|
| Recall where we left off. | The decisions, unfinished work, and next step from prior sessions. |
| Recall why we chose this approach. | The reasoning and alternatives discussed before the decision. |
| Recall — we solved this before. | The earlier fix, even when your new wording doesn't match the transcript. |
| Recall <session-uuid> and continue. | A UUID-backed conversation in a fresh session, centered on the relevant part. |
| Recall why this line exists. | The session behind a commit or line, including alternatives discussed at the time. |
The installed skill teaches Claude Code and Codex when and how to search, so your agent can invoke recall without you typing a special command.
Use the CLI directly
Search first:
recall "why did we choose this retry policy?"Every result includes a session id and the matched message id. For UUID-based Claude Code results, read the promising result centered on the match:
recall <session-uuid> <message-uuid>Search defaults to the current project's sessions. In 0.4.0, matching repositories share a search scope across clones and worktrees. Expand only when needed:
recall --all "the decision may have happened in another repo"
recall --project ~/dev/other-repo "the decision"
recall "the latest release issue" --recentrecall surfaces evidence, not truth. Good agents check recovered context against git HEAD, the current files, and fresh tests before acting on it.
Why recall?
My agent burned 20 minutes re-diagnosing a failure. The one-line fix sat in 24 prior sessions.
So I built crispy-recall — local, verbatim search across my agent's past sessions.
Your agent doesn't need to guess what will matter later. It needs a way to search what actually happened once the question becomes clear.
What makes recall different
The conversation, not a summary
recall keeps the user and assistant conversation word-for-word. It doesn't replace the record with a model's guess about which details might matter later.
That distinction matters when you need the exact constraint, command, promise, rejected idea, or one-line fix that a summary would reasonably discard.
Auto-memory saves what you knew to keep. recall finds what you didn't know you'd need. They complement each other: one keeps selected facts close; the other searches the verbatim conversation record on demand.
Tool calls, tool output, hidden thinking, and images are intentionally excluded from the searchable conversation. Tool output is re-runnable; the conversation that interpreted it isn't.
Continue without replaying the session
Read a past conversation by UUID-shaped session id:
Recall fe6cc221-2e63-4928-8417-65ec1587d062 and continue the release.recall reads the indexed conversation instead of replaying an entire raw transcript. Reads can open on the matched message, paginate forward, and combine context from several past sessions. That means your agent can recover the few facts that matter without pouring every old tool result back into its context window.
The indexed conversation stays available even after its original transcript is deleted. Your agent can also look up related discussions from other sessions as it works.
From a line of code back to the conversation
git blame can tell you who changed a line. recall --blame can take you back to the conversation that produced it.
recall --commit 25dd0f8
recall --blame src/paths.ts:82-84
recall --blame src/foo.ts:42 src/bar.ts:10-20 --limit 20Matching is structural: recall compares edits recorded in sessions with commit diffs instead of guessing from timestamps. A commit message summarizes intent; the conversation holds the reasoning, tradeoffs, and rejected alternatives.
Commit and blame attribution scans local Claude Code edits and Codex apply_patch records. It compares recorded changes with git diffs; edits made by arbitrary shell commands may not carry enough structured evidence for attribution.
git blame tells you who. recall --blame tells you why.
Search for the idea, not just the words
You rarely remember the exact phrase an agent used three weeks ago. recall searches two ways at once:
- SQLite FTS5 finds exact words and phrases quickly.
- Local semantic embeddings find the same idea under different wording.
- Rank fusion combines both result sets.
- Project scoping keeps everyday searches focused;
--allcrosses repositories when the project itself is the thing you forgot.
recall "the mac installer hang we fixed"
recall --all "why we stopped using the wasm sqlite binding"
recall --project ~/dev/my-app "booking slot id decision"Grep is still the right tool sometimes
If you know the exact string and the transcript still exists, use grep. recall earns its keep when:
- the transcript has already been deleted;
- your wording doesn't match the original conversation;
- the answer spans several sessions or repositories;
- you need to move from a commit or line of code back to the session that produced it; or
- you want your agent to retrieve the context itself instead of manually hunting through JSONL files.
Claude Code deletes transcripts after 30 days by default. The recall index doesn't. You can and often should raise cleanupPeriodDays; longer retention keeps more source files, while recall makes the record searchable after those files are gone.
Grep can't search a deleted file.
How it works
On a single machine:
- Stop and SubagentStop hooks index conversation text as turns finish.
- Nomic Embed Text v1.5 generates embeddings locally through llama.cpp.
- SQLite stores the text, FTS5 index, vectors, and session metadata in
~/.recall/. - A small skill teaches your agent to search first when prior work is likely to matter.
- Search results enter the context only when the agent asks for them.
On a single machine there's no resident daemon (the optional hub daemon runs only in satellite mode), and recall makes no LLM calls of its own. Indexing and search don't consume model tokens; retrieved text costs context tokens only when your agent reads it, like any other local file.
Install-time backfill indexes the Claude Code and Codex sessions still present on disk, so recall is useful on day one rather than only after day one.
Install
Requirements
- Node.js 24 recommended; Node.js 22.16+ is also supported for a local install or hub.
- Claude Code; Codex integration is added when detected.
- Linux x64/arm64, macOS x64/arm64, or Windows x64.
- macOS 14+ on Apple Silicon or macOS 13.7+ on Intel.
- 500 MB free for installation, plus space for database backups when upgrading.
Satellites also support Node.js 20, but installing on Node 20 requires Python, make and a C/C++ compiler. Node.js 21 and 23 are unsupported.
npm install -g crispy-recall
recall installDon't use
npx. recall installs persistent hooks, a skill, a model, and a command that must remain available after setup.
Run the installer in the environment where you use your agent. WSL and Windows-native are separate environments, so install once in each if you use both.
The installer:
- creates
~/.recall/; - downloads the llama.cpp binary and local embedding model;
- installs Claude Code and Codex lifecycle hooks when each harness is detected;
- installs the recall skill and a short AGENTS.md/CLAUDE.md nudge; and
- backfills the session history that is still on disk.
Use recall doctor if setup reports a problem. Use recall install --offline with pre-staged assets for an offline install.
Upgrading
Close active coding-agent sessions, upgrade the package, then run recall install
before using Recall again. For a stable release:
npm install -g crispy-recall
recall installOn an existing satellite, upgrade the package and re-run the satellite installer. It reuses the saved token for that hub:
npm install -g crispy-recall
recall install --hub http://<hub-private-ip>:7877The installer applies required migrations and keeps rollback snapshots. Allow up
to three database-sized backups when upgrading from 0.1.x, or two from 0.2.x.
If the database is busy, close the process using it and retry. Complete migrations
before searching; semantic results may be incomplete while background embedding
catches up. Check progress with recall status and recall doctor.
The 0.4.0 upgrade rebuilds Codex message identities from available transcripts. Keep the default backfill enabled to recover sessions previously missed by the index. Deleted source transcripts cannot be recovered.
If an earlier build missed messages or misordered turns, run this on the local installation or hub after upgrading:
recall repair --messages
recall backfill --auto-embedThis repairs known transcripts without clearing retained history. Avoid
recall repair --full unless you intend to rebuild the index from the transcripts
still on disk. Do not downgrade to 0.1.6 or earlier after database conversion.
Command reference
| Command | Purpose |
|---|---|
| recall "<query>" | Hybrid text + semantic search in the current project. |
| recall "<query>" --all | Search every indexed project. |
| recall <session-id> [<message-id>] | Read a session, optionally centered on a match. IDs are opaque — full stored IDs or literal prefixes (UUIDs, agent-<hex> leaves, codex-jsonl-* messages) all resolve. |
| recall read <session-ref> [<message-ref>] | Explicit read for any stored ID shape; a failed read exits nonzero and never falls back to search. |
| recall search <terms…> | Force a search when a term would otherwise look like a session/message ID. |
| recall --commit <hash> | Find local Claude Code or Codex sessions that produced a commit. |
| recall --blame <path>[:line[-line]] | Trace current code back to its producing local conversations. |
| recall install | Install or upgrade the hooks, skills, local assets, and history index. |
| recall backfill [--auto-embed] [--vendor <v>] [--detach] | Index session transcripts currently on disk, optionally for one vendor or as a detached job. |
| recall backfill --purge-meta [--dry-run] | Delete machine boilerplate rows indexed before the ingest filter existed; --dry-run opens the database read-only and only reports. |
| recall status | Show database size, message counts, embedding gap/migration progress, and active backfill state. |
| recall doctor [--integrity] | Run read-only install and database checks. |
| recall repair --fts \| --vectors \| --full | Rebuild FTS5, clear vectors for re-embedding, or fully reingest on-disk transcripts. |
| recall repair --messages | Re-read known transcripts to recover missed turns, fork history and ordering without clearing the index (hub only). |
| recall repair --rekey-codex | Run the one-time Codex message-id migration to full session UUIDs (hub only). |
| recall repair --rekey-projects [--force] | Fill project_key on existing rows; --force also re-keys already-keyed rows (hub only). |
| recall "<query>" --project-key K | Scope by an already-derived repo key (git:/origin:/path:), skipping derivation. |
| recall hub serve [--bind <addr>] [--port <n>] [--detach] | Run the hub daemon: mirror satellite transcripts and answer their queries (hub only). |
| recall hub token --host <name> \| --revoke <name> | Issue (or rotate) a satellite's bearer token, or revoke one without a restart (hub only). |
| recall hub status [--json] | Show the daemon, the resolved address, and per-host mirror and push/query state (hub only). |
| recall hub install-service | Register the systemd user unit so the daemon starts at login (hub only). |
| recall install --hub <url> --token <t>\|- | Register this machine as a satellite of that hub; - reads the token from stdin (satellite only). |
| recall push [--full] | Push pending transcripts to the hub now; --full re-offers every transcript (satellite only). |
| recall statusline [--suggest] | Print the session-id chip or integration guidance. |
| recall uninstall [--purge] | Remove the integration; --purge also deletes recall's data. |
Date-only --since and --until bounds cover UTC calendar days; explicit timestamps retain their stated offset. Both text and semantic searches apply these bounds before selecting candidates.
Run recall --help for the full search and read flag set. Add --json to install, uninstall, status, or doctor for machine-readable output. Installer options include --offline, --no-backfill, --auto-backfill, --statusline, and --no-statusline.
Optional statusline
recall install --statuslineIt is off by default: accepting the installer defaults, using --yes or a non-interactive install, or upgrading an install that has never enabled it will not opt you in. Once enabled, it stays enabled across upgrades. If Claude Code has no statusline, recall installs a muted line with the current folder and git branch, model, context use, and a 🔗 <session_id> chip. If you already have a statusline, recall leaves it unchanged and prints paste-ready integration guidance; recall statusline --suggest repeats it later.
The installed statusline never opens the database. Its only I/O is one guarded git status call with a 400 ms timeout; failure simply drops the git segment, and any segment whose input is missing is omitted. For composition with your own statusline, recall statusline prints only the bare, uncolored session-id chip. Uninstall removes the line only if recall still owns it, and doctor reports statusline problems as warnings.
Warning:
recall repair --fullis destructive: it replaces the index contents from the transcripts still on disk. If older source transcripts have already been cleaned up, their indexed history cannot be rebuilt. Prefer--ftsor--vectorsunless a full reingest is truly necessary. On a hub it also re-ingests the satellite mirror under~/.recall/remote/, and it refuses to run when that directory exists but enumerates no hosts — a satellite's history would otherwise be deleted and not rebuilt.
Privacy and data
- Your index lives in
~/.recall/recall.db. - On a single machine, search and indexing stay on that machine. In satellite mode the satellite forwards its query text and cwd to your hub and the hub does all indexing (see below).
- While a query is being embedded, its text is written to a transient file under
~/.recall/run/query-embed/(mode 0600) and deleted as soon as the embedding completes. - There is no telemetry.
- The database is plain SQLite and inspectable with ordinary SQLite tools.
- On a single machine, network access is limited to downloading the embedding runtime and model when missing, plus host reachability probes during install and doctor checks. A satellite additionally talks only to the hub URL you configured.
recall uninstall --purgeremoves the local store completely.
The installed integration is inspectable too: Claude's skill and hook live under ~/.claude/skills/recall/ and ~/.claude/settings.json. When Codex is detected, recall also uses ~/.codex/skills/recall/ and ~/.codex/hooks.json.
Satellites send raw transcripts and queries to your hub. Recall uses plain HTTP
without built-in TLS, so keep it on a private network. Each token can search the
whole hub index and upload only to its named satellite's mirror. Revoke a token
with recall hub token --revoke <name>; no restart is needed.
The index deliberately outlives source-transcript cleanup. recall doesn't encrypt recall.db; treat ~/.recall/ with the same care as your original Claude Code and Codex histories.
Limitations
- It isn't automatic fact injection into every prompt. Retrieval is pull-based.
- It isn't a replacement for documentation, tests, or git.
- It doesn't claim recalled context is still correct.
- It doesn't preserve tool output, hidden thinking, or images in the searchable conversation.
- It doesn't yet offer per-session deletion; forgetting is database-level today.
- Subagent transcripts (Claude Task leaves, Codex child rollouts) are stored durable and readable by explicit ID, but are excluded from default search, lists, and semantic vectors — the parent thread's narration is the canonical memory. There is no search mode that includes them yet.
- On a satellite,
recall --commitandrecall --blamesee local sessions only. They read local git and local transcripts, never the hub index. - A repo that is keyed
git:<root-commit>on one machine andorigin:<url>on another — a shallow clone, for instance — does not unify until both machines agree on the key. Rungit fetch --unshallow, thenrecall repair --rekey-projects --forceon the hub.
Project status
crispy-recall is in active development and was spun out of the recall subsystem in Crispy. See GitHub Releases for version history.
Issues and contributions are welcome at github.com/TheSylvester/crispy-recall.
License
MIT — see LICENSE.
Memory, lazily evaluated.
