Loreweave

io.github.lets-order-some-fries由 GitHub 账号 lets-order-some-fries 发布v0.39.0更新于 Oct 24, 2026

Durable agent memory over a markdown vault: bitemporal facts, timelines, hybrid graph search.

概览

AI 生成的概览

Loreweave 把本地 markdown 笔记库变成持久的智能体记忆:双时态事实、时间线与混合图检索,通过 MCP 提供给助手使用。

可以做什么
搜索与读取笔记:带来源标注和时间过滤的混合检索、读取笔记全文,以及一次调用返回相关段落、当前事实和近期变更的上下文包。查询事实:按时间点或按当时认知查询事实、查看实体时间线,并对事实历史做计数和分组聚合。写入事实:断言或作废事实,均写入日志并以取代而非覆盖的方式处理,也可先审阅抽取候选再断言。跟踪会话:查看智能体上次连接以来发生的全部变化,并列出重要但正在淡忘的段落供复习。维护笔记库:追加带时间戳的收件箱条目、标记段落已被使用、运行整合报告并触发重建索引。
适用场景
当助手需要在你已有的笔记之上跨会话保留持久、可审计的记忆时使用,尤其适合需要知道某个过去日期事实为真、或当时人们相信什么的情况。适用于 Obsidian 或普通 markdown 笔记库,且希望检索时不把内容发送给托管记忆服务。
运行要求
本地 Node.js 22 或更高版本运行时,以及一个 markdown 笔记文件夹;服务器以本地 stdio 进程通过 npx 启动,并需指定笔记库路径。原生依赖 better-sqlite3 在 npm 12 上可能需要 allow-scripts 参数。无需账号、API 密钥或网络访问;通过 Ollama 使用本地嵌入模型是可选项。
安装前请注意
助手可以写入你的笔记库:断言的事实、收件箱记录和整合摘要会追加到 lore 目录下,但不会修改用户自己的 markdown。通过 MCP 记录的事实会以智能体声明的来源标注,建议人工复核。可选的本地嵌入需要另外运行一个模型服务。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Loreweave,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

Loreweave

A temporal knowledge engine for markdown vaults.
It indexes, links, remembers, forgets, and dreams — locally, over files you own.

[npm] [CI] [node >= 22] [MIT]

Quickstart · What it does · CLI · Agent memory · Benchmarks · How it works · Research


[loreweave demo: temporal search, timeline, as-of facts, session resume]

Most knowledge tools are write-only. You capture diligently, the vault grows, and six months later you can't find the thing you know you wrote — because retrieval is keyword search over prose, nothing ever resurfaces on its own, and nothing notices when what you wrote last year stopped being true.

Loreweave is the layer that fixes that. Point it at a folder of markdown (Obsidian or plain) and it builds a knowledge graph, a bitemporal fact store, and a memory model over your notes — then hands them to you through a CLI and to your AI agents through MCP.

Three guarantees, enforced by the code rather than promised:

  • Your files win. User markdown is never mutated; the engine only appends, and only under lore/. The vault is the source of truth — the index is a cache you can delete at any time and rebuild identically (there's a test for that).
  • No LLM anywhere in the core. Indexing and retrieval use zero tokens and make zero network calls. Same vault, same query, same answer — forever.
  • Memory you can read. Every fact an agent stores is a markdown line you can open, edit, and git diff.

Quickstart

bash
npm i -g --allow-scripts=better-sqlite3 loreweave   # the flag is for npm 12: see Requirementscd ~/my-vaultlore init          # creates .lore/lore index         # incremental sync; one changed note: 32 ms at 1k notes, 656 ms at 20k (see Scale)
lore search "why did we drop the queue design"lore ask "what's the status of project atlas"lore dream         # what's duplicated, contradicted, stale, unlinked

Zero configuration and no network: out of the box it runs on BM25 + knowledge-graph spreading activation. Add local embeddings when you want them:

jsonc
// .lore/config.json{ "embedding": { "provider": "ollama", "model": "mxbai-embed-large" } }

Pick mxbai-embed-large (670 MB) for quality or nomic-embed-text (274 MB) when disk and indexing speed matter more — required task prefixes are applied automatically for both, and for the E5, BGE and Arctic families. The measured difference between the two is in Benchmarks. No embedding provider means lexical + graph retrieval, still fully functional.

Works with non-English vaults: Chinese, Japanese and Korean text is segmented per character so it is searchable at all, and other scripts index as written.

What it does

1. Knowledge that has a timeline. Facts are bitemporal: when they were true in the world (valid_from/valid_until) and when the system learned them (recorded_at). Contradictions supersede rather than overwrite, so history stays queryable.

bash
$ lore assert "Ledger Format" status draft --valid-from 2026-01-01$ lore assert "Ledger Format" status final --valid-from 2026-08-01✓ Ledger Format :: status :: final  superseded: "draft" (now valid until 2026-08-01)  journal: lore/journal/2026-08-01.md

(lore and loreweave are the same binary — the global install gives you both; npx --allow-scripts=better-sqlite3 loreweave runs it without installing.)

Both time axes are queryable, which is what makes it bitemporal rather than merely historical. --as-of asks what was true then; --as-known-at asks what was believed then. They disagree exactly when you learn something after the fact — which is when you most need to reconstruct what a past decision was actually based on:

bash
$ lore facts --subject Vendor --as-of 2024-06-01Vendor :: reliability :: poor — outage postmortem  (2024-01-01 → now)
$ lore facts --subject Vendor --as-known-at 2024-06-01Vendor :: reliability :: good  (2024-01-01 → 2024-01-01)  [superseded]

Which fact wins is decided deterministically (newest valid-time, provenance as tiebreak) — never by asking a language model which one looks fresher. And the whole history of anything is one command — every value change merged chronologically with the dated prose that mentions it:

bash
$ lore timeline Project Atlas2024-01-15  status: planning  (until 2024-09-01)2024-02-10  • [[Project Atlas]] kicked off with a three-person crew.  [kickoff.md]2024-09-01  status: planning → active2025-06-20  • The [[Project Atlas]] midpoint review went long but well.  [review.md]

Temporal-graph systems build this by running an LLM over every document at ingestion. Here the supersede chain has been maintained all along, so it is a read-side join: no LLM, no network, same answer every time.

2. Retrieval that follows connections, not just words. Queries fuse BM25, dense similarity (when configured), and Personalized PageRank over the vault's own graph — wiki-links, shared entities, tags, co-occurrence. Two-hop neighbors surface even when they share no vocabulary with your query, and every result tells you why:

• data/glacier-dataset.md#@0  (0.0327)  ⟨via amara osei⟩  The Glacier Dataset holds meltwater sensor readings from 2019-2024.

3. Memory with dynamics. Every passage carries FSRS-style stability and retrievability — a power-law forgetting curve. Passages that actually get used (not merely retrieved) decay slower; important-but-fading knowledge gets surfaced for review instead of silently rotting. Nothing is ever deleted.

4. It dreams. lore dream is an idle-time consolidation pass that reviews the vault and reports duplicate passages, contradicted facts, stale knowledge, missing links between notes that clearly belong together, and orphans. With --apply it writes a digest and a review queue — append-only, under lore/. It never rewrites your prose: LLM-driven whole-file rewriting is a documented failure mode — each rewrite quietly drops details until the file collapses to mush — so the architecture forbids it.

5. Questions retrieval can't answer. Counting, grouping, and date-range queries run as deterministic SQL over the fact store, not as vibes over embeddings:

bash
$ lore count --predicate trip_to --since 2025-01-01 --until 2025-12-31    2  Japan    1  Kenya

6. Facts come from your notes, not from a form. Nobody hand-writes - [fact] X :: y :: z, so the extractor mines the conventions vaults already use:

yaml
status: shipped              # frontmatter- owner:: Priya              # Dataview inline field- [location] Hyderabad       # Basic Memory observation

Only unambiguous field syntax is accepted automatically. Prose formatting like - **Owner:** Priya is precise on entity notes and noisy on report notes, so it is opt-in (facts.extract: "all") — or an agent can review candidates via lore_propose_facts and assert the real ones. Judgement stays out of the index.

7. Time means when it happened, not when you saved the file. --since and --until filter on content time — frontmatter dates, dated filenames (2025-03-14-standup.md), or dates in the text — falling back to file mtime only when a note carries no date of its own. lore watch keeps the index current so you never have to remember to reindex.

8. Built for agents. An MCP server exposes 15 typed tools so Claude Code, Cursor, or any MCP client can use your vault as durable memory. Session continuity is a query, not a paraphrase — lore resume returns exactly what changed since the agent last connected, computed from record time:

bash
$ lore resumesince 2026-08-11 15:55~ lore/journal/2026-08-11.md+ Project Atlas :: status :: shipped (since 2026-08-11)± Project Atlas :: status: active → shipped
$ lore resumesince 2026-08-11 15:56nothing changed

Alternatives that summarize the previous session with an LLM inject a paraphrase; this is a deterministic diff. Full setup in Agent memory.

The CLI

CommandWhat it does
lore initcreate .lore/ with a default config
lore index [--full] [--no-nlp] [--rebuild-similar]incremental sync of vault → index
lore search <q> [-k] [--since] [--until] [--tag] [--folder] [--json]hybrid retrieval with provenance
lore ask <q>extractive answer: current facts + top passages (no LLM needed)
lore facts [--subject] [--predicate] [--as-of] [--as-known-at] [--history] [--limit]query the fact store (200 rows unless --limit says otherwise; a capped list says how many it left out)
lore timeline <entity> [--since] [--until]chronological history: fact changes merged with dated mentions
lore resume [--since]what changed since the last resume: notes, facts, supersessions
lore review [--threshold] [--limit]important-but-fading knowledge to revisit or archive
lore assert <s> <p> <o…> [--valid-from]record a fact (journalled, supersedes)
lore invalidate <s> <p>close the current fact in a slot
lore count [--predicate] [--group-by] [--since]aggregate over fact history
lore capture <text…>append a timestamped line to lore/inbox.md
lore dream [--apply]consolidation pass + optional digest/review queue
lore watchreindex automatically as the vault changes
lore mark-used <note> [anchor]reinforce a passage that proved useful
lore graph export --format json|graphml|dotexport the graph
lore doctorhealth check: broken links, integrity, coverage
lore statsvault statistics and top entities
lore serve --mcpstart the MCP server on stdio

Use it as agent memory (MCP)

jsonc
// Claude Code: .mcp.json  (or claude_desktop_config.json){  "mcpServers": {    "loreweave": {      "command": "npx",      "args": ["--allow-scripts=better-sqlite3", "-y", "loreweave",               "--vault", "/path/to/vault", "serve", "--mcp"]    }  }}

The --allow-scripts argument is for npm 12; Requirements explains it, and how to clear an install npx already made without it.

ToolWhat the agent gets
lore_searchhybrid retrieval with provenance and temporal filters
lore_context_packone-call session context: relevant passages + current facts + recent changes
lore_read_notefull text of a note by path
lore_assert_fact / lore_invalidate_factwrite/close facts — journalled, superseding, never destructive
lore_query_factspoint-in-time fact queries (asOf, asKnownAt, history)
lore_timelinean entity's merged fact + prose chronology
lore_resumeexactly what changed since the agent last connected
lore_reviewimportant-but-fading passages worth resurfacing
lore_aggregate_factscount/group-by over fact history
lore_captureappend a timestamped line to the inbox
lore_mark_usedreinforcement signal: this passage actually helped
lore_propose_factsextraction candidates for the agent to review and assert
lore_dream_reportthe consolidation report (duplicates, contradictions, stale, orphans)
lore_indextrigger a reindex

Facts asserted through MCP are written back to lore/journal/YYYY-MM-DD.md as readable markdown, so an agent's memory is something you can open, edit, and git diff:

markdown
- [fact] Ledger Format :: status :: final {valid_from=2026-08-01, confidence=0.9, source=stated}

Delete .lore/ and reindex — every fact and edge is reconstructed from those files.

- [fact] lines are replayed out of any note, but the source= attribute is read back only under lore/journal/, which is the only path loreweave writes. The same line in an ordinary note still records the fact, as extracted — a note can state something; it cannot say that you stated it.

Compared to hosted memory services (Mem0, Zep): those run LLMs at write time to extract and summarize into their own store; loreweave runs no model in the core, keeps memory in your files under your version control, and makes every retrieval reproducible. The trade: they do abstractive summarization, this engine deliberately does not. Retrieval quality against their published benchmarks is below — with the caveats stated, because most published agent-memory numbers measure end-to-end QA with an LLM, which is a different quantity than retrieval.

Benchmarks

These are third-party benchmarks with relevance labels nobody here chose. All loreweave numbers are retrieval metrics — it finds the evidence, it does not write the answer — so they are not comparable to the end-to-end QA accuracy quoted by systems that put a language model after retrieval. Reproduce any number: docs/benchmarks.md. Field comparison with the traps called out: docs/scoreboard.md.

LongMemEval_S (ICLR 2025) — 500 questions, each with ~50 sessions of chat history; find the sessions holding the evidence. Session-level recall, all 500 questions:

configurationR@1R@5R@10
model-free (no embeddings, no network)0.5520.8990.943
+ embeddings & 8-turn chunking0.5900.9590.983

A third-party benchmark of the same task reports BM25 alone at 86.2% R@5, BM25+vector hybrid at 95.2%, and a vector-only system at 96.6%. One caveat before the comparison: their metric scores a question 1 if any gold session is retrieved, ours scores the fraction of gold sessions found — ours is the stricter definition, so treat cross-system gaps of under a point as noise. With that stated: at 95.9% loreweave is past the hybrid and just short of the vector-only system, with a local model, no network, and a lexical index it can fall back to.

BEIR / SciFact — 5 183 scientific abstracts, 300 claims, scored by nDCG@10 (ranking quality: rewards putting relevant documents nearer the top):

configurationnDCG@10Recall@10
BM25 baseline (BEIR paper, Anserini)0.665—
loreweave, model-free0.6810.817
loreweave + nomic-embed-text0.7270.865
loreweave + mxbai-embed-large0.7420.884

LoCoMo — 10 long conversations, 1 982 evidence-labelled questions, turn-level recall. No comparable third-party retrieval number exists (published LoCoMo results are LLM QA accuracy), so these are offered as a target rather than a comparison:

R@1R@5R@10R@20
model-free0.3370.5380.6100.656
+ embeddings0.3180.5320.6270.705

What the numbers say, plainly. Recall is strong and rank-1 is the weakness — LongMemEval R@10 0.983 vs R@1 0.590 — which is why figures here are quoted at R@5 and why an agent consuming these results should read a top-5 list, not trust rank 1. The single biggest quality lever measured is the embedding model itself: mxbai over nomic is worth more than every downstream tuning combined on document (BEIR) and session (LongMemEval) retrieval — and measures flat on LoCoMo's single-turn passages, so it is a scale effect, not magic. A cross-encoder reranker is available (rerank in config) but earns its keep only for rank-1 consumers without embeddings — stacked on embeddings it loses recall on both public benchmarks, so leave it off unless that trade is yours. Full analysis, including the failed experiments and the defect that benchmarking caught: docs/evaluation.md.

Loreweave also ships an internal regression benchmark (npm run eval) over three purpose-built vaults — including a temporal-perturbation test where the shipped config scores 100% consistency vs BM25's 0%, gated in CI on every push. Internal corpora are good for regression and worthless as proof, so the details live in docs/evaluation.md rather than here.

Scale

Measured, like the quality numbers — npm run scale reproduces this on your own machine (synthetic vaults, 3 blocks per note, dense interlinking):

notesblocksentitiesedgesfull indexincrementalsearch p50p95dreamheap
1 0003 0002 76617 k1.2 s32 ms3 ms4 ms0.2 s63 MB
5 00015 00013 76685 k6.1 s165 ms9 ms12 ms1.0 s145 MB
20 00060 00055 016339 k22.5 s656 ms38 ms53 ms4.8 s333 MB

Full index scales at 0.93× per note from 5 k to 20 k — linear or better, no superlinear step hiding in the middle. "Incremental" is one changed note, which is what lore watch actually does all day. Everything here is one process, one SQLite file, no daemon — and search at 3-38 ms p50 is fast enough to sit inside an agent loop.

How it works

vault/*.md ──parse──▶ notes · blocks · wiki-links · tags · entities                            │  (incremental: mtime + content hash)                            ▼                  SQLite .lore/index.db  ── disposable cache, rebuildable                            │        ┌───────────────────┼────────────────────┐        ▼                   ▼                    ▼   graph (CSR)         retrieval             facts   blocks ∪ entities   BM25 + dense + PPR    bitemporal, supersession,   2-iteration PPR     → weighted RRF        deterministic freshness,   α = 0.5             → FSRS boosts         aggregates        └─────────┬─────────┴──────────┬─────────┘                  ▼                    ▼             dream (idle-time)     CLI · MCP

Design rules the code enforces:

  • Files win. User markdown is never mutated. The engine only appends, and only under lore/.
  • Invariants in code, not prompts. Schema, migrations, graph construction, and supersession are typed, versioned, and tested — no LLM re-specifies them at runtime.
  • No LLM required anywhere in the core. Indexing and retrieval use zero tokens. Language models are consumers of this engine, not dependencies of it.
  • Everything is re-derivable. A full rebuild reproduces byte-identical derived state (there's a test for that).

Research lineage

Every significant choice traces to 2024-2026 literature; the survey lives in docs/research/.

ChoiceSource
Dense-sparse fusion + PPR with dense reset probabilitiesHippoRAG 2 (ICML 2025), 2502.14802
Shallow 2-iteration PPR, heterogeneous nodesNodeRAG (2025), 2504.11544
Relation-free graph — no LLM triple extractionLinearRAG (ICLR 2026), 2510.10114
No index-time community summarizationLazyGraphRAG (Microsoft, 2024) — same quality at 0.1% index cost
Route/fuse instead of graph-everythingGraphRAG-Bench (ICLR 2026), 2506.05690
Bitemporal facts, invalidate-never-deleteZep/Graphiti (2025), 2501.13956
Power-law forgetting, use-gated reinforcementFSRS; RMM (ACL 2025), 2503.08026
Consolidation as idle-time workSleep-time compute (Letta, 2025), 2504.13171
Never let an LLM rewrite whole memory filesACE (2025), 2510.04618
Computable facts for aggregationUser as Code (2026), 2606.16707
Fine-grained indexing + fact-augmented keysLongMemEval (ICLR 2025), 2410.10813

Library use

ts
import { openContext, indexVault, search, assertFact, queryFacts, dream } from 'loreweave';
const ctx = openContext('/path/to/vault');await indexVault(ctx.store, ctx.root);const hits = await search(ctx, 'streaming compaction', { k: 5 });assertFact(ctx, { subject: 'Atlas', predicate: 'status', object: 'shipped', validFrom: '2026-08-01' });const asOfMarch = queryFacts(ctx.store, { subject: 'Atlas', asOf: '2026-03-01' });const report = dream(ctx);ctx.close();

Development

bash
npm installnpm run build     # the stdio-server tests run the built CLI, and skip without itnpm test          # 546 testsnpm run eval      # retrieval benchmark vs BM25 baselinenpm run typecheck

Requirements

Node 22 or later. Tested in CI on Linux, macOS and Windows across Node 22, 24 and 26. The single native dependency, better-sqlite3, installs from a prebuilt binary on macOS, Linux and Windows with Node 22, 24, 25 or 26 — no compiler needed. Node 23 has none, so there npm compiles it from source, which needs a C++ toolchain.

npm 12 no longer runs a dependency's install script unless told to, and better-sqlite3 fetches its binary in one: without --allow-scripts=better-sqlite3 the install succeeds, but every command that opens the index fails with "Could not locate the bindings file". npm 10 and 11, which Node 22, 24 and 26 ship with, need nothing, and accept the flag with npm i -g and npx.

  • npm i -g and npx take the flag, as in Quickstart and the MCP config.
  • npx keeps reusing an install it made without the flag, even once you add it: find that install with npm cache npx ls and remove it with npm cache npx rm <key>.
  • In a project — your own, or a clone of this repository — npm 12 refuses the flag, and so does npm 11 from 11.16 on, which Node 24 and 26 ship with. npm 11 runs the script without it. On npm 12, approve the script instead with npm approve-scripts better-sqlite3, which records it under allowScripts in package.json, then run npm rebuild better-sqlite3.

License

MIT © Ambuj Upadhyay

来源:README.md,提交 303a418

工具

0
SourceWeft 尚未在沙箱中启动过该软件包,因此其工具未知。

版本历史

4
  1. v0.39.0最新Oct 9, 2026
  2. v0.38.0Sep 25, 2026
  3. v0.37.2Sep 22, 2026
  4. v0.36.1Sep 16, 2026

评分

已满足适用检查项的 50%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分

    请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。

  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具15 分

    请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。

  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分