paulxiep/code-rag

RAG for code search and understanding, chatbot for code queries, and MCP for Claude Code RAG skills.

1

stars

71

commits

Rust

primary language

Aug 12, 2026

updated

paulxie.com/demos/code-rag/

README

Code RAG

Test it by asking questions about my portfolio at paulxie.com/demos/code-rag/

A RAG chatbot that answers questions about code repositories. Ingests all sibling project directories, parses Rust, Python, TypeScript, and Go codebases with tree-sitter, extracts docstrings and a persistent AST call graph, generates embeddings, and responds via Google Gemini. Intent classification routes queries to optimized retrieval strategies — including graph augmentation for relationship queries and per-comparator decomposition for comparison queries. Retrieval traces surface all sources with relevance scores — the system shows its work.

Use as MCP server with Claude Code

The retrieval brain ships as code-rag-mcp, a single-binary MCP server you can drop into any of your own repos to give Claude Code intent-routed retrieval, call-graph traversal, architecture overviews, and topology insight — emergent-module maps with folder-drift comparison, "read these first" rankings, dependency-cycle detection, and call-path tracing with Mermaid output (nine tools). No API keys, no cloud.

Install is three steps, no terminal commands once the exe is on disk:

  1. Download the zip for your platform from the GitHub Release page and extract it. You get one binary plus a code-rag-mcp.config.yaml template.
  2. Edit the YAML — set target_path to your repo (or a parent folder with workspace: true for many sub-projects).
  3. Run the exe (double-click works). It writes .claude/skills/code-rag.md, .mcp.json, and a .gitignore entry into your target dir, then exits.

Open Claude Code in the target dir. The bundled skill instructs the agent to run code_rag_reindex mode=full for the initial ingest automatically.

Full walkthrough: crates/code-rag-mcp/README.md. Release process: docs/release.md.

Usage

Place this repo alongside the projects you want to index:

any-parent-folder/
├── code-rag/          ← this repo
├── project-a/
├── project-b/
└── ...

Ingestion walks all sibling directories — each becomes a separate project. The parent folder name doesn't matter.

  1. docker-compose -f docker-compose-ingest.yaml up
  2. docker-compose up

To clean, run sh clean_docker.sh.

Development Roadmap

VersionDateFocus
V0.12025-12-23MVP - Core engine
V0.22026-01-01Docker deployment
V0.32026-01-31Workspace restructuring
V1.12026-02-04Schema foundation (UUID, content_hash, delete API)
V1.22026-02-06LanguageHandler trait refactor
V1.32026-02-06Incremental ingestion (SHA256, three-layer architecture)
V1.42026-02-07TypeScript support (TSX grammar, JSDoc)
V1.52026-02-07Docstring extraction (Rust, Python, TypeScript)
V2.12026-02-07Inline call context (AST-based call extraction)
V2.22026-02-08Intent classification + query routing (cosine similarity)
V2.32026-02-08Retrieval traces (scored sources, cross-type ranking)
Leptos Migration2026-03-25WASM frontend (replace htmx/Askama with Leptos)
GitHub Pages Demo2026-03-25Shared engine crate + standalone WASM deployment
V3.12026-04-02Retrieval test dataset (43 queries, 4 intent categories)
V3.22026-04-02Recall measurement harness (recall@K, MRR, intent accuracy)
V3.32026-04-03Baseline quality metrics (dual-run, per-intent breakdown)
B12026-04-04Cross-encoder reranking (ms-marco-MiniLM-L-6-v2)
B22026-04-04Hybrid BM25+semantic search infrastructure (disabled pending B3)
B32026-04-05Declaration signatures + searchable_text + per-intent gating (recall@5 0.70→0.75)
B42026-04-05Intent classifier 58%→74% (prototypes + k-NN + keyword pre-filter)
B52026-04-06Dual-vector schema + per-intent ArmPolicy (bm25/rerank gating)
C12026-04-09Graph RAG — call graph edges + 3-tier resolution + traversal (relationship 0.50→0.57)
C22026-04-09Graph result protection — SOTA routing + soft reserve (relationship 0.57→0.60)
C32026-04-09Comparison query decomposition — per-comparator RRF + project filter (comparison 0.62→0.65, aggregate 0.71→0.72)
A12026-04-17Text module consolidation — single code-rag-engine::text for tokenize/IDF/BM25/searchable_text (WASM/native single source)
A22026-04-17Folder-level embeddings — FolderChunk (5-line template, 118 chunks) shipped dark for A3 activation
A32026-04-17Collapsed-tree routing — folder arm activated for Overview/Implementation/Comparison (comparison 0.31→0.67 +36pp)
A42026-04-18File-level embeddings — FileChunk (4-line template, 247 chunks) + stratified relationship retrieval (recall@pool metric introduced)
MCP2026-04-24Claude Code MCP server (code-rag-mcp) — five tools (search, graph, overview, neighbors, reindex) on rmcp 1.5; bundled Skill; single-binary install (download → edit code-rag-mcp.config.yaml → run exe); subsumes code-rag-ingest via internal ingest subcommand; manually-triggered cross-platform release pipeline; agent-driven first ingest
Caravan2026-05-21Caravan adoption (B0p → M5). Four #[wagon] seams (Embedder / Reranker / VectorReader / LlmClient); RigGeminiImpl extracted to code-rag-llm; chat-side core (AppState, retrieve) extracted to code-rag-core (MCP no longer transitively depends on chat binary); four mix-and-match caravan.yaml targets (dev-monolith / dev-split-light / dev-split-mixed / dev-split-heavy) exercise per-seam independent dispatch. caravan-rpc 0.1.0 published to crates.io
R02026-06-08Crate split — parser/ingester renamed code-rag-ingest; code-raptor reclaimed as the topology engine (Track R home)
R12026-06-08RelationGraph + typed relation edges (graph_edges: imports/re_exports/contains/implements/extends/embeds/references/rationale_for) with per-language anchored resolution. Hardened 2026-08: project-scoped identifier index (graph never links projects) + documented per-language import matching
R22026-06-10Emergent communities — deterministic Louvain (no RNG) + hub exclusion + cohesion scoring, persisted to additive community_assignments table; folder→file contains excluded from partition input by design
R32026-06-10ClusterChunk summaries (template tier, cluster_chunks table, retrieval arm) — arm gated OFF by measurement (displaced code/folder chunks on Overview; machinery stays wired for a slot-protection/LLM-tier revisit)
R42026-08-06Structural analytics + per-project architecture report — degree centrality (wasm-safe), Brandes edge-betweenness bridges, surprise ranking, import-cycle detection (Tarjan SCC + bounded canonical DFS), byte-deterministic markdown artifact
R52026-08-10Track R capstone — emergent-vs-folder drift comparison (report section), interactive topology view in the demo (d3-force, click-a-node → chat query), GraphML + viz JSON exports, four MCP topology tools (communities / central_nodes / cycles / path with Mermaid call-flow) via revived find_path

Purpose

  • To practice and demonstrate familiarity with
    • Rust
    • RAG
    • Chatbot Application
  • To function as meta-project
    • To answer questions about sibling code repositories

Tech Stack

  • Backend: Rust + Axum
  • LLM: Google Gemini (via rig-core)
  • Vector DB: LanceDB
  • Embeddings: FastEmbed
  • Frontend: Leptos (Rust WASM, CSR)
  • Deployment topology: Caravan — one yaml flips per-seam dispatch (inproc / container / lambda) without source edits

Deployment flexibility via Caravan

code-rag adopts Caravan, an application-definition compiler. The four inter-component boundaries (Embedder, Reranker, VectorReader, LlmClient) are wrapped as caravan-rpc seams; a single yaml projects code-rag onto multiple deployment topologies with zero source-code edits between them.

# caravan.yaml (excerpt)
targets:
  dev-monolith:           # all 4 seams inproc — baseline single binary
    runtime: docker-compose
    entries: { code-rag-chat: container }

  dev-split-mixed:        # 2 seams flipped to separate compose services
    runtime: docker-compose
    entries: { code-rag-chat: container }
    seams:
      Embedder: container
      Reranker: container
      # VectorReader + LlmClient default to inproc
caravan compile --target=dev-split-mixed
docker compose \
  -f docker-compose.yaml \
  -f infra/dev-split-mixed/generated/docker-compose.override.generated.yaml \
  up

Caravan emits a compose override that layers atop the hand-authored docker-compose.yaml — adding peer services for split seams + injecting the per-deploy-unit CARAVAN_RPC_PEERS table the SDK reads at runtime. Same chat image, same binary, same source tree; only the env var changes.

SDK adoption surface is closed at four touchpoints in user code:

No-config inertness: when CARAVAN_RPC_PEERS is unset, client::<dyn T>() returns the registered Arc<dyn T> directly with zero overhead. All existing deployment surfaces — compose chat, compose ingest, local cargo run, WASM gh-pages, single-binary MCP release — keep working unchanged.

See caravan.yaml for the full seam declarations and four mix-and-match targets (dev-monolith / dev-split-light / dev-split-mixed / dev-split-heavy).


Guiding Principles

"Vertical slices, retrieval quality, code understanding"

PrincipleMeaning
VerticalBuild working end-to-end first, then deepen
RetrievalQuality of retrieved context determines answer quality
UnderstandingGoal is semantic code understanding, not just text search

Architecture

CrateSingle Responsibility
code-rag-ingestIngestion CLI — parsing, chunk extraction, data export
code-raptorTopology engine (Track R) — derives architectural structure from persisted relation edges
code-rag-engineShared algorithms — intent, context, scoring (pure, no I/O)
code-rag-storeStorage seams + LanceDB-backed impls; fastembed Embedder + Reranker
code-rag-llmLLM-provider seam impls (rig-core-backed Gemini today; extracted at M5 so synthetic Caravan peer services can build against the impl)
code-rag-coreChat-side core shared between the chat binary and the MCP server — AppState, retrieve(), EngineError, SourceInfo. Extracted at M5 to break code-rag-mcp's transitive dep on code-rag-chat
code-rag-typesShared types — no logic
code-rag-chatHTTP routing + Askama templates + binary main (2 binaries: chat server + harness). Core logic moved to code-rag-core
code-rag-mcpMCP stdio server (single-binary release) — depends on code-rag-core directly, no chat-binary transitive
code-rag-uiLeptos WASM SPA — chat interface (backend or standalone mode)

Current State

  • Function-level chunking: 1 function/class → 1 vector (BGE-small, 384 dim)
  • Supports Rust, Python, TypeScript, and Go via tree-sitter AST parsing
  • Docstrings extracted: /// (Rust), """ (Python), /** */ (TypeScript JSDoc), // (Go)
  • Declaration signatures extracted: functions + structs/enums/traits/interfaces/classes
  • Hierarchy chunks (Track A): FolderChunk (1 per directory, 5-line template — folder/files+languages/key types/key functions/subfolders) and FileChunk (1 per source file, 4-line template — file/exports/imports/purpose). Built deterministically at ingest from existing CodeChunk metadata + C1 imports map — no LLM. Both render through pure code-rag-engine::{folder,file} functions, so server-embedded bytes and browser BM25 bytes are byte-identical
  • Persistent call graph (Graph RAG): LanceDB scalar-only call_edges table, 3-tier resolver (same-file → import-based → unique-global), AST scoped-identifier (module::function()) extraction
  • Typed relation topology (Track R): graph_edges table persists imports / re_exports / contains / implements / extends / embeds / references / rationale_for edges with per-language anchored resolution, project-scoped so the graph never links sibling projects (retrieval stays corpus-wide)
  • Emergent communities (Code Raptor): deterministic Louvain (fixed order, no RNG — identical partition every run) over calls ∪ imports ∪ type relations ∪ file-level containment, with hub exclusion + cohesion scoring; persisted per-chunk in community_assignments. Folder→file edges are deliberately excluded from the partition input so the emergent-vs-folder comparison is earned, not self-fulfilling
  • Architecture report + drift: per-project byte-deterministic markdown artifact — "read these first" degree centrality, cross-community bridges (Brandes edge-betweenness) with relation provenance, surprising-connection ranking, import cycles (Tarjan SCC + bounded canonical DFS), and an emergent-vs-folder drift section (community purity vs directory layout — e.g. it flags the vector_store.rs monolith splitting into 15 communities)
  • Topology exports: per-project graph_viz_<project>.json (browser artifact, capped 5000 nodes / 15 000 edges) + full-graph GraphML for Gephi/yEd — both byte-deterministic across runs
  • Test code exclusion at ingest (3-level): directory tests/, filename test_*.py / *.test.ts, AST-walked #[cfg(test)] enclosing-mod detection (~24% chunk reduction)
  • Intent classification: cosine similarity against prototype query embeddings
  • Query routing: declarative routing table maps intent → retrieval limits across all six chunk types (code, folder, file, readme, crate, module_doc)
  • Two-stage retrieval: hybrid (BM25 on searchable_text + vector) → cross-encoder reranking (ms-marco-MiniLM-L-6-v2), fused via N-ary RRF in shared code-rag-engine::fusion
  • Per-intent ArmPolicy: per-intent {body_vec, sig_vec, bm25, rerank, folder_vec, file_vec} gating (single source of truth, server + browser). Overview = hybrid+rerank; Implementation = rerank-only; Relationship = hybrid+rerank; Comparison = vector-only. Folder arm gated off for Relationship after empirical regression (folder chunks of X displaced consumers of X — stratified retrieval, file arm stays on)
  • Graph-augmented retrieval: shared code-rag-engine::graph (graph_augment, merge_graph_chunks, reserve_graph_slots, detect_direction). Two protection paths: SOTA routing for explicit-direction queries ("what calls X / called by") partitions graph chunks out of the reranker entirely; soft reserve for ambiguous-direction over-retains the code arm by +5 and rescues demoted graph chunks. Mirrored line-for-line in WASM standalone
  • Comparison query decomposition (code-rag-engine::comparison): regex extracts ≥2 comparators → per-comparator body-vec sub-searches (comparator name prepended to original query) → vote-based dominant-project filter → RRF fusion → max-of-natural rescoring so RRF outputs compete with non-code arms. Mirrored in WASM standalone
  • Single text module (A1): code-rag-engine::text is the sole home for tokenize, IdfTable, BM25 kernel, build_searchable_text, split_camel_case, and intent prototype texts. Compiles to native + wasm32 — no duplication across server, store, raptor, or UI
  • Dual-vector schema: nullable signature_vector column populated at ingest (shipped OFF after 8-config space sweep; column retained for future experiments)
  • Intent classifier: prototype cosine similarity + k-NN (k=3) weighted voting + Comparison keyword pre-filter with adversarial guards — 74% accuracy (was 58%)
  • Retrieval traces: all 6 chunk types surfaced with relevance scores, sorted by relevance
  • Quality harness: 87-query test dataset (79 recall-scoreable), recall@K, recall@pool (introduced in A4 — recall over every chunk reaching build_context, no top-k truncation), MRR, intent accuracy, latency — dual-run mode
  • Current baseline (post_rationale_anchor, 2026-08-07, 6-project corpus, classifier routing): recall@5 = 0.60 aggregate · overview 0.70 · implementation 0.61 · relationship 0.47 · comparison 0.62 · recall@10 = 0.69 · recall@pool = 0.72. Not comparable to the earlier post-A4 0.72@5: two projects were purged from the corpus (source repos deleted), the cross-project resolution leak was fixed (edges that once inflated recall were wrong answers), and the corpus now includes code-rag's own Track R code
  • Incremental ingestion: SHA256 file hashing, skips unchanged files
  • Shared code-rag-engine crate: pure algorithms compile to native + wasm32
  • GitHub Pages demo: standalone feature runs the full RAG pipeline in-browser (LLM generation optional), plus an interactive topology tab — d3-force canvas of each project's emergent communities (community-colored, degree-sized, relation-dashed edges; theme-aware palette), click a node to run a code-rag query about it

Known Limitations

  • Granularity: File and folder levels covered by Track A (FileChunk, FolderChunk). Repo-level summary considered and retired by measurement (existing READMEs + project-root FolderChunks already covered the 3 hero queries at recall@10=1.0)
  • Comparison short-identifier ceiling: Two stubborn pre-C3 failures (comp-retriever-generator, b4-comp-retriever-api) remain — BGE-small produces noisy vectors for bare hyphenated identifiers (retriever, generator), and the C3 regex extracts comparators only from explicit "compare X and Y / X vs Y" phrasings. Gated on a future embedder upgrade (BGE-base / jina-code) or MMR fallback
  • Classifier: No longer the dominant bottleneck post-B4 (+2pp classifier→GT gap on recall@5). Implementation and Relationship classification still below targets (70% / 53%)
  • Incremental reconcile under multi-file change: surfaced during A4 calibration — wipe-and-reinsert across many simultaneously-changed files corrupted BM25 IDF / row ordering and degraded hybrid retrieval. Workaround: fresh full ingest. Filed as a follow-up; not Track A-specific

Planned Features

See project-vision.md and development_plan.md for roadmap.


Keywords

  • Language: Rust
  • Architecture & Patterns: Layered Architecture (API/Store/Ingestion) · Trait-Based Abstraction (LanguageHandler) · Registry Pattern (OnceLock) · Three-Layer Pipeline (Parse→Reconcile→Orchestrate) · Router Pattern · Handler Pattern · Shared State (Arc) · Repository Pattern · DTO Pattern · Modular Design · Pipeline Pattern (Ingest→Embed→Store) · Visitor Pattern (WalkDir) · Error Propagation (thiserror) · Ephemeral Side-Channel Pattern · Declarative Routing Table · Scored Search API · ScoredChunk<T> (Generic Wrapper) · Retrieval Traces · Multi-Binary Crate (lib.rs extraction) · FlatChunk Centralization
  • LLM & RAG: RAG (Retrieval-Augmented Generation) · Graph RAG · Call Graph Augmentation · Graph-Augmented Retrieval · SOTA Routing (Reranker Bypass) · Soft Reserve · Comparison Query Decomposition · Per-Comparator RRF Fusion · Sub-Query Expansion · Vote-Based Project Filter · Max-of-Natural Rescoring · LLM Integration · Google Gemini API · rig-core · Semantic Search · Chatbot · Intent Classification (Cosine Similarity) · Prototype Query Embeddings · k-NN Prototype Voting · Keyword Pre-Filter (adversarial-guarded) · Intent-Aware Retrieval · Per-Intent Gating (ArmPolicy) · Two-Stage Retrieval · Cross-Encoder Reranking · Hybrid Search (BM25 + Dense) · RRF Fusion · Dual-Vector Schema · Declaration Signatures · searchable_text (IR field boosting) · camelCase Splitting (index-time) · Cross-Type Source Ranking · Distance-to-Relevance Scoring · Retrieval Transparency
  • Quality & Evaluation: Recall@K · MRR (Mean Reciprocal Rank) · Intent Accuracy · Latency Percentiles (p50/p95) · Dual-Run Evaluation (Classifier vs Ground-Truth) · Per-Intent Breakdown · Declarative Test Dataset · Substring File Matching · Dataset Freeze Policy · Baseline Regression Tracking · Space Search (per-intent ArmPolicy sweep) · Adversarial Test Cases · Held-out Classifier Eval
  • Vector Database: LanceDB · LanceDB FTS · Scalar-Only LanceDB Table (call_edges) · BM25 · FastEmbed · BGE Embeddings · ms-marco-MiniLM-L-6-v2 (ONNX)
  • Code Analysis: Tree-sitter · AST Parsing · Code Chunking · Docstring Extraction · JSDoc Parsing · Multi-Language (Rust, Python, TypeScript, Go) · Incremental Ingestion (SHA256) · Call Graph Extraction (AST-based) · Function Call Detection (Direct + Method) · Call Edge Resolution (3-tier) · Import-Based Symbol Resolution · Scoped Identifier Extraction · Test Code Exclusion (cfg(test) AST walk)
  • Graph & Topology (Track R): Community Detection (Louvain) · Modularity Maximization · Cohesion Scoring · Edge Betweenness (Brandes) · Tarjan SCC · Dependency Cycle Detection · Emergent Architecture · Architecture Drift (Emergent vs Folder) · Typed Relation Edges · Degree Centrality · GraphML Export · Mermaid Call-Flow · Force-Directed Layout (d3-force) · Deterministic Graph Algorithms
  • Web Framework: Axum · Leptos (WASM CSR) · Tower HTTP · CORS
  • Async & Runtime: Tokio Runtime · Async Programming
  • DevOps: Docker · Docker Compose · GitHub Pages (WASM) · Google OAuth2 (GIS)
  • Rust Ecosystem: tracing · Error Handling (anyhow/thiserror) · Serde · clap (CLI) · chrono

Contributors

paulxiep

71 commits

paulxiep/code-rag

RAG for code search and understanding, chatbot for code queries, and MCP for Claude Code RAG skills.

1

stars

71

commits

Rust

primary language

Aug 12, 2026

updated

paulxie.com/demos/code-rag/

README

Code RAG

Test it by asking questions about my portfolio at paulxie.com/demos/code-rag/

A RAG chatbot that answers questions about code repositories. Ingests all sibling project directories, parses Rust, Python, TypeScript, and Go codebases with tree-sitter, extracts docstrings and a persistent AST call graph, generates embeddings, and responds via Google Gemini. Intent classification routes queries to optimized retrieval strategies — including graph augmentation for relationship queries and per-comparator decomposition for comparison queries. Retrieval traces surface all sources with relevance scores — the system shows its work.

Use as MCP server with Claude Code

The retrieval brain ships as code-rag-mcp, a single-binary MCP server you can drop into any of your own repos to give Claude Code intent-routed retrieval, call-graph traversal, architecture overviews, and topology insight — emergent-module maps with folder-drift comparison, "read these first" rankings, dependency-cycle detection, and call-path tracing with Mermaid output (nine tools). No API keys, no cloud.

Install is three steps, no terminal commands once the exe is on disk:

  1. Download the zip for your platform from the GitHub Release page and extract it. You get one binary plus a code-rag-mcp.config.yaml template.
  2. Edit the YAML — set target_path to your repo (or a parent folder with workspace: true for many sub-projects).
  3. Run the exe (double-click works). It writes .claude/skills/code-rag.md, .mcp.json, and a .gitignore entry into your target dir, then exits.

Open Claude Code in the target dir. The bundled skill instructs the agent to run code_rag_reindex mode=full for the initial ingest automatically.

Full walkthrough: crates/code-rag-mcp/README.md. Release process: docs/release.md.

Usage

Place this repo alongside the projects you want to index:

any-parent-folder/
├── code-rag/          ← this repo
├── project-a/
├── project-b/
└── ...

Ingestion walks all sibling directories — each becomes a separate project. The parent folder name doesn't matter.

  1. docker-compose -f docker-compose-ingest.yaml up
  2. docker-compose up

To clean, run sh clean_docker.sh.

Development Roadmap

VersionDateFocus
V0.12025-12-23MVP - Core engine
V0.22026-01-01Docker deployment
V0.32026-01-31Workspace restructuring
V1.12026-02-04Schema foundation (UUID, content_hash, delete API)
V1.22026-02-06LanguageHandler trait refactor
V1.32026-02-06Incremental ingestion (SHA256, three-layer architecture)
V1.42026-02-07TypeScript support (TSX grammar, JSDoc)
V1.52026-02-07Docstring extraction (Rust, Python, TypeScript)
V2.12026-02-07Inline call context (AST-based call extraction)
V2.22026-02-08Intent classification + query routing (cosine similarity)
V2.32026-02-08Retrieval traces (scored sources, cross-type ranking)
Leptos Migration2026-03-25WASM frontend (replace htmx/Askama with Leptos)
GitHub Pages Demo2026-03-25Shared engine crate + standalone WASM deployment
V3.12026-04-02Retrieval test dataset (43 queries, 4 intent categories)
V3.22026-04-02Recall measurement harness (recall@K, MRR, intent accuracy)
V3.32026-04-03Baseline quality metrics (dual-run, per-intent breakdown)
B12026-04-04Cross-encoder reranking (ms-marco-MiniLM-L-6-v2)
B22026-04-04Hybrid BM25+semantic search infrastructure (disabled pending B3)
B32026-04-05Declaration signatures + searchable_text + per-intent gating (recall@5 0.70→0.75)
B42026-04-05Intent classifier 58%→74% (prototypes + k-NN + keyword pre-filter)
B52026-04-06Dual-vector schema + per-intent ArmPolicy (bm25/rerank gating)
C12026-04-09Graph RAG — call graph edges + 3-tier resolution + traversal (relationship 0.50→0.57)
C22026-04-09Graph result protection — SOTA routing + soft reserve (relationship 0.57→0.60)
C32026-04-09Comparison query decomposition — per-comparator RRF + project filter (comparison 0.62→0.65, aggregate 0.71→0.72)
A12026-04-17Text module consolidation — single code-rag-engine::text for tokenize/IDF/BM25/searchable_text (WASM/native single source)
A22026-04-17Folder-level embeddings — FolderChunk (5-line template, 118 chunks) shipped dark for A3 activation
A32026-04-17Collapsed-tree routing — folder arm activated for Overview/Implementation/Comparison (comparison 0.31→0.67 +36pp)
A42026-04-18File-level embeddings — FileChunk (4-line template, 247 chunks) + stratified relationship retrieval (recall@pool metric introduced)
MCP2026-04-24Claude Code MCP server (code-rag-mcp) — five tools (search, graph, overview, neighbors, reindex) on rmcp 1.5; bundled Skill; single-binary install (download → edit code-rag-mcp.config.yaml → run exe); subsumes code-rag-ingest via internal ingest subcommand; manually-triggered cross-platform release pipeline; agent-driven first ingest
Caravan2026-05-21Caravan adoption (B0p → M5). Four #[wagon] seams (Embedder / Reranker / VectorReader / LlmClient); RigGeminiImpl extracted to code-rag-llm; chat-side core (AppState, retrieve) extracted to code-rag-core (MCP no longer transitively depends on chat binary); four mix-and-match caravan.yaml targets (dev-monolith / dev-split-light / dev-split-mixed / dev-split-heavy) exercise per-seam independent dispatch. caravan-rpc 0.1.0 published to crates.io
R02026-06-08Crate split — parser/ingester renamed code-rag-ingest; code-raptor reclaimed as the topology engine (Track R home)
R12026-06-08RelationGraph + typed relation edges (graph_edges: imports/re_exports/contains/implements/extends/embeds/references/rationale_for) with per-language anchored resolution. Hardened 2026-08: project-scoped identifier index (graph never links projects) + documented per-language import matching
R22026-06-10Emergent communities — deterministic Louvain (no RNG) + hub exclusion + cohesion scoring, persisted to additive community_assignments table; folder→file contains excluded from partition input by design
R32026-06-10ClusterChunk summaries (template tier, cluster_chunks table, retrieval arm) — arm gated OFF by measurement (displaced code/folder chunks on Overview; machinery stays wired for a slot-protection/LLM-tier revisit)
R42026-08-06Structural analytics + per-project architecture report — degree centrality (wasm-safe), Brandes edge-betweenness bridges, surprise ranking, import-cycle detection (Tarjan SCC + bounded canonical DFS), byte-deterministic markdown artifact
R52026-08-10Track R capstone — emergent-vs-folder drift comparison (report section), interactive topology view in the demo (d3-force, click-a-node → chat query), GraphML + viz JSON exports, four MCP topology tools (communities / central_nodes / cycles / path with Mermaid call-flow) via revived find_path

Purpose

  • To practice and demonstrate familiarity with
    • Rust
    • RAG
    • Chatbot Application
  • To function as meta-project
    • To answer questions about sibling code repositories

Tech Stack

  • Backend: Rust + Axum
  • LLM: Google Gemini (via rig-core)
  • Vector DB: LanceDB
  • Embeddings: FastEmbed
  • Frontend: Leptos (Rust WASM, CSR)
  • Deployment topology: Caravan — one yaml flips per-seam dispatch (inproc / container / lambda) without source edits

Deployment flexibility via Caravan

code-rag adopts Caravan, an application-definition compiler. The four inter-component boundaries (Embedder, Reranker, VectorReader, LlmClient) are wrapped as caravan-rpc seams; a single yaml projects code-rag onto multiple deployment topologies with zero source-code edits between them.

# caravan.yaml (excerpt)
targets:
  dev-monolith:           # all 4 seams inproc — baseline single binary
    runtime: docker-compose
    entries: { code-rag-chat: container }

  dev-split-mixed:        # 2 seams flipped to separate compose services
    runtime: docker-compose
    entries: { code-rag-chat: container }
    seams:
      Embedder: container
      Reranker: container
      # VectorReader + LlmClient default to inproc
caravan compile --target=dev-split-mixed
docker compose \
  -f docker-compose.yaml \
  -f infra/dev-split-mixed/generated/docker-compose.override.generated.yaml \
  up

Caravan emits a compose override that layers atop the hand-authored docker-compose.yaml — adding peer services for split seams + injecting the per-deploy-unit CARAVAN_RPC_PEERS table the SDK reads at runtime. Same chat image, same binary, same source tree; only the env var changes.

SDK adoption surface is closed at four touchpoints in user code:

No-config inertness: when CARAVAN_RPC_PEERS is unset, client::<dyn T>() returns the registered Arc<dyn T> directly with zero overhead. All existing deployment surfaces — compose chat, compose ingest, local cargo run, WASM gh-pages, single-binary MCP release — keep working unchanged.

See caravan.yaml for the full seam declarations and four mix-and-match targets (dev-monolith / dev-split-light / dev-split-mixed / dev-split-heavy).


Guiding Principles

"Vertical slices, retrieval quality, code understanding"

PrincipleMeaning
VerticalBuild working end-to-end first, then deepen
RetrievalQuality of retrieved context determines answer quality
UnderstandingGoal is semantic code understanding, not just text search

Architecture

CrateSingle Responsibility
code-rag-ingestIngestion CLI — parsing, chunk extraction, data export
code-raptorTopology engine (Track R) — derives architectural structure from persisted relation edges
code-rag-engineShared algorithms — intent, context, scoring (pure, no I/O)
code-rag-storeStorage seams + LanceDB-backed impls; fastembed Embedder + Reranker
code-rag-llmLLM-provider seam impls (rig-core-backed Gemini today; extracted at M5 so synthetic Caravan peer services can build against the impl)
code-rag-coreChat-side core shared between the chat binary and the MCP server — AppState, retrieve(), EngineError, SourceInfo. Extracted at M5 to break code-rag-mcp's transitive dep on code-rag-chat
code-rag-typesShared types — no logic
code-rag-chatHTTP routing + Askama templates + binary main (2 binaries: chat server + harness). Core logic moved to code-rag-core
code-rag-mcpMCP stdio server (single-binary release) — depends on code-rag-core directly, no chat-binary transitive
code-rag-uiLeptos WASM SPA — chat interface (backend or standalone mode)

Current State

  • Function-level chunking: 1 function/class → 1 vector (BGE-small, 384 dim)
  • Supports Rust, Python, TypeScript, and Go via tree-sitter AST parsing
  • Docstrings extracted: /// (Rust), """ (Python), /** */ (TypeScript JSDoc), // (Go)
  • Declaration signatures extracted: functions + structs/enums/traits/interfaces/classes
  • Hierarchy chunks (Track A): FolderChunk (1 per directory, 5-line template — folder/files+languages/key types/key functions/subfolders) and FileChunk (1 per source file, 4-line template — file/exports/imports/purpose). Built deterministically at ingest from existing CodeChunk metadata + C1 imports map — no LLM. Both render through pure code-rag-engine::{folder,file} functions, so server-embedded bytes and browser BM25 bytes are byte-identical
  • Persistent call graph (Graph RAG): LanceDB scalar-only call_edges table, 3-tier resolver (same-file → import-based → unique-global), AST scoped-identifier (module::function()) extraction
  • Typed relation topology (Track R): graph_edges table persists imports / re_exports / contains / implements / extends / embeds / references / rationale_for edges with per-language anchored resolution, project-scoped so the graph never links sibling projects (retrieval stays corpus-wide)
  • Emergent communities (Code Raptor): deterministic Louvain (fixed order, no RNG — identical partition every run) over calls ∪ imports ∪ type relations ∪ file-level containment, with hub exclusion + cohesion scoring; persisted per-chunk in community_assignments. Folder→file edges are deliberately excluded from the partition input so the emergent-vs-folder comparison is earned, not self-fulfilling
  • Architecture report + drift: per-project byte-deterministic markdown artifact — "read these first" degree centrality, cross-community bridges (Brandes edge-betweenness) with relation provenance, surprising-connection ranking, import cycles (Tarjan SCC + bounded canonical DFS), and an emergent-vs-folder drift section (community purity vs directory layout — e.g. it flags the vector_store.rs monolith splitting into 15 communities)
  • Topology exports: per-project graph_viz_<project>.json (browser artifact, capped 5000 nodes / 15 000 edges) + full-graph GraphML for Gephi/yEd — both byte-deterministic across runs
  • Test code exclusion at ingest (3-level): directory tests/, filename test_*.py / *.test.ts, AST-walked #[cfg(test)] enclosing-mod detection (~24% chunk reduction)
  • Intent classification: cosine similarity against prototype query embeddings
  • Query routing: declarative routing table maps intent → retrieval limits across all six chunk types (code, folder, file, readme, crate, module_doc)
  • Two-stage retrieval: hybrid (BM25 on searchable_text + vector) → cross-encoder reranking (ms-marco-MiniLM-L-6-v2), fused via N-ary RRF in shared code-rag-engine::fusion
  • Per-intent ArmPolicy: per-intent {body_vec, sig_vec, bm25, rerank, folder_vec, file_vec} gating (single source of truth, server + browser). Overview = hybrid+rerank; Implementation = rerank-only; Relationship = hybrid+rerank; Comparison = vector-only. Folder arm gated off for Relationship after empirical regression (folder chunks of X displaced consumers of X — stratified retrieval, file arm stays on)
  • Graph-augmented retrieval: shared code-rag-engine::graph (graph_augment, merge_graph_chunks, reserve_graph_slots, detect_direction). Two protection paths: SOTA routing for explicit-direction queries ("what calls X / called by") partitions graph chunks out of the reranker entirely; soft reserve for ambiguous-direction over-retains the code arm by +5 and rescues demoted graph chunks. Mirrored line-for-line in WASM standalone
  • Comparison query decomposition (code-rag-engine::comparison): regex extracts ≥2 comparators → per-comparator body-vec sub-searches (comparator name prepended to original query) → vote-based dominant-project filter → RRF fusion → max-of-natural rescoring so RRF outputs compete with non-code arms. Mirrored in WASM standalone
  • Single text module (A1): code-rag-engine::text is the sole home for tokenize, IdfTable, BM25 kernel, build_searchable_text, split_camel_case, and intent prototype texts. Compiles to native + wasm32 — no duplication across server, store, raptor, or UI
  • Dual-vector schema: nullable signature_vector column populated at ingest (shipped OFF after 8-config space sweep; column retained for future experiments)
  • Intent classifier: prototype cosine similarity + k-NN (k=3) weighted voting + Comparison keyword pre-filter with adversarial guards — 74% accuracy (was 58%)
  • Retrieval traces: all 6 chunk types surfaced with relevance scores, sorted by relevance
  • Quality harness: 87-query test dataset (79 recall-scoreable), recall@K, recall@pool (introduced in A4 — recall over every chunk reaching build_context, no top-k truncation), MRR, intent accuracy, latency — dual-run mode
  • Current baseline (post_rationale_anchor, 2026-08-07, 6-project corpus, classifier routing): recall@5 = 0.60 aggregate · overview 0.70 · implementation 0.61 · relationship 0.47 · comparison 0.62 · recall@10 = 0.69 · recall@pool = 0.72. Not comparable to the earlier post-A4 0.72@5: two projects were purged from the corpus (source repos deleted), the cross-project resolution leak was fixed (edges that once inflated recall were wrong answers), and the corpus now includes code-rag's own Track R code
  • Incremental ingestion: SHA256 file hashing, skips unchanged files
  • Shared code-rag-engine crate: pure algorithms compile to native + wasm32
  • GitHub Pages demo: standalone feature runs the full RAG pipeline in-browser (LLM generation optional), plus an interactive topology tab — d3-force canvas of each project's emergent communities (community-colored, degree-sized, relation-dashed edges; theme-aware palette), click a node to run a code-rag query about it

Known Limitations

  • Granularity: File and folder levels covered by Track A (FileChunk, FolderChunk). Repo-level summary considered and retired by measurement (existing READMEs + project-root FolderChunks already covered the 3 hero queries at recall@10=1.0)
  • Comparison short-identifier ceiling: Two stubborn pre-C3 failures (comp-retriever-generator, b4-comp-retriever-api) remain — BGE-small produces noisy vectors for bare hyphenated identifiers (retriever, generator), and the C3 regex extracts comparators only from explicit "compare X and Y / X vs Y" phrasings. Gated on a future embedder upgrade (BGE-base / jina-code) or MMR fallback
  • Classifier: No longer the dominant bottleneck post-B4 (+2pp classifier→GT gap on recall@5). Implementation and Relationship classification still below targets (70% / 53%)
  • Incremental reconcile under multi-file change: surfaced during A4 calibration — wipe-and-reinsert across many simultaneously-changed files corrupted BM25 IDF / row ordering and degraded hybrid retrieval. Workaround: fresh full ingest. Filed as a follow-up; not Track A-specific

Planned Features

See project-vision.md and development_plan.md for roadmap.


Keywords

  • Language: Rust
  • Architecture & Patterns: Layered Architecture (API/Store/Ingestion) · Trait-Based Abstraction (LanguageHandler) · Registry Pattern (OnceLock) · Three-Layer Pipeline (Parse→Reconcile→Orchestrate) · Router Pattern · Handler Pattern · Shared State (Arc) · Repository Pattern · DTO Pattern · Modular Design · Pipeline Pattern (Ingest→Embed→Store) · Visitor Pattern (WalkDir) · Error Propagation (thiserror) · Ephemeral Side-Channel Pattern · Declarative Routing Table · Scored Search API · ScoredChunk<T> (Generic Wrapper) · Retrieval Traces · Multi-Binary Crate (lib.rs extraction) · FlatChunk Centralization
  • LLM & RAG: RAG (Retrieval-Augmented Generation) · Graph RAG · Call Graph Augmentation · Graph-Augmented Retrieval · SOTA Routing (Reranker Bypass) · Soft Reserve · Comparison Query Decomposition · Per-Comparator RRF Fusion · Sub-Query Expansion · Vote-Based Project Filter · Max-of-Natural Rescoring · LLM Integration · Google Gemini API · rig-core · Semantic Search · Chatbot · Intent Classification (Cosine Similarity) · Prototype Query Embeddings · k-NN Prototype Voting · Keyword Pre-Filter (adversarial-guarded) · Intent-Aware Retrieval · Per-Intent Gating (ArmPolicy) · Two-Stage Retrieval · Cross-Encoder Reranking · Hybrid Search (BM25 + Dense) · RRF Fusion · Dual-Vector Schema · Declaration Signatures · searchable_text (IR field boosting) · camelCase Splitting (index-time) · Cross-Type Source Ranking · Distance-to-Relevance Scoring · Retrieval Transparency
  • Quality & Evaluation: Recall@K · MRR (Mean Reciprocal Rank) · Intent Accuracy · Latency Percentiles (p50/p95) · Dual-Run Evaluation (Classifier vs Ground-Truth) · Per-Intent Breakdown · Declarative Test Dataset · Substring File Matching · Dataset Freeze Policy · Baseline Regression Tracking · Space Search (per-intent ArmPolicy sweep) · Adversarial Test Cases · Held-out Classifier Eval
  • Vector Database: LanceDB · LanceDB FTS · Scalar-Only LanceDB Table (call_edges) · BM25 · FastEmbed · BGE Embeddings · ms-marco-MiniLM-L-6-v2 (ONNX)
  • Code Analysis: Tree-sitter · AST Parsing · Code Chunking · Docstring Extraction · JSDoc Parsing · Multi-Language (Rust, Python, TypeScript, Go) · Incremental Ingestion (SHA256) · Call Graph Extraction (AST-based) · Function Call Detection (Direct + Method) · Call Edge Resolution (3-tier) · Import-Based Symbol Resolution · Scoped Identifier Extraction · Test Code Exclusion (cfg(test) AST walk)
  • Graph & Topology (Track R): Community Detection (Louvain) · Modularity Maximization · Cohesion Scoring · Edge Betweenness (Brandes) · Tarjan SCC · Dependency Cycle Detection · Emergent Architecture · Architecture Drift (Emergent vs Folder) · Typed Relation Edges · Degree Centrality · GraphML Export · Mermaid Call-Flow · Force-Directed Layout (d3-force) · Deterministic Graph Algorithms
  • Web Framework: Axum · Leptos (WASM CSR) · Tower HTTP · CORS
  • Async & Runtime: Tokio Runtime · Async Programming
  • DevOps: Docker · Docker Compose · GitHub Pages (WASM) · Google OAuth2 (GIS)
  • Rust Ecosystem: tracing · Error Handling (anyhow/thiserror) · Serde · clap (CLI) · chrono

Contributors

paulxiep

71 commits

Languages

Rust

97.3%

CSS

1.1%

JavaScript

1.0%