Memora
Verifiable cognitive memory for personal vaults. Cite-or-it-didn't-happen.
Memora retrieves claims, not notes - atomic facts with source-span pointers, validity windows, and privacy bands. Every LLM citation is architecturally validated against your markdown. Hallucinations are caught structurally, not by trust.
→ See the architecture in motion
The problem
Personal AI memory tools, from RAG over Obsidian to second-brain wrappers, share one weakness: they retrieve notes and trust the LLM to quote them faithfully. When the LLM fabricates a meeting that didn't happen, puts words in someone's mouth, or cites a claim your notes don't contain, you have no architectural defense. You either catch the hallucination yourself, or you don't.
For a personal knowledge base with decisions and meeting notes, that is the wrong trust model.
How Memora differs
The atomic unit of memory is a claim, not a note. A claim is an extracted statement of fact with:
- subject, predicate, object
- source note + byte-range span
- blake3 fingerprint of the source text
- valid_from / valid_until temporal window
- privacy band (public / private / secret)
- provenance edges to source claims when synthesized
When the LLM answers, it cites claim ids. The validator re-reads the source span from your markdown, recomputes the fingerprint, and rejects citations that don't match. Hallucinated ids get stripped and the LLM is re-prompted with verified-only context. The citation contract is enforced by Rust types and span hashes, not by prompt obedience.
What you get
| Verified citations | Every claim_id in an answer is re-validated against the source span before reaching you. Hallucinations stripped. |
| Provenance + staleness | Synthesis claims point to sources. Edit a note, downstream syntheses are auto-marked stale. |
| Time-aware reasoning | Claims have validity windows. "What was true in March" is queryable. Contradictions auto-supersede. |
| Per-claim privacy | Inline <!--privacy:secret-->...<!--/privacy--> markers. Secrets redacted at the wire boundary on cloud LLMs, type-system enforced. |
| Active challenger | Daily background worker surfaces stale claims, contradictions, cross-region patterns, and frontier gaps in your world_map.md. |
| Hybrid retrieval | BM25 + embedding + RRF fusion + Hebbian co-activation learning + spreading activation via wikilinks. |
| Local-first | Single Rust binary. SQLite + HNSW. Works fully offline with Ollama. |
| Obsidian-native | Plain markdown vault with frontmatter. Open and edit in Obsidian alongside Memora. |
| MCP-native | Drop into Claude Code, Cursor, or any MCP client over stdio. |
Where to go next
- Quickstart - install and first verified citation in 10 minutes.
- Architecture - claim graph, retrieval, validation pipeline.
- Obsidian guide - daily-driver setup with Claude Code.
- Comparison - vs RAG, LLM Wiki, and other systems.
- MCP tools - every tool, with examples.
Status
v0.1.26. Indexes 100-note vaults in 5 to 10 minutes with Claude Haiku for about $0.30. Local Ollama is supported. Vault sizes up to a few thousand notes are the target. Larger scales are unmeasured. The active challenger surfaces decisions, contradictions, stale dependencies, and open questions in every atlas.
Issues, edge cases, and design discussions welcome at github.com/radotsvetkov/memora/issues.
Quickstart (10 Minutes)
Verifiable cognitive memory for personal vaults. Cite-or-it-didn't-happen.
Memora retrieves claims, not notes - atomic facts with source-span pointers, validity windows, and privacy bands. Every LLM citation is architecturally validated against your markdown.
This walkthrough takes a determined user from install to first verified cited answer in about 10 minutes.
1) Install Memora
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/radotsvetkov/memora/releases/latest/download/memora-cli-installer.sh | sh
What just happened
The installer places the Memora binaries on your system path (typically including
memora and memora-mcp), so you can run CLI commands and expose MCP tools to
clients without manual build steps.
2) Initialize a vault
memora init --vault ~/brain
What just happened
Memora created a vault scaffold with:
world_map.md(generated memory overview surface)- a sample semantic region folder
.memora/config.tomlfor local configuration and sidecar state
Your markdown vault stays human-readable and Obsidian-compatible from the start.
3) Add your first note manually
Create ~/brain/semantic/projects/drift/roadmap.md:
---
title: drift Serialization Decision
type: semantic
date: 2025-09-12
region: projects/drift
privacy: private
tags: [drift, serialization, architecture]
---
drift switched its serialization format from JSON to MessagePack in Q3.
Benchmarking showed a 3x throughput improvement.
Decision recorded in roadmap, retro, and review notes.
What just happened
You wrote plain markdown with frontmatter. No proprietary format is required. Memora will use this as extraction input and anchor future citations to precise source spans inside this file.
4) Index the vault
memora index --vault ~/brain
What just happened
Indexing runs a full pipeline:
- note metadata parsed and recorded
- claim extraction generates atomic claim candidates
- each stored claim is linked to source byte range and fingerprinted
- lexical and vector indexes are updated
- contradiction checks compare new/current claims and supersede older conflicts
The result is a queryable claim graph rather than a plain chunk index.
5) Ask your first query
memora query "What did we decide about drift's serialization format?" --vault ~/brain
What just happened
Memora retrieved claims, assembled model context, generated an answer, and validated cited claim ids against source spans before returning output. In the answer footer, citation entries correspond to claim ids that survived validation.
6) Add Claude Code MCP integration
Add one server entry to your MCP config:
{"mcpServers":{"memora":{"command":"/usr/local/bin/memora-mcp","env":{"MEMORA_VAULT":"/absolute/path/to/brain"}}}}
What just happened
Claude Code can now call Memora tools over stdio MCP. Instead of passing raw note chunks manually, you get memory-tool access with claim-aware retrieval and built-in citation validation behavior.
7) Ask the same question in Claude Code
Prompt:
What did we decide about drift's serialization format?
What just happened
Claude Code routed the request through Memora MCP tools. The response surfaced with verified citations tied to your markdown-backed claims. If a citation fails validation, Memora strips/retries with verified-only context before returning.
Next 5 minutes (recommended)
- Run
memora watch --vault ~/brainin a dedicated terminal tab. - Add inline secret markers in mixed-sensitivity notes.
- Check
world_map.mdafter your next capture session. - Use
memora_record_usefulwhen a cited answer was especially helpful.
Troubleshooting basics
command not found: memora-> restart shell or verify installer path export.- No claims extracted -> confirm frontmatter + note content + successful indexing.
- MCP tool unavailable -> verify
memora-mcppath andMEMORA_VAULTvalue. - Sparse answers -> add more factual statements; reflection-only notes yield fewer claims by design.
Recommended Models
Memora makes two kinds of LLM calls. Extraction runs once per note and produces structured triples. Synthesis runs once per atlas and produces prose. Provider quality matters, especially for extraction.
Anthropic Claude Haiku (recommended)
This is what Memora was tuned against. Best balance of cost and quality.
[llm]
provider = "anthropic"
model = "claude-haiku-4-5-20251001"
Cost: about $0.30 to index a 100-note vault.
Speed: 5 to 10 minutes with parallelism = 8.
Anthropic's free tier limits requests to 50 per minute. Add at least $5 of credit to reach Tier 1, or set parallelism = 1 to stay under the free limit.
OpenAI gpt-5-mini (alternative)
Comparable extraction quality at similar cost.
[llm]
provider = "openai"
model = "gpt-5-mini"
Local (Ollama)
Use this when local-only is a hard requirement.
[llm]
provider = "ollama"
model = "qwen2.5:32b-instruct-q5_K_M"
Honest assessment:
- Qwen 14B is insufficient for production (hallucinates relationships, shallow triples).
- Qwen 32B is acceptable but misses cross-region patterns.
- Llama 70B can match Haiku quality with a large memory cost.
- Below 32B parameters, atlas synthesis quality drops noticeably.
Embeddings run locally regardless of chat provider:
[embed]
provider = "ollama"
model = "nomic-embed-text"
dim = 768
Vault Conventions
Memora reads markdown notes from your vault and writes derived artifacts under .memora/.
Frontmatter (recommended)
Memora works with plain Obsidian-created notes that have no frontmatter.
On first memora index or memora watch, it auto-fills any missing fields
and prepends a YAML block while preserving your original note body byte-for-byte.
You can still provide and manage frontmatter manually. Memora applies a few quality-of-life normalizations while indexing:
regionfollows the note's folder path relative to the vault root.updatedfollows the file mtime (second precision).refscan optionally mirror detected wikilinks (configurable).- Invalid
source/privacyenum values are normalized to defaults.
---
id: note-id
region: projects/drift
source: personal
privacy: private
created: 2026-04-01T00:00:00Z
updated: 2026-04-01T00:00:00Z
summary: "Short summary"
tags: [tag1, tag2]
refs: []
---
Example inferred frontmatter for an Obsidian note semantic/projects/drift/serialization-note.md:
---
id: serialization-note
region: projects/drift
source: personal
privacy: private
created: 2026-04-30T18:42:10Z
updated: 2026-04-30T18:42:10Z
summary: "drift switched from JSON to MessagePack after benchmarking"
tags: []
refs: []
---
Inline privacy markers
Use markers to narrow privacy to a sub-span:
This is public context.
<!--privacy:secret-->
Salary is 120k.
<!--/privacy-->
Claims extracted from secret spans are marked secret even when note privacy is broader.
Derived files
world_map.md<region>/_atlas.md<region>/_index.md.memora/config.toml.memora/memora.db.memora/vectors/*.memora/last_challenger.json.memora/watch.lock(present whilememora watchis running)
Derived markdown can be regenerated and should not be edited as source-of-truth notes.
Frontmatter config knobs
In .memora/config.toml:
[frontmatter]
refs_mode = "sync_from_wikilinks" # or "manual"
sync_from_wikilinks: keeprefsaligned to[[wikilinks]]in body.manual: never auto-rewriterefs.
Obsidian Properties Template
Use this template in Obsidian so source and privacy are always visible and quick to edit.
Suggested property options
source:personal,reference,derivedprivacy:public,private,secret
Recommended defaults:
source: personalprivacy: private
Example note template
---
id: "{{title}}"
region: default
source: personal
privacy: private
created: 2026-01-01T00:00:00Z
updated: 2026-01-01T00:00:00Z
summary: ""
tags: []
refs: []
---
Notes
- Memora keeps timestamps in second precision (
...T12:34:56Z). - If
frontmatter.refs_mode = "sync_from_wikilinks",refsis rewritten from body wikilinks. - Invalid
source/privacyvalues are normalized topersonal/private.
Obsidian + Memora Daily Driver Guide
Verifiable cognitive memory for personal vaults. Cite-or-it-didn't-happen.
Memora retrieves claims, not notes - atomic facts with source-span pointers, validity windows, and privacy bands. Every LLM citation is architecturally validated against your markdown.
This guide is for Obsidian users who want Memora as a local-first memory backend while using Claude Code as the conversational interface.
What this guide assumes
- You already keep (or want to keep) a markdown vault.
- You want to preserve prose as prose, not force everything into rigid fields.
- You want model answers that are grounded in verifiable source spans.
- You want a practical workflow you can run daily with minimal friction.
Recommended Vault Layout
Use a structure that keeps note intent clear and lets Memora infer context.
~/brain/
episodic/
meeting-2025-q3-arch.md
2025-10-design-review.md
semantic/
projects/
drift/
roadmap.md
serialization-strategy-2025-q3.md
drift-bench/
benchmark-language-notes.md
people/
sarah.md
james.md
priya.md
procedural/
release-checklist.md
incident-playbook.md
world_map.md
.memora/
config.toml
state.db
logs/
Why these folders
episodic/for dated observations, meetings, and journals.semantic/<region>/for durable facts and reference knowledge by domain.procedural/for repeatable processes, checklists, runbooks.
This layout is not a hard requirement. It is a practical default that helps both human navigation and memory extraction.
.memora/ sidecar and git
Keep .memora/ out of your notes repository unless you explicitly want derived
state tracked. Typical .gitignore entry:
.memora/
Your markdown remains the durable, user-owned artifact; .memora/ is generated
state for indexing, embeddings, and runtime metadata.
Frontmatter Spec
Memora reads frontmatter for classification, temporal cues, and privacy defaults.
Required fields (recommended baseline)
type:episodic|semantic|proceduraldate: ISO date (YYYY-MM-DD) for primary event/authoring contextregion: short domain label (for semantic grouping)privacy:public|private|secret
Optional fields
tags: array of topical labelsstatus:draft|active|archivedvalid_from,valid_until: explicit claim window hints for extractionsource: external provenance hint (book, meeting, URL, etc.)confidence: self-assessed confidence marker for nuanced material
Full frontmatter example
---
title: drift Serialization Decision
type: semantic
date: 2025-09-12
region: projects/drift
privacy: private
tags: [drift, serialization, architecture]
status: active
valid_from: 2025-09-12
valid_until:
source: leadership-sync
confidence: medium
---
Notes on strictness
Memora can still extract claims from imperfect notes. The frontmatter spec is a quality lever, not a binary gate. Missing optional fields reduce structure but do not block indexing.
Inline Privacy Marker Syntax
Use inline markers when only part of a note is sensitive.
This project update is broadly shareable.
<!--privacy:secret-->
The account number is 4451-XX and pending legal review details are in draft.
<!--/privacy-->
Action items remain public.
Supported marker levels:
publicprivatesecret
How inheritance works
Claim privacy is the strictest of:
- note frontmatter privacy
- inline marker privacy (if present)
So if note privacy is private and inline section is secret, extracted claims
from that section become secret.
world_map.md: What It Is
world_map.md is a generated overview of your current memory topology and review
signals. It is not your canonical writing surface; it is a maintenance and
situation-awareness artifact.
Typical sections include:
- active regions and note density
- recently superseded claims
- stale derivative hotspots
- contradiction clusters
- frontier gaps (thinly connected domains)
- "Today's review" block from the challenger run
When Memora rewrites it
Memora updates world_map.md during indexing/watch cycles when:
- enough new claims enter the graph
- contradiction/staleness landscape changes
- scheduled daily challenger run executes
You can edit this file manually, but treat generated sections as ephemeral.
Reading "Today's review"
The challenger writes concise operational prompts, such as:
- "q4-rollout-plan depends on serialization-strategy-2024, now superseded."
- "drift-bench language disagreement: rust vs go."
- "drift backpressure strategy is still pending decision."
Read this section as a queue for targeted note maintenance, not as an alarm log.
Daily Driver Workflow
This five-step loop is optimized for consistency, not perfection.
1) Capture in Obsidian (or via memora_capture)
Write naturally in Obsidian: meeting outcomes, decisions, reflections, plans.
If you are already in Claude Code and want quick capture, use memora_capture
to append a session note directly to the vault.
Guideline: prefer fast capture over over-structuring. Frontmatter and markers can be refined afterward.
2) Run memora watch in a terminal tab
Keep one terminal running:
memora watch --vault ~/brain
The watch loop handles:
- file change detection
- indexing and extraction
- contradiction checks and supersession updates
- atlas/consolidation updates
- daily challenger pass
This is the background "memory maintenance engine." You keep writing; Memora keeps the claim graph current.
3) Ask questions in Claude Code
Use Claude Code with Memora MCP configured. Ask normal questions:
- "What did the team decide about drift's serialization format?"
- "What changed in deployment strategy this month?"
- "Which assumptions in product strategy were superseded?"
Memora-backed responses include claim citations that are validated before display.
4) Reinforce useful retrievals with memora_record_useful
When a cited answer is useful, mark it:
- this feeds Q-value style reinforcement for retrieval policy
- high-value paths become easier to prioritize in future ranking
You are effectively training the memory prioritization loop with low-friction feedback from real usage.
5) Review world_map.md regularly
Open the "Today's review" section every day or two. Act on one or two items:
- resolve contradictions where intent changed
- refresh stale syntheses after major note edits
- fill frontier gaps by capturing missing context
Small, regular interventions are better than monthly cleanup marathons.
Claims vs Prose: What Goes Where
This distinction matters because Memora extracts claims from prose, but not every sentence should be forced into atomic-fact style.
Put in claims (naturally, through prose that contains facts)
- explicit decisions ("We chose X over Y.")
- commitments ("Deadline moved to May 10.")
- stable descriptors ("Service A depends on Service B.")
- measurable observations ("Error rate rose after deployment.")
Leave as prose
- reflections and uncertainty exploration
- narrative context and emotional processing
- rough ideation where assertions are intentionally fluid
- personal meaning-making that is not a stable factual statement
Both are valuable. Reflection-heavy notes may yield fewer extracted claims, and that is expected. The goal is not maximal claim density; the goal is faithful memory with usable evidence.
Practical writing pattern
A useful balance:
- write free-form reflection first
- include a short "Decisions / Facts" section when relevant
- keep sensitive lines wrapped with inline markers when needed
This gives Memora clear extraction anchors while preserving narrative richness.
Privacy Practice: Frontmatter vs Inline Markers
Use the privacy tools intentionally by granularity.
Use frontmatter privacy: secret when
- the whole note is sensitive
- sharing any part externally is inappropriate
- the note is primarily credentials, legal details, or private health data
Use inline markers when
- most of the note is shareable but a few passages are sensitive
- you want one note to hold both operational and confidential details
- you need surgical redaction without splitting files unnaturally
Operational rule of thumb
- whole-note sensitivity -> frontmatter
- partial sensitivity -> inline markers
This keeps notes readable while preserving strict outbound redaction behavior.
Querying Expectations in Practice
When you ask a question, expect three outcomes:
- Verified answer with citations (normal path)
- Answer with fewer citations because some were invalidated and stripped
- Retry-constrained answer generated from verified-only context
If a claim citation cannot be validated against source span fingerprint, it does not pass through as-is. This is central to Memora's trust model.
Maintenance Habits That Keep Quality High
- Keep frontmatter consistent in newly created notes.
- Prefer one fact per sentence for high-signal decisions and commitments.
- Re-index after major refactors or bulk note moves.
- Resolve challenger-highlighted contradiction clusters early.
- Keep vault paths stable when possible; large path churn can increase stale maintenance overhead.
Common Pitfalls
- Over-optimizing templates too early: start with a minimal frontmatter set.
- Ignoring stale flags: stale does not mean wrong, but it does mean review.
- Using
secreteverywhere: overuse reduces model utility; mark surgically. - Treating
world_map.mdas canonical prose: it is generated maintenance output, not your long-form notebook.
Minimal Setup Checklist
- Vault created and initialized with Memora
-
.memora/gitignored - Frontmatter defaults chosen
-
memora watchrunning in one terminal tab - MCP integration configured for Claude Code
- First verified cited query completed
-
First
world_map.mdreview done
Closing
Obsidian remains your writing environment. Memora adds a verifiable memory layer
that tracks claim provenance, temporal validity, privacy boundaries, and citation
integrity. Used daily, the combination gives you both narrative freedom and
evidence-backed recall: write naturally, query confidently, and review memory
health through world_map.md.
Memora Architecture Deep Dive
Verifiable cognitive memory for personal vaults. Cite-or-it-didn't-happen.
Memora retrieves claims, not notes - atomic facts with source-span pointers, validity windows, and privacy bands. Every LLM citation is architecturally validated against your markdown.
This document describes the concrete system design in four layers:
- Note Graph (vault and markdown substrate)
- Claim Graph (typed factual representation)
- Retrieval and Validation (query-time execution)
- Agent Interfaces (MCP tools and client integration)
The goal is not to maximize retrieval throughput at all costs. The goal is to make unsupported claims difficult to surface and easy to detect.
Layered System Diagram
+--------------------------------------------------------------------------+
| Layer 4: Agent Interfaces (MCP over stdio) |
| memora_query_cited | memora_capture | memora_stale_claims | challenger |
+--------------------------------------------------------------------------+
|
v
+--------------------------------------------------------------------------+
| Layer 3: Retrieval + Validation |
| Hybrid retrieval (BM25 + vector + RRF) |
| Spreading activation over links/edges |
| Privacy filter + typed prompt builder |
| Citation validator (span re-read + fingerprint recompute + retry) |
+--------------------------------------------------------------------------+
|
v
+--------------------------------------------------------------------------+
| Layer 2: Claim Graph (SQLite + edge model) |
| claim(subject,predicate,object,span,fingerprint,time,privacy,status) |
| edges: entails | contradicts | supersedes | derives | co_occurs |
| provenance DAG + stale propagation |
+--------------------------------------------------------------------------+
|
v
+--------------------------------------------------------------------------+
| Layer 1: Note Graph (Obsidian vault + watcher) |
| markdown notes + frontmatter + inline privacy markers |
| file events -> parse -> extraction jobs |
+--------------------------------------------------------------------------+
Design Principles
Memora uses a narrow set of invariants:
- Claims are addressable units. All downstream reasoning references claim ids, not free text snippets.
- Source spans are mandatory. Every extracted claim stores a byte range into a specific markdown file.
- Fingerprints are mandatory. A blake3 hash over the exact source span is captured at extraction and checked at validation time.
- Validity is explicit. Claims can become historical (
valid_until) without disappearing from history. - Privacy is monotonic. A claim can only move toward stricter visibility when inherited or overridden.
These rules are enforced in the data model and request pipeline, not only by prompts or post-hoc heuristics.
Layer 1: Note Graph
The Note Graph is the user-owned vault. Memora does not replace it and does not rewrite user prose as a primary persistence strategy. Notes remain markdown files editable in Obsidian or any text editor.
1.1 Vault as source of truth
Memora treats the vault as canonical for natural language content. Derived state
is stored in .memora/ and the local database; the authoritative prose remains
in markdown.
Input channels into this layer:
- manual note edits in Obsidian
- captured notes from MCP tools (for example
memora_capture) - file-level moves, renames, and deletions
1.2 Structural parsing
Each note is parsed for:
- frontmatter fields (type, date, region, privacy, tags, status, etc.)
- body sections
- inline privacy markers:
<!--privacy:secret--> ... <!--/privacy-->
The parser outputs typed segments with byte offsets. These byte offsets are the backbone for source-span references in claims.
1.3 Incremental change detection
A watcher detects modified files and schedules extraction jobs. The queue keeps work bounded and avoids full re-indexing for every keystroke. Hash-based change detection ensures unchanged notes are skipped.
1.4 Why this layer matters
Most memory systems jump directly from note chunks to retrieval. Memora adds a formal extraction boundary so claims can carry strict provenance. This boundary is what makes downstream citation checks deterministic.
Layer 2: Claim Graph
The Claim Graph is the core memory model. A claim has typed fields and graph relations to other claims.
2.1 Claim schema
Core fields:
subject,predicate,objectsource_notesource_span_start,source_span_end(byte offsets)span_fingerprint(blake3)valid_from,valid_untilprivacy_band(public,private,secret)- lifecycle flags (
current,superseded,stale, etc.)
This schema separates statement identity from rendering text. The same concept can be tracked across time with explicit supersession edges rather than silent overwrite.
2.2 Edge model
Memora stores directional, typed edges:
entailscontradictssupersedesderivesco_occurs
Edges support both retrieval-time context expansion and maintenance-time staleness propagation.
2.3 Storage strategy
Primary persistence is SQLite:
- relational tables for claims and edges
- FTS5 index for lexical retrieval
- JSON1-compatible metadata fields for structured payloads
Embeddings are stored for semantic retrieval and indexed with HNSW. This allows hybrid retrieval while keeping the memory model local-first.
2.4 Provenance and stale propagation
Synthesis claims store provenance links to source claims (derives). If any
source becomes invalid or superseded, dependent syntheses are marked stale.
This stale bit is not an error state. It is a review signal: the synthesis might still be useful, but it should be revalidated against current inputs.
Layer 3: Retrieval and Validation
This layer is where query-time guarantees are enforced.
3.1 Retrieval cascade
Retrieval is not a single query operation. It is a staged cascade:
- lexical retrieval from FTS5 (BM25-style scoring)
- vector retrieval from HNSW embeddings
- reciprocal-rank fusion (RRF)
- graph expansion via co-activation and spreading activation
- privacy filtering
- prompt context assembly
The output is a ranked claim set, not note paragraphs.
3.2 Citation validator
The validator checks every claim id cited by the model:
- fetch claim row by id
- open source markdown note
- read exact byte span
- recompute blake3 fingerprint
- compare to stored fingerprint
If any citation fails (missing id, span mismatch, fingerprint mismatch), that citation is rejected. Depending on tool mode, rejected citations are stripped and the model is retried using verified-only context.
3.3 Retry semantics
Retry is scoped and deterministic:
- first pass: full retrieved context
- validation pass: verify cited ids and spans
- fallback pass: re-prompt with only validated claim context
This avoids silently passing unverifiable citations through to the user.
3.4 Temporal and contradiction awareness
Retrieval defaults to currently valid claims. Historical queries can include time filters to reconstruct prior states without flattening history.
Contradictions are represented explicitly and alter validity windows rather than deleting data. That keeps historical trails auditable.
Layer 4: Agent Interfaces
Memora exposes capabilities through MCP over stdio. Clients query tools instead of linking to private internals.
4.1 Tool surface
Representative interfaces include:
- cited query tool for validated responses
- capture tools for episodic logging
- contradiction and stale-claim inspection tools
- challenger outputs for periodic review
Tool responses are shaped around claim ids and provenance so clients can show evidence, not just summaries.
4.2 Why MCP boundary matters
The interface layer keeps guarantees portable across clients. A user can switch between environments without changing citation behavior because validation lives inside Memora, not in client-specific prompt templates.
4.3 Failure mode handling
If external model output includes invalid citations, Memora handles that inside the pipeline. The client receives either verified results or explicit failure signals, not a hidden downgrade.
Claim Lifecycle Walk-through
This is a concrete path for one statement from note to cited answer.
- User writes text in
semantic/projects/drift/roadmap.md: "drift switched serialization from JSON to MessagePack after throughput benchmarks." - Watcher detects file change and schedules extraction.
- Extractor emits claim candidate:
drift | uses_serialization | messagepack. - Source span recorded as byte offsets into the markdown file.
- Fingerprint computed over that exact span and stored in claim row.
- Claim indexed in FTS and embedding index; edges updated as needed.
- User asks query through an MCP client.
- Retrieval returns ranked claim set including this claim id.
- Model drafts answer and cites
[claim:abc123]. - Validator re-opens source note, slices stored byte range, recomputes blake3, and confirms it matches stored fingerprint.
- Citation marked verified and answer is returned.
- User sees output with verified citations that map back to source text.
If step 10 fails, citation is removed and the retry path runs on verified-only claims.
Contradiction Handling Walk-through
Contradictions are a first-class maintenance event.
- A new claim arrives:
drift-bench | uses_language | go. - System fetches candidate claims with matching subject/predicate and current validity windows.
- Contradiction judge evaluates pairs (
new,candidate) for conflict, such asgovsrust. - If conflict is confirmed:
- older claim receives
valid_until = new.valid_from(or event timestamp) supersedesedge is written (new -> old)contradictsedge is written for explainability
- older claim receives
- Derivative claims linked to the older claim are marked stale.
- Challenger later surfaces stale derivatives for review/regeneration.
Two properties are intentional:
- old data is retained for historical reasoning
- current reasoning can exclude superseded claims by default
Privacy Redaction Walk-through
Privacy is applied during extraction and enforced before prompt construction.
- Parser reads note-level frontmatter privacy.
- Parser reads inline privacy markers in body spans.
- Each extracted claim receives
privacy = max(note_level, inline_level). - Query pipeline applies privacy filter before prompt assembly.
- Prompt builder accepts typed claim wrappers that distinguish:
- local-safe claims
- redacted claims for cloud transport
- For cloud model calls, secret claims are transformed:
subjectpreservedpredicate,objectreplaced with[redacted]
- Non-redacted secret claims are rejected by type constraints and cannot enter outbound model payload construction.
This architecture turns privacy from a policy suggestion into a compile-time and runtime boundary.
Five Differentiators
1) Architectural citation enforcement
Most systems ask the model to cite correctly and then trust it. Memora stores source spans and fingerprints at extraction time, then verifies cited ids by re-reading markdown at response time. This allows deterministic rejection of invalid citations and a retry path constrained to verified context.
2) Claim-first memory model
The memory primitive is an atomic claim, not a note chunk. Claims carry temporal state, privacy, provenance, and edges. That enables operations like supersession, stale propagation, and relation-aware retrieval that are difficult to represent when the only unit is free text.
3) Time-aware contradiction handling
Contradictions are modeled as graph relations with validity window updates. New claims can supersede old ones without deleting history. Queries can target either the current world state or historical states, and stale derivatives can be identified explicitly.
4) Per-claim privacy with typed redaction
Privacy is resolved at claim level using note metadata plus inline marker overrides. Secret claims can still contribute structurally while restricting outbound content. Cloud-bound payloads enforce redaction before model transport, which is stronger than relying on operators to remember manual filtering.
5) Active challenger loop
Memora runs a periodic challenger that inspects stale dependencies, contradictions, and sparsely connected frontier areas. This is not just retrieval: it is maintenance of memory integrity over time. The result is a continuously reviewable world map instead of a static index.
What We Do Not Do
- Not a faster RAG benchmark story: Memora's primary claim is architectural verifiability. Benchmark speed/latency comparisons against other systems are not published here.
- Not a multimodal memory store yet: current substrate is markdown-first with structured metadata; rich multimodal ingestion is future work.
- Not federated multi-vault reasoning yet: primary target is one personal vault and its sidecar state.
- Not a research-agent framework: Memora is a memory engine and interface layer, not an autonomous planner for open-ended web research.
Operational Notes
- Local-first operation works offline with local model backends.
- Derived state is reproducible from vault content plus config.
- Citation verification depends on byte-accurate spans; manual file rewrites are expected and handled through re-indexing.
- Claims may be skipped when extraction confidence or structure is insufficient; absence of a claim does not imply absence of prose.
Closing
Memora is engineered around a strict contract: if an answer cites your notes, the citation must survive structural checks against the source text. The system is intentionally conservative where trust boundaries are involved, and that conservatism is what enables personal-memory workflows where incorrect citations are treated as system errors, not normal behavior.
Citation Protocol
Memora treats citations as verifiable references to claim IDs.
Claim marker format
LLM responses use [claim:<id>].
Example:
drift switched to MessagePack for serialization [claim:drf75a1c9e10b2aa]
Verification steps
- Parse claim markers from LLM output.
- Resolve each claim ID from SQLite.
- Resolve note path and byte span.
- Re-read source span from markdown body.
- Recompute BLAKE3 fingerprint.
- Optionally verify quote overlap.
Status values
verifiedunverified(claim missing)fingerprint_mismatch(source changed)quote_mismatch(marker quote unsupported)
Verified answer semantics
clean_text is rewritten to keep only statements supported by verified claim markers.
This means "verified" in Memora is an architectural property (data + hash + span), not a prompt instruction.
For example, a verified claim can point to semantic/projects/drift/roadmap.md with a span that captures the MessagePack decision text.
Architectural Comparison
Verifiable cognitive memory for personal vaults. Cite-or-it-didn't-happen.
Memora retrieves claims, not notes - atomic facts with source-span pointers, validity windows, and privacy bands. Every LLM citation is architecturally validated against your markdown.
This document compares memory architectures, not benchmark performance.
Scope and framing
The systems below are useful in different contexts, and several have influenced how practitioners think about personal knowledge tooling. The comparison here focuses on one narrow question:
How does each system model memory when an LLM answer needs to be grounded in a user's personal notes?
For each system, we look at:
- primary unit of retrieval
- citation mechanism
- temporal state handling
- privacy boundaries
- synthesis staleness handling
- where Memora diverges
1) Traditional RAG over Obsidian
One-sentence description: Index markdown notes into chunks, retrieve top-k chunks with keyword/vector search, and pass those chunks to the model as context.
Architectural primitive
The core primitive is a chunk of note text (often overlapping windows). Metadata may include file path, heading, tags, or timestamps, but chunk text is still the object supplied directly to the model.
Citations
Usually prompt-level citation guidance. The prompt asks the model to cite notes or quote excerpts, but the pipeline often does not perform a strict post-generation verification of every cited identifier against immutable spans.
Temporal reasoning
Typically weak. Some setups use file modified time as a recency signal, which is helpful for ranking but not equivalent to claim-level validity windows. Temporal queries often degrade into "newer chunks rank higher."
Privacy handling
Commonly note-level or folder-level segregation (for example separate sensitive folders excluded from indexing). Fine-grained within-note redaction is possible, but usually depends on conventions, not typed enforcement.
Synthesis staleness
Rarely modeled explicitly. If a synthesis answer from last week depends on notes that changed today, the system does not track that dependency graph by default.
Where Memora diverges
Memora extracts atomic claims with source byte spans and fingerprints. The model cites claim ids; citations are verified against markdown spans before output is accepted. Contradictions and supersession update claim validity windows, and derived claims can be marked stale when their dependencies change.
2) LLM Wiki (Karpathy pattern)
One-sentence description: Curated wiki-style notes are maintained and queried through model prompts, with emphasis on human-maintained pages and summaries.
Architectural primitive
The primitive is generally the wiki page / full note rather than atomic factual units. Retrieval can be simple grep-like search, embedding search, or manual page curation.
Citations
Again mostly prompt-level trust. The model is asked to reference sections or pages, but strict claim-id-to-span validation is typically outside scope.
Temporal reasoning
Usually manual. Edits update the page narrative, but there is no built-in claim-level time window model unless custom logic is added.
Privacy handling
Mostly repository-level or file-level policies. Fine-grained secret redaction can be done procedurally, but not usually via a typed claim transport boundary.
Synthesis staleness
Not tracked as a first-class graph concern in the base pattern. If summaries depend on old sections, freshness is largely a human maintenance task.
Where Memora diverges
Memora keeps note prose but converts factual content into explicit claim records
with provenance edges. Staleness becomes computable (derives edges + stale
marks) and contradiction handling updates validity windows instead of relying on
manual page rewrites.
3) Ori-Mnemos
One-sentence description: A memory-oriented framework focused on organizing and recalling information from accumulated user interactions.
Architectural primitive
Typically event/memory entries or chunk-like artifacts depending on deployment. The unit is still generally larger and less strictly typed than subject-predicate- object claims with immutable source spans.
Citations
In most practical setups, citations are either absent or generated via prompt conventions. There is limited evidence of mandatory span-hash validation against source markdown at answer time.
Temporal reasoning
Temporal metadata may exist at entry level, but claim-level supersession and contradiction windows are not generally the default mechanism.
Privacy handling
Commonly policy/config driven at source or collection level. Per-claim typed redaction at model boundary is not the typical baseline.
Synthesis staleness
Dependency-tracked stale propagation is not usually central. Refresh behavior is often periodic re-summarization rather than DAG-aware invalidation.
Where Memora diverges
Memora's core divergence is strict verifiability: every claim maps to a source span with fingerprint, and cited ids are validated structurally. Temporal changes are represented as supersession edges and validity updates, not only recency.
4) MDEMG
One-sentence description: A memory graph style approach that structures knowledge for retrieval and agent use across sessions.
Architectural primitive
Graph nodes often represent memories/documents/entities, with varying granularity and schema. The primitive can be richer than flat chunks, but is not necessarily anchored to byte-accurate spans in user markdown.
Citations
Often graph-aware retrieval with model-mediated explanation. Citation guarantees are typically semantic/prompt level, not strict span-hash contracts.
Temporal reasoning
Some graph memory systems include timestamps or recency weighting, but explicit
valid_from/valid_until per atomic claim with contradiction-based supersession
is uncommon as a default.
Privacy handling
Depends on deployment policy and node metadata. Fine-grained transport redaction for secret fragments is usually custom rather than enforced by a dedicated typed pipeline.
Synthesis staleness
Graph updates may occur, but "this derived claim is stale because one ancestor was superseded" is not universally enforced without additional logic.
Where Memora diverges
Memora combines graph edges with strict source anchoring and citation validation. It treats provenance and stale propagation as standard maintenance behavior, not optional add-ons.
5) Vanilla Obsidian + Claude Code (no memory layer)
One-sentence description: Use Obsidian as note storage and ask questions in Claude Code directly, without a dedicated extraction/claim memory engine.
Architectural primitive
The primitive is whatever context is manually selected or searched at runtime: files, snippets, or ad hoc passages. There is no persistent claim graph.
Citations
Citations depend on what the model is prompted to provide and what context was manually supplied. Verification is user-driven rather than architecturally enforced.
Temporal reasoning
Handled manually by inspecting timestamps, file history, or narrative context. No built-in claim-level temporal windows or supersession semantics.
Privacy handling
Relies on user judgment and workspace boundaries. There is no dedicated claim privacy lattice with mandatory redaction at model transport boundaries.
Synthesis staleness
Not tracked by default. If prior synthesis depended on now-edited notes, there is no automatic stale marker.
Where Memora diverges
Memora adds a dedicated memory backend between vault and model: claim extraction, provenance, contradiction handling, stale propagation, and citation verification. The user still owns markdown, but verification does not depend on manual checking for every answer.
Summary Matrix
| Dimension | RAG over Obsidian | LLM Wiki | Ori-Mnemos | MDEMG | Obsidian + Claude Code | Memora |
|---|---|---|---|---|---|---|
| Atomic unit | chunks | pages/notes | memory entries | graph nodes/memories | ad hoc snippets | atomic claims |
| Citation model | prompt-level | prompt-level | prompt-level/varies | semantic/prompt-level | manual/prompt-level | architectural validation |
| Temporal model | recency-biased | manual edits | entry timestamps | recency/metadata | manual | validity windows + supersession |
| Privacy model | folder/note policy | file policy | policy/config | metadata/policy | manual | per-claim + typed redaction |
| Staleness tracking | usually none | usually none | limited | limited/custom | none | provenance DAG + stale flags |
Final note on benchmarking
This is an architectural comparison, not a performance comparison. Memora has not been run in published head-to-head benchmarks against these systems. The distinctions here are about memory modeling, citation guarantees, temporal representation, and privacy boundaries, not claims about retrieval speed or quality rankings.
MCP Tools
All tools return JSON payloads.
memora_query
Input:
{"query":"What did the team decide about drift's serialization format?","k":5}
Output:
{"hits":[{"id":"note-1","summary":"drift moved to MessagePack in Q3","region":"projects/drift","score":0.12,"snippet":"..."}],"regions_used":["projects/drift"]}
memora_query_cited
Input:
{"query":"What did the team decide about drift's serialization format?","k":5}
Output:
{"clean_text":"drift switched from JSON to MessagePack [claim:drf75a1c9e10b2aa]","verified_count":1,"checks":[{"claim_id":"drf75a1c9e10b2aa","status":"verified"}]}
memora_get_note
Input: {"id":"note-1"}
Output keys: id, region, summary, body, tags, refs, wikilinks, hebbian_neighbors
memora_get_atlas
Input: {"region":"projects/drift"}
Output keys: region, atlas_markdown, note_count
memora_get_world_map
Input: {}
Output: {"markdown":"# World Map ..."}
memora_neighbors
Input: {"id":"note-1","top_n":5}
Output keys: hebbian, wikilinks
memora_record_useful
Input: {"query_id":"...","useful_ids":["note-a","note-b"]}
Output: {"ok":true}
memora_capture
Input:
{"region":"inbox","summary":"Quick capture","body":"...", "tags":["inbox"], "privacy":"private"}
Output: {"id":"note-...","path":"inbox/note-....md"}
memora_consolidate
Input: {"scope":"all"} or {"scope":"region:work/projects"}
Output keys: regions_rebuilt, notes_moved
memora_verify_claim
Input: {"claim_id":"abcd1234"}
Output keys: exists, span_intact, current_text
memora_stale_claims
Input: {}
Output: array of stale claim rows.
memora_contradictions
Input: {"subject":"drift-bench"} (optional)
Output: array of contradiction rows.
memora_challenge
Input: {}
Output: ChallengerReport JSON.
memora_decisions
Input: {}
Output: [{id,title,decided_on,status}]
License
Apache 2.0 only. See LICENSE.
Why Apache 2.0
Personal memory infrastructure should be portable, forkable, and embeddable without surprise. Apache 2.0 was chosen specifically because:
-
It's permissive without being a free-for-all. Companies and individuals can build on Memora - wrappers, internal forks, MCP integrations, distribution bundles - without infecting their own license. That matters for adoption inside organizations where copyleft would be a non-starter.
-
It includes an explicit patent grant. Contributors who hold patents cannot retroactively assert them against downstream users of the code they contributed to. For a tool whose differentiators (claim graph, span fingerprint, citation validator) sit close to active patent thickets in the LLM tooling space, the explicit grant is non-negotiable.
-
It survives M&A. A future Memora acquirer cannot revoke the license on existing releases. Once Apache 2.0 is published, it stays Apache 2.0 for that version, forever.
-
It's compatible with the rest of the Rust ecosystem. Most Cargo crates are MIT or Apache 2.0 dual-licensed; choosing Apache 2.0 lets us depend on them without friction and lets others depend on us symmetrically.
What Apache 2.0 means in practice
You can:
- Use Memora commercially.
- Modify Memora and distribute the modifications (under Apache 2.0).
- Patent your own improvements while keeping Memora's grant intact.
- Bundle Memora into a closed-source product, as long as you preserve the notice file and don't claim Memora endorsement.
- Run Memora on private vaults, internal infrastructure, or air-gapped systems without contacting anyone.
You must:
- Include a copy of the Apache 2.0 license with any redistribution.
- Preserve copyright, patent, trademark, and attribution notices.
- State significant changes if you redistribute modified versions.
- Not use the Memora name or logo to imply endorsement of a fork without permission.
SPDX identifier
SPDX-License-Identifier: Apache-2.0
Full text
See LICENSE in the repository root for the canonical Apache 2.0 text.