# ParallelClaw · общая память + координация для твоих AI-агентов

> [English](README.md) · **Русский**

[![npm](https://img.shields.io/npm/v/parallelclaw.svg)](https://www.npmjs.com/package/parallelclaw)
[![downloads](https://img.shields.io/npm/dw/parallelclaw.svg)](https://www.npmjs.com/package/parallelclaw)
[![license](https://img.shields.io/npm/l/parallelclaw.svg)](LICENSE)

> **Одна дословная память для всех твоих AI-агентов — и слой координации, чтобы они передавали задачи друг другу.**

ParallelClaw — локальный **personal AI ops-слой** из двух уровней:

1. **Общая память (фундамент, уже работает).** Локальный MCP-сервер индексирует **все твои разговоры с AI** — Claude Code, Claude Cowork, Cursor, OpenClaw, Hermes, заметки Obsidian и выбранные Telegram-чаты — в один SQLite + FTS5-корпус и отдаёт их **любому MCP-совместимому клиенту**.
2. **Координация (направление, разворачивается).** Поверх общей памяти любой твой агент может **передать задачу любому другому** — между инструментами и машинами. Она выполнится, когда тот агент доступен; результат вернётся туда, где ты спросил. Транспорт (меж-машинный синк + происхождение каждой записи) уже работает; turnkey-цикл делегирования разворачивается.

Никакого облака. Никакого аккаунта. Только твой ноут.

> **Про имена CLI:** бинарь — `parallelclaw` (короткий алиас `pclaw`). Legacy-команды `memex` / `memex-sync`, каталог данных `~/.memex` и имена MCP-тулов `memex_*` сохранены для обратной совместимости — поэтому примеры ниже с `memex …` работают дословно.

---

## Как это работает

```
~/.memex/inbox/   ← кладёшь сюда экспорты (или симлинк на Claude Code .jsonl)
   ↓ chokidar watcher
   ↓
parser (Telegram JSON / Claude Code JSONL — flat и nested)
   ↓
SQLite + FTS5 (~/.memex/data/memex.db)
   ↓
MCP server (stdio JSON-RPC)
   ↓
любой клиент → 8 tool'ов:
   • memex_overview              — снэпшот корпуса + статус auto-capture
   • memex_search                — full-text поиск (с дедупом по чатам)
   • memex_recent                — последние N сообщений
   • memex_list_conversations    — список чатов по recency
   • memex_get_conversation      — полный транскрипт чата
   • memex_archive_conversation  — скрыть чат из выдачи (но не из поиска)
   • memex_status                — здоровье memex-sync daemon'а
   • memex_list_sources          — что импортировано
```

Спроси своему агенту «помнишь как мы решили проблему с миграцией Postgres?» — он **сам** вызовет `memex_search`, найдёт релевантное и ответит с реальным контекстом.

---

## Requirements / Требования

### Обязательное (без этого memex не запустится)

- **Node.js 20.x – 24.x** (рекомендуется **22 LTS**). В репо есть `.nvmrc` со значением `22` — если у тебя `nvm`, выполни `nvm use` в директории проекта.
- **macOS 12+ или Linux** с inotify (Windows — только через WSL).
- **Xcode Command Line Tools** на macOS (`xcode-select --install`) — нужны для нативной сборки `better-sqlite3`, если для твоей Node-версии нет prebuilt binaries.
- **MCP-совместимый AI-клиент** для использования: Claude Code, Cursor, OpenClaw или любой другой клиент с поддержкой MCP. Без этого memex стрит индекс, но обращаться к нему будет некому.

### Опциональное (по ситуации)

- **Telegram Desktop** — если хочешь индексировать TG-чаты. Мобильное приложение Telegram **не умеет** экспорт; нужен именно Desktop-клиент.
- **iCloud Drive / Syncthing** — если хочешь sync БД между несколькими своими ноутами.
- **Ollama / llama.cpp** — на будущее для локального LLM-extraction слоя (профильные факты). Сейчас в roadmap'е.

### Аппаратные требования (small)

- **Disk space:** ~5-30 МБ типичный корпус за год. Большие Telegram-экспорты с медиа — отдельно, до сотен МБ.
- **RAM:** daemon ~30 МБ, MCP-сервер ~50 МБ. Незаметно.
- **CPU:** на холостом ходу < 1%. Импорт сессии — миллисекунды.

### Известные ограничения

| Что **не** работает | Почему |
|---|---|
| ❌ Web-only AI (ChatGPT в браузере, Claude.ai web) | Эти сессии живут на серверах вендора, на твоём диске их нет |
| ❌ Мобильные AI-приложения (ChatGPT iOS, Claude Android) | Phone-data не пишется на твой компьютер |
| ❌ Сессии на VPS / в облаке | Memex читает локальную файловую систему |
| ❌ Windows напрямую | Только через WSL (chokidar на Win работает плохо без inotify-shim) |
| ❌ Auto-capture daemon на Linux | `npx memex-sync install` работает только на macOS (LaunchAgent). На Linux запускай daemon в foreground или сделай свой systemd unit |
| ❌ Mobile capture сегодня | В roadmap'е — Telegram-бот в `bot/` директории |

### Положительное «ограничение»

✅ **Internet не нужен.** Memex после установки работает полностью офлайн. Никаких phone-home, никаких API-ключей, никаких облачных зависимостей. Это feature, не bug.

> ⚠ **Node 25+ известная проблема.** На bleeding-edge Node (25.x) `better-sqlite3` ещё не имеет prebuilt binaries — fallback на компиляцию из исходников падает на macOS с `fatal error: 'climits' file not found`. Решение: `nvm install 22 && nvm use 22`, потом `npm install`.

---

## Установка за 60 секунд

**Установка в одну строку (рекомендуется):**

```bash
curl -fsSL https://memex.parallelclaw.ai/install.sh | bash
```

Эта команда сама делает:
1. Проверяет Node ≥ 20.
2. Запускает `npm install -g parallelclaw`, и если ловит `EACCES` — сама переносит npm prefix в `~/.npm-global` (sudo больше не нужен — никогда, ни для одного `npm install -g`).
3. Поднимает auto-capture daemon (`memex-sync install`) **вместе с** Brian Chesky auto-context хуком (v0.8+) в `~/.claude/settings.json` (другие хуки не трогает).
4. Бэкфиллит историю (`memex-sync scan`) — memex сразу знает о твоих прошлых сессиях.
5. Если на машине найден Claude Code CLI (`claude`), вызывает `claude mcp add memex --scope user -- memex` — MCP прописывается автоматом.

Идемпотентно — безопасно перезапускать. Хочешь сначала посмотреть скрипт: `curl -fsSL https://memex.parallelclaw.ai/install.sh | less`.

**Или вручную:**

```bash
npm install -g parallelclaw
memex-sync install      # macOS LaunchAgent для auto-capture
```

Если `npm install -g` упирается в `EACCES` (системный Node на macOS) — два пути:

```bash
# A. Один раз — починить prefix, чтоб больше не страдать:
mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.zshrc
source ~/.zshrc

# B. Или просто разово через sudo:
sudo npm install -g parallelclaw
```

**Альтернатива без global install** — `npx -p parallelclaw memex-sync install` ставит всё во временный кэш, ничего глобально не оставляет.

После установки `memex-sync install` поднимет фоновый daemon (`~/.memex/{inbox,data}/` создадутся автоматически при первом запуске).

### Установка через AI-скилл (Claude Code / OpenClaw)

Если хочешь чтобы агент сам всё сделал — закинь [install-memex skill](skills/install-memex/) в `~/.claude/skills/`:

```bash
mkdir -p ~/.claude/skills
curl -fsSL https://raw.githubusercontent.com/parallelclaw/memex-mvp/main/skills/install-memex/SKILL.md \
  -o ~/.claude/skills/install-memex/SKILL.md
```

Затем в Claude Code (или любом Skills-aware агенте) скажи:

> установи memex

…или `/install-memex`. Агент сам сделает `npm install`, пропишет MCP-config, поднимет daemon и проверит что всё работает — ~2 минуты.

### Сохранение URL'ов в memex (v0.6+)

После установки в любом MCP-агенте (Claude Code, Cursor, OpenClaw) можно сохранять **web-страницы, AI-chat share'ы и pasted-тексты** прямо в memex-память:

```
Сохрани https://www.perplexity.ai/share/<id> в memex
Добавь эту статью в memex: https://example.com/article
```

Агент сам fetch'ит страницу через свой WebFetch — для Cloudflare-защищённых сайтов (Perplexity, npm.com, Twitter, Medium) автоматически falls back на `r.jina.ai` proxy (memex учит агента этому трюку через tool description). Затем агент вызывает `memex_store_document`, который хранит контент verbatim как conversation с `source: "web"`.

**Memex остаётся 100% локальным** — fetch делает агент, memex только хранит. Никаких outbound network calls со стороны memex.

Полное руководство и edge cases (private Perplexity, paywall, login-walls): [HELP.md §8](HELP.md).

### Терминальный CLI (v0.7+) — запросы к memex без MCP

Тот же бинарь `memex`, который работает как MCP-сервер, имеет **terminal-режим** для прямых запросов. Полезно когда MCP не настроен, когда хочешь пайпить результаты в shell-скрипты, или дебажить MCP-конфиг:

```bash
memex search "Postgres миграция"            # полнотекстовый поиск
memex search "Q2 deck" --chat "Memex Bot"   # сузить до конкретного чата по title
memex search "JWT" --as-of 2026-05-01       # v0.8.1: time-travel — только до даты
memex when "Brian Chesky"                    # v0.8.1: «когда мы это обсуждали» — даты + чаты
memex recent --limit 5                       # последние 5 сообщений из всех источников
memex list --source web                      # все сохранённые URL'ы
memex get web-1582ab51a7b7                   # полный контент одной conversation
memex overview                               # snapshot корпуса + v0.8.1: capture streak
memex projects                               # уникальные project_paths
memex help                                   # полное руководство (HELP.md)
memex --help                                 # справка по командам
```

У каждого query-subcommand'a есть `--json` для machine-readable вывода: `memex search foo --json | jq '.results[].snippet'`. БД открывается **read-only** — безопасно запускать пока daemon пишет.

При запуске **без аргументов** (`memex`) бинарь по-прежнему работает как MCP stdio server (как и вызывают его Claude Code / Cursor / OpenClaw из своих конфигов). CLI-режим и MCP-режим — один и тот же пакет, без дополнительной установки.

**Использовать CLI, когда:**
- MCP-интеграция не подцепилась к твоему агенту → `memex overview` подтвердит что сам memex здоров
- Агент без MCP-поддержки, но с shell-доступом
- Хочешь пайпить результаты: `memex search foo --json | jq ...`
- Хочешь сдампить полный transcript в stdout для context'a

### Auto-context (v0.8+) — Claude уже знает что ты делал

После `memex-sync install` появляется промпт про **auto-context**. Если согласишься — memex добавит SessionStart хук в `~/.claude/settings.json`. Когда ты потом открываешь Claude Code в каком-то проекте, Claude **сам подгружает 500-1500 токенов контекста** про этот проект — что ты делал недавно, какие conversations его касались, какие связанные темы всплывали. Никаких вопросов, никаких tool-call'ов, просто Claude **знает**.

```bash
# Добавить/удалить хук вне install-flow:
memex hook install        # добавить SessionStart хук (idempotent)
memex hook uninstall      # удалить только memex-запись, остальные хуки не трогает
memex hook status         # показать текущее состояние

# Посмотреть что будет инжектиться:
memex context             # dry-run для текущей директории
memex context --pwd /path # для другого проекта
memex context --no-source telegram  # исключить источник
```

Хук **сохраняет существующие хуки** (gstack, твои кастомные) — добавляет только свою запись.

**Сейчас native SessionStart есть только в Claude Code.** Для Cursor fallback через MCP-tool доступен (v0.9+).

### Подключение к Claude Code

Сначала возьми **два абсолютных пути** в терминале:

```bash
pwd         # → путь до memex-mvp (из директории memex-mvp)
which node  # → путь до бинарника node (например /Users/you/.nvm/versions/node/v24.15.0/bin/node)
```

В `~/.claude/config.json` добавь, подставив оба пути:

```json
{
  "mcpServers": {
    "memex": {
      "command": "/абсолютный/путь/до/node",
      "args": ["/абсолютный/путь/до/memex-mvp/server.js"]
    }
  }
}
```

**Почему абсолютный путь к node, а не просто `"node"`?** GUI-приложения (Cursor, Claude Desktop) на macOS часто **не наследуют PATH из shell'a** (`~/.zshrc`). С `"command": "node"` MCP-сервер падает с `spawn node ENOENT` — особенно если node поставлен через nvm. Всегда используй путь из `which node`.

Перезапусти Claude Code. Готово — у тебя в session появятся `memex_*` tool'ы.

### Подключение к Cursor / OpenClaw

Каждый клиент имеет свой `mcpServers` config (у Cursor — `~/.cursor/mcp.json`; для OpenClaw — отдельный гайд memex.parallelclaw.ai/openclaw/). Структура та же — `command` = абсолютный путь до node, `args` = `[путь к server.js]`. Та же ENOENT-проблема актуальна для всех GUI-MCP клиентов.

---

## Что поддерживается

| Источник | Формат | Статус |
|----------|--------|--------|
| **Claude Code** | `*.jsonl` сессии в `~/.claude/projects/` | ✅ работает (nested + flat форматы) |
| **Claude Cowork** | `cowork-*.jsonl` (через filename prefix), включая subagents | ✅ работает |
| **Cursor IDE** (Composer + Chat) | SQLite `state.vscdb` в `~/Library/Application Support/Cursor/` | ✅ работает (poll каждые 5 мин) |
| **Obsidian** vault notes | `.md` файлы + YAML frontmatter | ✅ работает (FSEvents, hash-based dedupe) |
| **Telegram (JSON / HTML export)** | `result.json` или `ChatExport_*/` из Telegram Desktop | ✅ работает — **v0.10+: авто-детект.** Daemon следит за `~/Downloads/Telegram Desktop/`, экспорты сами попадают в pending, юзер per-chat подтверждает |
| **Telegram (live)** | бот `memex-bot` ловит твои сообщения / форварды | ✅ работает |
| **Web-страницы, AI-share'ы, paste'ы** | `memex_store_document` — агент fetch'ит, memex хранит verbatim (v0.6+) | ✅ работает |
| Claude.ai web export | будет в v0.7 | — |
| ChatGPT export | будет в v0.7 | — |
| Apple Notes | будет в v0.7 | — |

### Filename convention для inbox-файлов

Парсер различает источники по префиксу имени файла в inbox:
- `code-*.jsonl` или произвольное имя → tagged как `claude-code`
- `cowork-*.jsonl` → tagged как `claude-cowork`
- `cursor-*.jsonl` → tagged как `cursor`
- `obsidian-*.jsonl` → tagged как `obsidian`

Это позволяет фильтровать `memex_search` по конкретной экосистеме (`source: "cursor"`, `source: "obsidian"` и т.д.).

### Cursor IDE source — особый случай

Cursor хранит историю в SQLite (`state.vscdb`), не в JSONL-файлах. memex-sync daemon **поллит** эту БД каждые 5 минут (FSEvents бессмысленно — Cursor пишет в WAL практически на каждый keystroke). При обнаружении composer'а с обновлённым `lastUpdatedAt` daemon экспортит его dialogue (без thinking-bubbles и tool-call'ов) в inbox как `cursor-<short>.jsonl`. Заголовок берётся из `composerData.name` напрямую.

Поддерживаемые ОС для Cursor: macOS, Linux, Windows (пути в `lib/parse-cursor.js`).

### Obsidian source — заметки как первоклассные сущности

memex автоматически находит Obsidian-vault'ы в стандартных местах (`~/Documents/`, `~/Obsidian/`, `~/Library/Mobile Documents/iCloud~md~obsidian/Documents/` для iCloud-синка). Vault — это любая папка с `.obsidian/` подпапкой внутри. Можно явно указать пути через env-переменную:

```bash
export MEMEX_OBSIDIAN_VAULTS=/path/to/vault1,/path/to/vault2
```

Каждая `.md` нота → одна conversation в memex. Title берётся из `title:` frontmatter → первого `# H1` → имени файла. YAML frontmatter парсится для метаданных (дат, тегов). Body индексируется в FTS5 как один user-сообщение.

**Privacy**:
- Обнаружение vault'ов opt-in (только стандартные пути; кастомные через env var)
- Игнорируются: `.obsidian/`, `.trash/`, `.git/`, `.DS_Store`, `*.sync-conflict-*`
- Per-note opt-out через frontmatter `memex: false`
- Hash-based dedupe — пишем в inbox только когда содержание реально изменилось, не на каждый mtime-touch

### Bulk import за одну команду

memex полностью самодостаточен — не нужен Python, не нужны внешние CLI:

```bash
npx memex-sync scan            # Claude Code + Cowork + Cursor + Obsidian сразу
npx memex-sync scan-claude     # только Claude Code + Cowork
npx memex-sync scan-cursor     # только Cursor
npx memex-sync scan-obsidian   # только Obsidian vault(s)
```

Сканирует все источники один раз, эмитит JSONL в inbox, выходит. Идемпотентен — повторный запуск пропускает неизменённые файлы через state-cache. Удобно для cron, manual-первого-импорта, или дебага без daemon'а.

### Two pieces

memex поставляется в виде **двух независимых частей:**

- **MCP server** (`server.js`) — пассивная база знаний, всегда доступна после `npm install`. Отдаёт 8 tool'ов любому MCP-агенту.
- **memex-sync** (`ingest.js`) — **опциональный** фоновый daemon. Watch'ит `~/.claude/projects/` (Code) и `~/Library/Application Support/Claude/local-agent-mode-sessions/` (Cowork) через FSEvents и автоматически добавляет новые сессии в память в реальном времени.

> **Без memex-sync память замёрзла** на момент последнего ручного импорта. **С ним** — каждая новая сессия становится searchable за ~1.5 секунды.

### Включить auto-capture (memex-sync)

Одна команда — и dameon регистрируется как macOS LaunchAgent, автозапускается при логине, переживает перезагрузку и крэши:

```bash
npx memex-sync install
```

Дальше:

```bash
npx memex-sync status      # три состояния: installed / running / watching
npx memex-sync logs        # tail -f лог в реальном времени
npx memex-sync uninstall   # снять с автозапуска (БД остаётся)
```

Без `install` daemon можно гонять и в foreground'е (для отладки):

```bash
npx memex-sync             # = serve, в foreground
```

### Что под капотом

- chokidar (FSEvents на macOS, inotify на Linux) на обе source-директории
- Per-file state в `~/.memex/data/ingest-state.json` (sha1 первых 256B + size + mtime) — повторный запуск пропускает неизменённые файлы
- Safety rescan каждые 30 минут — ловит пропущенные FSEvents после sleep/lid-close
- Atomic writes (temp + rename) в `~/.memex/inbox/` — никаких частичных JSONL
- Idempotent: новые сообщения идут через UNIQUE(msg_id), дубли отсекаются на уровне БД
- LaunchAgent работает с `LowPriorityIO=true`, `Nice=5` — не мешает основной работе ноута

memex MCP server и memex-sync — два независимых процесса. MCP server отвечает агентам, memex-sync кормит inbox. Связи нет, кроме общей файловой системы.

### Управление источниками

По умолчанию memex-sync **собирает всё что находит** на машине: Claude Code, Cowork, Cursor, Obsidian (auto-detect). Это удобно для quick-start, но любой источник можно отключить через CLI без удаления daemon'а:

```bash
npx memex-sync sources                       # показать что сейчас включено
npx memex-sync sources cursor disable        # выключить cursor
npx memex-sync sources cursor enable         # вернуть
npx memex-sync vault add /path/to/MyVault    # явный список Obsidian-vault'ов
npx memex-sync vault remove /path            # убрать
npx memex-sync restart                       # применить изменения
```

Конфиг живёт в `~/.memex/config.json`. Файла нет → сборка по дефолту. Как только что-то изменено через CLI — файл создаётся, daemon его уважает.

Privacy: agent через `memex_sources_status` сам показывает что именно отслеживается, и **никогда не выключает источники сам** — это всегда команда от пользователя.

### Подсказка для агента

Если ты подключил memex к Claude Code/Cursor/OpenClaw и каждый раз когда вызываешь `memex_overview` видишь сверху ⚪ или 🔴 — это значит auto-capture не включён. Агент сам это увидит и предложит юзеру команду `npx memex-sync install`. Это та самая «один раз и забыл» механика — без README-чтения.

---

## Между устройствами / Across devices

### По-русски

**Встроенный настоящий синк (v0.13) — два copy-paste шага.** Ноут с
Claude/Cursor + сервер с агентом (OpenClaw и т.п.) связывают память без
публичных портов, правки фаервола, ручных SSH-ключей и написания сервисов.

**Шаг 1 — кинь этот промпт агенту на сервере:**

```
Настрой memex-sync как хаб и выдай join-токен для моего ноута:
1. npm install -g parallelclaw@latest   (пропусти, если уже стоит)
2. memex-sync sync-server install --bind 127.0.0.1
3. memex-sync sync-server invite --join
Пришли мне строку memex-join:...
```

**Шаг 2 — одна команда на ноуте:**

```bash
memex-sync sync-join memex-join:eyJ2...
```

Эта команда сама: проверяет SSH (нет доступа — печатает твой pubkey и что с
ним сделать), поднимает **самовосстанавливающийся** туннель (переживает сон,
смену сети, ребут), пиннит сертификат сервера, делает первый синк
(прерванный — продолжается с места обрыва), ставит авто-синк каждые 15 минут
и ежечасный watchdog, и в конце **доказывает** петлю — прогоняет тестовую
заметку туда-обратно и печатает время. Сервер остаётся на loopback; весь
трафик едет внутри SSH (порт 22). Бесконфликтно: verbatim-память append-only,
мёржить нечего.

Mobile: пересылай сообщения в Telegram-бота (`bot/`) — попадут на основную
машину и разойдутся синком. Продвинутые топологии (мульти-нода, reverse-туннели,
транзит-хабы) — в [SYNC.md](SYNC.md). Legacy file-sync рецепты (iCloud/Syncthing,
single-writer, DEPRECATED) — в [MULTI_MACHINE.md](MULTI_MACHINE.md).

### In English

**Built-in real sync (v0.13) — two copy-paste steps.** A laptop with
Claude/Cursor + a server with an agent connect their memory with no public
ports, no firewall changes, no manual SSH keys, no hand-written services.

**Step 1 — paste to the agent on the server:**

```
Set up memex sync as a hub and give me a join token for my laptop:
1. npm install -g parallelclaw@latest   (skip if installed)
2. memex-sync sync-server install --bind 127.0.0.1
3. memex-sync sync-server invite --join
Send me the memex-join:... line.
```

**Step 2 — one command on the laptop:**

```bash
memex-sync sync-join memex-join:eyJ2...
```

It verifies SSH (or prints your pubkey + instructions), builds a self-healing
tunnel (survives sleep/network changes/reboot), pins the server cert, runs the
first sync (resumable), installs 15-min auto-sync + an hourly watchdog, and
finishes by **proving** the loop with a round-tripped test note. The server
stays on loopback; everything rides inside SSH on port 22. Conflict-free:
verbatim memory is append-only — nothing to merge.

Advanced topologies (multi-node, reverse tunnels, transit hubs) — see
[SYNC.md](SYNC.md). Legacy file-sync recipes (single-writer, DEPRECATED) —
[MULTI_MACHINE.md](MULTI_MACHINE.md).

---

## Миграция между устройствами / One-time migration

> **Не то же самое что sync.** Это **разовый перенос** всей истории со старого ноута на новый — например при покупке нового мака. Sync — это паттерн в секции «Между устройствами» выше, когда два ноута постоянно делят одну БД через iCloud / Syncthing.

### По-русски

memex.db — обычный SQLite-файл, переезжает как любой документ.

**На старом ноуте:**

```bash
# 1. Останови daemon чтобы не было активной записи
launchctl unload ~/Library/LaunchAgents/com.parallelclaw.memex.sync.plist 2>/dev/null

# 2. Сверни WAL в основной файл (чтобы не потерять свежие записи)
sqlite3 ~/.memex/data/memex.db "PRAGMA wal_checkpoint(TRUNCATE)"

# 3. Скопируй ОДИН файл (AirDrop / scp / iCloud / external USB)
cp ~/.memex/data/memex.db ~/Desktop/memex-backup.db
```

⚠ Копируй **только `memex.db`** — НЕ копируй `memex.db-wal`, `memex.db-shm` (временные, после checkpoint'a не нужны) и НЕ копируй `~/.memex/data/ingest-state.json` (machine-specific — там пути и fingerprint'ы старого ноута).

**На новом ноуте:**

```bash
# 1. Установи memex как при первой установке
git clone https://github.com/parallelclaw/memex-mvp
cd memex-mvp && npm install

# 2. Положи DB-файл
mkdir -p ~/.memex/data
cp /path/to/memex-backup.db ~/.memex/data/memex.db

# 3. Пропиши MCP-конфиг с абсолютным путём к node (см. секцию "Подключение к Claude Code")

# 4. Перезапусти Cursor / Claude Code и вызови memex_overview
```

**Что переедет:** все разговоры, FTS5-индекс, Telegram-экспорты, conversation IDs. Поиск работает сразу.

**Что НЕ переедет автоматически:**
- Новые Claude Code / Cursor сессии нового ноута — это уже файлы нового ноута. Решение: `npx memex-sync install` на новом — daemon начнёт ловить новые сессии и добавлять их в ту же БД.
- `project_path` в существующих записях содержит **старые пути** (`/Users/oldname/...`). Memex не сломается, но `memex_list_projects` покажет старые пути. При необходимости — `UPDATE conversations SET project_path = REPLACE(...)` руками.

### In English

memex.db is a regular SQLite file — moves like any document.

**On the old laptop:**

```bash
# 1. Stop the daemon to prevent active writes
launchctl unload ~/Library/LaunchAgents/com.parallelclaw.memex.sync.plist 2>/dev/null

# 2. Checkpoint the WAL into the main file (don't lose recent writes)
sqlite3 ~/.memex/data/memex.db "PRAGMA wal_checkpoint(TRUNCATE)"

# 3. Copy ONE file (AirDrop / scp / iCloud / external USB)
cp ~/.memex/data/memex.db ~/Desktop/memex-backup.db
```

⚠ Copy **only `memex.db`** — do NOT copy `memex.db-wal`, `memex.db-shm` (transient, unneeded after checkpoint), and do NOT copy `~/.memex/data/ingest-state.json` (machine-specific — it contains paths and fingerprints from the old laptop).

**On the new laptop:**

```bash
# 1. Install memex like a first-time install
git clone https://github.com/parallelclaw/memex-mvp
cd memex-mvp && npm install

# 2. Place the DB file
mkdir -p ~/.memex/data
cp /path/to/memex-backup.db ~/.memex/data/memex.db

# 3. Wire MCP config with absolute path to node (see "Connecting to Claude Code" above)

# 4. Restart Cursor / Claude Code and call memex_overview
```

**What transfers:** all conversations, FTS5 index, Telegram exports, conversation IDs. Search works immediately.

**What does NOT auto-transfer:**
- New Claude Code / Cursor sessions on the new laptop — those are new files on the new machine. Solution: run `npx memex-sync install` on the new laptop — the daemon will start catching new sessions and adding them to the same DB.
- `project_path` in existing rows still contains **old paths** (`/Users/oldname/...`). Memex won't break, but `memex_list_projects` will show old paths. If needed — `UPDATE conversations SET project_path = REPLACE(...)` manually.

---

## Приватность и безопасность / Privacy & Security

### По-русски

Один файл со всеми твоими AI-разговорами — звучит страшнее, чем есть.

✅ **Что memex делает:** Живёт только на твоей машине, никуда не звонит, без API-ключей, без network access. OS-level права на файлы — читает только твой user.

❌ **Что не делает:** Не шифрует БД, не редактирует секреты которые ты вставлял в чаты с AI, нет пароля на сам memex.

📦 **Не добавляет риск — концентрирует.** Твоя AI-история **уже** на диске в plain text — Claude Code JSONL, Cursor `state.vscdb`, Cowork session files, Obsidian `.md`, Telegram local DB. Memex консолидирует их в один SQLite-файл. Те же данные, в одном месте вместо пяти. Attack surface не растёт — растёт видимость.

🛡️ **Топ-рекомендация: FileVault.** На macOS: `System Settings → Privacy & Security → FileVault → Turn On`. Шифрует весь диск AES-256 на уровне OS. Без твоего пароля диск нечитаем — закрывает ~80% реалистичных угроз (украденный ноут, кража backup, malware без root). На Linux то же делает LUKS. Сделай это **прежде** чем волноваться про app-level шифрование.

### In English

One file with all your AI conversations — sounds scarier than it is.

✅ **What memex does:** Lives only on your machine, never phones home, no API keys, no network access. OS-level file permissions — readable only by your user.

❌ **What it doesn't:** Doesn't encrypt the DB file, doesn't redact secrets you pasted into AI chats, no password on memex itself.

📦 **Doesn't add risk — concentrates it.** Your AI history is **already** on disk in plain text — Claude Code JSONL, Cursor `state.vscdb`, Cowork session files, Obsidian `.md`, Telegram local DB. Memex consolidates them into one SQLite file. Same data, one place instead of five. Attack surface doesn't grow — visibility does.

🛡️ **Top recommendation: FileVault.** On macOS: `System Settings → Privacy & Security → FileVault → Turn On`. Encrypts the entire disk with AES-256 at the OS level. Without your password, the disk is unreadable — closes ~80% of realistic threats (stolen laptop, stolen backup, non-root malware). On Linux: LUKS does the same. Do this **before** worrying about app-level encryption.

---

## Telegram export

1. Telegram **Desktop** (mobile не умеет export)
2. Чат → меню → **Export chat history**
3. **Format:** JSON или HTML — оба работают (HTML — с v0.9+)
4. **Path:** Daemon следит за `~/Downloads/Telegram Desktop/` и подхватывает экспорты автоматически. **Также с v0.10.12 — `memex import <путь>`** из любой папки ([см. ниже](#импорт-из-любого-пути-v01012)). Legacy-путь `~/.memex/inbox/` тоже работает.
5. Готово. После экспорта запусти `memex telegram pending` чтобы увидеть staged-чаты для импорта. Если daemon ещё не подхватил (например, экспорт лежал до установки memex'а) — `memex telegram scan` сделает backfill.

## Импорт из любого пути (v0.10.12+)

Если файл лежит не в `~/.memex/inbox/`, а в обычном месте на диске (`~/Downloads/`, `~/Desktop/`, `~/projects/foo/`) — одна команда:

```bash
memex import ~/projects/memex/result.json
memex import ~/Downloads/ChatExport_2026-05-18/         # Telegram HTML-папка
memex import ~/path/to/session.jsonl                    # Claude Code сессия
memex import ~/Downloads/result.json --force            # пропустить privacy-gate
```

То же через AI-агента: `memex_import_file({path: "..."})` — один MCP tool-call. Не нужно вручную переносить файлы.

---

## Web-дашборд (v0.10.8+) — увидеть свою память без AI

Опциональный read-only локальный UI для просмотра корпуса. Та же SQLite, другая поверхность — пригождается когда хочется просто посмотреть на свои разговоры глазами, без MCP-агента в цикле.

```sh
memex web --open       # localhost:8765, откроет браузер
memex web --port 9000  # свой порт
memex web --public --token s3cret   # 0.0.0.0 с bearer-авторизацией (для remote / туннеля)
memex web --help
```

Пять страниц:

| Страница          | Что внутри                                                                                |
|-------------------|-------------------------------------------------------------------------------------------|
| `/`               | Сетка статов · sources breakdown · callout про pending Telegram · последние 10 conversations |
| `/conversations`  | Live FTS5-поиск через htmx (200мс debounce) · фильтры-чипы по source · кол-во hit'ов на чат |
| `/c/:id`          | **Verbatim** транскрипт chat-bubble'ами · поиск внутри чата с `<mark>` подсветкой · пагинация |
| `/pending`        | Telegram-экспорты ждущие решения · чекбоксы bulk Import / Skip · история твоих решений    |
| `/settings`       | Статус daemon'а · путь и размер БД · установленные хуки · TG decisions counts (read-only) |

**Принципы:**
- **Opt-in, не always-on.** `memex web` поднимает сервер; Ctrl+C гасит. Никакого фонового демона.
- **Read-only по умолчанию.** Единственные записи — TG import / skip на `/pending` (тот же privacy-gate, что и `memex telegram import`).
- **Localhost-only по умолчанию.** Слушает на `127.0.0.1`. Для удалённого доступа — `--public --token <…>` (на этом же endpoint в будущем поедет multi-host sync API).
- **Без build-step'а.** Raw Node `http` + tagged template literals + htmx 14KB с CDN. Клиентский bundle ≈ 30KB.
- **Брендирование совпадает с лендингом.** Inter + mint-палитра как на [memex.parallelclaw.ai](https://memex.parallelclaw.ai).

---

## Как использовать на практике / How to actually use it

Полный guide с **6 типовыми use case'ами** (Telegram → action plan, cross-AI bridge, recall, project resume, patterns, deck-анализ), описанием всех MCP-tools и troubleshooting — в [HELP.md](HELP.md). Скопируй любой промпт из этого файла → вставь в свой AI-агент → попробуй сразу после установки.

---

## Проверь что работает

В Claude Code/Cursor/OpenClaw напиши:

```
Используй memex_list_sources — что у меня в локальной памяти?
```

Должен ответить чем-то вроде:

```
Total messages: 15021
Sources:
  • telegram     — 13640 messages, 3 chat(s)
  • claude-code  — 1381 messages, 16 chat(s)
```

Дальше пробуй настоящие запросы:

```
Помнишь как мы обсуждали бизнес-модели для арбитража?
Найди мою сессию про SberBusiness структуру.
Что было в апреле про создание YC-презентации?
```

Агент сам вызовет `memex_search`, отдаст реальные совпадения с conversation_id и timestamps.

---

## MCP tools

> **Все tool'ы поддерживают параметр `format: "markdown" | "json"`** (дефолт `"markdown"`).
> Markdown — для глаз, JSON — для агентов: меньше токенов, можно парсить поля напрямую.

> **Server-side instructions для агентов.** В MCP `initialize`-ответе сервер отдаёт ~3 КБ системного контекста: что хранится, какой tool когда выбирать, FTS5-синтаксис, известные ограничения. Любой подключающийся агент (Claude Code, Cursor, OpenClaw) получает это автоматически — отдельную инструкцию писать не нужно. Текст в `SERVER_INSTRUCTIONS` в [server.js](server.js).

### `memex_overview(recent_limit?, format?)`
Снэпшот корпуса одним вызовом — для ориентации в начале сессии. Возвращает: общее число сообщений, breakdown по источникам (telegram / claude-code / claude-cowork), date range, и последние N разговоров с заголовками. Этот call даёт агенту mental map за ~500 токенов и резко повышает качество последующих `memex_search` запросов (т.к. агент уже знает что у пользователя в памяти есть, а чего нет). Server-side instructions явно рекомендуют вызывать его первым шагом в новой сессии.

### `memex_search(query, limit?, source?, project?, chat?, conversation_id?, origin?, since_ts?, until_ts?, sort?, half_life_days?, group_by_conversation?, include_archived?, expand_match?, format?)`
Full-text поиск через FTS5. Возвращает ranked сниппеты с `<<word>>` подсветкой.

**Фильтры скоупа:** `source` (telegram/claude-code/…), `project` (по project_path), `chat` (нечёткий матч по названию), **`conversation_id` (точный поиск ВНУТРИ одной сессии)**, **`origin` (v0.14 — с какого узла захвачено: в synced-меше source'ы всех машин совпадают, origin различает)**.

**Фильтр по датам (v0.12):** `since_ts` / `until_ts` (Unix-секунды, включительно) — ограничить окном: «что обсуждали про X в июне». Это настоящий фильтр, в отличие от `sort` (только порядок) и `half_life_days` (только recency-boost).

**По умолчанию `group_by_conversation: true`** — возвращает один лучший хит на каждый conversation_id плюс `match_count` (сколько всего совпадений в этом чате). Это убирает шум, когда один длинный диалог занимает всю выдачу одинаковыми кусками. Передай `false` чтобы получить классический список всех совпадений.

Архивные чаты по умолчанию исключены из выдачи; передай `include_archived: true` чтобы искать везде.

### `memex_recent(limit?, source?, include_archived?, format?)`
Последние N сообщений по timestamp.

### `memex_list_conversations(limit?, source?, since_ts?, include_archived?, format?)`
Список чатов отсортированных по последней активности (most recent first). Каждая запись — `conversation_id`, источник, заголовок, диапазон дат и кол-во сообщений. Удобно, когда хочется быстро увидеть какие у тебя вообще разговоры с конкретным ботом или внутри одного источника, прежде чем вытаскивать полный транскрипт.

Архивные чаты скрыты по дефолту, помечены 🗄️ если включены через `include_archived: true`.

### `memex_get_conversation(conversation_id, limit?, offset?, order?, include_subagents?, format?)`
Transcript одного чата. **Пагинация (v0.12):** `offset` листает длинные сессии (0, 200, 400…), `order` задаёт порядок — `asc` (старые первыми, дефолт) или `desc` (свежие первыми). Вывод сообщает `total` — сколько всего сообщений, чтобы знать докуда листать. Для сессии на тысячи сообщений `order:"desc"` отдаёт хвост в один вызов (раньше был доступен только старый «нос»).

### `memex_archive_conversation(conversation_id, archive?)`
Заархивировать (или восстановить) чат. Архивный чат остаётся в индексе и доступен для поиска через `include_archived: true`, но не засоряет дефолтную выдачу `memex_list_conversations` / `memex_search`. Передай `archive: false` чтобы расколоть.

### `memex_list_sources(format?)`
Метаданные: счётчики по источникам, последние импорты, путь к БД, число архивных чатов.

---

## Архитектура

```
memex-mvp/
├── server.js            ← MCP-server + parsers + chokidar inbox watcher
├── ingest.js            ← optional daemon: live-tail Code/Cowork → inbox
├── lib/parse.js         ← shared dialogue parser (used by both)
├── package.json         ← 3 dependencies (mcp-sdk, better-sqlite3, chokidar)
├── install.sh           ← создаёт ~/.memex/, npm install, печатает config
└── test/parser.test.js  ← unit-тесты парсера (13 кейсов)

~/.memex/
├── inbox/               ← drop-zone, chokidar watching
├── data/
│   ├── memex.db         ← SQLite с FTS5 (3 таблицы: messages, messages_fts, conversations)
│   ├── memex.log        ← server log
│   └── conversations/   ← обработанные оригиналы (telegram/, claude-code/)
```

### Schema

- `messages` — `(source, conversation_id, msg_id, role, sender, text, ts, metadata)` с UNIQUE на `(source, conversation_id, msg_id)` для дедупликации
- `messages_fts` — FTS5 виртуальная таблица, токенизатор `unicode61 remove_diacritics` (русский + английский, case-insensitive)
- `conversations` — агрегаты per-чат (first_ts, last_ts, message_count)

---

## Ограничения v0.1

- 🟡 Поиск keyword-based — нет semantic similarity. «арбитраж» найдёт «арбитраж», но не «монетизация трафика»
- 🟡 Manual import (кладёшь файл в inbox) — нет автоматического pull
- 🟡 Single-device — нет cross-machine sync
- 🟡 Plaintext SQLite — нет encryption-at-rest
- 🟡 ID-based dedupe требует стабильного `id` у сообщений; memex-sync (и claude-backup feed-memex для совместимости) генерируют sha1-hash из `role|timestamp|text[:200]` для гарантии

Всё лечится в следующих версиях.

---

## Roadmap

- **v0.1** (сейчас) — Telegram + Claude Code + Claude Cowork, FTS5, dialogue-only фильтр noise'а
- **v0.2** — Semantic search через BGE-M3 + sqlite-vec; ChatGPT export; Obsidian vault
- **v0.3** — Cloud relay (zero-knowledge) для auto-pull с серверов
- **v0.4** — Multi-device sync (CRDT-based)
- **v1.0** — Personal embedding adapter, behavioral routing rules

---

## Companion projects

- **[claude-backup](https://github.com/parallelclaw/claude-backup)** — отдельный Python-CLI для экспорта Claude Code/Cowork сессий **в Markdown** (для backup'а, чтения вне memex, sharing). **Не нужен для memex** — `npx memex-sync scan-claude` импортирует ту же историю напрямую без Python. Используй claude-backup если хочется именно Markdown-файлы как side-effect.

---

## Лицензия

MIT — делай что хочешь.
