AI-powered code intelligence for JavaScript, TypeScript, and React codebases — AST parsing, knowledge graphs, hybrid semantic search, and grounded RAG in one platform.
TwoGraph-RAG analyzes entire repositories with Tree-sitter, builds a persistent knowledge graph in Memgraph, indexes code semantically with local (or API-based) embeddings, and answers complex developer questions through a hybrid retrieval pipeline (BM25 + vectors + graph traversal → RRF → cross-encoder reranking). It can also edit code safely via AST transformations with diff previews and approval gates, and keeps itself up to date as files change.
Think Sourcegraph Cody + Greptile + GraphRAG + Cursor, focused on the JS/TS/React ecosystem, fully open source.
Question → Multi-Query → Hybrid Search → Graph Expansion → RRF → Rerank → Context Assembly → LLM → Grounded Answer
Packages aren't published to npm yet (tracked in #76) — for now, run from a clone.
Prerequisites: Node ≥ 22, Docker, pnpm.
git clone https://github.com/Nahid-NHB/TwoGraph-RAG.git
cd TwoGraph-RAG
pnpm install
docker compose up -d # Memgraph :7687, Qdrant :6333
pnpm buildIndex a repo and ask it a question — examples/sample-repo is a small fixture repo bundled for exactly this:
cd examples/sample-repo
node ../../packages/cli/dist/main.js init # writes .twograph/config.json
node ../../packages/cli/dist/main.js index # parses, builds the graph, embeds
node ../../packages/cli/dist/main.js search "verify jwt token" # no LLM neededsearch works out of the box — semantic embedding is fully local (ONNX) by default. query (grounded RAG "ask") needs an LLM: set OPENROUTER_API_KEY (default provider, free tier available) or edit .twograph/config.json's llm block to switch to anthropic/openai/gemini/ollama, then:
export OPENROUTER_API_KEY=sk-or-...
node ../../packages/cli/dist/main.js query "how does authentication work?"-
Datastores — start Memgraph and Qdrant (skip if already running from the quickstart above):
docker compose up -d
-
Build the workspace (needed once, and again after pulling code changes):
pnpm build
-
Configure env vars — copy the template and fill in what you need:
cp .env.example .env
- Set the API key for whichever
llm.provideryou use (OPENROUTER_API_KEY,ANTHROPIC_API_KEY,OPENAI_API_KEY, orGEMINI_API_KEY) — not needed forollamaor if you only usesearch. - Set
HF_TOKEN(free, from huggingface.co/settings/tokens) — the default local embedder downloads its ONNX model from Hugging Face on first use, and anonymous requests are frequently rate-limited/blocked (401 Unauthorized). A free read-only token fixes this.
- Set the API key for whichever
-
Start the REST API server (reads
.env, so eitherexportits contents first or run via a tool likedotenv/direnv):set -a && source .env && set +a node packages/cli/dist/main.js serve & # REST API on :4801
-
Start the web UI, in a separate terminal from the repo root:
pnpm --filter @twograph/web dev # opens on :5173 -
Open
http://localhost:5173, register a repository by its absolute path (e.g./home/you/projects/my-repo), then index it from the UI before chatting/searching.
Changed code in packages/*? Re-run pnpm build and restart the serve process (step 4) to pick it up — the web dev server (step 5) hot-reloads on its own.
- Whole-repo understanding — functions, classes, hooks, components, props, contexts, routes, API handlers, imports/exports, tests, configs
- Knowledge graph — 20+ node types, 20+ edge types (CALLS, IMPORTS, USES_HOOK, PROVIDES_CONTEXT, …), incrementally updated, never rebuilt from scratch
- Semantic search — "authentication" finds
verifyToken(),validateJWT(),login()even when the word never appears - Grounded answers — every answer cites files, functions, snippets, and graph paths, verified against real file spans
- AST-based editing — rename, move, extract, parameter changes; never regex; approval required before writes
- Dead code & dependency analysis — reachability from entry points, full dependency graph from package.json/tsconfig/bundler configs, with a web dependency explorer and expandable call/component-usage trees
- Real-time indexing — filesystem watcher reparses and updates graph + embeddings incrementally
- Caching — content-hash embedding cache survives restarts; generation-keyed LRU caching for hot graph queries and RAG search/multi-query results
- Benchmarks —
pnpm benchtracks indexing throughput/latency and retrieval quality against a committed baseline, gated in CI - MCP server —
repository_summary,semantic_search,query_graph,call_hierarchy,component_usage,dependency_graph,dead_code,edit_function,optimize_function - Modern web UI — repository explorer, graph visualization, call/component hierarchy trees, chat, diff viewer, dependency explorer, dark mode
- Interchangeable LLMs — Anthropic, OpenAI, Gemini, Ollama, OpenRouter
| Doc | Contents |
|---|---|
| Requirements | Functional & non-functional requirements |
| Architecture | Components, package layout, data flow |
| Folder Structure | Monorepo layout |
| Database Schema | SQLite metadata store, Qdrant collections |
| Knowledge Graph Schema | Node labels, edge types, Cypher patterns |
| API Design | REST/SSE API, MCP tools, CLI |
| Retrieval Pipeline | Hybrid retrieval + RAG pipeline |
| Editing Pipeline | AST editing with approval workflow |
| Extension Points | Plugging in languages, stores, providers |
@twograph/mcp exposes the index to any MCP-compatible agent (Claude Code, Claude Desktop, Cursor, …) via repository_summary, semantic_search, query_graph, call_hierarchy, component_usage, dependency_graph, dead_code, edit_function, and optimize_function. Index a repo first (twograph init && twograph index), then run:
twograph mcp # stdio (default) — for clients that spawn a child process
twograph mcp --http # streamable HTTP on :4802 (POST/GET/DELETE http://localhost:4802/mcp)Claude Code: claude mcp add twograph -- twograph mcp
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"twograph": {
"command": "twograph",
"args": ["mcp"]
}
}
}Every tool takes a repo argument — the absolute path to an already-indexed repository root.
Does my code get sent to an LLM? Only the context blocks assembled for a specific question/edit-suggestion (via query, chat, or optimize) go to your configured LLM provider. Parsing, graph-building, and the default embedder all run locally — search, deadcode, and deps never call an LLM at all.
Which LLMs are supported? Anthropic, OpenAI, Gemini, Ollama (fully local), and OpenRouter — see Extension Points. Switching is a one-line config change.
Is this production-ready? Pre-1.0 and under active development (see milestones). Core indexing/search/RAG/editing paths are covered by the release-gate e2e test that runs in CI on every change.
How is this different from Cursor/Copilot/Cody? Those are primarily editor-integrated code assistants. TwoGraph-RAG is a standalone knowledge-graph + retrieval platform (CLI, REST API, MCP server, web UI) you can point any MCP-compatible agent at, index once and query many ways, and inspect directly (graph visualization, dependency explorer, dead-code report) without needing an editor plugin.
What's next? See the non-goals/roadmap in Extension Points §9 and the open milestones.
pnpm install
docker compose up -d # Memgraph + Qdrant
pnpm test
pnpm build && pnpm bench # indexing + retrieval benchmarks vs scripts/bench/baseline.jsonSee CONTRIBUTING.md. Work is organized into 10 milestones; every change lands as one PR closing one issue. Please also read our Code of Conduct; see SECURITY.md to report a vulnerability.
MIT
