graph-memory-starter README

The project's README from github.com/Glitch-Cat-Club/graph-memory-starter. As one markdown file: README.md.

graph-memory-starter

A knowledge graph your AI assistant reads before it answers. Three SQLite tables, one recursive query, one prompt hook. No server, no API key. Purpose: demonstrate the design's effectiveness so you can apply it to your own system.

Which one

rag/    works on notes as they are, matches meaning when words differ
graph   modelled docs, typed links, multi-hop answers walked by code

Start with rag/. Move up when your questions chain facts across documents and you are willing to model for it.

Set up

Two pastes, both for Claude Code, opened in the folder you keep your notes in. The first is the RAG. The second is the digest, which turns every session you close into a note the RAG can find.

Check Python first. In a terminal, try python3 --version, then python --version, then py --version. One of them prints a 3.x version. If none does, install Python from python.org with "Add to PATH" ticked.

Paste one, the RAG

Set up the memory starter for me, one step at a time, and stop if a step fails.
1. Check Python 3.10 or newer runs here (try python3, python, then py). If none runs, or the one that runs is older than 3.10, stop and tell me to install it from python.org with "Add to PATH" ticked.
2. Clone https://github.com/Glitch-Cat-Club/graph-memory-starter into a folder called memory-starter here, inside this folder and nowhere else (no git installed: download the zip from that page and unzip it as memory-starter). Then run: python -m pip install fastembed
3. Ask me which folder my markdown notes are in. Then run: python memory-starter/rag/build_index.py --corpus <that folder>
4. Run: python memory-starter/rag/search.py "a question about my notes" and show me the top hits.
5. Merge the recall hook from memory-starter/rag/hooks.json into .claude/settings.json here. Keep any permissions and model already in it. Use python3 in the hook command if that is the one that runs.
6. Tell me in five lines what you did, and how to rebuild the index when I add notes.

Then /exit and open Claude Code again, so the hook loads.

Paste two, the digest

Add the digest to my memory starter, one step at a time, and stop if a step fails.
1. Merge the three hooks from memory-starter/digest/hooks.json into .claude/settings.json here. Keep everything already in it, including the recall hook from lesson 1. Use python3 in the hook commands if that is the one that runs.
2. Open memory-starter/digest/config.json. It ships as "session". If claude -p runs from this folder (try: claude -p "say ok"), set "mode" to "headless". If it does not, leave it and tell me.
3. Tell me in three lines where the daily log will land and how to switch the digest off.

Then /exit and open Claude Code again.

Which model does what

bge-small-en-v1.5   local, 67 MB, your CPU, no key. Turns text into a
                    384-dim vector for the meaning leg of the search. Downloaded
                    once on the first index build, by fastembed.
Claude              distils a note into questions, writes the session
                    entry, answers you. Through claude -p on your
                    subscription, so no API key here either.

Markdown files, subfolders included. Hidden folders, .git, node_modules, __pycache__ and this starter's own folder are skipped, so a starter cloned inside your notes never indexes itself.

The two digest modes

session    the filtered text waits in digest/pending/. Your next session
           hands it to a background sub-agent, so you carry on working.
headless   the hook starts claude -p with no window. The entry lands about
           a minute later, and your next session opens clean.

One switch, "mode" in digest/config.json. Headless needs claude on your PATH.

The dials

All of them are one line in digest/config.json, apart from the voice, which is digest/digest-prompt.md.

max_turns    30       how much of the session is read
max_chars    15000    the character budget, the end kept
min_turns    5        below this the session is not memory
model        sonnet   which Claude writes the entry
log_dir      daily    the folder inside your notes the entry lands in
distil       true     whether the entry feeds the index
mode         session  session or headless

What is kept from a session is not a dial, it is code: your words and the replies. Tool calls, results, file dumps and thinking are dropped before any model reads it, so nothing is judged out by mistake.

Switch it off

Take the hook entries back out of .claude/settings.json, the recall hook and the three digest ones. Your notes, your logs and the index all stay, and the index rebuilds any time.

Prerequisites

Python 3, SQLite included. Claude Code, or another assistant with prompt hooks. For the meaning leg of the search, python -m pip install fastembed. Without it the search runs keyword only and says so. The graph half needs nothing installed.

Layout

rag/               the semantic layer: index, search, recall hook, distil
digest/            the session write up: hooks, config, prompt
corpus/            8 modelled docs (front matter)
corpus-before/     12 unstructured docs (the A/B control)
extraction/        LLM output per doc: nodes, edges, aliases
src/               schema.sql, build_graph.py, recall.py, recall_hook.py
hooks.json         the graph recall hook, copy into .claude/settings.json
extract-prompt.md  the extraction prompt, for your own docs

Modelling

Ontology: a closed vocabulary, fixed before writing any doc. Entity types: PERSON, ROLE, POLICY, PROCESS, DOCUMENT. Relationships: approved_by, held_by, delegates_to, part_of, references. Logical model: entities with hashed identity (uuid5 of type + name), typed relations carrying their source doc, aliases for name variants. Each doc declares its type, entities and links in front matter. Apply the same design to your own docs; your AI assistant can do the extraction.

Run

python src/build_graph.py
python src/recall.py "A customer wants an £800 refund in March. Who signs it off?"

Wire hooks.json and the same lookup runs before every prompt, injected as context.

Test cases

Question Expected Why
A customer wants an £800 refund in March. Who signs it off? Marcus Webb 3 hops: policy, role, holder, delegate
Who approves supplier payments over £2,000? Alex Doyle 2 hops: policy, role, holder
What is the onboarding process? Ops Manager, day-one checklist 1 hop, several edges
What does Priya do? Support Lead alias seeding
Who is in charge when the boss is away? no memory matches outside the vocabulary; fails loudly, never guesses

Evals

Glitch Cat Club evals, Aug 2026. One question, three model tiers, two conditions. The answer needs a 3-hop chain: policy -> role -> holder -> delegate.

Search condition: ask in corpus-before/, no hook. Tooling: the model drives Grep and Read itself. Graph condition: wire hooks.json and ask. Tooling: a SQLite recursive query runs inside the hook before the model is invoked; the model receives the result as text. Reproduce both yourself.

Model Condition Tooling Result Hops reached Tool calls Docs read Context read
Fable 5 search Grep+Read, model correct 3 of 3 6 4 ~780 tokens
Fable 5 graph SQL walk, code correct 3 of 3 0 0 ~400 tokens
Sonnet search Grep+Read, model correct 3 of 3 13 8 ~1180 tokens
Sonnet graph SQL walk, code correct 3 of 3 0 0 ~400 tokens
Haiku search Grep+Read, model wrong 1 of 3 5 3 ~660 tokens
Haiku graph SQL walk, code correct 3 of 3 0 0 ~400 tokens

Retrieval: 2 ms per query. The ~400-token injection is fixed at any corpus size; search reads grow with it. Live terminal runs: 20 s of visible searching vs an answer that starts immediately after the 2 ms recall line.

In the graph condition the model does no retrieval. Zero tool calls, zero searching, zero multi-hop reasoning: the traversal ran as code before the model was invoked, and the model reads the injected facts and states the answer. Proof: the smallest model reaches 1 of 3 hops searching, and 3 of 3 through the graph, because the graph walks the hops, never the model. Two places a model still exists: one call speaks the final answer, and a strong model built the graph once at write time. Spend intelligence at build; answer from structure.

graph-memory-starter (Glitch-Cat-Club/graph-memory-starter)

Searching Database…

这是什么?一个为 AI 助手打造的知识图谱记忆层,仅由三张 SQLite 表和一个递归查询构成,让你的助手在开始搜索之前就能回答关于你笔记的多跳问题。
这是要安装的插件,还是粘贴进 Claude Code 的代码片段?它是两段粘贴到笔记文件夹内 Claude Code 设置中的提示钩子片段,背后由负责索引和图查询的本地 Python 脚本支撑——没有需要安装的软件包。
怎么让记忆钩子跑起来?粘贴 RAG 片段,运行 /exit 并重新打开 Claude Code 让钩子加载,然后粘贴摘要片段并再次重启;之后运行 `python src/buildgraph.py` 来构建图谱。
除了 Claude Code 和 Python,我还需要别的吗?你需要 Python 3(自带 SQLite)和一个支持提示钩子的助手;要使用语义搜索层,还需要 `pip install fastembed`,它会在本地下载 67MB 的 bge-small-en-v1.5 模型。
如果我跳过 fastembed,或者没有好好为文档建模,会发生什么?没有 fastembed,搜索会退化为仅关键词匹配;而图谱部分只有在你为文档建模了本体(实体类型、关系)之后才能工作;无头摘要模式还要求 `claude` 位于你的 PATH 中。
我的笔记数据会离开我的机器吗?不会——一切都针对你自己的笔记在本地运行,不依赖外部服务器或 API 密钥;嵌入在你的 CPU 上计算,LLM 调用则通过 `claude -p` 走你现有的 Claude 订阅。
我应该从 rag/ 文件夹开始,还是从 graph/ 开始?从 rag/ 开始即可,它按原样在笔记之间匹配语义;只有当你的问题需要串联多个文档中的事实,并且你愿意为此建模本体时,再转向图谱方案。
会话模式和无头摘要模式有什么区别?会话模式下摘要文本会先等待,由你下一次会话的后台子智能体写入笔记;无头模式下钩子会在你关闭后立即静默运行 `claude -p`,让你回来之前条目就已就绪。
图谱方案真的有用,还是白费功夫?在该项目的评估中,最小的模型用普通搜索只能完成 3 跳推理中的 1 跳,而用图谱则能完成全部 3 跳,因为 SQLite 递归查询在模型看到问题之前就在代码中完成了多跳遍历。
我能关闭记忆系统而不丢笔记吗?可以——从 `.claude/settings.json` 中删除那四个钩子条目即可禁用召回和摘要功能,但你的笔记、日志和索引都保持原样,索引随时可以重建。
Size
<0.1 MB
Stars
245
Updated
CommitAug 30
Age
2mo
Commits · 90 Days