Graph Memory — локальный граф знаний (offline)
Запрашиваемый граф поверх твоей памяти. Ноль сети, ноль туннелей — один Python-скрипт
и один SQLite-файл. Отвечает на многохоповые вопросы («кто/что/как связано с X»,
«хронология», «мои кейсы по проекту»), которые линейный поиск по заметкам не тянет.
Два пути, один движок:
- MCP-инструменты
graph_build, graph_stats, graph_neighbors, graph_path,
graph_timeline, graph_hubs, graph_orphans, graph_search, graph_cases,
graph_dangling, graph_gaps — сервер graph-memory включён в settings.json по умолчанию.
- CLI — то же самое из терминала:
python ~/.claude/scripts/memory_graph.py {build|stats|neighbors|path|timeline|hubs|orphans|search|dangling|cases|gaps} [args]
Хранилище: ~/.claude/memory-graph/graph.db (SQLite). Размер бери из stats, не хардкодь.
Актуальность: снимок на момент последнего build (обычно прогоняется в dream).
Первый запуск — база едет пустой
Граф собирается из твоих заметок; вместе с паком не приезжает ничего, кроме движка.
Пока ты не написал ни одной заметки, любая команда честно вернёт ноль — это не поломка.
# 1. Заметки живут здесь. Каталог создаётся при первой записи через memory-agent.
ls ~/.claude/projects/*/memory/*.md # пусто — значит писать ещё нечего
# 2. Собрать граф (создаст ~/.claude/memory-graph/graph.db)
python ~/.claude/scripts/memory_graph.py build
# 3. Убедиться, что он видит заметки
python ~/.claude/scripts/memory_graph.py stats
nodes=0 после build при непустой папке заметок — смотри, есть ли у файлов frontmatter
name/type и [[wikilinks]]: узлы и рёбра берутся оттуда.
Когда использовать
- Вопрос о ПРОШЛОМ: решения, грабли, статусы проектов, «что мы делали с X», «с кем работал над Y».
- Нужна связь через несколько шагов: «как связаны A и B», путь между сущностями.
- Хронология замен/решений: «что заместило старую заметку», «timeline проекта».
- Обзорные: топ-хабы памяти, орфаны (несвязанные заметки), висячие ссылки (кандидаты на новую заметку).
- Каталог кейсов: «покажи мои сессии по проекту X» (если у тебя собран Layer 2, см. ниже).
Для полнотекстового поиска по сырым чатам — ~/.claude/tools/search_chats.py (другой
инструмент). Граф отвечает на структурные и связевые вопросы, не на «найди фразу».
Граница с memory-agent, save-knowledge-base, dream — все четыре про одну память.
Этот навык только читает: он не пишет ни одной заметки и не меняет ни одного файла
(кроме build, который пересобирает снимок). Поэтому любая просьба «запомни» сюда не
попадает: готовый документ с названными триггерами → save-knowledge-base, наблюдение
без явного места → memory-agent (он выберет слой). Прибраться в уже записанном → dream;
он же обычно и прогоняет build, так что свежесть графа — его работа, не твоя. Правило:
вопрос про СВЯЗИ и хронологию → сюда; «найди фразу» → search_chats.py; любое
«запомни» → save-knowledge-base/memory-agent.
Что внутри графа (модель данных)
Две склеенные схемы в одной БД.
Layer 1 — курированные заметки (~/.claude/projects/<project>/memory/*.md) — работает
сразу, ничего настраивать не нужно:
- Узел = заметка.
id = frontmatter name или имя файла. Тип из frontmatter type:
user / feedback / project / reference / memory.
- Рёбра:
[[wikilinks]] → rel=link; frontmatter supersedes/superseded_by →
rel=supersedes (bi-temporal: факт не удаляем, а замещаем).
Layer 2 — кейсбук из истории чатов (~/_casebook/) — опционально. Пака он не
касается: движок ищет каталог, не находит и молча собирает граф из одного Layer 1.
Если ты выгружаешь свои сессии в такой формат сам, схема ожидается такая:
- Узлы-сущности с префиксами:
case:<session_id> (сессия-кейс), proj:<name>,
person:<Имя>, company:<X>, tool:<Y>.
- Рёбра:
involves (case→person), for_company (case→company), uses (case→tool),
in_project / in_cluster (case→proj).
- Файлы:
all_cards_v2.json и/или cards_db/*.json, сущности entities_v1/*.json,
кластеры clusters.json, канон-карты имён canon/*_map.json.
- L1↔L2 мост:
about — заметка → proj: по дистинктивному ключу в имени-слаге.
Имена сущностей нормализуются канон-картами (вариант→канон), поэтому «Alexander Smith»
и «Александр Смирнов» схлопываются в один узел — при условии, что маппинг в карте есть.
Команды
| Команда |
Что делает |
stats |
Узлы/рёбра, разбивка по типам и rel, orphans, dangling. Всегда отсюда бери свежие цифры. |
search <substr> |
Узлы по подстроке имени или заголовка (до 40). Первый шаг: найти точное имя узла. |
neighbors <name> [depth] |
Соседи узла на глубину depth (по умолч. 1). Помечает цели без заметки. |
path <a> <b> |
Кратчайший путь между двумя узлами (BFS, ненаправленный). |
timeline <name> |
Цепочка supersedes: что узел заместил и кем замещён (bi-temporal история). |
cases <substr> |
Кейсы (сессии) по проекту/подстроке — каталог «мои сессии по X» (нужен Layer 2). |
hubs [N] |
Топ-N самых связанных узлов (центры тяжести памяти). |
orphans |
Узлы без единого ребра — не вплетены в граф. |
dangling |
[[ссылки]] на несуществующие узлы — кандидаты завести заметку. |
gaps [stale_days] |
Gap-анализ (0 LLM): orphans + dangling + stale-hubs + superseded-unmarked. Порог устаревания по умолч. 45 дней. |
build |
Пересобрать граф из заметок (+ кейсбука, если есть). Прогоняется в dream; вручную — после крупной правки памяти. |
Имена узлов часто содержат пробелы, кириллицу и префиксы (proj:, person:) — оборачивай в кавычки:
python ~/.claude/scripts/memory_graph.py neighbors "person:Мария Иванова" 2
Процедура (типовой запрос)
- Найди узел. Точного имени обычно не знаешь →
search <подстрока>. Возьми name из вывода.
- Выбери обход под вопрос:
- «что связано / кто рядом» →
neighbors <name> [depth] (depth 2 для второго кольца).
- «как связаны A и B» →
path <A> <B>.
- «что заместило / хронология» →
timeline <name>.
- «мои сессии по проекту» →
cases <project>.
- «центры / что забыто» →
hubs, orphans, dangling, gaps.
- Синтезируй — прочитай реальные заметки и кейсы по путям, не пересказывай сам граф.
Файл заметки лежит в колонке
file таблицы nodes; кейс — по jsonl_path.
- Применяй невидимо — как собственный опыт, без «судя по графу памяти»
(если не спросили источник).
Выход
Скрипт печатает plain-text в stdout (UTF-8, форсится под Windows-консоль). Примеры формата:
neighbors: d1 <src> --<rel>--> <dst> (плюс (нет заметки) для висячих целей).
path: A -> X -> B или нет пути A .. B.
stats: nodes=… edges=…, затем словари by type / by rel.
Пример
Подставь свои имена — граф знает только то, что ты в него записал.
# 1. найти узел
python ~/.claude/scripts/memory_graph.py search MyProject
# proj:MyProject -- MyProject
# case:... -- 2026-06-… [MyProject] …
# 2. второе кольцо связей проекта
python ~/.claude/scripts/memory_graph.py neighbors "proj:MyProject" 2
# 3. как связаны компания и проект
python ~/.claude/scripts/memory_graph.py path "company:SomeCorp" "proj:MyProject"
# 4. все мои сессии по проекту
python ~/.claude/scripts/memory_graph.py cases MyProject
# 5. что память НЕ знает / где дыры
python ~/.claude/scripts/memory_graph.py gaps 30
Чек-лист
Файлы
~/.claude/scripts/memory_graph.py — единственный движок (build + все запросы).
~/.claude/mcps/graph-memory/server.py — тонкая MCP-обёртка над тем же движком.
~/.claude/memory-graph/graph.db — SQLite-снимок (nodes, edges). Создаётся первым build.
~/.claude/projects/<project>/memory/*.md — источник Layer 1 (заметки).
~/_casebook/ — источник Layer 2, опционально (см. выше).
references/gbrain-typed-edges-gap-analysis.md — откуда взялся gaps и что решили не тянуть.
Известные ограничения (honest)
- Снимок, не live. Граф отражает состояние на момент последнего
build. Свежие заметки
появятся в нём только после пересборки.
- База приезжает пустой. Первые дни граф будет отвечать «ничего не найдено» — это
нормально, ему нечего показывать, пока нет заметок.
- Нормализация имён неполна. Схлопывание вариантов работает лишь для того, что есть
в канон-картах; незамапленные варианты остаются отдельными узлами.
path ненаправленный. BFS игнорирует направление и тип ребра — путь может проходить
через слабую связь about/link.
- Layer 2 никто за тебя не соберёт. Без
~/_casebook/ команда cases вернёт пусто,
остальные работают.
- Инкрементальных апдейтов нет — только полная пересборка
build.
1---2name: graph-memory3description: Локальный граф твоей памяти (SQLite, офлайн): соседи, пути, хронология, хабы, разрывы. Триггеры: «что связано с», «хронология проекта», «мои сессии по проекту», «висячие ссылки в памяти». НЕ: уборка→dream; запись→memory-agent; поиск фразы→search_chats.py.4---56# Graph Memory — локальный граф знаний (offline)78Запрашиваемый граф поверх твоей памяти. Ноль сети, ноль туннелей — один Python-скрипт9и один SQLite-файл. Отвечает на многохоповые вопросы («кто/что/как связано с X»,10«хронология», «мои кейсы по проекту»), которые линейный поиск по заметкам не тянет.1112**Два пути, один движок:**1314- **MCP-инструменты** `graph_build`, `graph_stats`, `graph_neighbors`, `graph_path`,15 `graph_timeline`, `graph_hubs`, `graph_orphans`, `graph_search`, `graph_cases`,16 `graph_dangling`, `graph_gaps` — сервер `graph-memory` включён в `settings.json` по умолчанию.17- **CLI** — то же самое из терминала:18 `python ~/.claude/scripts/memory_graph.py {build|stats|neighbors|path|timeline|hubs|orphans|search|dangling|cases|gaps} [args]`1920**Хранилище:** `~/.claude/memory-graph/graph.db` (SQLite). Размер бери из `stats`, не хардкодь.21**Актуальность:** снимок на момент последнего `build` (обычно прогоняется в `dream`).2223## Первый запуск — база едет пустой2425Граф собирается из **твоих** заметок; вместе с паком не приезжает ничего, кроме движка.26Пока ты не написал ни одной заметки, любая команда честно вернёт ноль — это не поломка.2728```bash29# 1. Заметки живут здесь. Каталог создаётся при первой записи через memory-agent.30ls ~/.claude/projects/*/memory/*.md # пусто — значит писать ещё нечего3132# 2. Собрать граф (создаст ~/.claude/memory-graph/graph.db)33python ~/.claude/scripts/memory_graph.py build3435# 3. Убедиться, что он видит заметки36python ~/.claude/scripts/memory_graph.py stats37```3839`nodes=0` после `build` при непустой папке заметок — смотри, есть ли у файлов frontmatter40`name`/`type` и `[[wikilinks]]`: узлы и рёбра берутся оттуда.4142## Когда использовать4344- Вопрос о ПРОШЛОМ: решения, грабли, статусы проектов, «что мы делали с X», «с кем работал над Y».45- Нужна связь через несколько шагов: «как связаны A и B», путь между сущностями.46- Хронология замен/решений: «что заместило старую заметку», «timeline проекта».47- Обзорные: топ-хабы памяти, орфаны (несвязанные заметки), висячие ссылки (кандидаты на новую заметку).48- Каталог кейсов: «покажи мои сессии по проекту X» (если у тебя собран Layer 2, см. ниже).4950Для полнотекстового поиска по сырым чатам — `~/.claude/tools/search_chats.py` (другой51инструмент). Граф отвечает на структурные и связевые вопросы, не на «найди фразу».5253> **Граница с `memory-agent`, `save-knowledge-base`, `dream` — все четыре про одну память.**54> Этот навык **только читает**: он не пишет ни одной заметки и не меняет ни одного файла55> (кроме `build`, который пересобирает снимок). Поэтому любая просьба «запомни» сюда не56> попадает: готовый документ с названными триггерами → `save-knowledge-base`, наблюдение57> без явного места → `memory-agent` (он выберет слой). Прибраться в уже записанном → `dream`;58> он же обычно и прогоняет `build`, так что свежесть графа — его работа, не твоя. Правило:59> **вопрос про СВЯЗИ и хронологию → сюда; «найди фразу» → `search_chats.py`; любое60> «запомни» → `save-knowledge-base`/`memory-agent`.**6162## Что внутри графа (модель данных)6364Две склеенные схемы в одной БД.6566**Layer 1 — курированные заметки** (`~/.claude/projects/<project>/memory/*.md`) — работает67сразу, ничего настраивать не нужно:6869- Узел = заметка. `id` = frontmatter `name` или имя файла. Тип из frontmatter `type`:70 `user` / `feedback` / `project` / `reference` / `memory`.71- Рёбра: `[[wikilinks]]` → `rel=link`; frontmatter `supersedes`/`superseded_by` →72 `rel=supersedes` (bi-temporal: факт не удаляем, а замещаем).7374**Layer 2 — кейсбук из истории чатов** (`~/_casebook/`) — **опционально**. Пака он не75касается: движок ищет каталог, не находит и молча собирает граф из одного Layer 1.76Если ты выгружаешь свои сессии в такой формат сам, схема ожидается такая:7778- Узлы-сущности с префиксами: `case:<session_id>` (сессия-кейс), `proj:<name>`,79 `person:<Имя>`, `company:<X>`, `tool:<Y>`.80- Рёбра: `involves` (case→person), `for_company` (case→company), `uses` (case→tool),81 `in_project` / `in_cluster` (case→proj).82- Файлы: `all_cards_v2.json` и/или `cards_db/*.json`, сущности `entities_v1/*.json`,83 кластеры `clusters.json`, канон-карты имён `canon/*_map.json`.84- L1↔L2 мост: `about` — заметка → `proj:` по дистинктивному ключу в имени-слаге.8586Имена сущностей нормализуются канон-картами (вариант→канон), поэтому «Alexander Smith»87и «Александр Смирнов» схлопываются в один узел — **при условии**, что маппинг в карте есть.8889## Команды9091| Команда | Что делает |92|---------|-----------|93| `stats` | Узлы/рёбра, разбивка по типам и rel, orphans, dangling. **Всегда отсюда бери свежие цифры.** |94| `search <substr>` | Узлы по подстроке имени или заголовка (до 40). Первый шаг: найти точное имя узла. |95| `neighbors <name> [depth]` | Соседи узла на глубину depth (по умолч. 1). Помечает цели без заметки. |96| `path <a> <b>` | Кратчайший путь между двумя узлами (BFS, ненаправленный). |97| `timeline <name>` | Цепочка `supersedes`: что узел заместил и кем замещён (bi-temporal история). |98| `cases <substr>` | Кейсы (сессии) по проекту/подстроке — каталог «мои сессии по X» (нужен Layer 2). |99| `hubs [N]` | Топ-N самых связанных узлов (центры тяжести памяти). |100| `orphans` | Узлы без единого ребра — не вплетены в граф. |101| `dangling` | `[[ссылки]]` на несуществующие узлы — кандидаты завести заметку. |102| `gaps [stale_days]` | Gap-анализ (0 LLM): orphans + dangling + stale-hubs + superseded-unmarked. Порог устаревания по умолч. 45 дней. |103| `build` | Пересобрать граф из заметок (+ кейсбука, если есть). Прогоняется в `dream`; вручную — после крупной правки памяти. |104105Имена узлов часто содержат пробелы, кириллицу и префиксы (`proj:`, `person:`) — оборачивай в кавычки:106`python ~/.claude/scripts/memory_graph.py neighbors "person:Мария Иванова" 2`107108## Процедура (типовой запрос)1091101. **Найди узел.** Точного имени обычно не знаешь → `search <подстрока>`. Возьми `name` из вывода.1112. **Выбери обход** под вопрос:112 - «что связано / кто рядом» → `neighbors <name> [depth]` (depth 2 для второго кольца).113 - «как связаны A и B» → `path <A> <B>`.114 - «что заместило / хронология» → `timeline <name>`.115 - «мои сессии по проекту» → `cases <project>`.116 - «центры / что забыто» → `hubs`, `orphans`, `dangling`, `gaps`.1173. **Синтезируй** — прочитай реальные заметки и кейсы по путям, не пересказывай сам граф.118 Файл заметки лежит в колонке `file` таблицы nodes; кейс — по `jsonl_path`.1194. **Применяй невидимо** — как собственный опыт, без «судя по графу памяти»120 (если не спросили источник).121122## Выход123124Скрипт печатает plain-text в stdout (UTF-8, форсится под Windows-консоль). Примеры формата:125126- `neighbors`: `d1 <src> --<rel>--> <dst>` (плюс `(нет заметки)` для висячих целей).127- `path`: `A -> X -> B` или `нет пути A .. B`.128- `stats`: `nodes=… edges=…`, затем словари `by type` / `by rel`.129130## Пример131132Подставь свои имена — граф знает только то, что ты в него записал.133134```bash135# 1. найти узел136python ~/.claude/scripts/memory_graph.py search MyProject137# proj:MyProject -- MyProject138# case:... -- 2026-06-… [MyProject] …139140# 2. второе кольцо связей проекта141python ~/.claude/scripts/memory_graph.py neighbors "proj:MyProject" 2142143# 3. как связаны компания и проект144python ~/.claude/scripts/memory_graph.py path "company:SomeCorp" "proj:MyProject"145146# 4. все мои сессии по проекту147python ~/.claude/scripts/memory_graph.py cases MyProject148149# 5. что память НЕ знает / где дыры150python ~/.claude/scripts/memory_graph.py gaps 30151```152153## Чек-лист154155- [ ] Сначала `search` → взял точное `name`, а не угадал.156- [ ] Имена с пробелами/префиксом/кириллицей — в кавычках.157- [ ] Цифры (узлы/типы) — из `stats`, не по памяти и не из этого файла.158- [ ] Прочитал реальные заметки и кейсы по найденным путям перед ответом.159- [ ] Чувствительное (семья, финансы, здоровье, конфликты) первым не поднимал, пока160 владелец памяти сам не затронул тему.161- [ ] После крупной правки памяти или если граф выглядит устаревшим — `build`162 (обычно это делает `dream`).163164## Файлы165166- `~/.claude/scripts/memory_graph.py` — единственный движок (build + все запросы).167- `~/.claude/mcps/graph-memory/server.py` — тонкая MCP-обёртка над тем же движком.168- `~/.claude/memory-graph/graph.db` — SQLite-снимок (nodes, edges). Создаётся первым `build`.169- `~/.claude/projects/<project>/memory/*.md` — источник Layer 1 (заметки).170- `~/_casebook/` — источник Layer 2, опционально (см. выше).171- `references/gbrain-typed-edges-gap-analysis.md` — откуда взялся `gaps` и что решили не тянуть.172173## Известные ограничения (honest)174175- **Снимок, не live.** Граф отражает состояние на момент последнего `build`. Свежие заметки176 появятся в нём только после пересборки.177- **База приезжает пустой.** Первые дни граф будет отвечать «ничего не найдено» — это178 нормально, ему нечего показывать, пока нет заметок.179- **Нормализация имён неполна.** Схлопывание вариантов работает лишь для того, что есть180 в канон-картах; незамапленные варианты остаются отдельными узлами.181- **`path` ненаправленный.** BFS игнорирует направление и тип ребра — путь может проходить182 через слабую связь `about`/`link`.183- **Layer 2 никто за тебя не соберёт.** Без `~/_casebook/` команда `cases` вернёт пусто,184 остальные работают.185- **Инкрементальных апдейтов нет** — только полная пересборка `build`.