OpenLore
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@OpenLoreorient("add a new payment method")"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
AI coding agents are powerful but amnesiac and ungoverned. Every task starts by re-reading the same files to rediscover structure; every long session quietly drifts toward confident-but-stale assumptions; and nothing tells the agent when a change is about to break a contract, cross an architectural boundary, or open a path into sensitive code.
OpenLore fixes both halves. It runs a one-time static analysis of your codebase and keeps a navigable knowledge graph — call structure, types, tests, decisions, IaC, and spec drift — incrementally fresh as you edit. Agents query it through MCP tools (or the CLI) to start every task already oriented, and to certify a change before it lands. It is deterministic and local-first — no LLM in the hot path — so the same question returns the same grounded answer, and an agent is told when a fact has gone stale instead of served a confident guess.
Install in one command
npm install -g openlore && openlore installThat one command auto-detects your agent (Claude Code, Cursor, Cline, Continue, AGENTS.md), wires it to call orient() automatically, registers the MCP server, and builds the index — no API key, no config, no questions asked. Then ask your agent:
orient("add a payment method")
…and it begins the task already knowing the relevant functions, their callers, the matching specs, the tests, and the risk of changing each one — in a single call. Full setup, variants, and verification: 5-Minute Quickstart.
Zero config, everything discoverable. Core value needs no keys. To see every opt-in capability — embeddings, covering surfaces, the commit gate, the spec store, and more — whether each is active, and the one command to turn it on, run
openlore features.
Related MCP server: Blueprint MCP
What you get
OpenLore does two things for an agent, both deterministic and local — it remembers your architecture so every task starts oriented, and it governs what the agent changes before the change lands.
🧠 Memory — start every task already oriented
Persistent architectural memory —
orient()once; agents stop re-deriving the system from dozens of file reads, across sessions. Anchored notes and decisions survive refactors: a renamed or moved symbol carries its memory forward at the nextanalyze(withcarriedAcrossprovenance) instead of orphaning it.One-call orientation —
orient(task)returns the relevant functions, their callers, matching spec sections, and insertion-point candidates in a single call. ~430µs p50 on a 15k-node graph.One unified graph — application code, Infrastructure-as-Code, and architectural decisions all project onto the same node/edge primitives, so a single traversal answers questions that span all three.
Test-impact selection & dead-code — "I changed
parseConfig()— which tests should I run?" by backward call-graph reachability; cross-language mark-and-sweep finds what's dead, confidence-tagged, never deletion authority.Context-freshness tracking (Epistemic Lease) — an agent is told when a cached fact has gone stale (context aged, repo moved) instead of acting on a confident guess.
🛡️ Governance — guardrails on what the agent changes
Change-impact certificate —
change_impact_certificateflags when a diff newly opens a path into a sensitive boundary you declared (reachable after the change but not before) — differential, deterministic, no LLM.Breaking-change verdict —
certify_public_surfaceclassifies every changed exportbreaking / non-breaking / potentially-breakingover a diff and names the in-repo consumers each break hits; conservative by construction, never silently "safe".Architecture invariants, pre-edit —
check_architectureanswers "may a file under A import B?" against your declared layer/forbidden rules before the import is written — cross-language.Grounded claims, not guesses —
verify_claimreturns a deterministicconfirmed / refuted / unverifiableverdict with a citation receipt before an agent asserts "X is dead" or "Y is safe to change".One commit gate —
openlore enforceresolves every governance finding through yourenforcement.policyand blocks only on what you classblocking(advisory by default, no API key). Decisions are recorded, gated, and synced into living specs; spec/code drift detected in milliseconds.
📊 Honest by construction — −26% agent round-trips on deep traces in large repos, with the losses published next to the wins; every public claim traces to a command you can run. Pure static analysis: no API key, no network, same answer every time.
See it in action
{
"functions": [
{
"name": "processPayment",
"file": "src/payments/processor.ts",
"risk": "medium",
"fanIn": 4,
"callers": ["handleCheckout", "retryFailedCharge"],
"callType": "direct"
},
{
"name": "validateCard",
"file": "src/payments/validator.ts",
"risk": "low",
"fanIn": 1,
"testedBy": [{ "name": "validateCard.test.ts", "confidence": "called" }]
}
],
"specDomains": ["payments — §CardValidation, §PaymentFlow"],
"insertionPoints": [
"src/payments/processor.ts:87 — after existing charge logic"
],
"callPath": "POST /charge → handleCheckout → processPayment → validateCard → stripeClient.charge"
}The agent knows exactly where to look, what it touches, and what risks to consider — before reading a single file.
openlore impact-certificate --base main # does my diff open a new path into a declared sensitive boundary?
openlore certify-public-surface --base main # did I break a consumer's public API contract?
openlore blast-radius # callers/layers touched, tests to run, specs & decisions that drift
openlore enforce --hook # one gate; blocks only on findings you've classed `blocking`No LLM, no API key — the same grounded answer every run. Advisory by default; you opt into blocking per finding.
Value Scorecard — does it pay for itself?
OpenLore only earns its place if an agent with it reaches a correct answer for less total cost than the same agent without it. We measure that inequality and publish it — wins and losses. Numbers are from the Spec 14 agent benchmark (claude -p, sonnet, N=4 medians, pinned SHAs, --strict-mcp-config isolating each arm), measured 2026-06-01.
Scenario (task × repo) | Cost Δ | Round-trips Δ | Correctness | Verdict |
Large/unfamiliar repo · deep "how does X flow through Y" (its target) | −7% to −21% | −26% | 100% = 100% | ✅ helps — and the win grows with repo size |
Small/familiar repo · shallow "who calls X" | task-dependent (Round 1: +43%) | +38% | 100% = 100% | ❌ often adds overhead — measure with |
Re-confirmed live 2026-06-03 (N=2): the deep-task win reproduces — okhttp −13%. The small/familiar case is task-dependent, not a flat loss: same repo class, opposite outcomes (chalk −32% win vs express +59% loss). Don't guess from our repos — run
openlore proveon yours.
Deep-trace detail — the win scales with codebase size (cost Δ; round-trips WITHOUT → WITH):
Repo (size) | Cost Δ | Round-trips |
excalidraw (~640 files) | −21% | 25 → 16 |
tokio (~790 files) | −21% | 17 → 13 |
okhttp | −13% | 13 → 11 |
django (~3k files) | −7% | 21 → 15 |
gin (110 files, smallest) | +4% (≈even) | 10 → 9 |
Where it helps — and where it doesn't:
Helps: large, unfamiliar, or private codebases the model hasn't memorized; deep multi-hop questions; long sessions where re-reading an ever-growing context compounds. The hardest-to-game signal is round-trips: −26%, fewer on every deep task.
Doesn't (yet): small, famous repos already in the model's weights answered by a shallow query — there's no orientation tax to remove, so the tool surface is pure overhead.
Honesty contract. We never publish a savings number the benchmark didn't produce; we always show the loss cases next to the wins; the scorecard is date-stamped and re-measured after each optimization phase. Every public token claim traces to a command you can run in this repo — if it doesn't reproduce, treat it as marketing and call it out. Full methodology and per-task numbers: docs/AGENT-BENCHMARKS.md. Plumbing latency (orient ~430µs p50) is separate and real: scripts/BENCHMARKS.md.
Prove it on your repo — no API key needed.
openlore prove --estimateprojects the orientation tax from your own call graph in seconds (zero API key, zero network); plainopenlore proveruns the full measured WITH/WITHOUT pass (needsclaude+ a key). Add--json(CI-consumable),--markdown(a paste-ready scorecard block + a shields.io badge for your README), or--save(a dated record under.openlore/prove/). An estimate is labeledestimateeverywhere and never presented as a measurement. Details: docs/AGENT-BENCHMARKS.md.
5-Minute Quickstart
npm install -g openlore
cd /path/to/your-project
openlore install # detect your agent, wire it up, AND build the indexThat single command:
Auto-detects which agent surfaces are present (Claude Code, Cursor, Cline, Continue, AGENTS.md) and wires each one to call
orient()— no manualCLAUDE.mdediting.Registers the MCP server so it starts automatically when your agent launches (you don't run
openlore mcpyourself).Builds the index (
init+analyze→ a keyword/BM25 graph, no network needed) soorient()returns real results in your very first session.Wires task-scoped orientation (Claude Code): a
UserPromptSubmithook orients each new prompt and injects a bounded, ignorable orientation block before the first turn — so the common task begins already oriented without a manualorient()call. A deterministic relevance gate keeps it out of the small/familiar case; disable withcontextInjection.mode: "off".
openlore install --no-analyze # wire surfaces only; build the index later
openlore install --dry-run # preview every change without writing
openlore doctor # verify config, index, MCP wiring, and embedding setupZero-interaction by design. Nothing prompts you and nothing touches your repo on npm install. openlore install never asks a question. And if an agent wires the MCP server without a prior install, the server self-bootstraps — it builds the index once in the background on first run (opt out with OPENLORE_NO_AUTO_ANALYZE=1).
Stays current automatically. A once-a-day, non-blocking "update available" line; upgrade with openlore update (detects npm vs. Homebrew vs. npx). Silence with OPENLORE_NO_UPDATE_NOTIFIER=1. The MCP server keeps the index fresh as you edit (file watcher on by default; build dirs like target/, node_modules/, dist/ are pruned automatically). See docs/install.md.
Full pipeline (specs + decisions — optional and additive):
openlore generate # generate living specs (requires API key)
openlore drift # detect spec/code drift (no API key)
openlore decisions # manage architectural decisionsgit clone https://github.com/clay-good/openlore
cd openlore
npm install && npm run build && npm linknix run github:clay-good/openlore -- analyze
nix shell github:clay-good/openloreSystem flake:
environment.systemPackages = [ openlore.packages.x86_64-linux.default ];Migrating from
spec-gen? The package is nowopenloreand the command isopenlore— see docs/RENAME-TO-OPENLORE.md for the short checklist.
Governance — guardrails on what your agent changes
Memory makes an agent fast. Governance makes it safe. As agents get more autonomous, the bottleneck moves from "can it write the code" to "can I trust what it just changed." OpenLore answers that deterministically — every check below is static analysis, no LLM, advisory by default with opt-in blocking — and all of it rides the one graph, so it spans application code, IaC, and your recorded decisions at once.
Guardrail | What it certifies | Run it |
| Whether a diff newly opens a path into a sensitive boundary you declared — reachable after the change but not before (a differential, not a snapshot) — plus blast radius, drifted specs, and the tests to run. |
|
| A breaking-change verdict over a diff: each changed export |
|
| "May a file under A import B?" against your declared layer / forbidden / allowed-only rules — a pre-write verdict, cross-language, instead of a post-hoc CI failure. | declare rules in |
| A deterministic | MCP tool ( |
| One commit gate over every governance finding. Map each finding |
|
Epistemic Lease | Tells the agent when its context has gone stale (aged, or the repo moved) so a long session can't drift onto confident-but-wrong assumptions. Facts, never commands. | automatic on every MCP response |
A reviewer doesn't even need an agent: openlore review --base main composes the structural delta and the blast radius into one Markdown briefing, and the bundled GitHub Action posts it as a single sticky PR comment (advisory by default). See PR review.
Agent Cheat Sheet
The default MCP surface is the substrate preset — 13 tools: the navigation graph-traversal core plus the three highest-value governance reads (recall, verify_claim, blast_radius), so an agent is both-faced out of the box. It cleared the DefaultSurfaceRevealsAllFaces benchmark — no task-completion or tool-selection regression vs. the lean core across two models and both repo tiers. The lean navigate-only navigation preset (10 tools) stays a one-flag escape (--preset navigation), and the full surface of 72 tools is opt-in via --preset full. Every tool declares one of six capability families — navigate · change · remember · verify · coordinate · federate — surfaced in its MCP annotations.family, so a wide surface stays discoverable by family rather than as a flat list. Reach for the right tool by situation:
Situation | Tool |
Starting any task |
|
Shallow "who calls X / where is Y?" |
|
"Which file/function handles X?" |
|
"What's the blast radius if I change this?" |
|
"How does request X reach function Y?" |
|
"I changed X — which tests should I run?" |
|
"What's dead / what dies if I delete X?" |
|
"What's the blast radius of my whole diff before I commit?" |
|
"Does my diff open a new path into a sensitive boundary?" |
|
"Did my change break a consumer's public API contract?" |
|
"May I add this import here?" |
|
About to assert a fact / cite a decision |
|
Recording an architectural choice |
|
"What changed structurally / whose callers are stale?" |
|
"What changes together with this / what's volatile?" |
|
Reading / checking a spec |
|
"A lot changed since I last looked — what matters?" |
|
"Does a near-duplicate of this already exist to reuse?" |
|
Everything else (read a file, grep, list files) uses your native tools. Full reference — all 72 tools and parameters: docs/mcp-tools.md.
Use OpenLore as a Claude Code Skill
OpenLore ships a canonical Claude Code Skill at skills/openlore-orient/. Install it once and Claude Code calls orient() at the start of every task — no CLAUDE.md editing.
npm run skill:install-local # → ~/.claude/skills/openlore-orient/
cp -R skills/openlore-orient /path/to/your-project/.claude/skills/ # or per-projectThe 8 multi-agent workflow skills (brainstorm, plan-refactor, write-tests, review-changes, debug, …) install via openlore setup into .claude/, .opencode/, or .vibe/. See skills/openlore-orient/README.md.
OpenLore vs. Alternatives
Cursor / Claude Code | Sourcegraph | OpenLore | |
Graph-aware MCP context | ❌ file-based reads | Partial | ✓ call graph + clusters |
Persistent cross-session architectural memory | ❌ | Partial | ✓ |
Token-efficient | ❌ | ❌ | ✓ −7%→−21% cost, −26% round-trips on deep tasks † |
Change-impact certificate (paths into sensitive boundaries) | ❌ | ❌ | ✓ deterministic, pre-commit |
Breaking-change verdict over a diff | ❌ | ❌ | ✓ consumers named |
Architecture invariants, pre-edit | ❌ | ❌ | ✓ cross-language |
Governance commit gate (decisions + findings) | ❌ | ❌ | ✓ |
Spec/code drift detection | ❌ | ❌ | ✓ milliseconds, no API |
Long-session confidence decay (Epistemic Lease) | ❌ | ❌ | ✓ |
Offline structural analysis, no LLM in the hot path | ❌ | ❌ | ✓ |
† Measured, and it depends on the task — full numbers in the Value Scorecard. Small/familiar repos + shallow queries add overhead; larger codebases + deep questions are a net win (−7%→−21% cost, −26% tool-calls, scaling with repo size), at 100% answer correctness in both arms. The savings hold where OpenLore is designed to help, not on toy queries.
How It Works
Three layers, each usable independently:
Layer | What it does | API key? |
1. Static Analysis | Call graph, clusters, McCabe CC, IaC, external deps → | No |
2. Spec & Governance | Living specs, ADRs, drift detection, change certificates, decision & finding gates | For spec generation only |
3. Agent Runtime | 72 MCP tools — | No |
Use layer 1 alone for structural context. Add layer 2 for semantic intent and governance. Layer 3 keeps it all continuously accessible through graph-native MCP tools once openlore mcp is running.
flowchart TD
Code[Codebase] --> Analyze[openlore analyze<br/>tree-sitter · pure static analysis]
Analyze --> DB[(SQLite graph store)]
Analyze --> Digest[CODEBASE.md<br/>~600-token structural digest]
subgraph shared["Projected onto shared node + edge primitives"]
direction LR
CodeNodes[functions + call edges]
Iac[IaC resources + references]
Dec[decisions + affects edges]
end
Analyze --> CodeNodes
Analyze --> Iac
Analyze -. active decision store .-> Dec
CodeNodes --> DB
Iac --> DB
Dec --> DB
DB --> MCP[72 MCP tools<br/>orient · analyze_impact · certify · verify · enforce]
MCP --> Agent((Coding Agent))
Code -. optional, API key .-> Gen[openlore generate]
Gen --> Specs[openspec/specs/*.md<br/>RFC 2119 living specs]
Code --> Drift[openlore drift<br/>spec/code drift, ms, no API]
Agent -. record_decision .-> Gate[decisions + findings gate]
Gate --> SpecsCrucially, application code, Infrastructure-as-Code, and architectural decisions all project onto one shared set of node/edge primitives — so a single traversal answers questions that span all three, and impact analysis returns governance as a graph neighbor. See docs/ARCHITECTURE.md.
Core Features
Analyze (no API key) — Continuously maintains a structural representation using pure static analysis: a full call graph in SQLite, label-propagation community detection, McCabe complexity per function, and extracted DB schemas, HTTP routes, UI components, middleware, and env vars. Outputs .openlore/analysis/CODEBASE.md — a ~600-token digest that compresses tens of thousands of exploratory tokens. With --watch-auto the graph updates incrementally on every save and converges to what analyze --force would produce; when a change's reverse-dependency closure exceeds the per-save budget, the un-recomputed files are marked explicitly stale rather than left silently divergent.
Generate (API key) — Sends the analysis to an LLM in 6 structured stages (survey → entities → services → APIs → architecture → ADRs), producing openspec/specs/ living specifications in RFC 2119 with Given/When/Then scenarios.
Drift (no API key) — Compares git changes against spec mappings in milliseconds: Gap, Uncovered, Stale, and ADR-gap. Installs as a pre-commit hook. → docs/drift-detection.md
Test impact selection (no API key) — select_tests walks the call graph backward from a change to every test that transitively reaches it, returning each test with its reaching path. Static, call-graph-based regression test selection at edit time, not after CI. An honest over-approximate prioritizer ("run these first"), not a sound replacement for the full suite. → docs/test-impact-selection.md
Reachability & dead-code (no API key) — find_dead_code runs cross-language mark-and-sweep from roots (tests, imports, route handlers, main), and answers "what becomes dead if I delete X?" Results are confidence-tagged candidates, never deletion authority. The import resolver follows re-export/barrel chains and Python relative imports so a call resolves precisely. → docs/reachability-dead-code.md
Change-impact certificate (no API key) — change_impact_certificate certifies whether a diff newly opens a path into a declared covering surface (differential reachability — reachable after but not before), plus blast radius, drifted specs, and tests to run. Decays via the freshness lease. Advisory; opt-in blocking on a configured surface severity. CLI: openlore impact-certificate.
Public API surface contract (no API key, opt-in) — certify_public_surface gives a deterministic breaking-change verdict over a diff: each changed export breaking / non-breaking / potentially-breaking, each break paired with the in-repo consumers it hits. Conservative — a change it can't prove compatible is potentially-breaking, never silently safe. Renamed exports detected via symbol-identity continuity. CLI: openlore certify-public-surface.
Architecture invariant guardrails (no API key) — check_architecture turns an architectural rule from a post-hoc CI failure into a pre-write verdict. Declare layers / forbidden / allowedOnly in .openlore/architecture.json (or via an Invariant: marker on a synced ADR), and the tool answers "may a file under A import B?" with a deterministic verdict + the governing rule. Cross-language over the unified graph. → docs/architecture-invariants.md
Claim verification (no API key, opt-in) — verify_claim returns confirmed / refuted / unverifiable with a citation receipt (index commit, content hashes, the reaching path) — never an LLM guess. Structural kinds check the call graph; decision-current checks a recorded decision is still authoritative and names the live superseder if it isn't.
Finding enforcement (no API key, advisory by default) — openlore enforce is the unified gate over all governance findings. A single enforcement.policy block maps each finding code → blocking / advisory / off, decoupling a finding's intrinsic severity from your risk posture. The --hook gate fails a commit only on a blocking finding; a repo that declares no policy never blocks. It always runs the deterministic stale-decision-reference check and folds in blast-radius and impact-certificate findings where configured. → docs/configuration.md
Decisions on the graph (API key for consolidation) — Agents call record_decision before writing code; a pre-commit hook gates the commit until verified decisions are reviewed and written back as requirements. Decisions are also first-class graph nodes: projected into decision::<id> nodes joined to the files they govern by affects edges, so analyze_impact and get_subgraph return the governing decisions of a symbol and its blast radius as typed neighbors. → docs/specs/openlore-spec-16-decisions-as-graph-nodes.md
Epistemic Lease (no API key) — Models architectural drift as a navigation phenomenon, not a knowledge one: decay is driven by where the agent goes (cross-module trajectory), time since orient(), and weighted cognitive load. Once context ages or the repo moves, every MCP response carries a brief, factual freshness note — "informational signal; you decide whether to act on it" — never a command. Calling orient() resets it; when fresh, injection is zero-overhead.
Structural change analysis (no API key) — structural_diff is the structural complement to git diff: functions and edges added/removed, signature changes, and the callers in other files now stale because a callee's signature moved. → docs/structural-diff.md
Change-coupling & volatility (no API key) — get_change_coupling mines two facts the call graph can't see: co-change coupling ("these files always change together" — invisible coupling with no import edge) and churn ("changed 23 times" — a risk flag). Advisory, correlation not causation. → docs/change-coupling.md
Test-coverage gaps (no API key, opt-in) — report_coverage_gaps answers the inverse of select_tests: which load-bearing code has no test reaching it at all? Walks forward from every test, reports the code outside that set, ranked by hub/chokepoint significance. No test run, no instrumentation. Gaps-only and honest — it never claims a symbol is "tested". CLI: openlore coverage-gaps. → docs/coverage-gaps.md
get_style_fingerprint— a descriptive, deterministic idiom profile (arrow vs. declared function,const/let, naming case…) so an agent matches the house style. Honest by construction: a counter below the evidence floor, or a choice the compiler enforces, reports a null signal, never a guess.find_clones— the edit-time, scoped "does a near-duplicate of this already exist?" companion to the whole-repoget_duplicate_report. One query (a symbol or a raw snippet), clones ranked exact > structural > near. CLI:openlore find-clones.analyze_error_propagation— the exceptions that escape a function vs. those caught within it (TS/JS/Python). A sound lower bound — un-analyzable callees disclosed, never assumed exception-free. CLI:openlore error-propagation.analyze_env_impact— "what breaks if I remove this env var?": line-precise read sites, the upstream callers that reach them, tests to run, and per-siterequired. CLI:openlore env-impact.briefing_since— the catch-up lens: changed symbols since a base ref, ranked into a fixed tier order (surprising-change > hub-change > chokepoint-change > ordinary) from existing classifiers, no weighted score. CLI:openlore briefing-since.plan_parallel_work/map_in_flight_conflicts— a hazard-typed conflict graph over a task list, or over every in-flight branch/PR/agent-task, with a suggested landing order (opt-incoordinationpreset).get_language_support— the deterministic per-language capability matrix, derived from the live extractors so it can't over-claim. → docs/language-support.md
Preflight (no API key) — A CI staleness gate: any PR that edits indexed files fails until the graph is refreshed, weighted so hubs surface first. Drop-in templates in examples/ci/. → docs/preflight.md
Share the index (no API key) — The graph is a deterministic function of the committed source, so a team analyzes once and everyone else imports. openlore export bundle serializes the index into a portable, integrity-stamped .olbundle; openlore import bootstraps a verified index in seconds — validate-or-rebuild, never serving a stale or tampered bundle. → docs/shareable-bundle.md
Telemetry (opt-in, no API key) — Gated by OPENLORE_TELEMETRY=1 (off by default). Append-only JSONL under .openlore/telemetry/ for empirically measuring Epistemic Lease behavior (obstinacy index, recovery efficiency, trajectory dynamics). Analyze with openlore telemetry.
Languages & Infrastructure-as-Code
Languages: TypeScript · JavaScript · Python · Go · Rust · Ruby · Java · C++ · Swift · C# · Kotlin · PHP · C · Scala · Dart · Lua · Elixir · Bash — call graphs ride the same node/edge primitives for every language. Per-language extraction limits: docs/languages.md.
Infrastructure-as-Code: Terraform/HCL · Kubernetes · Helm · CloudFormation · Ansible · Pulumi · AWS CDK · CDKTF · Dockerfile · Docker Compose · GitHub Actions · Azure Bicep — IaC resources and their references project onto the same graph as application code, so orient, search_code, and analyze_impact answer "what's the blast radius of changing this security group / ConfigMap / IAM role / base image / CI job?" with zero new tooling. A compose service's build: resolves to its Dockerfile stage to its FROM base image — so one analyze_impact on a base image surfaces every stage and service that would rebuild. → docs/iac.md
Cross-domain impact: for embedded IaC (Pulumi/CDK/CDKTF), the code that provisions a resource is linked to it by a references edge, so analyze_impact traverses the code↔infra boundary end-to-end — "what infrastructure does this handler reach?" and the reverse. A code-only navigator structurally cannot answer this. → docs/cross-domain-impact.md
Federation, Interop & PR review
Federation (cross-repo)
The hardest orientation questions cross repo boundaries: who calls BillingService.refund, where is event X consumed, how does data flow from service A to B. Each repo keeps its own independently-built .openlore index; a project-local registry references peers, and federated queries load only what they need — no merged graph is ever materialized.
openlore federation add ../billing-service --name billing # register a peer repo's index
openlore federation list # ✓ indexed / ⚠ stale / ∅ unindexedanalyze_impact, find_dead_code, select_tests, and find_path take an opt-in federation flag and answer across the fleet — always naming the repos consulted vs skipped, never guessing for an unindexed one. analyze_impact on a route handler additionally surfaces its cross-service consumers — client call sites in other services that target the endpoint, matched by normalized route key. Enable with openlore mcp --preset federation. → docs/federation.md · docs/cross-service-topology.md
PR review (no agent required)
OpenLore's deterministic value usually flows through an agent calling an MCP tool — but everyone opens pull requests. openlore review drops the same distinctive output into that workflow, no agent required:
openlore review --base main # one Markdown briefing for a base..head range
openlore review --format json # machine-readable, for any CI / forgeIt composes the structural delta (structural_diff) and the blast radius (hubs touched, layers crossed, tests to run, spec/decision/memory drift) into one comment. The bundled GitHub Action posts it as one sticky comment — created once, updated in place, never spammy — advisory by default. Adoption is one workflow file: .github/workflows/openlore-review.yml.example. → docs/cli-reference.md
Interop (SCIP)
OpenLore exports SCIP. Plug it into Sourcegraph code nav, GitHub stack graphs, Glean importers, or any SCIP-aware tool:
openlore analyze && openlore export scip # writes ./index.scipThe SQLite graph stays canonical; SCIP is a one-way export of the subset it can model. → docs/scip-export.md
OpenSpec plugin (marketplace)
OpenLore is the inaugural engine and reference plugin for the OpenSpec marketplace: generate specs from existing code, then hand evolution back to core OpenSpec. OpenSpec discovers OpenLore by a declarative plugin manifest and invokes it as a subprocess — it never imports OpenLore's code. → docs/OPENSPEC-INTEGRATION.md
We dogfood our own governance
OpenLore's architecture is governed by the same decision system it ships. These ADRs were recorded with record_decision, gated at commit, synced into openspec/specs/, and projected onto the graph — they are the live, load-bearing constraints behind the design, not aspirational docs.
Decision | Rationale | Where |
North star is a deterministic structural context substrate | Local-first plumbing (like tree-sitter/SCIP/LSP) agents build on; every feature must make the coding-agent case more useful and stay grounded in static analysis, not LLM guessing | |
IaC resources project onto the existing graph primitives | One projector maps infrastructure onto |
|
Decisions project onto the graph the same way | A parser→projector split turns the decision store into |
|
EdgeStore uses SCHEMA_VERSION rebuild-on-bump, not migrations | The graph is fully derivable from source, so a schema change drops and rebuilds — no migration code, no drift |
|
BM25 keyword retrieval is the zero-network floor |
| Spec 06 |
The default MCP surface is the | The navigation core plus the top governance reads; cleared the DefaultSurfaceRevealsAllFaces benchmark (no regression across two models / both tiers), so | ADR-0023 (supersedes ADR-0022) |
This is the live decision log the pre-commit gate enforces. See docs/governance-dogfooding.md.
Known Limitations
We'd rather you know these up front than discover them mid-task.
Incremental updates converge or flag, never silently diverge. The watcher re-indexes the changed file's reverse-dependency closure on save; when that exceeds the per-save budget (default 40 files) the un-recomputed files are marked explicitly stale (freshness verdicts report non-authoritative) instead of left wrong. A full
analyze --forceclears the region.The index is integrity-checked, never served half-built. Every
analyzewrites an attestation (schema version, counts, content digest); on load the store is reconciled intohealthy/degraded/mismatched, and a non-healthy index is disclosed in the conclusion tools whose soundness depends on completeness — never silently answered over.Static analysis only. Dynamic dispatch, runtime metaprogramming, and
eval-based patterns are not captured in the call graph.LLM spec quality varies. Generated specs reflect the model's understanding — review complex business logic before treating it as authoritative.
Keyword (BM25) is the first-class default; semantic is an opt-in upgrade.
orient/search_codework immediately with no API key. Upgrade to hybrid dense+BM25 withopenlore embed --local(a bundled, CPU-only, no-API-key on-device embedder, ~23 MB pinned model) or a remoteEMBED_BASE_URL. Each surface states its active mode (keyword/local-semantic/remote-semantic).Large monorepos may take several minutes to
analyze— the AST/symbol-extraction pipeline is the bottleneck, not graph storage.
Requirements
Node.js 22.5+ (launching under an older Node fails fast with a one-line message and exit code 78, never a stack trace).
No API key for
analyze,drift,mcp,init, and every governance/navigation tool.API key only for
generate,verify, anddrift --use-llm:export ANTHROPIC_API_KEY=sk-ant-... # default provider export OPENAI_API_KEY=sk-... # OpenAI export GEMINI_API_KEY=... # Google Gemini…or use a CLI-based provider (
claude-code,gemini-cli,mistral-vibe,cursor-agent) — no key, just the CLI on your PATH.
Documentation
Start here: the documentation index maps what you want to do to the one canonical page that answers it.
Topic | Doc |
Full documentation index (task → canonical page) | |
MCP tools reference (72 tools + parameters) | |
| |
Agent setup (Claude Code, Cline, OpenCode, Vibe…) | |
Agent benchmarks (methodology + per-task numbers) | |
LLM providers + embedding config | |
Language support + the "add a language" checklist | |
Configuration reference (incl. | |
Change-impact certificate & surfaces | |
Architecture invariant guardrails (pre-edit) | |
Test impact selection (which tests to run) | |
Reachability & dead-code analysis | |
Test-coverage gaps (untested surface) | |
Structural change analysis (graph diff) | |
Change-coupling & volatility (git-mined) | |
Drift detection in depth | |
Cross-domain impact (code ↔ infrastructure) | |
Cross-service topology (federation) | |
Federation manifest (cross-repo) | |
Shareable graph bundle (export/import the index) | |
SCIP export (Sourcegraph/Glean interop) | |
Preflight CI staleness gate | |
CI/CD integration | |
Local provenance (git/PR, no OAuth) | |
CLI command reference | |
Interactive graph viewer | |
Configuration · Programmatic API · Pipeline | |
Internal design · Algorithms | |
Agentic workflows (BMAD, Vibe, GSD, spec-kit) | |
Troubleshooting · Philosophy |
Development
npm install
npm run build
npm run test:run # 5500+ unit tests, one-shot (npm test is watch mode)
npm run typecheckNew contributor? See CONTRIBUTING.md for setup, the agent-context / MCP wiring, and the commit gate. Please also read our Code of Conduct; to report a vulnerability, see SECURITY.md.
Star History & Community
If OpenLore saves your agents from re-reading the same files — or catches one risky change before it lands — star the repo. It's the signal that tells us to keep building, and it helps other engineers find it.
⭐ Star to follow along: github.com/clay-good/OpenLore
🐛 Found a bug or have an idea? Open an issue.
🤝 Want to contribute? Start with CONTRIBUTING.md.
📦 Install in one line:
npm install -g openlore && openlore install
Links
This server cannot be installed
Maintenance
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/clay-good/OpenLore'
If you have feedback or need assistance with the MCP directory API, please join our Discord server