Technical data sheet · measured, not declared

codeindex

Zero-install, deterministic repo-indexing engine — one vendorable file, a library, a CLI, and 26 MCP tools.

Walks a repo, extracts symbols and imports across 15 languages, resolves cross-file references into a typed link-graph, and renders byte-identical artifacts every time it runs. Vendor the single engine.mjs, install it from npm or Homebrew, or run it from a container — nothing else to install, ever.

MIT license v2.15.0 Node ≥ 18 npm · @maxgfr/codeindex ghcr.io/maxgfr/codeindex 0 runtime deps

Install

npm i -g @maxgfr/codeindex

Same zero-dependency engine.mjs bundle behind all three — CLI, library import, and Docker image.

Key measured numbers

Fig. 01 — measured, reproducible

Benchmarks

Measured against universal-ctags, Serena (LSP over MCP) and Graphify with a reproducible harness (scripts/bench/) — median of 5 runs, one warmup discarded. Every number on this page comes from the same site/benchmarks.json committed to this repo; nothing here is rounded or typed in by hand. Full methodology and every scenario: BENCHMARKS.md.

Cold index — code-du-travail

2,823 files, every tool measured on the same repo. Lower is faster.

Warm reindex — against codeindex's own cold build

No competitor here exposes an incremental reindex, so the baseline is the cold build of the same repo: what a rerun costs once the cache is warm, and what one touched file costs. Lower is faster.

Axis by axis

One row per thing an agent-tooling team weighs. A filled tile marks the leader on that axis — hover any cell for the measured number. Where a rival wins it stays at the top of the table, unedited: on a small repo ctags takes the cold-index row, because a flat tags pass is a smaller job than a typed cross-file graph and there is too little work to spread across cores. That ordering flips on the largest repo measured here. The rows below are what the bigger job buys.

codeindex leads a competitor leads tie / not this tool's job — = n/a (not measurable)

Fig. 02 — capabilities

Features

Everything below ships in the same zero-dependency bundle — no feature is an optional add-on package.

Keyless search + deterministic fuzzy

BM25 lexical ranking over symbol names, path segments and headings. A term with zero document frequency falls back to a byte-deterministic character-trigram match (Dice ≥ 0.6) — typo tolerance with no embeddings. Disable with --no-fuzzy.

Deterministic semantic tier

An opt-in static token → vector lookup table — no neural forward pass. Encode → mean-pool → L2-normalize → round-half-to-even int8 quantize; ranking is a pure integer dot product, byte-identical everywhere. No model on disk, no behavior change.

Rich embedding tier — v2.11.0

Point at a containerized HTTP endpoint (ghcr.io/maxgfr/codeindex-embed, all-MiniLM-L6-v2) via CODEINDEX_EMBED_ENDPOINT. Wins over the static tier by explicit intent; degrades to lexical on exit 0 if unreachable — never a silent fallback to the wrong model.

Call graph & caller index

Typed import / call / use / doc-link / mention edges at file and module level. Per-symbol callers and references resolve in-proc in sub-millisecond time on an already-loaded warm scan.

Graph analytics

Louvain communities, PageRank & betweenness centrality, dead-code detection, complexity × churn hotspots, change coupling, surprise-edge detection, and a tests→code map — all derived from the same link-graph.

SCIP export

index.scip via a hand-rolled zero-dependency protobuf encoder — validated against the official scip CLI's stats/lint.

Multi-ecosystem workspaces

npm/yarn, pnpm, lerna, nx, cargo, go.work, maven, gradle, uv and Composer — detected and named without running any of their own tooling.

Symbolic edits over MCP

replace_symbol_body, insert_after_symbol, insert_before_symbol — precise edits addressed by symbol name, not by line ranges that drift.

mermaid & repo map

Render a mermaid dependency diagram or a plain-text repo map directly from the graph — no separate diagramming step.

Byte-deterministic outputs

Two cold builds of an unchanged repo produce identical graph.json/symbols.json — confirmed on 7 of 7 measured repos this session. Graphify's graph.json differed on 5 of the 6 measurable repos; determinism is a value we hold across every repo, not just where it's easy.

Fig. 03 — usage

Quickstart

Five ways in — pick the one matching your integration.

Install it as a regular dependency and import the pure functions.

npm i @maxgfr/codeindex
import { scanRepo, ENGINE_VERSION } from "@maxgfr/codeindex";

const scan = scanRepo("/path/to/repo");

Fig. 04 — what each tool is

How it compares

The axis-by-axis scoreboard sits with the benchmarks, where its numbers come from. This is the shape of each tool: what it models, what it covers, what it costs to install.

Tool comparison codeindex vs. universal-ctags, Serena and Graphify.
Tool Model Language coverage Install Worth knowing
codeindex Static byte-stable artifacts (graph.json/symbols.json), rebuilt each run with an incremental cache 15 (regex, always on) / 13 (tree-sitter AST, opt-in grammars) npm i -g, brew, or docker — zero runtime deps A single-file incremental reindex is slower than a live database (see Benchmarks)
universal-ctags A flat tags file Broad, generic parser rules Binary install Fastest cold index on small repos, overtaken on the largest one measured — and definitions only: no call graph, no import resolution, no cross-file links
Serena LSP client orchestrating per-language language servers Any language with an LSP server 114 MB venv + per-language language servers Type-aware references no static tool claims — bought with the slowest activation and per-call latency measured here, and no on-disk artifact to reproduce
Graphify tree-sitter knowledge graph (graph.json); code-only mode is keyless, the docs/PDF tier needs an LLM and is excluded here 36 via tree-sitter 140 MB Python venv (uv tool) ~1 ms per lookup, but graph.json is not byte-identical across rebuilds on 5 of the 6 measurable repos, and file nodes are basename-keyed (no file-overview)