Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

repomap — GitHub Codebase RAG

Upload or clone a repository. Instead of "here are similar chunks," it answers:

  • Explain architecture — repo-wide structure, core modules, languages
  • Where is authentication handled? — locates the actual implementation, not just nearby text
  • Which code calls the database? — traces real call-graph edges, not keyword guesses
  • What breaks if I remove this? — blast-radius / impact analysis via reverse call-graph traversal
  • Generate dependency graphs — interactive force-directed call graph, rendered live in the browser

Powered by NVIDIA Nemotron (free tier, via OpenRouter) for generation, and local, free, CPU-only embeddings for retrieval — no paid API required to run this end-to-end.

Why this isn't "just RAG"

Plain codebase RAG retrieves chunks by embedding similarity and asks the LLM to summarize them. That fails on anything structural: "what calls this," "what breaks if I delete it," "what's the architecture" are graph questions, not similarity questions.

This project parses every file into a real AST (via Tree-sitter), builds two graphs from it — a call graph (function/method → function/method) and a file dependency graph (file → file, resolved from imports) — and uses a lightweight query router to decide, per question, whether to answer from:

  1. Semantic chunk retrieval (symbol-aware chunks — each function/class is its own chunk, not an arbitrary line window)
  2. Structured call-graph traversal (callers/callees, resolved by name across the whole repo)
  3. Reverse-graph blast-radius analysis (for "what breaks if I remove X")
  4. Repo-wide centrality ranking (for "explain the architecture" / repo map)

The LLM then receives structured context — actual resolved call edges and import edges, not just nearby text — and is explicitly instructed to reason over relationships, not summarize chunks.

Architecture

+-------------+      +------------------------------------------------+
|   Frontend  |      |                Backend (FastAPI)                |
|  (vanilla   |<---->|                                                  |
|  JS + D3,   | HTTP |  ingestion.py --+--> ast_parser.py (Tree-sitter) |
|  no build   |      |   (clone/zip)   |     symbols, calls, imports    |
|  step)      |      |                 +--> graph_builder.py (networkx)|
+-------------+      |                 |     call graph, file graph,   |
                      |                 |     impact analysis, repo map |
                      |                 +--> vector_store.py (Chroma)  |
                      |                       symbol-aware chunking,    |
                      |                       local sentence-transformer|
                      |                                                  |
                      |  rag_engine.py -- query router + structured     |
                      |                   context assembly               |
                      |       |                                          |
                      |       v                                          |
                      |  llm_client.py -- OpenRouter -> Nemotron (free) |
                      +------------------------------------------------+

Extra features (as requested)

Feature Where
AST parsing app/services/ast_parser.py — Tree-sitter grammars for Python, JS/TS/TSX, Go, Java, Ruby, Rust, C/C++, C#, PHP
Call graphs app/services/graph_builder.py — resolves call sites to definitions across the whole repo, builds a networkx.DiGraph
Symbol retrieval app/services/vector_store.py — chunks are symbol-aligned (one function/class = one chunk + metadata)
Tree-sitter Same parser is reused for every supported language via tree_sitter_languages
Repository map graph_builder.repo_map_summary() — centrality-ranked "most depended-on files" and "most-called symbols"

Setup

You need a free OpenRouter API key (no credit card required for free-tier models): https://openrouter.ai/keys

git clone <this-repo>
cd codebase-rag
cp backend/.env.example backend/.env
# edit backend/.env and paste your OPENROUTER_API_KEY

./run.sh

Then open http://localhost:8000 in your browser.

The first run downloads the local embedding model (~80MB, one-time, runs on CPU) and installs Python dependencies — this can take a few minutes. Subsequent runs are fast.

Manual setup (if you don't want to use run.sh)

cd backend
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env   # then add your OPENROUTER_API_KEY
uvicorn app.main:app --reload

Using it

  1. Click "+ Add repository" — paste a GitHub URL (public repos, shallow-cloned) or upload a .zip of a local project.
  2. Wait for ingestion (parsing + graph building + embedding) — usually 10–60 seconds for small-to-medium repos.
  3. Ask questions, or use the quick actions in the sidebar:
    • Explain architecture
    • Where is authentication handled?
    • Which code touches the database?
    • What breaks if I remove function_name?
    • Generate repository map
  4. The right-hand panel shows a live, draggable call graph for the symbols involved in your last answer, or a structured impact report / repository map, depending on the question.

Notable design decisions

  • Symbol-aware chunking: instead of fixed-size sliding windows, each parsed function/class becomes its own chunk (with file path + signature + docstring prepended as a header). Module-level code not covered by any symbol falls back to windowed chunking. This means retrieval returns complete, coherent units of code.
  • Best-effort import resolution: import/require statements are resolved to actual files in the repo using path heuristics (relative imports, common extensions, index files). Unresolved imports become external::<package> nodes so the dependency graph still reflects "this file depends on an external package" without crashing on it.
  • Free-tier-first: embeddings run locally via sentence-transformers (no API cost, no rate limits), and the LLM defaults to nvidia/nemotron-nano-9b-v2:free on OpenRouter with automatic fallback to nvidia/llama-3.1-nemotron-70b-instruct:free on rate-limit (HTTP 429) — free-tier endpoints can be rate-limited under load.
  • No build step on the frontend: plain HTML/CSS/vanilla JS + D3 from a CDN, so there's nothing to compile and the whole frontend is readable in two files.

Known limitations

  • Call-graph resolution matches callees by identifier name across the repo; in large codebases with many same-named functions (e.g. multiple get() methods), this can over-link. A production version would add type-aware resolution per language.
  • Import resolution is heuristic, not a full per-language module resolver (no tsconfig.json/go.mod/package.json path-alias awareness yet).
  • Free-tier OpenRouter models can be slower or rate-limited under heavy use; the fallback model mitigates but doesn't eliminate this.

Project structure

codebase-rag/
├── backend/
│   ├── app/
│   │   ├── core/config.py          # settings (env vars)
│   │   ├── services/
│   │   │   ├── ast_parser.py       # Tree-sitter parsing -> symbols/calls/imports
│   │   │   ├── graph_builder.py    # call graph + file graph + impact analysis
│   │   │   ├── vector_store.py     # symbol-aware chunking + Chroma embeddings
│   │   │   ├── ingestion.py        # orchestrates clone/upload -> parse -> embed
│   │   │   ├── llm_client.py       # OpenRouter / Nemotron client
│   │   │   └── rag_engine.py       # query router + structured context + answer
│   │   ├── routers/
│   │   │   ├── repos.py            # ingest (git/upload), status, list, delete
│   │   │   └── rag.py              # ask, repo map, graph export, impact, files
│   │   ├── models/schemas.py       # Pydantic request/response models
│   │   └── main.py                 # FastAPI app + static frontend serving
│   ├── requirements.txt
│   └── .env.example
├── frontend/
│   ├── index.html
│   └── static/
│       ├── app.js                  # SPA logic (state, rendering, D3 force graph)
│       └── styles.css              # design system
├── run.sh
└── README.md

Releases

Packages

Contributors

Languages