project-recall
by mishazim
README.md
# ProjectRecall
Local retrieval over your own project notes, served to Claude Code as an MCP server.
Ask "how did I fix that crash?" and get the paragraph you wrote months ago, with its file and line.
## How it works
1. **Index** — markdown files in allowlisted folders are split by heading, so every chunk keeps
its breadcrumb (`Project > Bugs > Encoder drift`).
2. **Embed** — chunks are embedded on your machine with `nomic-embed-text` through Ollama.
3. **Store** — one SQLite file holds the text, an FTS5 keyword index and the vectors.
4. **Search** — BM25 and vector rankings are merged with weighted reciprocal rank fusion.
5. **Serve** — an MCP server over stdio exposes `search_notes` and `list_projects`.
New to search or RAG? Start with the [documentation](docs/README.md): concepts, usage,
architecture, retrieval, evaluation and privacy, written for readers without a background
in any of them.
## Privacy model
The repository contains code and an invented sample corpus only.
- The index and the real config live in `%LOCALAPPDATA%\ProjectRecall`, outside the repository.
- Indexing is allowlist-only, and files that look like secrets (`.env*`, `*.key`, ...) are always skipped.
- Embeddings are computed locally; no hosted embedding API or vector database is used.
- The server speaks stdio only and opens no network port.
- A pre-commit guard blocks database files and any staged line that matches a privately indexed note.
Retrieved snippets do become part of the conversation with whichever MCP client asks for them.
## Setup
```
py -3.11 -m venv .venv
.venv\Scripts\pip install -e ".[dev]"
ollama pull nomic-embed-text
git config core.hooksPath .githooks
.venv\Scripts\recall init # creates the config; add your folders to it
.venv\Scripts\recall index
.venv\Scripts\recall search "why did training crash"
```
Register with Claude Code:
```
claude mcp add --scope user project-recall -- <repo>\.venv\Scripts\python.exe -m recall.server
```
## Evaluation
`python eval/run_eval.py` indexes `sample_corpus/` (16 invented projects with deliberately
overlapping topics, 148 chunks) and scores questions from `eval/golden.jsonl`. A question is
answered at rank *r* if the *r*-th chunk comes from the expected file and contains the
expected text.
Fusion settings were tuned on 99 dev questions. The table is the held-out test split: 59
questions (42 paraphrased, 17 exact-term), assigned by hash and scored once, after the
settings were fixed.
| Mode | hit@1 | hit@3 | hit@5 | MRR@5 |
| --- | --- | --- | --- | --- |
| BM25 | 67.8% | 78.0% | 84.7% | 0.735 |
| Vector | 88.1% | 96.6% | 98.3% | 0.921 |
| Hybrid (weighted RRF) | 91.5% | 96.6% | 100.0% | 0.943 |
Hybrid hit@1 has a 95% interval of 81.6% to 96.3%. It beats BM25 on 19 questions and loses
on none. Against vector search it is ahead on average but level question by question (2
better, 2 worse), so this eval does not show hybrid beating vector search; it does show
hybrid as the only mode that puts the answer in the top five every time.
Plain RRF (equal weights, k = 60) scored below vector search alone. The fix was a small k, a
vector weight of 0.8, and equal weights for short exact-term queries. See
[docs/retrieval.md](docs/retrieval.md) and [docs/evaluation.md](docs/evaluation.md).
## Tests
```
.venv\Scripts\python -m pytest
```
## License
MIT. See [LICENSE](LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues