grep, but semantic, for your Claude Code conversation history. Local-first, hybrid BM25+vector retrieval.
Project description
claudegrep
grep, but semantic, for your Claude Code conversation history. Local-first, private, fast.
Every Claude Code session vanishes the moment you close it. claudegrep indexes
your ~/.claude/projects/ JSONL files into a single SQLite database and
gives you a fast CLI (recall) to find any past turn — hybrid BM25 + vector
search with optional cross-encoder reranking.
$ recall search "sqlite vec hybrid"
1. 2026-04-29 claude-recall score=-18.4
how should we store the chunk vectors — sqlite-vec or lancedb?
[assistant] for <10M vectors sqlite-vec wins on ops simplicity…
2. 2026-04-22 gstack score=-14.1
…
Status
Week 5 / 6 — recall serve is live: a local FastAPI + HTMX web UI at
http://127.0.0.1:7777 with hybrid search, inline filters, session viewer,
and one-click "copy turn" to clipboard. v0.3.0 ships it.
See PLAN.md.
Install
# CLI only (~120 MB with embedder model)
uv tool install claudegrep
# or:
pipx install claudegrep
# CLI + local web UI
uv tool install 'claudegrep[serve]'
# first run
recall index
recall search "your query"
recall serve # opens http://127.0.0.1:7777
Dev install:
git clone https://github.com/lbbstarry/claudegrep
cd claudegrep
uv sync
uv run recall index
Commands
| Command | What it does |
|---|---|
recall index |
Scan ~/.claude/projects/ and index + embed new/changed sessions (incremental via mtime + sha256). --no-embed for BM25-only. |
recall search <q> |
Hybrid BM25 + vector search by default. --mode bm25|vector|hybrid, --rerank, --limit N, --project NAME. Inline filters: project:foo since:7d role:user tool:Bash. |
recall show <session> |
Render a session as Markdown. Accepts an 8+ char prefix; use --turn N to view one turn. |
recall inject <chunk> |
Copy a chunk's text to your clipboard so you can paste it into a new Claude session. |
recall export <session> -o file.md |
Export a session to disk as Markdown. |
recall watch |
Re-index in the background as JSONL files change (debounced; uses polling on WSL2). |
recall serve |
Local web UI on 127.0.0.1:7777 (FastAPI + HTMX). Requires [serve] extras. |
recall stats |
Index size, vector count, DB path. |
python -m claude_recall.eval.run |
Run the labeled eval set, print Recall@10 / MRR / nDCG@10, write benchmarks/eval_results.md. |
Coming in Week 6+:
- bge-m3 + query expansion (planned biggest single eval bump)
- Pro tier: encrypted cross-machine sync, voyage-3-lite embedder
- v1.0 + Product Hunt launch
Architecture
~/.claude/projects/*.jsonl
│
▼
parsers/claude_code.py typed Message records
│
▼
ingest/chunker.py per-turn chunks (one user msg + following assistant)
│
▼
embed/local.py sentence-transformers (bge-small-zh) + disk cache
│
▼
store/ SQLite + FTS5 + sqlite-vec (vec0 virtual table)
│
▼
search/ bm25 · vector (KNN) · hybrid (RRF) · rerank (cross-encoder)
│
▼
cli.py Typer app
Why per-turn chunks? Per-message loses Q-A pairing; sliding-window inflates
the index 3-5×. A turn averages ~1.2k tokens — perfect for bge-m3's 8k
context, no truncation needed.
Why SQLite + FTS5 + (later) sqlite-vec? Single file, zero ops, ships with the wheel, hybrid search is a JOIN away. Beats Chroma at this scale.
Eval
51 hand-labeled (query, relevant_chunk_id) pairs from real developer
sessions in tests/fixtures/queries.jsonl. Index size: 6,593 chunks across
127 sessions / 6 projects. Reproduce with python -m claude_recall.eval.run.
| Method | Recall@10 | MRR | nDCG@10 | p95 ms |
|---|---|---|---|---|
| BM25 (FTS5) | 0.216 | 0.125 | 0.148 | 2 |
Vector (bge-small-zh-v1.5, 512d) |
0.353 | 0.175 | 0.217 | 13 |
| Hybrid (RRF) | 0.392 | 0.175 | 0.228 | 16 |
Hybrid + rerank (bge-reranker-base) |
0.471 | 0.230 | 0.289 | 214 |
Hybrid + rerank gives +118% Recall@10 and +95% nDCG@10 over BM25.
Reranker latency is dominated by CPU cross-encoder inference; GPU or
bge-reranker-v2-m3-onnx will reduce it. Numbers are CPU-only on a WSL2
Ryzen laptop.
Why the absolute numbers look modest: the eval queries are deliberately
short (median 5 chars) and developer-domain-specific, e.g. prefab,
figma示例. That is the realistic distribution for "I vaguely remember
talking about this last month" — and the gap between methods, not the
absolute floor, is what matters. Query expansion and bge-m3 (8k context,
multilingual) are next.
Roadmap
- Week 1 — Typer CLI, SQLite + FTS5, incremental ingest, BM25 search
- Week 2 — bge-small-zh embeddings, sqlite-vec, RRF hybrid, reranker, 51-query eval
- Week 3 —
show/inject/export,watchdaemon, filter DSL,--rerankflag - Week 4 — v0.2 on PyPI, eval blog post drafts (EN + ZH)
- Week 5 —
recall serve(FastAPI + HTMX local UI), v0.3 - Week 6 — v1.0, Pro tier (cloud sync, Voyage embedder), Product Hunt
Privacy
Everything stays on your machine. The index is a single SQLite file under your
OS's user data dir (~/.local/share/claude-recall/recall.db on Linux). No
network calls are made by the OSS build.
License
Apache-2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file claudegrep-0.3.0.tar.gz.
File metadata
- Download URL: claudegrep-0.3.0.tar.gz
- Upload date:
- Size: 166.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
505f37c0f56251dcf4f2e32bb6310c776de6de3735031a40d7aa07482c08b335
|
|
| MD5 |
6a5f0bc6bc3fabeb44357f71b72e98d1
|
|
| BLAKE2b-256 |
6b8c3b9299ad7a9aabe1bd87aa24a334a7f5b3424d7aac3abbebdd1b15a2425b
|
File details
Details for the file claudegrep-0.3.0-py3-none-any.whl.
File metadata
- Download URL: claudegrep-0.3.0-py3-none-any.whl
- Upload date:
- Size: 33.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
565302643c744d1bd1475dd556656d64188a64ddaf3d61b0bd9e82f6dbd36f14
|
|
| MD5 |
433849292b4b5fd3ec3b734a57601c47
|
|
| BLAKE2b-256 |
382ba6f94dcc2328ebac81c87bf7fee51d0ae0686d77145024e96423a66a6c6e
|