Relic answers "why is this code the way it is?" by walking the decision chain that produced it — a line of code → the commit that wrote it → the PR that merged it → the issue that forced it → the people who decided. It reconstructs the intent behind code from a repository's own history, and every claim links back to a real source on GitHub.
Relic builds a typed knowledge graph of a repository's history and answers by traversing the relationships between symbols, commits, pull requests, issues, and people — not by matching text.
Relic is not a code reviewer, a linter, or a "chat with your codebase" Q&A bot. Those tools read the code as it is now and tell you what it does. Relic reads the history and tells you why it became that way — the constraint, the bug report, the review argument, the person who made the call. It's a provenance engine, not a code assistant. (It plugs into your code assistant — see Use it from your editor.)
Built for the Cognee × WeMakeDevs hackathon — submitted to both the open-source and Cognee Cloud tracks.
Normal (vector) RAG chops text into chunks and returns whatever sounds most similar. It matches words, not relationships — so it can't answer a question whose answer is spread across a commit, a PR, an issue, and a person.
Relic stores entities (File, Commit, PullRequest, Issue, Person) and the typed edges between them, then walks those edges. The answer is composed only from the traversed subgraph, so it can't hallucinate beyond what the graph actually says — and when the chain doesn't exist, it says so instead of guessing.
Relic ships a live side-by-side: ask the same question of flat vector RAG and of Relic's graph walk, over the same embedded data, and watch flat RAG miss the chain.
- Repo ingestion — pulls commits, PRs, review comments, issues, and per-commit file diffs (with line ranges) via the GitHub GraphQL + REST APIs, paginated past the 100-per-page cap.
- Typed knowledge graph — maps history into Cognee
DataPointnodes with typed edges (modifies,part_of,closes,authored_by,opened_by,reviewed_by,raised_by,supersedes…), scoped to a per-repo NodeSet. - Code layer (tree-sitter) — parses JS/TS/Python into
Symbolnodes (functions, methods, classes) and joins each commit to the symbols it actually touched, using blame-accurate historical mapping (files are re-parsed at each commit, not just at HEAD). - The "why" query — vector search finds the entry node, a graph walk assembles the decision chain, and the LLM composes an answer grounded only in the traversed subgraph (it can't hallucinate past the graph; when the chain doesn't exist, it says so).
- Symbol-level retrieval — ask "why is this function like this?" and Relic anchors on the specific symbol and walks its history — the same path the editor plugin uses.
- Reference-aware seeds — queries naming
#123,issue 52, a commit SHA, or@handleresolve to that exact node instead of relying on fuzzy vector match. - Cited provenance — every answer lists its sources (PR #, issue #, commit SHA,
@handle), each a real GitHub link. - Provenance graph visualization — an interactive React Flow graph of the traversed subgraph; click a node to open it on GitHub.
- Flat-RAG comparison — a toggle to run vanilla vector RAG on the same embedded data, side by side, so you can watch flat RAG miss the chain.
- MCP server — exposes
get_decision_context(file, symbol_or_line, repo)so Claude Code / Cursor can pull a symbol's decision chain mid-edit (see below). - Cognee Cloud support — set cloud credentials and the graph syncs to your managed tenant; without them Relic runs fully self-hosted.
- Honest counts — the UI shows ingested / repo-total (e.g.
150 / 812 PRs) so coverage is transparent. - Depth control —
Standard(fast) orDeep(up to 100+ each, paginated).
┌────────────────────────────────────────────┐
│ Frontend (React + Vite) │
│ Ingest · Query · Provenance graph · Compare │
└───────────────┬──────────────────────────────┘
│ REST (proxied in dev)
┌───────────────▼──────────────────────────────┐
│ Backend (FastAPI) │
│ /ingest /query /query/naive /graph ... │
└───┬───────────────┬───────────────┬──────────┘
│ │ │
┌────────▼──────┐ ┌──────▼───────┐ ┌─────▼─────────┐
│ GitHub │ │ Cognee │ │ LLM (Groq) │
│ GraphQL API │ │ graph+vector │ │ + fastembed │
│ (ingestion) │ │ engine │ │ (local embed) │
└───────────────┘ └──────────────┘ └───────────────┘
The "why" query flow: question → Cognee vector search finds relevant entry nodes → graph walk over the typed edges builds the provenance subgraph → Groq composes an answer grounded only in that subgraph → response returns { answer, chain, citations, subgraph }.
| Layer | Choice |
|---|---|
| Backend | Python 3.12, FastAPI, Uvicorn |
| Graph + memory | Cognee 1.2.2 (self-hosted) |
| LLM | Groq (llama-3.3-70b-versatile) via LiteLLM |
| Embeddings | fastembed — local, BAAI/bge-small-en-v1.5 (384-dim), no API |
| Code parsing | tree-sitter + tree-sitter-language-pack (JS / TS / Python) |
| Ingestion | GitHub GraphQL + REST API + personal access token |
| Editor integration | MCP server (FastMCP) |
| Frontend | React 18, Vite, React Flow |
Why Groq + fastembed? Groq offers a generous free tier for the LLM, and fastembed runs embeddings locally with no API key and no rate limits — so ingesting a real repo (hundreds of nodes) never hits a quota wall.
- Python 3.12 and
pip - Node.js 18+ and
npm - A Groq API key — free at console.groq.com (starts with
gsk_) - A GitHub Personal Access Token — github.com/settings/tokens, classic with
public_reposcope is enough (starts withghp_)
git clone https://github.com/Photon079/Relic.git
cd Relicpython3.12 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r backend/requirements.txtThe first run downloads the fastembed model (~50 MB, one time).
cp .env.example .envThen fill in the two empty values in .env:
LLM_API_KEY="gsk_your_groq_key"
GITHUB_TOKEN="ghp_your_github_token"Everything else (Groq model, local fastembed embeddings) is preconfigured — no other keys needed.
cd frontend
npm installOpen two terminals from the repo root.
Terminal 1 — backend (http://127.0.0.1:8000):
source venv/bin/activate
uvicorn backend.main:app --reload --port 8000Terminal 2 — frontend (http://localhost:5173):
cd frontend
npm run devThen open http://localhost:5173, paste a small public repo (e.g. sindresorhus/slugify), click Build graph, and ask a "why" question. The interactive API docs are at http://127.0.0.1:8000/docs.
Whenever you edit
.env, restart the backend — env vars are read once at startup (even--reloadonly watches.pyfiles).
The pipeline runs standalone too — handy for testing or pre-loading a graph.
# Build a repo's graph (into Cognee's local store)
python -m backend.graph.builder sindresorhus/slugify --depth standard --prune
# --depth standard | deep (deep = up to 150 commits/PRs/issues, paginated)
# --prune wipe all prior Cognee data first (clean slate)
# Ask a "why" question against the built graph
python -m backend.retrieval.query "Why does slugify support an empty separator?"
# Day-0 sanity check: prove Cognee ingests the typed ontology cleanly
python scripts/validate_cognee.pyRelic ships an MCP server so a coding assistant (Claude Code, Cursor) can ask for a symbol's provenance while you edit it — before you change a function, pull the history that shaped it.
# Run the server (stdio transport)
python -m backend.mcp.serverRegister it with your assistant (Claude Code example):
claude mcp add relic -- python -m backend.mcp.serverIt exposes one tool:
| Tool | Args | Returns |
|---|---|---|
get_decision_context |
file, symbol_or_line, repo? |
{ symbol, why, decision_chain[], citations[] } |
symbol_or_line accepts a name ("pLimit") or a line number ("42", resolved to the enclosing symbol). The assistant gets back the same grounded "why" + ranked commit→PR→issue chain + GitHub citations the UI shows — so its edit suggestions are informed by why the code is that way, not just what it says.
Base URL: http://127.0.0.1:8000
| Method | Route | Body / params | Returns |
|---|---|---|---|
GET |
/health |
— | { status: "ok" } |
POST |
/ingest |
{ repo_url, depth? } |
{ repo_id, status: "processing" } |
GET |
/ingest/{repo_id}/status |
— | { status, node_types, repo_totals, ... } |
POST |
/query |
{ question, repo_url? } |
{ answer, chain, citations, subgraph } |
POST |
/query/naive |
{ question, repo_url? } |
{ answer, sources } (flat-RAG baseline) |
GET |
/graph/{repo_id} |
?files=true (optional) |
{ repo, subgraph } (full ingested graph) |
Ingestion is asynchronous: POST /ingest returns immediately, and you poll /ingest/{repo_id}/status until status is "done" (or "error"). repo_id is owner/name.
Example
# Start an ingest
curl -X POST http://127.0.0.1:8000/ingest \
-H "Content-Type: application/json" \
-d '{"repo_url":"sindresorhus/slugify","depth":"standard"}'
# Poll status
curl http://127.0.0.1:8000/ingest/sindresorhus/slugify/status
# Ask why
curl -X POST http://127.0.0.1:8000/query \
-H "Content-Type: application/json" \
-d '{"question":"Why does slugify support an empty separator?","repo_url":"sindresorhus/slugify"}'Relic/
├── backend/
│ ├── main.py # FastAPI app, CORS, route mounting
│ ├── config.py # env + settings (loaded before Cognee)
│ ├── ingestion/
│ │ ├── github_client.py # GraphQL fetch (paginated) + repo totals
│ │ └── mappers.py # raw JSON -> wired DataPoint instances
│ ├── ingestion/
│ │ └── code_parser.py # tree-sitter -> Symbol nodes (JS/TS/Python)
│ ├── graph/
│ │ ├── models.py # Cognee DataPoint ontology (nodes + edges)
│ │ ├── symbols.py # join commits -> symbols (blame-accurate)
│ │ ├── cloud.py # optional Cognee Cloud sync
│ │ └── builder.py # add_data_points pipeline, NodeSet scoping
│ ├── retrieval/
│ │ ├── query.py # vector entry -> graph walk -> grounded answer
│ │ ├── citations.py # nodes -> GitHub-linked citations
│ │ └── naive.py # flat vector-RAG baseline (the foil)
│ ├── mcp/
│ │ └── server.py # MCP server: get_decision_context tool
│ ├── api/
│ │ ├── routes_ingest.py # async ingest + status
│ │ ├── routes_query.py # /query and /query/naive
│ │ ├── routes_graph.py # /graph/{repo_id}
│ │ └── schemas.py # request/response models
│ └── requirements.txt
├── frontend/
│ ├── src/
│ │ ├── App.jsx # main flow + state
│ │ ├── api/client.js # fetch wrappers
│ │ ├── entities.js # shared entity colors
│ │ └── components/ # RepoInput, AnswerPanel, CitationList,
│ │ # ProvenanceGraph, ComparePanel
│ ├── vite.config.js # dev server + API proxy
│ └── package.json
├── scripts/
│ └── validate_cognee.py # Day-0 Cognee validation harness
├── .env.example
└── README.md
Nodes are Pydantic classes inheriting from Cognee's DataPoint. Assigning one node to another's field creates a typed edge (the field name is the relationship).
| Node | Key properties |
|---|---|
File |
path |
Commit |
sha, message |
PullRequest |
number, title, discussion |
Issue |
number, title, body, state |
Person |
handle |
Symbol |
name, kind, path, start/end line |
| Edge | Meaning |
|---|---|
Commit → modifies → File / Symbol |
a commit changed this file / symbol |
Commit → part_of → PullRequest |
this commit belongs to a PR |
PullRequest → closes → Issue |
this PR resolved an issue |
Issue → raised_by → Person |
who reported it |
Commit → authored_by → Person |
who wrote it |
PullRequest → opened_by → Person |
who opened it |
PullRequest → reviewed_by → Person |
who reviewed it |
Issue → assigned_to → Person |
who's assigned |
Commit → supersedes → Commit |
a later change to the same code |
- Coverage is capped per ingest.
Standardpulls ~40 PRs;Deepup to ~150. Large repos have far more — the stat bar shows ingested / total so the gap is visible. Raise it with the depth toggle orRELIC_PR_LIMIT/RELIC_COMMIT_LIMIT/RELIC_ISSUE_LIMITin.env. - Best on repos with real PR/issue history. The value is the decision chain; a repo of direct-to-main commits with no PRs yields a thin answer (by design, not a bug).
- Single-process store. Cognee's embedded DB is single-process — don't run a query during an ingest (the UI prevents this).
.envis git-ignored. Your keys never get committed; each contributor supplies their own.
Relic deploys as a Dockerized FastAPI backend (Render blueprint in render.yaml) plus a static frontend (Vercel/Netlify), with optional Cognee Cloud sync for the managed tenant. Full walkthrough in DEPLOY.md.
- "Why" enrichment via Cognee
cognify(extract decisions, constraints, tradeoffs as first-class nodes) - Blast-radius view ("what breaks if I change this") and expert-finder ("who knows this symbol")
- More languages in the code layer (Go, Rust, Java)
- Full-history pagination and incremental refresh on new commits