Skip to content

FedeMadoery/coderecall

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

10 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

coderecall

Your repo's memory, indexed locally. One SQLite file. Zero API keys.

coderecall β€” confidence-tiered local code search and knowledge store for AI coding agents

License: MIT MCP Local-first Bun

coderecall is an MCP server that turns any local repo into a searchable index your AI coding agent can query directly β€” code and the notes, decisions, and patterns you've accumulated about it. It runs entirely on your laptop. No OpenAI key. No Ollama. No vector DB to host. Vendor it into your project, run init, restart Claude Code.

  • Confidence-tiered context. Searches return full content for high-confidence hits, summaries for medium, and metadata-only stubs for the rest β€” so the model spends tokens where it's confident, not everywhere.
  • Knows when it's stale. Every search response embeds a banner the agent can see (🟑 Index is 17 days old), so the model can prompt you to reindex instead of silently searching old code.
  • Code + knowledge in one call. add_knowledge("we use SWR not React Query because…") lives next to your source in the same index, retrieved by the same search tool.
  • 6 languages with real parsers β€” TypeScript/JavaScript, Python, Go, Rust, Ruby, Elixir β€” plus a generic fallback. Adding a new one is a single file.
  • Truly local. Embeddings run in-process via Xenova/bge-small-en-v1.5 (384-D, ~30 MB on first run). Index lives in a single .coderecall/index.db β€” gitignored per developer, vectors never travel through git. The tool itself is vendored at tools/coderecall/ and committed, so the whole team stays on the same pinned version.

How it compares

coderecall claude-context basic-memory continue.dev @codebase
Local-only, no API key βœ… ❌ (needs embedder + Milvus) βœ… βœ… (deprecated)
Indexes code βœ… βœ… ❌ βœ…
Stores notes / decisions alongside code βœ… ❌ βœ… (separate) ❌
Single-file SQLite β€” no daemon, no Docker βœ… ❌ ❌ ❌
Tells the agent when the index is stale βœ… ❌ ❌ ❌
git diff aware incremental reindex βœ… partial n/a ❌
Works with any MCP client βœ… βœ… βœ… ❌ (VS Code extension)

Quick start

coderecall is vendored per project β€” its source lives at <your-project>/tools/coderecall/, gets committed alongside your code, and every dev shares the same pinned version. The local index (.coderecall/) and tools/coderecall/node_modules/ are gitignored automatically by init.

πŸ€– Agent-first (recommended)

Open Claude Code (or Cursor) inside the project you want to give a memory to, and paste this prompt:

Set up coderecall (https://github.com/FedeMadoery/coderecall) in this project: install bun if it's missing, vendor the repo into ./tools/coderecall with `bunx degit FedeMadoery/coderecall tools/coderecall` (so no nested .git), run `bun install` inside tools/coderecall, then from this project's root run `bun ./tools/coderecall/scripts/cli.ts init && bun ./tools/coderecall/scripts/cli.ts index`. Append the "Code Memory" snippet from the repo's README to my CLAUDE.md (create it if missing), then tell me to restart so the mcp__coderecall__search tools load. Don't commit or push anything.

The agent vendors the tool into ./tools/coderecall, wires it into this project's .mcp.json with a portable relative path, runs the first index (~30 MB model download), and updates CLAUDE.md. Restart Claude Code when it's done.

Manual

# 1. Install bun (one-time)
curl -fsSL https://bun.sh/install | bash

# 2. From your project root, vendor coderecall into ./tools/coderecall
bunx degit FedeMadoery/coderecall tools/coderecall
cd tools/coderecall && bun install && cd ../..

# 3. Wire it into the project (writes .coderecall.json + a relative .mcp.json entry)
bun ./tools/coderecall/scripts/cli.ts init

# 4. Index the codebase (downloads ~30 MB embedding model on first run)
bun ./tools/coderecall/scripts/cli.ts index

# 5. Restart Claude Code (or Cursor). The `mcp__coderecall__search` tools appear.

# 6. Commit ./tools/coderecall β€” its node_modules is gitignored, your team gets a pinned version.
git add tools/coderecall .gitignore .coderecall.json .mcp.json
git commit -m "Add coderecall MCP server"

Tip: alias coderecall="bun ./tools/coderecall/scripts/cli.ts", then coderecall init, coderecall index, coderecall search "...".

Updating coderecall: re-run bunx degit FedeMadoery/coderecall tools/coderecall --force && cd tools/coderecall && bun install to pull the latest version. Diff and commit β€” your team gets the update on next pull.

Recommended CLAUDE.md note

Add this to your project's CLAUDE.md so the agent reaches for the tool first:

## Code Memory

Before reading source files directly, **search the index first**:

  mcp__coderecall__search("how does authentication work")

Use `filter: "code"` or `filter: "knowledge"` to narrow. The index covers
this repo and any knowledge entries added via `add_knowledge`.

MCP tools exposed

Tool Purpose
search Confidence-tiered search β€” returns full / summary / metadata tiers. Use this by default.
search_memory Same hybrid search, always returns full content.
add_knowledge Store a knowledge entry (architecture / decision / pattern / note / troubleshooting).
list_knowledge List entries, optionally filtered by category or tag.
index_files Index a path. Defaults to extensions from .coderecall.json.
index_diff Index only files changed between two git refs β€” fastest way to refresh after a branch switch or git pull.
get_file_context List every chunk in a file with line ranges and signatures.
get_index_stats File count, chunk count, knowledge count, last-indexed timestamp.

How confidence-tiered context works

The search tool retrieves 5Γ— the requested number of candidates, scores them with FTS5 keyword + cosine vector + recency, enforces diversity (max 3 chunks per file), then expands each result into one of three tiers:

Tier Score What you get
🟒 Full β‰₯ 0.7 Complete content
🟑 Summary 0.4 – 0.7 Signature + first docstring line
πŸ”΄ Metadata < 0.4 Title, filepath, tags

That trade-off is the point: you spend context on results the model is confident about, and keep low-confidence hits visible (cheap) so the model can request expansion if needed.


What init does

coderecall init writes (or updates) three things in your project:

File What it is
.coderecall.json Project config: indexed extensions, ignore globs, embedding model, staleness thresholds.
.mcp.json (or .cursor/mcp.json with --client cursor) MCP server entry for coderecall. Merges next to any existing servers β€” won't clobber.
.gitignore Appends .coderecall/ (and tools/coderecall/node_modules/ for vendored installs).

The .mcp.json entry adapts to where coderecall lives:

  • Vendored (the recommended setup β€” coderecall is inside the project at tools/coderecall/): server path is written as a portable relative path (./tools/coderecall/src/index.ts) and the CODERECALL_PROJECT_ROOT env var is omitted β€” the server uses the MCP client's launch CWD. The result is fully portable: commit .mcp.json and every teammate's setup works without path rewrites.
  • External (coderecall lives somewhere outside the project): server path is absolute, and CODERECALL_PROJECT_ROOT is set explicitly.

It auto-detects the project language by scanning for a manifest file (mix.exs, Cargo.toml, go.mod, pyproject.toml / requirements.txt / Pipfile, Gemfile, tsconfig.json, package.json) and picks sensible default extensions. If no manifest is found, init will prompt interactively for a language; in non-interactive runs (agents, CI) it exits non-zero with a list of known languages so the agent can ask you, then re-run with --language <name> or --extensions ".ext1,.ext2". Both flags also override auto-detection β€” useful for polyglot repos (e.g. a Python service with a package.json for tooling). Re-run with --force to overwrite, --no-mcp to skip the MCP file, or pass a path: coderecall init /path/to/project.


Indexing & re-indexing

The index is local per developer. .coderecall/ is gitignored β€” vectors are never shared via git. Every teammate runs indexing on their own machine against their own checkout.

First-time indexing

coderecall index

Scans the project, parses every file matching extensions, chunks it, embeds each chunk (384-D, batched), and stores everything in .coderecall/index.db. The first run also downloads the ~30 MB embedding model. Rough numbers on CPU: ~15–30 ms per chunk with batched embeddings; a 5,000-chunk repo finishes its first index in ~2–3 min.

Which files get scanned. In a git repo, the scanner uses git ls-files (tracked + untracked-but-not-gitignored) β€” so anything in your .gitignore is skipped automatically, including weirdly-named Python venvs (api-venv/, my-env-3.11/, etc.). Outside a git repo, it falls back to a glob walk using the ignore patterns in .coderecall.json; for Python projects it also detects venvs by their pyvenv.cfg marker so the directory name doesn't matter. Pass --no-git-ls to force the glob path.

Re-indexing is cheap

coderecall index is content-hash-aware: every file's SHA-256 is stored, and unchanged files are skipped instantly. Running coderecall index against a fully-up-to-date repo finishes in under a second. So the safe default after a work session is to just re-run it.

The one thing a full index does not handle is deleted or renamed files β€” chunks for files that no longer exist stay in the DB. Use index-diff (which inspects git diff --name-status) or nuke .coderecall/ when that matters.

When to run what

Situation Command
You edited some files coderecall index
You deleted, moved, or renamed files coderecall index-diff . --base HEAD~1 --head HEAD
You just git pulled teammate work coderecall index-diff . --base ORIG_HEAD --head HEAD
You switched branches coderecall index-diff . --base <prev-branch> --head HEAD
You changed extensions or ignore in config rm -rf .coderecall && coderecall index
You changed embeddingModel rm -rf .coderecall && coderecall index

Staleness alerts

The server tracks when the last full index run completed and surfaces age in every search response. Two thresholds are configurable in .coderecall.json:

"staleAfterDays": 14,
"veryStaleAfterDays": 30

Past the first threshold, every search response prefixes a yellow banner:

🟑 Index is 17 days old (threshold: 14d). Consider `coderecall index` to refresh.

Past the second, it turns red. The point is that the agent sees the warning and can suggest a reindex instead of silently searching against a stale snapshot.

Knowledge entries

Knowledge entries created via add_knowledge, import-obsidian, or import-knowledge-file are embedded the moment they're added β€” no separate reindex step. They live in the same SQLite DB and are searched alongside code by default.

Automating it

No file watcher is built in β€” re-indexing while a tool is reading from the DB can race. Pick whichever fits your workflow:

  • Manual β€” just run coderecall index before searching, after a work session.
  • Git post-commit hook β€” cheap on every commit thanks to content-hash skipping:
    # .git/hooks/post-commit
    coderecall index >/dev/null 2>&1 &
  • Editor task β€” bind a key in VS Code / your editor to coderecall index.

Architecture

Layer What it does
MCP tools search Β· add_knowledge Β· index_files Β· index_diff Β· get_file_context Β· get_index_stats
Confidence-tiered retrieval pool β†’ scoring β†’ diversity β†’ tiered expansion
Hybrid search FTS5 (porter) + cosine 384-D
Indexing scanner β†’ parsers β†’ chunker β†’ embeddings
SQLite knowledge_entries Β· code_files Β· code_chunks Β· embeddings Β· memory_fts

Adding a language

A new language is a single file in src/indexer/parsers/<lang>.ts implementing the LanguageParser interface (regex or tree-sitter β€” your call), then a one-line entry in src/indexer/parsers/index.ts. PRs welcome.


CLI reference
coderecall init [path] [--language <name>] [--extensions ".ext1,.ext2"] [--force] [--no-mcp]
coderecall index [path] [--extensions ".ext1,.ext2"] [--no-git-ls]
coderecall index-diff [path] --base HEAD~1 --head HEAD
coderecall search "<query>" [--filter code|knowledge] [--limit 10] [--expansion selective|all|metadata_only]
coderecall search-legacy "<query>"       # full-expansion mode (no tiering)
coderecall stats
coderecall add-knowledge                 # interactive
coderecall list-knowledge [--category X] [--tag Y]
coderecall import-obsidian --vault /path/to/vault
coderecall import-knowledge-file ./NOTES.md --category note

init resolution order for which extensions to index: --extensions flag β†’ --language preset β†’ auto-detect from manifest β†’ interactive prompt (TTY) β†’ exit with instructions (non-TTY, so an agent can ask you).

Known --language presets: typescript, javascript, python, ruby, go, rust, elixir, java, kotlin, swift, csharp, cpp, php.

All commands honor CODERECALL_PROJECT_ROOT, CODERECALL_INDEX_PATH, CODERECALL_EXTENSIONS, CODERECALL_IGNORE, and CODERECALL_EMBEDDING_MODEL.

Config (.coderecall.json)
{
  "indexPath": ".coderecall",
  "extensions": [".ts", ".tsx", ".js", ".jsx"],
  "ignore": [
    "**/node_modules/**", "**/dist/**", "**/build/**",
    "**/.next/**", "**/.git/**", "**/.coderecall/**"
  ],
  "embeddingModel": "Xenova/bge-small-en-v1.5",
  "staleAfterDays": 14,
  "veryStaleAfterDays": 30
}
  • indexPath β€” where the SQLite DB lives. Relative paths resolve from the project root.
  • extensions β€” what gets parsed. Anything not in the language registry falls back to a generic block chunker.
  • ignore β€” glob patterns excluded during scanning.
  • embeddingModel β€” defaults to Xenova/bge-small-en-v1.5 (384-D, ~30 MB). Any other 384-D model is a drop-in. Switching to a different dimension (e.g. Xenova/bge-base-en-v1.5 at 768-D) requires reindexing β€” old vectors are silently incompatible.
  • staleAfterDays / veryStaleAfterDays β€” yellow / red staleness banner thresholds. Defaults: 14 / 30.
Troubleshooting

MCP tools don't appear after init β€” restart your MCP client. Claude Code reloads .mcp.json on launch.

Search returns nothing β€” run coderecall stats. If Total chunks is 0, run coderecall index.

Search returns stale results / deleted files β€” full index doesn't clean deletions. Run coderecall index-diff or rm -rf .coderecall && coderecall index.

First search/index is slow β€” first run downloads the ~30 MB embedding model. Subsequent runs use the local cache.

Type errors when editing β€” bun install && bunx tsc --noEmit.


Acknowledgments

The confidence-tiered expansion idea is loosely inspired by recent RAG-decoding research (notably Meta's REFRAG paper on selective chunk expansion), adapted here as a simple retrieval-side scoring heuristic rather than a learned decoder modification.

Credits

@jichon
@jichon

Original idea
@FedeMadoery
@FedeMadoery

Author & maintainer

@jichon originally conceived the idea this project is based on β€” he sketched it out for a single use case, and this repo generalizes it into a reusable tool.

License

MIT

About

Your repo's memory, indexed locally. One SQLite file. Zero API keys.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors