This document describes how RepoMind v0.1.0 actually works, module by module. It reflects the code in repomind/ — not aspirational design.
- Zero third‑party dependencies.
pyproject.tomldeclaresdependencies = []. Everything runs on the Python 3.11+ standard library (ast,re,http.server,urllib,threading,uuid,json,hashlib). - Offline‑first. No Neo4j, Qdrant, Docker, database, or queue is required. No LLM key is required.
- Graceful enhancement. Optional integrations (currently OpenRouter) light up when configured and degrade cleanly when not.
- Single artifact. Analysis is a plain JSON file (
.repomind/analysis.json); the search index is a sibling (.repomind/index.json).
Repository ──► analyzer.py ──► analysis.json ──► server.py ──► static/ dashboard
│ ▲
└──► retrieval.py ──► index.json ──┘
│
assistant.py / conversation.py (grounded answers)
│
integrations/llm.py (optional OpenRouter)
argparse‑based. Two subcommands:
analyze <target> [--output PATH] [--json]— analyzes a local path or a GitHub URL. If the target looks like a URL, it shallow‑clones withgitinto a temporary directory (cleaned up afterward). Writesanalysis.jsonand builds/writesindex.json.serve [--analysis PATH] [--host HOST] [--port PORT]— starts the dashboard server.
Console entry point: repomind = repomind.cli:main (see pyproject.toml). python -m repomind routes through __main__.py.
The core. analyze_repository(target) returns a dict with:
repository,summary(headline, languages, primary components, entry points, architecture layers, stats),components,files,apis,nodesandrelationships(the knowledge graph),onboarding(generated guide),impact_index(see below).
Parsers:
- Python — parsed with the
astmodule (imports, classes, functions, methods, calls, inheritance, and decorator‑based routes for FastAPI/Flask). Falls back to a regex scan onSyntaxError. - JavaScript / TypeScript / JSX / TSX — lightweight regex extraction of imports, classes, functions,
app/router/server.<method>(...)routes, Next.jsroute.*handlers, and call names. - Java — regex extraction of imports, classes, inheritance,
@…Mappingroutes, and methods.
Graph model: node types Repository, Directory, File, Class, Function, Method, API, ExternalDependency; relationship types include CONTAINS, IMPORTS, CALLS, EXTENDS, TESTS.
Impact index: _build_impact_index performs a 2‑hop reverse‑dependency walk over the graph for every File/Class/Function/Method/API node, producing affected files, affected APIs, affected tests, and a Low/Medium/High risk rating.
build_index(root) chunks source files into overlapping line windows (CHUNK_LINES / CHUNK_STEP, capped by MAX_CHUNKS) and stores them in index.json. SearchIndex provides search(query, k) using:
- BM25 ranking (
_BM25_K1,_BM25_B), - identifier‑aware tokenization (
tokenizesplitscamelCaseandsnake_case, drops stopwords), - structural boosts — a query term that matches a chunk's file path or symbol label is weighted higher.
This is the same search() contract that a future embeddings backend (Qdrant) would implement — see integrations/vector_store.py.
answer_question(analysis, index, question, assistant=None):
- Runs retrieval for the question.
- Builds grounded context (
_build_context) from the summary + top snippets. - If OpenRouter is configured, calls the LLM; otherwise returns
_local_answer— an extractive answer built from retrieval and structural signals (routes, entry points, impact).
Every answer includes sources (file + line). This module powers the stateless /api/ask.
Adds conversation memory on top of assistant.py without changing it:
Turn,Conversation(rolling, capped byMAX_TURNS_PER_CONVERSATION), and a thread‑safeConversationManager(capped byMAX_CONVERSATIONS, guarded by athreading.Lock).resolve_query(question, conversation)— finds the salient entity from the last turn's citation and rewrites deictic references ("it", "that function", "this module"), then augments the retrieval query with terms from recent turns.chat_answer(...)— resolve →search()→ LLM‑with‑history or local fallback → record the turn. Context is bounded byMAX_HISTORY_TURNSandMAX_HISTORY_CHARS.
This module powers /api/chat. All state is in‑process memory.
Standard‑library ThreadingHTTPServer. Routes:
| Method | Path | Purpose |
|---|---|---|
| GET | /api/analysis |
Return the loaded analysis.json. |
| GET | /api/impact?id=<node_id> |
Return the impact entry for a node. |
| POST | /api/analyze |
Analyze a path, rewrite analysis + index. |
| POST | /api/ask |
Stateless, single‑shot grounded answer. |
| POST | /api/chat |
Multi‑turn answer (conversation_id, reset). |
| GET | /* |
Serve static dashboard assets. |
A single shared ConversationManager lives on the handler class.
Vanilla index.html, app.js, and styles.css — no framework, no build step. Tabs: Overview, Graph (canvas), APIs, Impact, Guide, plus the Repository Assistant (multi‑turn chat with citations and a reset control).
llm.py— implemented OpenRouter client usingurllib(activates only withOPENROUTER_API_KEY).vector_store.py— stub Qdrant boundary for a future embeddings layer.graph_store.py— stub Neo4j boundary for a future production graph.
The stubs document the contract; they are not used by the MVP and require no services.
| File | Written by | Contents |
|---|---|---|
.repomind/analysis.json |
analyzer.write_analysis |
Full knowledge map. |
.repomind/index.json |
retrieval.write_index |
BM25 chunk index. |
Both live under .repomind/, which is git‑ignored. Re‑run analyze after code changes so retrieval reflects the latest code.
tests/ uses the standard‑library unittest (no pytest required):
python -B -m unittest discover -s tests -vCovers analyzer parsing/routes, retrieval ranking + tokenization, the OpenRouter request wiring (mocked, no network), local fallback, and the full multi‑turn conversation surface (follow‑ups, pronoun resolution, long conversations, missing context, reset).