repository-intelligence-engine
v0.2.1
Published
> Turn any repository into a queryable **code knowledge graph** — then feed your AI agent *structure*, not a wall of text.
Readme
Repository Intelligence Engine (RIE)
Turn any repository into a queryable code knowledge graph — then feed your AI agent structure, not a wall of text.
RIE reads a codebase and builds a semantic graph of it — files, modules, symbols, imports, calls, inheritance, packages — using a deterministic, compiler-inspired pipeline. No LLM is involved in building it. Everything else (AI context bundles, reports, MCP tools) is a plugin that reads from that graph.
Repository ──▶ RIE pipeline ──▶ Knowledge Graph ──┬──▶ AI context bundles
(SQLite) ├──▶ MCP tools for agents
├──▶ Reports & hub analysis
└──▶ Your own pluginsThe graph is the product. AI is an output, not the engine.
Table of contents
- Why this exists
- Install
- Quickstart (60 seconds)
- Using RIE for AI agent context ← start here for the main use case
- The graph model
- CLI reference
- Query language
- Programmatic API
- Plugins
- Configuration
- Ignoring files
- Diagnostics and exit codes
- Packages
- How it works
- Developing RIE
- Roadmap
Why this exists
Tools like repomix and gitingest flatten your repository into one enormous text blob and hand it to an LLM. That works until the repo is bigger than the context window — and it throws away every relationship in the code. The model gets text when what it needs is structure.
RIE builds the structure first, then answers the question "what does the agent actually need to see for this task?" by traversing the graph outward from relevant seed symbols, ranking by relevance, and pruning to a token budget.
Measured on this repository (rie benchmark . --for "incremental scanning"):
| Approach | Tokens | |---|---:| | Naive dump of all 161 parsed files | 158,148 | | RIE context bundle for the same question | 8,662 | | Reduction | 94.5% |
The bundle isn't a random 5% slice. It's the symbols that actually participate in incremental scanning, their signatures, their relationships to each other, and span-scoped excerpts of just the relevant lines.
Design properties that matter for agents:
- Deterministic — same commit in, byte-identical graph out. Graph hashes are comparable across machines and CI runs.
- No fabrication — if an import or call can't be resolved, RIE emits a diagnostic instead of inventing an edge. Unresolved edges are flagged
resolved: false, and heuristic matches carry aconfidencescore. - Incremental by default — edit one file, RIE re-parses exactly that file. A content-addressed facts cache keeps rescans cheap enough to run from a git hook.
- Offline — the whole pipeline, including context generation, runs with no network access.
Install
RIE ships as a set of scoped npm packages. Which one you want depends on how you plan to use it.
The CLI — rie (most people want this)
npm i -g @ri-engine/rie-cliThis is what gives you the rie command. Or run it without installing:
npx @ri-engine/rie-cli scan .The library — build graphs from your own code
npm i @ri-engine/rie-core @ri-engine/rie-contracts @ri-engine/rie-graph-store-sqlite @ri-engine/rie-lang-typescript@ri-engine/rie-core is the scan orchestrator. It depends only on contracts and takes the graph store and language analyzers as injected dependencies, so you install the store and languages you actually want. Add @ri-engine/rie-plugin-host for querying and @ri-engine/rie-lang-python for Python support. See Programmatic API.
Requirements
- Node.js >= 22.13 — RIE uses the built-in
node:sqlitemodule, which needs 22.13+ unflagged. - Node 24+ recommended —
node:sqliteis still marked experimental below 24 and prints a warning.
Run rie doctor to check your environment:
✓ node-version — Node 22.22.0 (node:sqlite is experimental below 24; Node 24+ recommended)
✓ sqlite-fts5 — node:sqlite loads, FTS5 available
✓ graph-integrity — PRAGMA integrity_check: ok
✓ schema-version — graph schema 0.1.0
✓ stale-lock — no lock present
All checks passed.Languages supported today: TypeScript (.ts .tsx .mts .cts), JavaScript (.js .jsx .mjs .cjs), Python (.py). Adding a language is adding a package that implements LanguageDescriptor — the core never changes.
Quickstart (60 seconds)
# 1. Build the graph. Writes .rie/graph.db — add .rie/ to your .gitignore.
rie scan .
# 2. See what it found.
rie graph stats .
# 3. Ask a structural question.
rie query 'callers of buildGraph'
# 4. Generate context for an AI task.
rie context --for "how does incremental scanning work" -o context.mdStep 1 on this repository prints:
rie scan: ok — 1855 nodes, 3838 edges (330 files, 0 parsed)0 parsed means every file was served from the incremental cache. Run rie scan --force for a cold rebuild.
Using RIE for AI agent context
This is the primary use case: give your coding agent a real model of the codebase instead of a pile of files. There are three ways to wire it up, and they compose.
Option 1 — rie install (one command, done)
RIE ships a declarative installer for nine assistant platforms. It writes the instruction files, registers the MCP server, and installs agent hooks — all idempotent, all reversible.
rie install --list claude-code tier 1 Claude Code
cursor tier 1 Cursor
codex tier 1 Codex
antigravity tier 1 Google Antigravity
agents-md tier 1 Universal AGENTS.md
mcp tier 1 MCP (any client)
gemini-cli tier 2 Gemini CLI
windsurf tier 2 Windsurf
copilot-cli tier 2 GitHub Copilot# Preview exactly what would be written — nothing is touched
rie install --platform claude-code --dry-run
# Actually install (writes require explicit consent)
rie install --platform claude-code --yes
# Install every tier-1 platform
rie install --all --yes
# Detect drift in CI: RIE4001 missing / RIE4002 stale / RIE4003 tampered
rie install --checkEach platform descriptor declares its target files and an ownership mode:
| Mode | Meaning |
|---|---|
| rie-file | RIE owns the whole file (e.g. .claude/skills/rie/SKILL.md) |
| marker-block | RIE owns a marked block inside your file (e.g. a section of CLAUDE.md) |
| structured-merge | RIE merges keys into your JSON (e.g. .mcp.json, .claude/settings.json) |
rie uninstall reverses an install byte-identically — your content and any foreign settings entries come back exactly as they were. This is end-to-end tested, not aspirational.
For Claude Code specifically, installing writes a skill at .claude/skills/rie/SKILL.md, a marked block in CLAUDE.md, an MCP server entry in .mcp.json, and a PreToolUse hook in .claude/settings.json that steers the agent toward graph queries before it starts grepping.
Option 2 — MCP server (works with any MCP client)
rie serve --mcpThis starts a stdio MCP server over the persisted graph. It scans for freshness first, then watches the repo and live-refreshes on a 300 ms debounce, so the graph never goes stale while the agent is working. Use --no-watch to disable, --debounce <ms> to tune.
Register it with any MCP client:
{
"mcpServers": {
"rie": { "command": "rie", "args": ["serve", "--mcp"] }
}
}Six tools are exposed to the agent:
| Tool | What it does |
|---|---|
| query_graph | Run a bounded query expression (see Query language) |
| get_node | Fetch one node by id, e.g. sym:src/auth.ts#AuthService:class |
| get_neighbors | Edges + neighbor nodes around a node, optionally filtered by edge type |
| shortest_path | BFS-shortest path between two nodes |
| graph_stats | Node/edge counts by label and type, plus top hubs |
| top_hubs | Highest-degree nodes — the "everything flows through these" list |
Every tool is bounded. There is no raw SQL surface, and no query can run away with your context window.
Option 3 — rie context (pipe a bundle into any prompt)
When you want a self-contained bundle to paste or pipe:
rie context --for "how does authentication work" -o context.md# Seed from specific symbols or files instead of a natural-language question
rie context --focus AuthService --focus src/api/routes.ts
# Tune the budget and traversal depth
rie context --for "payment flow" --budget 4000 --depth 3
# Machine-readable output for your own tooling
rie context --for "payment flow" --format json| Flag | Default | Meaning |
|---|---|---|
| --for <question> | — | Natural-language intent; seeds are matched from its terms |
| --focus <ref> | — | Explicit seed (symbol name, qualified name, or file path). Repeatable |
| --budget <n> | 8000 | Token budget for the bundle |
| --depth <n> | 2 | Max expansion depth from the seeds |
| --format <fmt> | markdown | markdown, xml, or json |
| -o, --out <file> | stdout | Write to a file |
The bundle is structure-first: an overview, key symbols with real signatures, the relationships between them, then span-scoped source excerpts — in that order, because that's the order a model can use them in.
# RIE context: "how does incremental scanning work"
## Overview
- 54 key symbols, 39 relationships, 50 excerpts (budget: 8000 tokens)
- Expanded subgraph: 69 nodes, 102 edges
## Key symbols
- `incrementalDelta` (function) [packages/core/src/pipeline/diff.ts:90]
`function incrementalDelta( next: GraphSnapshot, oldIds: { nodeIds: string[]; edgeIds: string[] }, unchangedFiles: ReadonlySet<string>, ): GraphDelta`
- `runScan` (function) [packages/core/src/orchestrator/scan.ts:130]
`async function runScan(options: ScanOptions): Promise<ScanResult>`
- `FactsCache.open` (method) [packages/core/src/pipeline/cache.ts:53]
`static async open(dir: string, versionKey: string): Promise<FactsCache>`
...Bundles are byte-deterministic — same graph and same question produce the same bytes, which makes them cacheable and diffable.
Keeping the graph fresh
A stale graph is worse than no graph. Three mechanisms keep it current:
Git hooks — incremental rescan after every commit and checkout:
rie hook installThis adds a marker-delimited block to .git/hooks/post-commit and post-checkout. It is fail-open by contract: a hook failure never blocks your git operation. Your existing hooks survive install and uninstall untouched. Check status with rie hook status.
Automatic freshness — context, query, report, graph path, graph show, and serve all run an incremental scan before reading. Pass --no-scan to skip it when you know the graph is current.
File watching — rie serve --mcp watches the repository and rescans on change by default.
CI integration
rie scan . --fail-on warning # exit code 3 if any warning-or-worse diagnostic
rie install --check # exit non-zero if assistant integrations driftedThe graph model
Node labels
| Label | Represents | ID formula |
|---|---|---|
| Repository | The repo root | repo:<name> |
| Directory | A directory | dir:<path> |
| File | A file on disk | file:<path> |
| Module | A language-resolved module | mod:<moduleId> |
| Package | An npm/PyPI package or workspace member | pkg:<name>@<version> (external) · pkg:<name> (internal) |
| Symbol | A declaration | sym:<moduleId>#<qualifiedName>:<kind>[:<n>] |
SymbolKind covers function, method, class, interface, type, typeAlias, enum, enumMember, variable, constant, field, property, parameter, namespace, module, constructor, getter, setter.
IDs come from a single derivation function (deriveNodeId) that every producer must call. That's what makes the graph stable across runs and safe to cache — and it structurally eliminates the "ghost node" bug class where two producers disagree on an id.
Edge types
| Category | Types |
|---|---|
| Structural | CONTAINS, DECLARES, MEMBER_OF |
| Dependency | IMPORTS, EXPORTS, DEPENDS_ON |
| Reference | CALLS, REFERENCES, INSTANTIATES, TYPED_AS |
| Type hierarchy | EXTENDS, IMPLEMENTS, OVERRIDES |
Edge id formula: <TYPE>:<srcId>->:<dstId>[:<ordinal>]. The ordinal disambiguates repeated edges between the same endpoints (function overloads, repeated call sites).
Reference edges carry provenance: CALLS has a callSite span plus resolved and optional confidence; IMPORTS carries the raw specifier, an importKind (default, named, namespace, sideEffect, dynamic, typeOnly), and resolved.
What a node looks like
{
"id": "sym:packages/core/src/orchestrator/scan.ts#runScan:function",
"label": "Symbol",
"kind": "function",
"name": "runScan",
"qname": "runScan",
"file_id": "file:packages/core/src/orchestrator/scan.ts",
"lang": "typescript",
"start_line": 130,
"end_line": 423,
"props": {
"visibility": "public",
"exported": true,
"signature": "async function runScan(options: ScanOptions): Promise<ScanResult>",
"span": { "startLine": 130, "startCol": 8, "endLine": 423, "endCol": 2 }
}
}Resolution the graph actually performs
- Relative and absolute imports, re-export chains, barrel files
tsconfig.jsonpathsandbaseUrlaliases, including per-directory tsconfigs- Bare imports →
Packagenodes (node builtins, workspace manifests, declared externals) this.-qualified member calls, and a conservative unique-method fallback that carries aconfidencescore- Class inheritance and interface implementation across files
- Python relative imports, inheritance, cross-file calls, and
self.→ receiver normalization
Edge accuracy is gated in CI at 100% precision and recall against a hand-labeled ground-truth fixture (fixtures/goldens/ts-small.expected-edges.json).
CLI reference
rie scan [path] Scan a repository, build + persist its knowledge graph
rie context Generate a structure-aware AI context bundle
rie query '<expr>' Run a bounded graph query
rie report [path] Deterministic repo summary: hubs, communities, entry points
rie graph stats [path] Node/edge counts and top hubs
rie graph path <a> <b> Shortest path between two nodes
rie graph show <ref> One node in detail: fields + neighbors by edge type
rie serve --mcp [path] Serve the graph over MCP stdio
rie plugins <sub> List or run plugins (list | run <name>)
rie install Install RIE into AI assistants
rie uninstall Reverse an install (byte-identical restore)
rie hook <sub> Git rescan hooks (install | uninstall | status)
rie config <sub> Show or validate rie.config.json (show | validate)
rie doctor [--fix] Check node version, sqlite, graph integrity, stale locks
rie benchmark [path] Context-token reduction vs dumping all parsed filesGlobal options: -C, --cwd <dir> · --json · --no-scan · --version · --help
rie scan
Builds the graph and persists it to .rie/graph.db. Incremental by default.
| Flag | Meaning |
|---|---|
| --force | Cold rebuild — ignore the cache, still refresh it |
| --no-cache | Neither read nor write the cache |
| --stats | Print the graph hash and db path after scanning |
| --json | Print the full RunReport as JSON |
| --debug | Print every diagnostic verbatim, no grouping or suppression |
| --fail-on <sev> | Exit 3 when diagnostics at or above <sev> exist (warning | error) |
A timestamped backup is taken before any destructive rebuild, and a single-writer lock prevents two scans from racing on the same .rie directory.
rie graph stats
Graph: 1855 nodes, 3838 edges (/path/to/repo/.rie/graph.db)
Nodes by label:
Directory 85
File 330
Module 161
Package 27
Repository 1
Symbol 1251
Edges by type:
CALLS 413
CONTAINS 576
DECLARES 1251
EXPORTS 294
EXTENDS 2
IMPLEMENTS 1
IMPORTS 577
INSTANTIATES 12
MEMBER_OF 614
REFERENCES 98
Top hubs (by degree):
74 mod:packages/contracts/src/graph/graph-query.ts
72 mod:packages/contracts/src/language/language.ts
70 mod:packages/contracts/src/graph/node-types.tsrie graph show
rie graph show buildGraphsym:packages/core/src/pipeline/build.ts#buildGraph:function
end_line: 349
file_id: file:packages/core/src/pipeline/build.ts
kind: function
label: Symbol
lang: typescript
name: buildGraph
qname: buildGraph
start_line: 91
CALLS (in):
sym:packages/core/src/orchestrator/scan.ts#runScan:function (function)
CALLS (out):
sym:packages/core/src/pipeline/build.ts#ancestorDirs:function (function)
sym:packages/core/src/pipeline/build.ts#assertUniqueIds:function (function)
...References resolve loosely — you can pass a node id, a symbol name, a qualified name, or a module path.
rie graph path
rie graph path runScan buildGraphsym:packages/core/src/orchestrator/scan.ts#runScan:function (function)
--CALLS--> sym:packages/core/src/pipeline/build.ts#buildGraph:function (function)rie report
A deterministic, golden-tested repository summary: overview counts, top hubs by degree, union-find module clusters, entry points, and runnable suggested queries.
rie report . # markdown to stdout
rie report . -o report.md # to a file
rie report . --html -o report.html # self-contained offline pagerie benchmark
Measures how much context RIE saves versus naively dumping every parsed file:
rie benchmark . --for "incremental scanning"question: "incremental scanning"
naive context (161 parsed files, est.): 158,148 tokens
rie context bundle (est.): 8,662 tokens
reduction: 94.5%Query language
rie query and the MCP query_graph tool share one bounded DSL. There is deliberately no raw SQL surface — every form maps to a safe, limited traversal over graph primitives, capped at 100 results.
| Form | Example |
|---|---|
| callers of <symbol> [depth <n>] | rie query 'callers of buildGraph' |
| callees of <symbol> [depth <n>] | rie query 'callees of buildGraph depth 2' |
| importers of <module-path> | rie query 'importers of src/auth/service.ts' |
| dependencies of <module-path> | rie query 'dependencies of src/app.ts' |
| search <text> | rie query 'search AuthService' |
| <label> where <field>=<value> [and ...] | rie query 'symbols where kind=class and lang=typescript' |
Labels: files, symbols, modules, packages, directories, repositories
Filter fields: kind, name, lang, qname
Real output:
$ rie query 'callers of buildGraph'
runScan function sym:packages/core/src/orchestrator/scan.ts#runScan:function
$ rie query 'symbols where kind=class'
UnknownToolError class sym:apps/cli/src/mcp/server.ts#UnknownToolError:class
AuthService class sym:fixtures/ts-small/src/auth/service.ts#AuthService:class
RieLockError class sym:packages/core/src/orchestrator/lock.ts#RieLockError:class
FactsCache class sym:packages/core/src/pipeline/cache.ts#FactsCache:classAdd --json for full node objects.
Programmatic API
Everything the CLI does is available as a library. The core is dependency-injected: you supply the store and the language analyzers, so @ri-engine/rie-core itself stays free of native dependencies.
npm i @ri-engine/rie-core @ri-engine/rie-graph-store-sqlite \
@ri-engine/rie-lang-typescript @ri-engine/rie-plugin-host \
@ri-engine/rie-plugin-ai-contextBuild a graph
import { runScan } from "@ri-engine/rie-core";
import { SqliteGraphStore } from "@ri-engine/rie-graph-store-sqlite";
import { defaultLanguages } from "@ri-engine/rie-lang-typescript";
const store = new SqliteGraphStore();
await store.open({ path: "./.rie/graph.db" });
const { report } = await runScan({
path: ".",
languages: defaultLanguages, // add pythonLanguage from @ri-engine/rie-lang-python
store,
cacheDir: "./.rie/cache", // omit to disable incremental caching
});
console.log(report.graph.nodes, report.graph.edges, report.graph.hash);
console.log("incremental:", report.incremental);ScanOptions also accepts concurrency (default 8), force, exclude (gitignore syntax), and respectGitignore.
Query it
import { createGraphQuery, parseQuery, executeQuery } from "@ri-engine/rie-plugin-host";
const graph = createGraphQuery(store);
// The bounded DSL
const { nodes } = await executeQuery(graph, parseQuery("callers of greet"));
console.log(nodes.map((n) => n.qname)); // [ 'main' ]
// Or the primitives directly
for await (const node of graph.findNodes({ label: "Symbol", kind: "function", limit: 5 })) {
console.log(node.id, node.props.signature);
}
for await (const { edge, node } of graph.neighbors("file:src/index.ts", { direction: "out" })) {
console.log(edge.type, "->", node.id);
}
const sub = await graph.subgraph(["sym:src/auth.ts#login:function"], {
edgeTypes: ["CALLS", "IMPORTS"],
maxDepth: 2,
budget: { maxNodes: 120, maxEdges: 300 },
rank: "proximity", // "bfs" | "degree" | "pathWeight" | "proximity"
});
console.log(sub.nodes.length, sub.truncated);The full GraphQuery surface: getNode, getNodes, findNodes, neighbors, traverse, subgraph, search, callers, callees, importers, dependencies. Traversals are async iterables, so large results stream instead of materializing.
Generate a context bundle
import { runPlugins } from "@ri-engine/rie-plugin-host";
import { aiContextPlugin } from "@ri-engine/rie-plugin-ai-context";
const run = await runPlugins({
store,
cwd: ".",
plugins: [aiContextPlugin],
grants: ["readFiles"], // required for source excerpts (ADR-010)
pluginArgs: {
"ai-context": { for: "authentication", budget: 4000, format: "json" },
},
});
const bundle = JSON.parse(String(run.outputs[0].artifacts[0].content));
console.log(bundle.symbols.length, bundle.relationships.length);Without the readFiles grant the plugin still runs — you get structure and signatures, just no source excerpts. Capabilities are off by default and must be granted explicitly.
Plugins
The graph is the stable interface. Outputs are plugins.
rie plugins listreport ^0.3.0 [readGraph, writeOutput] report/v1 (first-party)
ai-context ^0.3.0 [readGraph, writeOutput, readFiles] ai-context/v1 (first-party)Writing one
import type { RiePlugin, GraphQuery, RunContext, Output } from "@ri-engine/rie-contracts";
export const deadCodePlugin: RiePlugin = {
name: "dead-code",
apiVersion: "^0.3.0",
capabilities: ["readGraph", "writeOutput"],
outputs: [{ schemaId: "dead-code/v1" }],
async generate(graph: GraphQuery, ctx: RunContext): Promise<Output> {
const orphans: string[] = [];
for await (const sym of graph.findNodes({ label: "Symbol", kind: "function" })) {
let referenced = false;
for await (const _ of graph.neighbors(sym.id, { type: ["CALLS", "REFERENCES"], direction: "in" })) {
referenced = true;
break;
}
if (!referenced && sym.props?.exported !== true) orphans.push(sym.id);
}
return {
pluginName: "dead-code",
schemaId: "dead-code/v1",
schemaVersion: "1.0.0",
deterministic: true,
artifacts: [{ path: "dead-code.json", content: JSON.stringify(orphans, null, 2) }],
};
},
};Register it in rie.config.json:
{
"extensions": ["./plugins/dead-code.js"],
"plugins": { "dead-code": { "includeExported": false } }
}rie plugins run dead-codeThe plugin contract
| Capability | Grants |
|---|---|
| readGraph | Read-only GraphQuery access (granted by default) |
| writeOutput | Emit artifacts (granted by default) |
| readFiles | Repo-confined file reads — must be granted explicitly |
| network | Network access — off by default |
| env | Environment variables — off by default |
Lifecycle hooks: setup → analyze → generate → teardown, all optional.
Safety guarantees enforced by the host:
- apiVersion compatibility is checked before load; incompatible plugins are refused with a clear diagnostic.
- Failure isolation — a crashing plugin produces an
RIE3xxxdiagnostic and never breaks the run. - Path confinement — artifact writes and
readFilescannot escape the repository root. - Output schemas are enforced against the declared
schemaId.
Configuration
Optional rie.config.json at the repo root. Every key below is read and applied today:
{
"discovery": {
"respectGitignore": true,
"exclude": ["vendor/**", "**/*.generated.ts"]
},
"languages": { "enable": ["typescript", "javascript", "python"] },
"plugins": { "ai-context": { "budget": 12000 } },
"extensions": ["./plugins/my-plugin.js"],
"install": { "platforms": ["claude-code", "cursor"], "scope": "project" }
}rie config show # resolved config
rie config validate # validate without running anything$ rie config show
source: (defaults)
languages: typescript, javascript, python
exclude: (none)
install: (none)
extensions: (none)The file is validated against a zod schema and fails fast — a syntax error is RIE2001, a schema violation is RIE2002, and both exit 2 before any scanning happens.
Not yet wired up. The schema also accepts
graph.store,graph.path,cache.enabled,cache.dir,discovery.maxFileSizeBytes, andlog.level. These validate but are not consumed yet — graph and cache paths are currently fixed at.rie/graph.dband.rie/cache. Config formats other than JSON (.ts,.js,.yaml) andRIE_*environment layering are also specified but not implemented. Don't rely on them until they land; seedocs/08-CLI/Configuration.md.
Ignoring files
RIE honors .rieignore and .gitignore, with full gitignore syntax including ! negation.
Default exclusions: node_modules, .git, .rie, dist, build, out, .next, .turbo, coverage, .cache, graphify-out, *.tsbuildinfo, and similar.
Re-include something the defaults dropped:
# .rieignore
!out/
docs/generated/**Turn off .gitignore handling entirely with discovery.respectGitignore: false.
Diagnostics and exit codes
Every diagnostic carries a stable, greppable code.
| Range | Stage |
|---|---|
| RIE10xx | Discovery / filesystem |
| RIE11xx | Classification |
| RIE12xx | Language detection |
| RIE13xx | Parsing |
| RIE14xx | Semantic analysis / linking |
| RIE15xx | Graph build / store |
| RIE2xxx | Configuration |
| RIE3xxx | Plugins |
| RIE4xxx | Assistant install drift |
Diagnostics from unchanged files are grouped and suppressed by default. Use --debug for the full verbatim list.
| Exit code | Meaning |
|---|---|
| 0 | Success |
| 1 | Runtime failure |
| 2 | Usage error |
| 3 | --fail-on diagnostics gate tripped |
| 130 | Interrupted (Ctrl-C) |
Packages
All published under the @ri-engine scope at v0.2.0, Apache-2.0.
| Package | Purpose |
|---|---|
| @ri-engine/rie-cli | The rie command — composition root for everything below |
| @ri-engine/rie-core | Scan orchestrator and pipeline. Depends only on contracts |
| @ri-engine/rie-contracts | Types, zod schemas, id derivation. The shared vocabulary |
| @ri-engine/rie-graph-store-sqlite | SQLite + FTS5 graph store via node:sqlite |
| @ri-engine/rie-lang-typescript | TypeScript + JavaScript analyzer (tree-sitter) |
| @ri-engine/rie-lang-python | Python analyzer (tree-sitter) |
| @ri-engine/rie-plugin-host | Plugin runtime, GraphQuery implementation, query DSL |
| @ri-engine/rie-plugin-ai-context | ai-context/v1 — the context bundle generator |
| @ri-engine/rie-plugin-report | report/v1 — deterministic repository summary |
Module boundaries are enforced in CI with dependency-cruiser: core never imports a concrete store or language, and everything is wired at the CLI composition root.
How it works
discovery → classification → language detection → per-file analysis
→ cross-file linking → graph build → store persist- Discovery — parallel walk honoring
.rieignoreand.gitignore. - Classification — each file typed as
source,config,doc,data,binary,generated, orvendor. - Language detection — by extension, against the injected
LanguageDescriptorset. - Per-file analysis — tree-sitter parse producing
FileFacts: declarations, imports, call sites, spans. Content-addressed and cached, so unchanged files are never re-parsed. - Cross-file linking — import resolution (relative, aliased, re-export chains, bare →
Package), then semantic linking for calls, instantiation, and inheritance. - Graph build — nodes and edges via the canonical id formulas, with uniqueness assertions.
- Persist — a structural delta applied transactionally to SQLite.
Incremental scanning
The facts cache (ADR-009) is keyed on contentHash + languageId + grammarVersion. Editing one file re-parses exactly that file — structurally asserted in tests, not just measured. The store then receives a two-tier delta proportional to the change, with no content diffing.
Incremental output equals cold output is property-tested at both graph and store level, so freshness never costs correctness.
Measured on a ~50k-LOC fixture: 6.7× speedup for incremental over cold. The documented target is ≥10×; closing the remaining gap needs a per-file serialized-line cache and lazy graph materialization, both recorded as follow-ups. Cold throughput measures 56k files/min single-threaded — 5.6× the ≥10k budget, which is why worker threads were descoped with evidence rather than built.
Quality gates in CI
Determinism · golden fixtures · labeled edge accuracy (100% precision + recall) · module boundaries · install verification · license audit · 403 tests across 10 packages.
Developing RIE
git clone https://github.com/Priyanshu337/RIE--Repository-Intelligence-Engine.git
cd RIE--Repository-Intelligence-Engine
pnpm install
pnpm build
pnpm rie -- scan .| Command | What it does |
|---|---|
| pnpm build | Build all packages (turbo) |
| pnpm test | Run all tests (vitest) |
| pnpm test:property | Property-based tests only |
| pnpm typecheck | Type-check everything |
| pnpm lint | Biome check |
| pnpm format | Biome format --write |
| pnpm boundaries | Enforce module boundaries (dependency-cruiser) |
| pnpm license-check | Audit dependency licenses |
| pnpm verify:install | Verify the install matrix end-to-end |
Requires Node >= 22.13 and pnpm 10.28+.
Documentation
The design handbook lives in docs/:
docs/00-Overview/— start here; vision and reading guidedocs/03-Architecture/HighLevelDesign.md— the architecturedocs/05-KnowledgeGraph/— node types, edge types, query model, incremental updatesdocs/07-Plugins/— plugin architecture and first-party pluginsdocs/08-CLI/— commands, configuration, assistant integrationsdocs/10-ArchitectureDecisionRecords/— every decision and its rationale
Roadmap
| Version | Theme | Highlights | |---|---|---| | V1 ✅ | CLI foundation | Repo scan · knowledge graph · AI context · report · MCP server · assistant installers | | V2 | Documentation & diagrams | Auto docs · architecture diagrams · dependency visualization | | V3 | Repository intelligence | Dead-code detection · impact analysis · API inventory | | V4 | Editor integration | VS Code extension | | V5 | Hosted platform | Multi-tenant, team-scale intelligence |
V1 is feature-complete — M0 through M4 delivered and tested. Two exit criteria remain open by nature: the ≥70% context win-rate versus repomix and graphify needs blind human evaluation (the harness is ready — rie context emits comparable bundles), and cross-OS npx verification needs the CI matrix to run.
See docs/11-Roadmap/ for the truthed checklist.
Contributing
Issues and pull requests welcome at the repository. Before submitting, please run pnpm test, pnpm typecheck, pnpm lint, and pnpm boundaries — CI enforces all four.
License
Apache-2.0 — see LICENSE.
