📜 Летопись (Letopis)
Движок архива и умного поиска по истории Telegram-чатов
Сырые сообщения в JSONL · полнотекстовый поиск с русской морфологией · качалка с менеджером
Идея
Летопись — это не бот и не сервис, а CLI-инструмент, заточенный под то, чтобыLLM-агент (в первую очередь Claude Code) могчитать историю ваших Telegram-чатов и отвечать по ней на вопросы, как по обычнойбазе знаний.
Архив хранится как обычные файлы — .jsonl, по одному на чат и месяц,append-only. Поверх них строится индекс SQLite с полнотекстовым поиском (FTS5),который понимает русские словоформы: запрос «хостинг» находит сообщения сословом «хостингами». К поиску подключены расшифровки голосовых, имена файлови текст опросов.
$ ./tg search переезд хостинг --chat devops --from 2025-06
Движок и данные разделены. Этот репозиторий содержит только код —сами архивы чатов,
config.toml,.envи сессия Telegram живут в отдельномприватном репозитории, который держит вас в контроле над тем, что публично,а что нет. Подробнее — в разделе «Устройство».
✨ Возможности
| 🔎 Полнотекстовый поиск | SQLite FTS5 + pymorphy3: ищет по леммам, а не только точным словам |
| 📦 Архив как файлы | archive/<chat_id>/<YYYY-MM>.jsonl, append-only, ничего не переписывается задним числом |
| ⬇️ Качалка с менеджером | download / sync докачивают только новое; manifest.json помнит, что отслеживается |
| 🎙️ Транскрипция голосовых | локально (faster-whisper), через Telegram Premium или OpenAI Whisper API |
| 🌐 Веб-просмотрщик | чаты → топики-чипы, бесконечная прокрутка, фильтры, плеер голосовых, прыжки по реплаям |
| ⌨️ TUI-просмотрщик | тот же функционал в терминале (textual) |
| 👥 Несколько аккаунтов | разные чаты можно скачивать разными Telegram-аккаунтами |
| 🤖 Заточен под агентов | JSON-вывод, компактные короткие форматы, стабильный CLI-контракт |
🚀 Быстрый старт
git clone https://github.com/Toligrim/letopis.git
cd letopis
python3 -m venv .venv && .venv/bin/pip install -e .
.venv/bin/pip install faster-whisper # опционально: локальная транскрипция голосовых
Летопись — это только движок. Чтобы подключить его к конкретному архиву, создайтеотдельный репозиторий с данными и положите туда обёртку ./tg:
#!/bin/sh
exec "$HOME/projects/letopis/.venv/bin/tg" "$@"
Дальше всё запускается из корня репозитория с данными:
chmod +x tg
./tg login # авторизация Telegram-сессии (телефон / код / 2FA)
./tg download --chat mychat --media all
./tg index && ./tg meta
./tg search привет
Движок сам находит корень с данными: при запуске tg ищет от текущей директориивверх папку, где рядом лежат config.toml и archive/ (либо это явно задаётсяпеременной окружения TG_ROOT).
🤖 Read-only MCP для ChatGPT
Letopis может работать как read-only MCP retrieval gateway для ChatGPT:сервер использует тот же data/index.db, что и обычный поиск, но отдаёт толькопять безопасных retrieval-инструментов — обзор архива, поиск, агрегаты, выборкусообщений и локальный контекст. MCP-процесс не синхронизирует Telegram, нескачивает файлы и не меняет индекс.
Установка и запуск
Установите MCP SDK и тестовые зависимости в окружение движка:
.venv/bin/pip install -e ".[mcp,test]"
Запуск через entrypoint:
.venv/bin/letopis-mcp
Альтернативная форма — .venv/bin/python -m tgarchive.mcp.server. По умолчаниюсервер слушает http://127.0.0.1:8765/mcp и принимает только loopback-адреса.Для production задайте стабильный секрет курсоров и путь к индексу в окружениипроцесса, например:
export LETOPIS_MCP_DB=/srv/letopis-data/data/index.db
export LETOPIS_MCP_CURSOR_SECRET='случайный-длинный-секрет'
.venv/bin/letopis-mcp
Переменные окружения
| Переменная | По умолчанию | Назначение |
|---|---|---|
LETOPIS_MCP_DB |
значение [general].db из config.toml, обычно data/index.db |
Путь к SQLite-индексу; относительный путь считается от корня проекта. |
LETOPIS_MCP_CURSOR_SECRET |
нет; временный случайный секрет на процесс | HMAC-SHA256 для непрозрачных курсоров. Обязателен в production: без него курсоры не переживают рестарт процесса. |
LETOPIS_MCP_HOST |
127.0.0.1 |
Loopback-адрес bind; приложение отклоняет нелокальные адреса. |
LETOPIS_MCP_PORT |
8765 |
TCP-порт Streamable HTTP endpoint. |
LETOPIS_MCP_LOG_LEVEL |
INFO |
Уровень структурированных логов (DEBUG, INFO, WARNING, ERROR, CRITICAL). |
LETOPIS_MCP_MAX_CONCURRENCY |
8 |
Максимум конкурентных операций с read-only БД. |
LETOPIS_MCP_QUERY_TIMEOUT_SECONDS |
30.0 |
Дедлайн SQLite-запроса и ожидания слота concurrency. |
LETOPIS_MCP_ROLLING_CALLS_MAX |
60 |
Максимум завершённых вызовов в глобальном rolling-окне. |
LETOPIS_MCP_ROLLING_CHARS_MAX |
250000 |
Максимум отданных символов в том же окне. |
LETOPIS_MCP_ROLLING_WINDOW_SECONDS |
600 |
Длина rolling-окна в секундах. |
Rate limit намеренно глобальный для одного процесса: в v1 нет OAuth иидентифицированных principals, поэтому это не per-user ACL. MCP читает этипеременные как конфигурацию процесса и не загружает .env автоматически.
Подключение к ChatGPT
Рекомендуемая схема не публикует Letopis в интернет напрямую:
ChatGPT ↔ OpenAI Secure MCP Tunnel ↔ tunnel-client на этом хосте
↔ 127.0.0.1:8765/mcp
Конкретные команды и шаги настройки Secure MCP Tunnel зависят от текущегоOpenAI workspace и актуальной документации OpenAI. Уточните их на моментподключения; этот репозиторий не выдумывает непроверенную OAuth/tunnel-команду.
Безопасность deployment
MCP-процессу нужны только data/index.db и необходимые SQLite sidecar-файлыdata/index.db-wal / data/index.db-shm. Ему не должны быть доступны.env, telegram.session*, archive/, media или manifest. Запускайте серверпод отдельным Unix-пользователем с минимальными правами, а синхронизацию ииндексацию выполняйте отдельным процессом с нужными правами записи.
🗂 Устройство
репозиторий с данными/
├── config.toml # настройки: аккаунты, транскрипция, веб-порт
├── .env # api_id / api_hash Telegram
├── telegram.session # сессия аккаунта (и доп. сессии из [accounts])
├── tg -> letopis/.venv/bin/tg # обёртка-энтрипоинт
├── data/
│ └── index.db # SQLite + FTS5 — производный, пересобирается
└── archive/
├── manifest.json # какие чаты отслеживаем, каким аккаунтом, какие медиа качаем
└── <chat_id>/
├── 2025-06.jsonl # сырые сообщения этого месяца — источник истины
├── 2025-07.jsonl
├── transcripts.jsonl # расшифровки голосовых/кружков
├── media_index.jsonl # реестр скачанных файлов
└── media/ # сами файлы
- JSONL — источник истины. Файлы по месяцам,
syncтолько дописывает новыесообщения, старые никогда не трогает. index.db— производный слой. Можно удалить и пересобрать (./tg index --rebuild)в любой момент без потери данных.manifest.json— менеджер. Переживает пересборку индекса; хранит, какиечаты/топики отслеживаются и какие типы медиа для них качать.
Такое разделение (движок в git, открыто · данные — отдельно, приватно) позволяетсвободно развивать и делиться кодом, не рискуя утечкой переписки.
🧭 Команды
Поиск — основное для агента
| Команда | Что делает |
|---|---|
tg search <слова…> |
Полнотекстовый поиск. Флаги: --any (OR вместо AND), --chat, --topic, --sender, --from / --to, --media, --around N (контекст вокруг находок), --count, --by-chat / --by-topic / --by-sender (агрегаты), --rank (по релевантности), --json, --short N, --limit N|0 |
tg dump --chat X [--topic N] |
Хронологический кусок переписки целиком |
tg context --chat X --id N |
Сообщения вокруг конкретного (--before / --after / --whole-chat) |
tg chats |
Обзор чатов в архиве |
tg topics --chat X |
Топики форум-чата |
tg status |
Состояние архива и индекса |
Просмотрщики — ручной режим
| Команда | Что делает |
|---|---|
tg web |
Локальный веб-интерфейс: чаты → топики-чипы, бесконечная прокрутка, поиск с фильтрами, прыжок к дате, фильтр по автору (клик по нику), фото/видео инлайн, плеер голосовых с расшифровкой, реплаи с прыжком по треду, ссылки t.me. Порт — в config.toml [web] |
tg tui |
То же самое в терминале: / поиск · g дата · s автор · o/n старее/новее · c контекст · m открыть в Telegram · f открыть файл · Esc назад · q выход |
Качалка и менеджер
| Команда | Что делает |
|---|---|
tg dialogs |
Все чаты аккаунта (✓ — уже в архиве) |
tg download --chat <имя|id|@user> |
Скачать чат/топики и поставить на отслеживание. Флаги: --topic N, --from 2025-01, --media photo,voice|all|none |
tg sync [--chat X] |
Докачать новые сообщения всех отслеживаемых чатов |
tg media --chat X --media voice |
Докачать файлы для уже скачанных сообщений |
tg transcribe [--provider …] |
Расшифровать голосовые в текст, чтобы он попал в поиск |
tg untrack --chat X |
Снять чат с отслеживания (файлы остаются на диске) |
tg meta / tg index |
Обновить названия чатов / доиндексировать архив |
tg login [--account имя] |
Авторизовать Telegram-сессию (телефон / код / 2FA) |
Чат можно указывать как id, алиас из config.toml, часть названия, @usernameили ссылку t.me/.... Новые сообщения скачиваются со всеми реакциями, опросамии сервисными событиями.
🎙 Транскрипция голосовых
Провайдер задаётся в config.toml [transcription]:
| Провайдер | Стоимость | Требования |
|---|---|---|
whisper-local |
бесплатно, локально | faster-whisper, модель small по умолчанию |
telegram |
бесплатно | Telegram Premium на аккаунте |
openai |
платно (Whisper API) | OPENAI_API_KEY в .env |
👥 Несколько аккаунтов
[accounts]
default = "telegram.session"
backup = "sessions/backup.session"
tg login --account backup авторизует новую сессию. У download / sync /dialogs / meta есть флаг --account. Каждый чат в манифесте закреплён засвоим аккаунтом.
🗺 Статус
| Этап | Статус | Что входит |
|---|---|---|
| A | ✅ готово | Индекс, поиск, CLI, интеграция с Claude Code |
| B | ✅ готово | Качалка (download/sync, append-only), медиа по настройкам, бэкфилл, транскрипция, менеджер (manifest.json), несколько аккаунтов, FloodWait-защита |
| C | ✅ готово | Просмотрщики: tg web (браузер, медиа) и tg tui (терминал) |
Дальше: автосинк по расписанию, OCR картинок, Azure Speech-провайдер, экспорт выборок.
🔒 Безопасность
telegram.session и .env дают полный доступ к Telegram-аккаунту.Держите их в отдельном приватном репозитории с данными, не коммитьте в этоти никуда не публикуйте.
Сделано для того, чтобы агент помнил переписку лучше, чем вы сами.