ultraindex — the verified knowledge layer over codeindex
For engine evidence and coverage limits, read engine-evidence.
For a handoff that claims every answer claim was checked, use verify --complete --answer <file> --repo <dir>. Read and adjudicate the current batch
files listed in VERIFY.md (default 40 pairs each; --batch-size changes that).
Fold the comma-separated verdict paths with verify --apply, then gate with
check --answer <file> --semantic --complete. Default verification is sampled;
do not describe it as complete when pairs remain uncovered. Generation is only
a worklist, and support still requires reading the excerpts.
The mechanical work is not ours. ultraindex vendors
codeindex — a deterministic,
zero-dependency, keyless engine — and it does the scanning, symbol
extraction, import resolution and link-graph (node scripts/ultraindex.mjs <command> — no npm install, no API keys, run --help for the full surface).
Everything ultraindex adds exists only because you are in the loop: the
encyclopedia is your durable memory of this repo — it outlives the session and
the context window — and the gates exist so nothing you write into it can be
unfounded. If the user only needs to find code fast, say so and point them at
codeindex; they do not need this skill for that.
The core rules:
- The codeindex engine owns the code view and the graph (
ui:gen
regions) — regenerated every build; never hand-edit them.
- You own the business view (
ui:human regions). build preserves your
prose across rebuilds and renames.
- Analyze from evidence, not memory. Write analysis only from the real
source
dossier shows you, cite it [file:line], and check fails on any
citation that doesn't resolve — so don't guess.
- Load the minimum. Read one entry (or one
dossier) at a time — that is
the intended pattern, and exactly what a per-module enrichment subagent does.
Never bulk-load graph.json or the whole encyclopedia/ directory into
context — that defeats the purpose.
- Prose can go stale silently; code cannot. The code view is regenerated
every build, so it can't drift — but an analysis written against source
that has since changed still reads as true, and downstream trusts it MORE.
check and status report, per entry, whether its prose predates its
source. A stale entry is unverified: don't quote it and don't build on
it. Re-run dossier <slug>, revise the prose, then check. An entry
reported as unverifiable (no recorded source state, or one stamped when
manifest.json was missing) is not a pass either — nothing proves it fresh.
Most commands accept --json — prefer it whenever you branch on the result
rather than read it as prose.
Route by situation
Work out which situation you are in, in this order, and read the matching
reference for the detailed workflow:
No index yet — no .ultraindex/ or docs/ultraindex/ at the repo root
(look for graph.json inside). Build it, then enrich the top modules:
read references/generate.md.
Index exists — check freshness first.
node scripts/ultraindex.mjs check --out <index-dir> --json. If it reports
stale or broken, re-run build (your prose survives), then continue. If
only files irrelevant to the task changed, you may proceed and note it.
If it reports proseStale for some modules, the code view is fresh but a
model's explanation of those modules was written against source that has
since changed — rebuilding does NOT fix that. Those entries are unverified:
re-enrich them (situation 6) before relying on them, or say explicitly that
you did not.
The user has a task or question ("where is X", "how does Z work",
"which files do I change") — navigate the index, open only the files it
points at, ground answers with verified citations:
read references/navigate.md.
The user asks to review a branch, PR, or staged changes — build (fresh
index is a hard precondition), then delta for the risk-ranked worklist
(changed symbols → blast radius → explained reasons), then ground each risky
item: read references/review.md.
The answer must be high-assurance (audit, security, a correctness-critical
claim), or the user asks you to verify/adjudicate an answer — after
check --answer passes (citations resolve), escalate to the semantic verify
gate so each cited excerpt is proven to support its claim, not just exist:
read references/verify.md.
The user asked to index/analyze/document, or status --json shows
unenriched hubs and you have budget — run the status-driven enrichment
loop (dossier → write cited analysis → check). On a large repo this
parallelizes: one subagent per module from the queue, if your host supports
subagents — orchestrate emits that fan-out for you (see Orchestration —
route by harness below) — read references/generate.md.
find keeps missing, or the user wants semantic/better search — set up
the optional keyless embeddings layer (embed, hybrid find):
read references/semantic.md.
A typical first visit chains 1 → 6 → 3; a return visit is usually 2 → 3; a
review of a branch is 2 → 4; a high-assurance answer adds → 5.
Command cheat-sheet
build --repo <dir> [--out .ultraindex] [--include/--exclude <glob>] [--max-bytes <n>] [--max-files <n>] [--no-cache] [--full-hash] [--no-mermaid] [--no-gitignore] — scan and (re)write the index. Idempotent; keeps enriched prose. Incremental (reuses unchanged files' extraction); warns if --max-files truncates. --out docs/ultraindex for a committed, PR-reviewable index.
map [--module <slug>] [--json] — print INDEX.md (or one entry, or the module table).
find "<query>" [--k <n>] — rank modules, print the exact files to open. Lexical (with IDF term weighting) by default; hybrid (+ semantic) when vectors.json exists.
neighbors <file|module> [--depth <n>] [--kind <k>] — what links to / from it (--kind filters edge kinds: import,call,use,doc-link,mention).
symbols "<name>" [--json] — where a symbol is defined (file:line, kind, owning module) and which files reference it. Fuzzy by identifier sub-token.
impact <file|module> [--depth <n>] [--json] — the reverse dependency closure: everything that imports or uses the target. "What breaks if I change this."
delta [--base <ref>] [--staged] [--depth <n>] [--json] — map the git diff onto the index: changed files → enclosing symbols → blast radius → a risk-scored review panel with explained reasons (exported API, hub centrality, blast size, test gap, surprising coupling, dangling imports). Needs a fresh index (fails closed on drift). See references/review.md.
status — the enrichment work-queue, in the exact order to enrich: entries whose prose went stale first (an outdated explanation misleads more than a missing one), then never-enriched, then done.
dossier <slug> [--budget <n>] — a module's grounding packet (real source + neighbours; a docs/config-only module, e.g. root, shows no code — enrich it by citing its README/config instead).
ask "<question>" [--budget <n>] — assemble grounded evidence to answer from; --budget caps the inlined source at ~n tokens (also on dossier).
check [--answer <file>] [--semantic] [--prose] [--quiet] — staleness + integrity + grounding (citations must resolve). Non-zero exit ⇒ stale, broken, or ungrounded (--quiet suppresses output — exit code only). Stale prose is reported separately from a stale index — different failure, different remedy (re-enrich vs rebuild) — and is a warning unless you pass --prose, which promotes it to a failure. --semantic also folds the verify gate (fails a claim whose cited excerpt refutes it, or that is fully adjudicated with no support); it re-reduces the verdict from the raw verdicts[] and re-reads every adjudicated excerpt from the live repo — a doctored summary or drifted source fails, never passes.
verify --answer <file> [--apply <verdicts.json>] [--max-verify <n>] — the high-assurance gate above check --answer: emit a claim↔citation worklist for adversarial support-checking, then --apply reduces your verdicts to a pass/fail gate. See references/verify.md.
embed [--force] — build/refresh vectors.json for semantic find. Keyless: pulls the model on first use, no provider to stand up (see references/semantic.md).
orchestrate [--phase enrich|verify-answer] [--answer <file>] [--eco] [--list] — emit the multi-agent fan-out (workflow scripts + dispatch contracts + a sequential RUNBOOK) into <index>/orchestration/ from the CURRENT enrichment queue / verify worklist. See Orchestration — route by harness.
engine <engine-command> … — run any vendored codeindex command, arguments passed through untouched. The commands above are the encyclopedia; this is the engine's own deterministic code view, and it answers questions the encyclopedia does not hold: engine literals (values with no single source of truth — one value written across many files while a constant already holds it), engine deadcode, engine complexity, engine hotspots, engine rules (architecture CI gate), engine search "<q>". Run engine --help for the full surface. Use it when the question is about the CODE as it is, not about what a module MEANS — and remember its output is evidence you still have to cite.
Orchestration — route by harness
The judgment work fans out: the enrichment queue status --json reports is one
independent dossier→prose unit per module, and VERIFY.todo.json (one pair per
claim↔citation, written by verify --answer next to the answer) fans out the same
way. The engine manages the fan-out — orchestrate emits the orchestration from the
CURRENT index state, with absolute paths and the real module slugs baked in:
node scripts/ultraindex.mjs orchestrate [--out <dir>] [--repo <dir>] [--answer <file>] [--phase enrich|verify-answer] [--eco] [--list]
| Your harness |
How to run each phase |
| Claude Code exposes Workflow |
orchestrate --phase <p>, then Workflow({ scriptPath: "<index>/orchestration/<p>.workflow.mjs" }). Enrichers WRITE their own encyclopedia/<slug>.md entries (the sanctioned disjoint-write exception) and return what they wrote; refuters only RETURN verdict fragments you fold and verify --apply yourself. |
| Codex or another host exposes subagents |
Same orchestrate; dispatch one subagent per batch following <index>/orchestration/agents/<role>.md (the workflow script shows batches + prompts). |
| Eco mode, or no subagents |
orchestrate --eco → follow <index>/orchestration/RUNBOOK.md sequentially, playing each role yourself. Correctness-identical; only wall-clock differs. |
Fan-out is an optimization, never a requirement — the gates (check,
verify --apply) are harness-independent and every phase has a sequential fallback
with identical artifacts. The one hard rule: no build or map runs while a
fan-out is in flight — build rewrites every entry, so a mid-fan-out rebuild
races and clobbers the agents' writes; the orchestrator runs one repo-wide check
after the join and routes each grounding failure back to the entry that caused it.
Re-run orchestrate whenever the queue changes (emission is deterministic and
idempotent); --phase <p> before its input exists fails and names the command that
produces it.
Scope notes
- Everything below is the vendored codeindex engine's, not ultraindex's.
Report engine defects upstream; ultraindex owns the encyclopedia, the gates
(
check/verify), the work-queue and the fan-out — nothing else.
- No keys, deterministic, offline after a one-time setup — the only network
touches are two first-use pulls into shared per-machine caches: the
tree-sitter grammars (see AST-exact symbols below) and the optional embedding
model. Both are sha256-verified and both degrade rather than fail (regex
extractor; lexical-only
find). Two builds of an unchanged repo are
byte-identical except for manifest.json's builtAt provenance timestamp —
vectors.json included, since the static embedding tier is byte-deterministic.
Only the optional CODEINDEX_EMBED_ENDPOINT tier, whose floats come from a
server, falls outside that guarantee.
- AST-exact symbols via tree-sitter grammars for JS/TS/TSX, Python, Go,
Rust, Java, C, C++, C#, Ruby, PHP — real nesting, precise kinds, structural
export. Other languages fall back to regex extractors (still searchable). The
grammar wasms are no longer shipped in the bundle: the first
build on a
machine pulls them (17 MiB) into a shared cache
(`<XDG_CACHE_HOME|/.cache>/codeindex/grammars//), sha256-verified, then reuses them forever — so AST precision is on by default after a single download, and the installed skill is that much smaller. **Offline with no cache yet** ⇒ buildsays so and indexes with the regex extractor (never a silent downgrade). Pre-warm before going offline withnode scripts/ultraindex.mjs
grammars pull(inspect the active tier withgrammars status), or point CODEINDEX_GRAMMARS_DIR` at an existing grammars dir.
- Import edges for JS/TS (tsconfig
paths, package exports maps),
Python, Go (multi-module + replace), Rust (mod/use), Java (packages),
C/C++ (#include "..."), Ruby (require_relative/require), PHP (composer
PSR-4 + relative require), C# (using → namespace). Plus conservative
code→code use edges when a file references another file's unique exported
symbol without importing it. Remaining languages get no import edges.
Yarn PnP's virtual filesystem is out of scope (workspace names still resolve).
- Dangling edges usually mean the repo itself has broken imports or stale
doc links — that's a finding to report, not to paper over.
1---2name: ultraindex3description: Build and navigate a cited codebase encyclopedia to locate behavior, trace flows, and assess change impact.4license: MIT5---67# ultraindex — the verified knowledge layer over codeindex89For engine evidence and coverage limits, read [engine-evidence](references/engine-evidence.md).1011For a handoff that claims **every** answer claim was checked, use `verify12--complete --answer <file> --repo <dir>`. Read and adjudicate the current batch13files listed in VERIFY.md (default 40 pairs each; `--batch-size` changes that).14Fold the comma-separated verdict paths with `verify --apply`, then gate with15`check --answer <file> --semantic --complete`. Default verification is sampled;16do not describe it as complete when pairs remain uncovered. Generation is only17a worklist, and support still requires reading the excerpts.1819The mechanical work is not ours. `ultraindex` vendors20**[codeindex](https://github.com/maxgfr/codeindex)** — a deterministic,21zero-dependency, keyless engine — and *it* does the scanning, symbol22extraction, import resolution and link-graph (`node scripts/ultraindex.mjs23<command>` — no `npm install`, no API keys, run `--help` for the full surface).2425Everything ultraindex adds exists only because **you** are in the loop: the26encyclopedia is your durable memory of this repo — it outlives the session and27the context window — and the gates exist so nothing you write into it can be28unfounded. **If the user only needs to find code fast, say so and point them at29codeindex; they do not need this skill for that.**3031> **The core rules:**32> 1. The **codeindex engine** owns the *code view* and the *graph* (`ui:gen`33> regions) — regenerated every build; never hand-edit them.34> 2. You own the *business view* (`ui:human` regions). `build` preserves your35> prose across rebuilds and renames.36> 3. **Analyze from evidence, not memory.** Write analysis only from the real37> source `dossier` shows you, cite it `[file:line]`, and `check` fails on any38> citation that doesn't resolve — so don't guess.39> 4. **Load the minimum.** Read one entry (or one `dossier`) at a time — that is40> the intended pattern, and exactly what a per-module enrichment subagent does.41> Never bulk-load `graph.json` or the whole `encyclopedia/` directory into42> context — that defeats the purpose.43> 5. **Prose can go stale silently; code cannot.** The code view is regenerated44> every build, so it can't drift — but an analysis written against source45> that has since changed still reads as true, and downstream trusts it MORE.46> `check` and `status` report, per entry, whether its prose predates its47> source. A stale entry is **unverified**: don't quote it and don't build on48> it. Re-run `dossier <slug>`, revise the prose, then `check`. An entry49> reported as *unverifiable* (no recorded source state, or one stamped when50> `manifest.json` was missing) is not a pass either — nothing proves it fresh.5152Most commands accept `--json` — prefer it whenever you branch on the result53rather than read it as prose.5455## Route by situation5657Work out which situation you are in, in this order, and read the matching58reference for the detailed workflow:59601. **No index yet** — no `.ultraindex/` or `docs/ultraindex/` at the repo root61 (look for `graph.json` inside). Build it, then enrich the top modules:62 read [references/generate.md](references/generate.md).63642. **Index exists — check freshness first.**65 `node scripts/ultraindex.mjs check --out <index-dir> --json`. If it reports66 stale or broken, re-run `build` (your prose survives), then continue. If67 only files irrelevant to the task changed, you may proceed and note it.6869 If it reports `proseStale` for some modules, the *code view* is fresh but a70 model's *explanation* of those modules was written against source that has71 since changed — rebuilding does NOT fix that. Those entries are unverified:72 re-enrich them (situation 6) before relying on them, or say explicitly that73 you did not.74753. **The user has a task or question** ("where is X", "how does Z work",76 "which files do I change") — navigate the index, open only the files it77 points at, ground answers with verified citations:78 read [references/navigate.md](references/navigate.md).79804. **The user asks to review a branch, PR, or staged changes** — build (fresh81 index is a hard precondition), then `delta` for the risk-ranked worklist82 (changed symbols → blast radius → explained reasons), then ground each risky83 item: read [references/review.md](references/review.md).84855. **The answer must be high-assurance** (audit, security, a correctness-critical86 claim), or the user asks you to *verify*/adjudicate an answer — after87 `check --answer` passes (citations resolve), escalate to the semantic verify88 gate so each cited excerpt is proven to *support* its claim, not just exist:89 read [references/verify.md](references/verify.md).90916. **The user asked to index/analyze/document, or `status --json` shows92 unenriched hubs and you have budget** — run the status-driven enrichment93 loop (dossier → write cited analysis → check). On a large repo this94 parallelizes: one subagent per module from the queue, if your host supports95 subagents — `orchestrate` emits that fan-out for you (see **Orchestration —96 route by harness** below) — read [references/generate.md](references/generate.md).97987. **`find` keeps missing, or the user wants semantic/better search** — set up99 the optional keyless embeddings layer (`embed`, hybrid `find`):100 read [references/semantic.md](references/semantic.md).101102A typical first visit chains 1 → 6 → 3; a return visit is usually 2 → 3; a103review of a branch is 2 → 4; a high-assurance answer adds → 5.104105## Command cheat-sheet106107- `build --repo <dir> [--out .ultraindex] [--include/--exclude <glob>] [--max-bytes <n>] [--max-files <n>] [--no-cache] [--full-hash] [--no-mermaid] [--no-gitignore]` — scan and (re)write the index. Idempotent; keeps enriched prose. Incremental (reuses unchanged files' extraction); warns if `--max-files` truncates. `--out docs/ultraindex` for a committed, PR-reviewable index.108- `map [--module <slug>] [--json]` — print INDEX.md (or one entry, or the module table).109- `find "<query>" [--k <n>]` — rank modules, print the **exact files to open**. Lexical (with IDF term weighting) by default; hybrid (+ semantic) when vectors.json exists.110- `neighbors <file|module> [--depth <n>] [--kind <k>]` — what links to / from it (`--kind` filters edge kinds: import,call,use,doc-link,mention).111- `symbols "<name>" [--json]` — where a symbol is **defined** (file:line, kind, owning module) and which files reference it. Fuzzy by identifier sub-token.112- `impact <file|module> [--depth <n>] [--json]` — the **reverse dependency closure**: everything that imports or uses the target. "What breaks if I change this."113- `delta [--base <ref>] [--staged] [--depth <n>] [--json]` — map the git diff onto the index: changed files → enclosing symbols → blast radius → a **risk-scored review panel** with explained reasons (exported API, hub centrality, blast size, test gap, surprising coupling, dangling imports). Needs a fresh index (fails closed on drift). See [references/review.md](references/review.md).114- `status` — the enrichment **work-queue**, in the exact order to enrich: entries whose prose went **stale** first (an outdated explanation misleads more than a missing one), then never-enriched, then done.115- `dossier <slug> [--budget <n>]` — a module's grounding packet (real source + neighbours; a docs/config-only module, e.g. `root`, shows no code — enrich it by citing its README/config instead).116- `ask "<question>" [--budget <n>]` — assemble grounded evidence to answer from; `--budget` caps the inlined source at ~n tokens (also on `dossier`).117- `check [--answer <file>] [--semantic] [--prose] [--quiet]` — staleness + integrity + **grounding** (citations must resolve). Non-zero exit ⇒ stale, broken, or ungrounded (`--quiet` suppresses output — exit code only). Stale **prose** is reported separately from a stale **index** — different failure, different remedy (re-enrich vs rebuild) — and is a warning unless you pass `--prose`, which promotes it to a failure. `--semantic` also folds the verify gate (fails a claim whose cited excerpt refutes it, or that is fully adjudicated with no support); it re-reduces the verdict from the raw `verdicts[]` and re-reads every adjudicated excerpt from the live repo — a doctored summary or drifted source fails, never passes.118- `verify --answer <file> [--apply <verdicts.json>] [--max-verify <n>]` — the high-assurance gate **above** `check --answer`: emit a claim↔citation worklist for adversarial support-checking, then `--apply` reduces your verdicts to a pass/fail gate. See [references/verify.md](references/verify.md).119- `embed [--force]` — build/refresh vectors.json for semantic `find`. Keyless: pulls the model on first use, no provider to stand up (see [references/semantic.md](references/semantic.md)).120- `orchestrate [--phase enrich|verify-answer] [--answer <file>] [--eco] [--list]` — emit the multi-agent fan-out (workflow scripts + dispatch contracts + a sequential RUNBOOK) into `<index>/orchestration/` from the CURRENT enrichment queue / verify worklist. See **Orchestration — route by harness**.121- `engine <engine-command> …` — run any vendored codeindex command, arguments passed through untouched. The commands above are the encyclopedia; this is the engine's own deterministic code view, and it answers questions the encyclopedia does not hold: `engine literals` (values with no single source of truth — one value written across many files while a constant already holds it), `engine deadcode`, `engine complexity`, `engine hotspots`, `engine rules` (architecture CI gate), `engine search "<q>"`. Run `engine --help` for the full surface. Use it when the question is about the CODE as it is, not about what a module MEANS — and remember its output is evidence you still have to cite.122123## Orchestration — route by harness124125The judgment work fans out: the enrichment queue `status --json` reports is one126independent dossier→prose unit per module, and `VERIFY.todo.json` (one pair per127claim↔citation, written by `verify --answer` next to the answer) fans out the same128way. The engine manages the fan-out — `orchestrate` emits the orchestration from the129CURRENT index state, with absolute paths and the real module slugs baked in:130131```132node scripts/ultraindex.mjs orchestrate [--out <dir>] [--repo <dir>] [--answer <file>] [--phase enrich|verify-answer] [--eco] [--list]133```134135| Your harness | How to run each phase |136|---|---|137| Claude Code exposes Workflow | `orchestrate --phase <p>`, then `Workflow({ scriptPath: "<index>/orchestration/<p>.workflow.mjs" })`. Enrichers WRITE their own `encyclopedia/<slug>.md` entries (the sanctioned disjoint-write exception) and return what they wrote; refuters only RETURN verdict fragments you fold and `verify --apply` yourself. |138| Codex or another host exposes subagents | Same `orchestrate`; dispatch one subagent per batch following `<index>/orchestration/agents/<role>.md` (the workflow script shows batches + prompts). |139| Eco mode, or no subagents | `orchestrate --eco` → follow `<index>/orchestration/RUNBOOK.md` sequentially, playing each role yourself. Correctness-identical; only wall-clock differs. |140141Fan-out is an optimization, never a requirement — the gates (`check`,142`verify --apply`) are harness-independent and every phase has a sequential fallback143with identical artifacts. The one hard rule: **no `build` or `map` runs while a144fan-out is in flight** — `build` rewrites every entry, so a mid-fan-out rebuild145races and clobbers the agents' writes; the orchestrator runs one repo-wide `check`146after the join and routes each grounding failure back to the entry that caused it.147Re-run `orchestrate` whenever the queue changes (emission is deterministic and148idempotent); `--phase <p>` before its input exists fails and names the command that149produces it.150151## Scope notes152153- **Everything below is the vendored codeindex engine's**, not ultraindex's.154 Report engine defects upstream; ultraindex owns the encyclopedia, the gates155 (`check`/`verify`), the work-queue and the fan-out — nothing else.156- **No keys, deterministic, offline after a one-time setup** — the only network157 touches are two first-use pulls into shared per-machine caches: the158 tree-sitter grammars (see AST-exact symbols below) and the optional embedding159 model. Both are sha256-verified and both degrade rather than fail (regex160 extractor; lexical-only `find`). Two builds of an unchanged repo are161 byte-identical except for `manifest.json`'s `builtAt` provenance timestamp —162 `vectors.json` included, since the static embedding tier is byte-deterministic.163 Only the optional `CODEINDEX_EMBED_ENDPOINT` tier, whose floats come from a164 server, falls outside that guarantee.165- **AST-exact symbols** via tree-sitter grammars for JS/TS/TSX, Python, Go,166 Rust, Java, C, C++, C#, Ruby, PHP — real nesting, precise kinds, structural167 export. Other languages fall back to regex extractors (still searchable). The168 grammar wasms are **no longer shipped in the bundle**: the first `build` on a169 machine pulls them (~17 MiB) into a shared cache170 (`<XDG_CACHE_HOME|~/.cache>/codeindex/grammars/<engine>/`), sha256-verified,171 then reuses them forever — so AST precision is on by default after a single172 download, and the installed skill is that much smaller. **Offline with no cache173 yet** ⇒ `build` says so and indexes with the regex extractor (never a silent174 downgrade). Pre-warm before going offline with `node scripts/ultraindex.mjs175 grammars pull` (inspect the active tier with `grammars status`), or point176 `CODEINDEX_GRAMMARS_DIR` at an existing grammars dir.177- **Import edges** for JS/TS (tsconfig `paths`, package `exports` maps),178 Python, Go (multi-module + `replace`), Rust (`mod`/`use`), Java (packages),179 C/C++ (`#include "..."`), Ruby (`require_relative`/`require`), PHP (composer180 PSR-4 + relative `require`), C# (`using` → `namespace`). Plus conservative181 code→code `use` edges when a file references another file's unique exported182 symbol without importing it. Remaining languages get no import edges.183 Yarn PnP's virtual filesystem is out of scope (workspace names still resolve).184- Dangling edges usually mean **the repo itself** has broken imports or stale185 doc links — that's a finding to report, not to paper over.