Skip to content

Selvedge vs. OpenLore

OpenLore is the closest thing to Selvedge in the category, and the most useful comparison because of it: both are local-first, both are deterministic, and neither puts an LLM in the retrieval path. The difference is where the memory comes from, and what survives in it.

Selvedge OpenLore
Reasoning source Captured live, by the agent in the same context that produced the change Derived — tree-sitter static analysis of code state, plus commit-gated decision notes
Granularity Entity — DB column, table, env var, dep, API route, function AST node (18 languages + 12 IaC)
Mechanism MCP server — the agent calls it as work happens MCP server — one-time index + commit-time certificates
Grouping Changesets — named feature/task slugs across many entities Call-graph edges
Prior attempts Yes — prior_attempts surfaces tried-and-rejected paths Purged — rejected is an inactive status, dropped from the queryable store after each decision sync
Storage SQLite SQLite graph in .openlore/
  • Determinism is shared ground here, not a differentiator. Against most of this category Selvedge leads on having no model in the storage or retrieval path. OpenLore is deterministic-native too — its own description is “no LLM in the hot path” — so that argument doesn’t separate the two, and we won’t pretend it does.
  • Testimony vs. derivation. OpenLore derives what it knows from the code as it stands: a static analysis can always be recomputed, so it can only ever describe the state that survived. Selvedge stores what the agent said at the time. Testimony is not re-derivable from the repository, which is exactly why it’s worth keeping.
  • What happens to a rejected decision. This is the sharp one. In OpenLore, rejected is one of the inactive statuses, and purgeInactiveDecisions drops those from the store after every decision sync — the annotation survives in the synced spec markdown, but the queryable record does not. In Selvedge the store is append-only: a rejection is a first-class, permanent, queryable fact, and prior_attempts is built to return it. Nothing in a purged store can answer “has this been tried, and how did it turn out?”
  • Entity granularity vs. AST node. OpenLore’s node coverage is broader across languages. Selvedge’s entities are the things you search for six months later that have no AST node at all — users.email, env/STRIPE_SECRET_KEY, deps/stripe.

If what you want is a deterministic map of the code as it exists now — call graphs, AST-level structure, broad language coverage, decisions kept in step with the current spec — OpenLore is a strong and genuinely well-built fit, and its language coverage is wider than ours. Reach for Selvedge when the question you need answered is about the path not taken.