18 KiB
Как пользоваться memo
Инструкция для человека. Без внутренностей — только что делать руками.
Смысл одной фразой: вы пишете обычные markdown-файлы, а memo рядом с ними отвечает на вопросы
по смыслу — не по словам, а по содержанию, и не отправляя ничего в интернет.
1. Что это и зачем
У вас есть папка с заметками. Обычные .md-файлы, обычные подпапки-темы. memo строит рядом
с каждой папкой-темой маленький индекс (SQLite) и умеет искать по нему:
- по смыслу — «как чинят карточку в jellyfin» найдёт заметку, где написано «удаление элемента из медиатеки», хотя слова «карточка» там нет;
- по точному значению —
76.117, номер тикета, версия — найдёт точную строку; - сразу и то, и другое (по умолчанию) — режим называется гибридный.
Что важно понять сразу:
| Ваши файлы — главные | memo только читает .md. Он никогда ничего в них не пишет и не переименовывает. |
| Индекс — расходник | .memo/index.db внутри папки можно удалить в любой момент. Он пересоберётся. Это не ваши данные. |
| Всё локально | Никаких облаков и API. Модель лежит файлом на диске, считает на процессоре. |
| Никакого «формата memo» | Никаких спец-тегов, баз данных для правки, экспортов. Только markdown. |
2. Структура вашей библиотеки
memo не навязывает вам схему — он просто следует за вашими папками.
Коллекция = папка, в которой лежат .md напрямую. Одна папка = одна тема = одна независимая
база. Папки друг о друге не знают.
Пример нормальной библиотеки:
~/notes/ <- корень библиотеки (не коллекция: тут нет .md напрямую)
├── infra/ <- КОЛЛЕКЦИЯ (тут *.md)
│ ├── servers.md
│ ├── hosts.md
│ └── .memo/index.db <- индекс, создастся сам
├── work/
│ └── jira/ <- КОЛЛЕКЦИЯ (тут *.md)
│ ├── access.md
│ └── ci.md
└── life/
└── books/ <- КОЛЛЕКЦИЯ (тут *.md)
├── history.md
└── notes.md
Тут три коллекции: infra, work/jira, life/books. Папки work и life — просто группировка,
коллекциями они не считаются (в них нет .md напрямую), и это правильно: иначе одни и те же заметки
индексировались бы по нескольку раз.
Правило простое: завёл папку, положил туда .md — это новая коллекция. Ничего регистрировать
не надо.
3. Установка (один раз)
Нужен JDK 21.
cd /root/WORK/memo
# 1. Собрать всё
./gradlew installDist
# 2. Скачать модель (в артефакты не входит, 287 МБ, один раз)
mkdir -p models/siglip2
curl -fSL -o models/siglip2/text_model_int8.onnx http://static.binom.pw/models/siglip2/text_model_int8.onnx
curl -fSL -o models/siglip2/tokenizer.model http://static.binom.pw/models/siglip2/tokenizer.model
# 3. Сказать, где модель (добавьте в ~/.bashrc, чтобы не повторять)
export MEMO_MODEL_DIR=/root/WORK/memo/models/siglip2
Без переменной MEMO_MODEL_DIR программы ищут модель в /root/WORK/memo/models/siglip2 —
если у вас этот путь, шаг 3 можно пропустить.
После сборки появятся три программы:
memo-cli/build/install/memo/bin/memo <- для человека и для скриптов
memo-mcp/build/install/memo-mcp/bin/memo-mcp <- для агента (MCP)
memo-watch/build/install/memo-watch/bin/memo-watch <- демон слежения (необязателен)
4. Первый запуск: проиндексировать и найти
CLI=/root/WORK/memo/memo-cli/build/install/memo/bin/memo
# Проиндексировать всю библиотеку (коллекции найдутся сами)
$CLI index ~/notes
#> индексировано: 4 обновлено, 4 файлов всего
#> индексировано: 4 обновлено, 4 файлов всего
#> индексировано: 4 обновлено, 4 файлов всего
#> итого: 12 обновлено в 3 коллекциях
# Спросить по смыслу
$CLI search ~/notes/infra "где публикуются релизы"
#> 0.016 /root/notes/infra/hosts.md:6 Прокси
#> Корпоративные домены проксируются кади на 76.132.
#> 0.016 /root/notes/infra/hosts.md:3 Nexus
#> Нексус доступен на 76.117, публикация — только через CI.
Первая строка в каждой паре — похожесть, адрес файл:строка и заголовок раздела; ниже — сам
текст куска.
Обратите внимание: первая команда была index, но она не обязательна. search сам до-индексирует
то, что изменилось, прямо перед поиском. Можно просто писать заметки и сразу спрашивать.
Команды целиком
$CLI index <путь> # проиндексировать (повторный прогон — быстрый)
$CLI search <путь> "<вопрос>" # искать: и смысл, и точные слова
$CLI search <путь> "<вопрос>" --k 5 # вернуть 5 результатов (по умолчанию 8)
$CLI search <путь> "<вопрос>" --json # машинный вывод (для скриптов и агента)
$CLI search <путь> "<вопрос>" --mode lex # только точные слова (BM25)
$CLI search <путь> "<вопрос>" --mode vec # только по смыслу (вектор)
$CLI status <путь> # что проиндексировано и когда
Что писать в <путь>:
- корень библиотеки (
~/notes) — поиск по всем коллекциям сразу, ответы перемешиваются и сортируются по релевантности; - одну папку-коллекцию (
~/notes/infra) — поиск только внутри неё.
Область видно по адресам в результатах: .../infra/hosts.md — значит, нашли в infra.
5. Подключить к агенту (Hermes)
Здесь memo и живёт по-настоящему: агент получает инструмент поиска и перестаёт перечитывать
всю библиотеку целиком.
Добавьте в конфиг Hermes (~/.hermes/config.yaml, секция mcp_servers):
mcp_servers:
memo:
command: /root/WORK/memo/memo-mcp/build/install/memo-mcp/bin/memo-mcp
env:
MEMO_MODEL_DIR: /root/WORK/memo/models/siglip2
enabled: true
Инструменты подхватятся только в новой сессии Hermes — как и любой MCP-сервер, они читаются
при старте процесса. В текущей беседе их не будет; начните новую и проверьте, что появились
memo_search, memo_status, memo_reindex.
Агенту после этого можно говорить просто: «поищи в заметках, чем мы чинили карточку в jellyfin».
Он вызовет memo_search и получит пути, строки и текст найденных кусков.
Три инструмента
| Инструмент | Что делает |
|---|---|
memo_search(path, query, k, mode) |
Гибридный поиск. Если индекса нет — создаёт его сам. |
memo_status(path) |
Что проиндексировано, сколько файлов и чанков, когда обновлялось. |
memo_reindex(path) |
Полная переиндексация (нужна редко — обычный поиск и так до-индексирует). |
Проверить без агента
Тот же код инструмента, но из командной строки — удобно, когда что-то не работает:
$CLI mcp-probe --tool memo_search --args '{"path":"/root/notes/infra","query":"домены","k":3}'
$CLI mcp-probe --tool memo_status --args '{"path":"/root/notes"}'
Ответ печатается ровно в той форме, которую получил бы агент.
6. Демон слежения — нужен ли он вам
Короткий ответ: для работы с агентом — не нужен. Поиск сам замечает изменения: перед каждым запросом он сверяет дату и размер файлов и до-индексирует то, что поменялось. Написали заметку — сразу нашли её.
Демон memo-watch нужен ровно в одном случае: заметки правят мимо агента — вы сами в редакторе,
через git pull, синхронизацию, чужой скрипт, — и вы хотите, чтобы индекс был свежим заранее,
а не в момент вопроса.
memo-watch/build/install/memo-watch/bin/memo-watch ~/notes
#> индексирую: /root/notes/infra -> обновлено 4
#> индексирую: /root/notes/life/books -> обновлено 4
#> индексирую: /root/notes/work/jira -> обновлено 4
#> наблюдаю: /root/notes/infra
#> наблюдаю: /root/notes/life/books
#> наблюдаю: /root/notes/work/jira
При старте он сразу проходит по всем коллекциям — индекс полный с первой секунды, ждать
изменений не надо. Дальше печатает наблюдаю: по каждой и доиндексирует по факту правок:
#> индексирую: /root/notes/infra -> обновлено 1
Какие папки он мониторит
Ровно те, что вы передали аргументом, — по тому же правилу, что и остальные команды:
- передали корень (
~/notes) — следит за всеми коллекциями внутри него (в примере —infra,work/jira,life/books) и держит индекс по каждой; - передали одну папку (
~/notes/infra) — следит только за ней.
Внутрь служебных папок (.memo, .git, любые .-папки) он не заглядывает. Список наблюдаемых
папок печатается при старте строками наблюдаю: <путь> — это и есть ответ на вопрос «что он мониторит».
Демон переживает правки так: ловит изменения (с задержкой 0.5 с, чтобы не дёргаться на каждое нажатие), раз в 10 минут делает полный сверочный проход — это страховка для случаев, когда система о событиях файлов не сообщила (сетевые диски, sshfs).
Пока это ручной запуск: автостарта (systemd) нет, сам он нигде в системе не прописан и сейчас не работает — его надо запускать руками, когда понадобится.
7. Порядок работы: как это выглядит в жизни
# 1. Завести тему — просто папка с markdown
mkdir -p ~/notes/infra
cat > ~/notes/infra/hosts.md <<'EOF'
# Хосты
## Nexus
Нексус доступен на 76.117, публикация — только через CI.
## Прокси
Корпоративные домены проксируются кади на 76.132.
EOF
# 2. Спросить
$CLI search ~/notes/infra "где публикуются релизы"
#> 0.031 /root/notes/infra/hosts.md:10 Nexus
#> Нексус доступен на 76.117, публикация — только через CI.
# 3. Дописать заметку — и сразу спросить про неё, без переиндексации
printf '\n## Свежий раздел\nуникальное_слово_дзынь_47\n' >> ~/notes/infra/hosts.md
$CLI search ~/notes/infra "уникальное слово дзынь"
#> 0.016 /root/notes/infra/hosts.md:10 Свежий раздел
#> уникальное_слово_дзынь_47
#> 0.016 /root/notes/infra/hosts.md:6 Прокси
#> Корпоративные домены проксируются кади на 76.132.
# 4. Периодически освежать всё скопом (обычно не нужно — бывает после git pull)
$CLI index ~/notes
Записывать заметки можно любым способом: редактором, >>, агентом, git pull. memo не
требует, чтобы записи шли через него.
8. Если что-то не так
Поиск ничего не находит, хотя файлы на месте.
Проверьте, что папка — коллекция, то есть .md лежат в ней напрямую:
$CLI status ~/notes # должны быть видны коллекции и число файлов
find ~/notes -name '*.md' | head # файлы на месте?
$CLI status ~/notes/emptygroup
#> коллекции не найдены
Если status пишет коллекции не найдены — вы указали папку, в которой нет .md напрямую
(например, общую группировку вроде work, где лежат только подпапки). Укажите корень библиотеки
или папку-коллекцию.
Свежая правка не находится.
Проверьте, что ищете в той же папке, где файл: поиск по ~/notes/infra не увидит заметку из
~/notes/work. Поиск по корню видит всё.
Хочу начать с чистого листа. Удалите индексы — данные не пострадают:
find ~/notes -name .memo -type d -prune -exec rm -rf {} +
$CLI index ~/notes
database is locked.
Значит, одновременно пишут два процесса. Подождите минуту и повторите; если повторяется — пришлите
текст ошибки, это повод для отдельного разбирательства.
Инструменты memo_* не появились у агента.
MCP-серверы читаются при старте Hermes: начните новую сессию. Проверьте, что путь к memo-mcp
в конфиге верный и файл исполняемый.
Где посмотреть, что вообще происходит.
$CLI status ~/notes # по каждой коллекции: файлов, чанков, когда индексировали
find ~/notes -name index.db # где лежат индексы
9. Что можно удалять без страха
| Путь | Что это | Удалять? |
|---|---|---|
~/notes/**/*.md |
ваши заметки | Нет — это ваши данные |
~/notes/**/.memo/ |
индексы | Да, пересоберутся командой index |
models/siglip2/ |
модель | Да, но придётся скачать заново |
build/ |
сборка | Да, но придётся пересобрать |
Правило: всё, что не .md, — расходник.