Start here: Install in one command · What you get · Is OpenLore for you? · See it in action · 5-Minute Quickstart · What it costs to adopt
Evaluate it: Value Scorecard (wins and losses) · OpenLore vs. Alternatives · Known Limitations · We dogfood our own governance
Understand it: How It Works · Governance · Core Features · Languages & IaC · Federation, Interop & PR review
Use it: Agent Cheat Sheet · Claude Code Skill · Requirements · Documentation · Development · Community
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 install
That 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.
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.
Is OpenLore for you?
The fastest way to evaluate a tool is to find out quickly that it isn't for you. So:
| ✅ Strong fit | A codebase big enough that you can't hold it in your head — and neither can the model. Private or niche code the model never memorized. Long agent sessions where stale assumptions compound. Polyglot repos, or code plus the IaC that deploys it. Anywhere "the agent changed something it shouldn't have" is a real cost, not a hypothetical. |
| 🤔 Try it, but measure | Mid-size repos and mixed workloads. The orientation win scales with size and depth, so run openlore prove --estimate (seconds, no API key) before you commit to it. |
| ❌ Probably not yet | A small repo the model already knows, answering shallow questions like "who calls parseArgs" — your agent's built-in search is cheaper, and we publish the measurement that says so. Also: if you want something to perform the refactor, OpenLore is the wrong layer — it locates and certifies, it never edits your code. |
One idea, if you only read one line of this README: an agent's expensive failure mode isn't ignorance — it's confidence. A model that doesn't know a function exists will go look. A model that "knows" a stale fact will confidently build on it, and you pay for that at review time. OpenLore is built so the agent can be told "that fact is stale" and "this change opens a path you said was sensitive" — deterministically, from the graph, with no second model in the loop guessing about the first.
See it in action
The same task, twice. Ask an agent to add a flag to a command it has never seen:
| Without OpenLore | With OpenLore | |
|---|---|---|
| Opening move | grep a guessed name → open a file → wrong layer → open three more | orient("add a --since flag to the blast-radius command") |
| What it learns | file contents, one at a time, in whatever order it guessed | the functions, their callers, the matching spec sections, and the ranked insertion points — in one call |
| What it misses | the five callers living in files it never opened | every caller the graph can see — statically resolvable ones, at least; dynamic dispatch is still nobody's friend |
| Before it commits | "looks right to me" | blast_radius → tests to run; certify_public_surface → the consumers this signature change breaks, by name |
The measured effect of that shape change on deep, multi-hop tasks: 25 → 16 round-trips on excalidraw, −26% aggregate. It is not magic — it is the difference between rediscovering structure per task and querying it. Full numbers, including where this doesn't pay off, in the Value Scorecard.
Real output — openlore orient --json "add a --since flag to the blast-radius command", run on this repo (abridged: fields elided, caller lists flattened to names):
{
"relevantFiles": ["src/cli/commands/blast-radius.ts", "src/core/services/mcp-handlers/blast-radius.ts"],
"relevantFunctions": [
{ "name": "computeBlastRadius", "filePath": "src/core/services/mcp-handlers/blast-radius.ts",
"signature": "async function computeBlastRadius(input: BlastRadiusInput): Promise<BlastRadiusBriefing>",
"fanIn": 5, "isHub": true, "language": "TypeScript" }
],
"callPaths": [
{ "function": "computeBlastRadius",
"callers": ["handleBlastRadius", "computeImpactCertificate", "runBlastRadiusCli",
"composeReview", "collectGovernanceFindings"] }
],
"landmarks": [
{ "name": "runBlastRadiusCli", "hops": 1,
"signals": [{ "label": "orchestrator", "evidence": { "fanOut": 11 } },
{ "label": "volatile", "evidence": { "level": "medium", "commits": 6, "coChangedWith": 5 } }] }
],
"insertionPoints": [
{ "rank": 2, "name": "computeBlastRadius", "role": "hub", "strategy": "cross_cutting_hook",
"reason": "computeBlastRadius is called by 5 functions -- adding logic here affects the entire callsite surface." }
],
"suggestedTools": ["record_decision", "analyze_impact", "get_subgraph", "check_spec_drift"]
}
The agent knows exactly where to look, what it touches, and what's risky to touch — before reading a single file. Every field is computed from the graph; nothing is inferred by a model.
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 openlore prove |
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 index
That 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 setup
Zero-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 decisions
git clone https://github.com/clay-good/openlore
cd openlore
npm install && npm run build && npm link
nix run github:clay-good/openlore -- analyze
nix shell github:clay-good/openlore
System flake:
environment.systemPackages = [ openlore.packages.x86_64-linux.default ];
What it costs to adopt
Every tool asks for something. Here is exactly what OpenLore asks for, measured on a fresh clone of ripgrep with the published [email protected] — reproduce it in about a minute:
git clone --depth 1 https://github.com/BurntSushi/ripgrep && cd ripgrep
npx openlore init && time npx openlore analyze && du -sh .openlore
| What it costs | On ripgrep (232 source files indexed) |
|---|---|
| One-time index build | 13.6 s, entirely local — no API key, no network call |
| Disk | 27 MB under .openlore/ (gitignorable; the graph is a pure function of your source, so it's always rebuildable) |
| Per-query latency | ~430 µs p50 in-process via the MCP server; a cold one-shot CLI call is ~2 s, nearly all of it Node startup and opening the index |
| Keeping it fresh | automatic — the file watcher re-indexes the changed file's dependency closure on save |
| Your source code | never leaves the machine. No account, no telemetry (opt-in only), no hosted index |
| Lock-in | none — it's one gitignored directory. Delete .openlore/ and nothing about your repo has changed. |
Large monorepos take minutes rather than seconds; that limit is stated plainly in Known Limitations.
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 |
|---|---|---|
change_impact_certificate |
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. | openlore impact-certificate --base main |
certify_public_surface |
A 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 — what it can't prove safe is never called safe. |
openlore certify-public-surface --base main |
check_architecture |
"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 .openlore/architecture.json |
verify_claim |
A deterministic confirmed / refuted / unverifiable verdict with a citation receipt before an agent asserts "X is dead", "Y is safe to change", or "decision abc12345 still governs this". |
MCP tool (verify preset) |
openlore enforce |
One commit gate over every governance finding. Map each finding code → blocking / advisory / off in enforcement.policy; the gate blocks only on what you class blocking. |
openlore enforce --hook |
| 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 out-of-box agent gets the read face on top of navigation (the write face — remember, record_decision — stays opt-in via --preset memory/minimal/full). 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 73 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 | orient(task) — functions, callers, specs, insertion points in one call |
| Shallow "who calls X / where is Y?" | orient(task, lean:true) — navigation core only, ~40% smaller |
| "Which file/function handles X?" | search_code |
| "What's the blast radius if I change this?" | analyze_impact — risk score + up/downstream chain + governing decisions |
| "How does request X reach function Y?" | trace_execution_path |
| "I changed X — which tests should I run?" | select_tests — backward reachability to the reaching tests + paths |
| "What's dead / what dies if I delete X?" | find_dead_code — cross-language reachability, confidence-tagged |
| "What's the blast radius of my whole diff before I commit?" | blast_radius — callers/layers, tests to run, anchored memories & specs that drift |
| "Does my diff open a new path into a sensitive boundary?" | change_impact_certificate — differential reachability into declared surfaces |
| "Did my change break a consumer's public API contract?" | certify_public_surface — breaking-change verdict, consumers named |
| "May I add this import here?" | check_architecture — pre-edit verdict against declared rules |
| About to assert a fact / cite a decision | verify_claim — deterministic verdict + citation receipt |
| Recording an architectural choice | record_decision before writing the code |
| "What changed structurally / whose callers are stale?" | structural_diff — graph diff, stale callers, rename flags |
| "What changes together with this / what's volatile?" | get_change_coupling — co-change + churn from git |
| Reading / checking a spec | get_spec · search_specs · check_spec_drift |
| "A lot changed since I last looked — what matters?" | briefing_since — changed symbols ranked by structural significance |
| "Does a near-duplicate of this already exist to reuse?" | find_clones — edit-time, scoped clone query |
Everything else (read a file, grep, list files) uses your native tools. Full reference — all 73 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-project
The 8 multi-agent workflow skills (brainstorm, plan-refactor, write-tests, implement-story, debug, …) install via openlore setup into .claude/, .opencode/, or .vibe/. See skills/openlore-orient/README.md.
OpenLore vs. Alternatives
A good tool should tell you when not to use it. So here is the honest map of the space.
Everyone in this category is answering the same first question: "how does the agent see the codebase without reading it file by file?" LSP toolkits answer it with symbols. Graph MCP servers answer it with a parsed graph. Search platforms answer it with an index. They are all real answers, and several of them are good.
OpenLore answers it too — and then keeps going into the second question almost nobody is answering: what happens when the agent starts writing? A retrieval layer makes an agent informed. It does not make the agent safe. Nothing in a symbol index tells you that this diff just opened a path into your auth boundary, that this signature change breaks four consumers by name, that the decision governing this module was superseded last month, or that the fact your agent has been confidently using for the last 40 tool calls went stale 12 commits ago. That half of the problem — governance, on the same graph, with no LLM in the loop — is the part OpenLore was built for.
| Agent built-ins(Cursor, Claude Code) | LSP toolkits(e.g. Serena) | Graph MCP servers(e.g. CodeGraph) | Search platforms(e.g. Sourcegraph) | OpenLore | |
|---|---|---|---|---|---|
| Structural context instead of file reads | ❌ grep + file reads | ✓ symbols via LSP | ✓ parsed graph | ✓ index | ✓ call graph + clusters + IaC + decisions on one graph |
| Local, no API key, deterministic | Partial | ✓ | ✓ | ❌ hosted/indexed service | ✓ no LLM in the hot path |
| Cross-session memory anchored to code | ❌ | Partial (notes) | ✓ stored notes | ❌ | ✓ anchored to a symbol — carried across renames/moves, self-invalidating |
| Told when a cached fact goes stale | ❌ | ❌ | ❌ | ❌ | ✓ Epistemic Lease |
| Blast radius + which tests to run | ❌ | ❌ references only | Partial | Partial | ✓ backward reachability, with reaching paths |
| Breaking-change verdict over a diff | ❌ | ❌ | Partial (impact heuristics) | ❌ | ✓ per export, consumers named, conservative by construction |
| "Did this diff open a new path into a sensitive boundary?" | ❌ | ❌ | ❌ | ❌ | ✓ differential reachability, pre-commit |
| Architecture invariants before the import is written | ❌ | ❌ | ❌ | ❌ | ✓ cross-language |
| Spec/code drift + ADRs gated at commit | ❌ | ❌ | ❌ | ❌ | ✓ milliseconds, no API key |
| One policy-driven commit gate | ❌ | ❌ | ❌ | ❌ | ✓ enforcement.policy, advisory by default |
| Claims backed by a citation receipt | ❌ | ❌ | ❌ | ❌ | ✓ confirmed / refuted / unverifiable |
| Cost/round-trip effect published with the losses | ❌ | ❌ | ❌ | ❌ | ✓ −7%→−21% cost, −26% round-trips on deep tasks † |
Where the others are genuinely the better pick — we would rather you use the right tool than ours:
- Doing surgical, symbol-level edits (rename across files, move a symbol, replace a body) — that is an LSP toolkit's home turf. OpenLore is deliberately read-only: it locates and certifies, it does not refactor for you. The two compose well.
- Search across hundreds of repos, org-wide, in a browser, with an audit trail — that is a code search platform. OpenLore is local-first and repo-scoped by default (federation is opt-in and read-only).
- You just want fast graph retrieval and nothing else — a graph MCP server is a smaller surface to adopt, and several are excellent at it. OpenLore's extra weight is governance; if you do not want a commit gate, drift detection, or change certificates, you are paying for capability you will not use.
- A small, familiar repo and shallow questions ("who calls X") — your agent's built-in search is often cheaper. We measured this and published it below; we did not hide it.
What you cannot get anywhere else: one graph where your code, your infrastructure, and your architectural decisions are the same node type — so a single traversal answers "what breaks, what does it cost, what governs it, and is that still true?" — and a substrate that would rather tell you "I don't know, this is stale" than hand your agent a confident guess.
† 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.
Comparisons reflect each project's publicly documented capabilities as of July 2026 and describe categories, not verdicts on quality; these are fast-moving projects, and a correction PR is always welcome. Named examples: Serena (MIT), CodeGraph (Apache-2.0), codebase-memory-mcp, Sourcegraph. OpenLore exports SCIP, so it sits alongside them rather than against them.
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 → CODEBASE.md digest |
No |
| 2. Spec & Governance | Living specs, ADRs, drift detection, change certificates, decision & finding gates | For spec generation only |
| 3. Agent Runtime | 73 MCP tools — orient(), graph traversal, semantic search, verdicts & gates |
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[73 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 --> Specs
Crucially, 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
Skimmable by design: each bold lead-in is one capability, with the command that runs it and the doc that explains it. Everything is deterministic and local; only the two entries marked "API key" ever talk to a model.
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. The MCP server's file watcher (--watch-auto, on by default) updates the graph 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 bl
No comments yet
Be the first to share your take.