ktalk-cli 视频会议记录处理命令行工具

ktalk-cli 是一个以编程方式处理 Kontur.Talk (KTalk) 视频会议记录的命令行工具,支持读取录制文件、转录文本和会议摘要、管理日程安排,并通过 SQLite 维护本地处理注册表,适用于自动化会议记录工作流以及作为 Claude Code 插件的运行前提。

  • by mdemyanov
  • Python
  • 本地部署
  • 5 星标
  • 更新于
在 GitHub 查看 mdemyanov/ktalk-mcp

使用说明

ktalk-cli

CLI ktalk — интерфейс командной строки для тех, кто работает с записями видеовстреч Контур.Толк (KTalk) программно: читает записи, транскрипты и саммари, управляет расписанием, ведёт локальный реестр обработки записей на SQLite. Годится и как самостоятельный инструмент, и как предусловие плагина Claude Code ktalk — подробнее в разделе «Пакет и плагин Claude Code» ниже.

Раньше пакет назывался ktalk-mcp и, помимо CLI, поднимал MCP-сервер для Claude Code (инструменты вида ktalk_list_recordings). Этот слой снят целиком — MCP в пакете больше нет, единственная точка входа — команда ktalk. Пришли по старой ссылке или ищете ktalk-mcp — это тот же проект под новым именем, старый пакет дальше не развивается (о конфликте имени команды при апгрейде — ниже, в «Установке»).

Умеет:

  • Список записей конференций и детали одной записи.
  • Транскрипты (речь по спикерам с таймкодами, с чанкингом для длинных).
  • Саммари и протоколы встреч.
  • Полный состав участников записи (обходит лимит в 6 из списковых ответов).
  • Скачивание видеофайла записи.
  • Историю чата встречи.
  • Конфигурацию комнаты и календарь запланированных встреч.
  • Предпросмотр и создание новой встречи — создание требует интерактивного терминала и явного подтверждения, см. «Планирование встречи» ниже.
  • Диагностику авторизации — жив ли токен и почему запрос не проходит.
  • Операционный реестр обработки записей на SQLite — синхронизация, статусы, markdown-зеркало для git, см. «Реестр записей» ниже.

Установка

Требуется Python 3.12+ и uv.

uv tool install ktalk-cli

Или через pip:

pip install ktalk-cli

Если на машине уже стоит старый ktalk-mcp (он тоже владел командой ktalk), uv tool install ktalk-cli откажет: uv не отдаёт занятое имя команды второму пакету молча. Сначала освободите имя:

uv tool uninstall ktalk-mcp
uv tool install ktalk-cli

Проверка версии — после установки или обновления:

ktalk --version    # печатает, например: ktalk-cli 2.1.0

Обновление до последней версии — та же команда install, только upgrade:

uv tool upgrade ktalk-cli

Авторизация

С версии 4.0.0 конфигурация каждого значения имеет ровно один источник (ADR-027): session token — только файл, записанный ktalk token set; адрес стенда — только config.toml, записанный ktalk config set base-url. Ни одна переменная KTALK_* и ни один .env в рабочем каталоге больше не читаются как источник значения — их присутствие не проходит молча: ktalk auth-status, ktalk doctor и тексты отказов называют обнаруженную снятую переменную по имени (значение не печатается никогда) и советуют её убрать.

С версии 3.0.0 CLI работает только через session token (кука браузера) — режим персонального API-ключа (KTALK_PERSONAL_API_KEY) снят целиком (ADR-025): он конкурировал с сессией молча (при обеих заданных переменных побеждал ключ без объяснения в тексте отказа) и диагностика auth-status объявляла заведомо невалидный ключ «валидным» на 403.

Цена снятия для тех, кто держал постоянный ключ: персональный ключ не протухал без предупреждения, session token — протухает. Постоянная работа теперь требует ручного обновления токена по мере его протухания (ktalk token set -, см. ниже) — это не восстанавливается автоматически снятием ключа.

Переменные KTALK_PERSONAL_API_KEY, KTALK_SESSION_TOKEN и остальные KTALK_*, если они всё ещё заданы в окружении (частая причина — блок env в ~/.claude/settings.json), не читаются ни на одном шаге — CLI печатает об этом одно предупреждение на stderr при каждом вызове и продолжает работу на файле токена/config.toml.

Session token

Session token — токен вашей браузерной сессии Толка. Единственный поддерживаемый источник credential (ADR-025). Живёт недолго и протухает без предупреждения — при регулярной работе повторяйте те же два шага ниже, когда команда начнёт отказывать кодом авторизации.

Два шага. На вкладке, где вы залогинены в https://your-domain.ktalk.ru, откройте DevTools (F12, или Cmd+Option+I на Mac) → Console и выполните:

copy(JSON.parse(localStorage.session).data.token)

Токен — в буфере обмена. Положите его в файл одной командой:

pbpaste | ktalk token set -          # macOS
xclip -o | ktalk token set -         # Linux (X11)

Команда сама создаёт ~/.config/ktalk-mcp/token с правами 0600 (каталог — 0700), отвергает значение, не похожее на токен, и никогда не печатает его в вывод. Проверка:

ktalk token status    # есть ли файл, права, маска значения
ktalk auth-status     # жива ли авторизация — реальный запрос, не имитация

Путь файла — ${XDG_CONFIG_HOME:-~/.config}/ktalk-mcp/token; переменной- переопределения нет (снятая KTALK_TOKEN_FILE не читается, ADR-027).

Единственный источник токена — этот файл (ADR-027). Переменная KTALK_SESSION_TOKEN и .env в рабочем каталоге не читаются вовсе: заданная переменная больше не перекрывает файл ни молча, ни с предупреждением — она просто не участвует в разрешении credential, а CLI называет её в выводе auth-status/doctor как снятую.

Ротация больше не может «застрять» на невидимой переменной: ktalk token set - перезаписывает файл, и следующий же вызов читает новое значение. Разводка источников из старых установок (переменная против файла, рунбук OPS-003) снята самим устройством 4.0.0 — переменную достаточно убрать из окружения.

Ни один запрос не несёт заголовок X-Auth-Token — единственный транспорт credential теперь query-параметр sessionToken.

Путь ~/.config/ktalk-mcp/token не переименован вместе с пакетом и остаётся таким намеренно: он выбран независимо от имени дистрибутива (каталог ktalk/ уже занят другим — санкцией на запись, у неё свой жизненный цикл), а смена пути молча лишила бы уже настроенные машины третьего источника авторизации.

Токен из файла обслуживает и чтение, и запись: создание и отмена встречи шлют то же значение другим транспортом (заголовок Authorization: Session, а не query-параметр) — источник значения транспорт не меняет. Санкция на запись при этом остаётся обязательной, она к токену отношения не имеет.

Файл с правами шире 0600 читается так, будто его нет (ktalk token status покажет usable: False) — секрет не должен молча читаться с диска, доступного другим пользователям машины.

Важно: session token имеет ограниченный срок жизни. Если команда возвращает ошибку авторизации, повторите те же два шага — ktalk token set - перезаписывает файл, права переставлять не нужно.

Конфигурация: адрес стенда (config.toml)

Адрес контура задаётся один раз, машинной командой:

ktalk config set base-url https://your-domain.ktalk.ru

Команда пишет ${XDG_CONFIG_HOME:-~/.config}/ktalk-mcp/config.toml (рядом с файлом токена, права 0644 — адрес не секрет) и отвергает значение без схемы http(s) или без хоста до записи. Проверка — ktalk config show: секция ## Толк называет адрес, путь config.toml и статус файла токена.

Переменные окружения и .env больше не читаются вовсе (4.0.0, ADR-027). KTALK_BASE_URL, KTALK_SESSION_TOKEN, KTALK_PERSONAL_API_KEY, KTALK_REGISTRY_DB, KTALK_TOKEN_FILE и .env в рабочем каталоге не участвуют в разрешении ни одного значения. Если какая-то из них всё ещё задана, ktalk auth-status и ktalk doctor называют её по имени и советуют убрать — значение при этом не печатается никогда.

Диагностика авторизации

Проверьте авторизацию без запроса записей:

ktalk auth-status

Диагностика различает два случая, которые снаружи выглядят одинаково — просто ошибка, — но чинятся по-разному:

  • 401 — токен невалиден либо истёк. Вердикт alive: false, код возврата 1. Обновите токен: ktalk token set - — файл перезаписывается, права переставлять не нужно.
  • 403 — токен рабочий, но у текущей сессии нет прав на эту операцию. Вердикт alive: true, код возврата 0: нехватка прав не является отказом токена, и перевыпускать его не нужно.

У session token понятия scope и срока действия нет — диагностика выполняет реальный пробный запрос (список записей), а не имитацию без сети.

--json-ответ — {"alive": bool, "note": str | None}. Отказ пробного запроса виден по обоим каналам сразу: поле alive: false в теле ответа И ненулевой код возврата процесса — полагаться только на один из двух нельзя.

Команды чтения записей и справочников

Все команды поддерживают --json (валидный JSON в stdout; ошибки — в stderr с ненулевым кодом возврата).

Коды возврата

Код Значение
0 Успех.
1 Отказ вызова — сеть, сервер, конфигурация.
2 Usage error — неверные аргументы CLI (argparse).
3 Только ktalk get-transcript. Данные получены и напечатаны полностью, но независимая сверка идентичности не сошлась (identity_check.result == "mismatch") — состав участников транскрипта разошёлся с составом записи. Это не сбой команды: код 3 отличает «данные есть, но сверка не сошлась» от 0 (сошлось или не проверялось) и от 1/2 (данных нет вовсе). Подробности — в самом теле ответа, поле identity_check (ADR-024 §Д1).
Команда Назначение
ktalk list-recordings [--query Q] [--start-from ISO] [--start-to ISO] [--top N] [--order O] [--page-token T] Список записей. --top 1–1000 (по умолчанию 30); --order: byTimeNewFirst (умолчание), byTimeOldFirst, byTitle, bySizeBigFirst, bySizeSmallFirst.
ktalk get-recording <recording_key> Детали записи — автор, дата, длительность, участники (список ограничен 6, полный состав — get-participants).
ktalk get-transcript <recording_key> [--chunk N] [--chunk-size N] Транскрипт по спикерам с таймкодами. Длинный транскрипт режется на чанки по границам реплик: --chunk 0 (умолчание) — целиком или первый чанк; --chunk-size — макс. символов в чанке (умолчание 30000, ~7500 токенов). Независимая сверка идентичности включена по умолчанию (--no-verify-identity отключает); --chunk вне диапазона сверку по сети не запускает вовсе, identity_check.result == "not_checked"/reason: "chunk_out_of_range".
ktalk get-summary <recording_key> Полное саммари (краткое резюме + протокол).
ktalk get-summary-type <recording_key> --type shortSummary|protocol Саммари одного типа.
ktalk get-participants <recording_key> Полный состав участников, включая анонимных — обходит лимит в 6, который отдают get-recording/list-recordings.
ktalk download-recording <recording_key> --target PATH [--quality Q] Скачивает видеофайл потоково, без буферизации в памяти. Существующий файл не перезаписывается; --quality не указано — берётся дефолт для записи (например 900p).
ktalk list-archive --from ISO --to ISO [--room-name N] Архив встреч за период. Недоступна — архив никогда не имел рабочего пути под session token; команда отказывает до сети с явным сообщением на каждый вызов (ADR-025).
ktalk get-chat-messages [--recording-key K | --conference-key K] [--channel C] Сообщения чата встречи; один из двух ключей обязателен. Канал не указан — определяется автоматически.
ktalk get-room <room_name> Конфигурация комнаты — политики аудио/видео/демонстрации, модераторы, SIP, чат, маскирование. Побочный эффект: если комнаты с таким именем ещё нет, она создаётся.
ktalk list-calendar --start ISO --end ISO [--room-name N] Встречи за окно дат, видимые активной авторизации — это не «ваш личный календарь», а всё, что видит текущая авторизация, включая чужие встречи. Сервер лимитирует один запрос семью днями и сотней встреч на сегмент — команда сама режет произвольное окно на сегменты; при упоре в потолок ответ предупреждает о возможно неполной выдаче.

Планирование встречи

Создание встречи — единственная операция пакета, которая что-то меняет вне вашего компьютера: она рассылает приглашения реальным людям. Удаление созданного события эти письма не отзывает. Из-за этого создание устроено умышленно неудобно:

  • Создание — команда ktalk create-meeting-confirm. Она работает только в интерактивном терминале (проверяет, что и ввод, и вывод — реальный TTY) и перед отправкой печатает предпросмотр и требует набрать слово да.
  • Предпросмотр без создания — ktalk create-meeting-preview, не делает ни одного сетевого запроса.
  • Обе команды используют session token — единственный оставшийся режим авторизации (ADR-025).

Ни одно поле не имеет значения по умолчанию (кроме описания встречи — пустая строка, если не задано). Тема, начало, конец, часовой пояс, комната, участники, анонимный доступ, PIN — каждое нужно передать явно; иначе команда откажет и назовёт, какого поля не хватает. Так сделано намеренно: молчаливый часовой пояс сдвинет встречу в календаре участников на другое время, а молчаливая автозапись незаметно для организатора изменит, записывается ли встреча.

Из этого вытекают практические следствия:

  • Часовой пояс принимает только форму GMT±N (пример GMT+3) — IANA-имена вида Europe/Moscow, смещения ISO и аббревиатуры сервер не распознаёт.
  • --enable-auto-recording и --allow-anonymous принимают только явные true или false — «флаг просто не указан» не считается ответом.
  • «Встреча без обязательных участников» — это отдельный флаг --no-required-attendees, а не просто отсутствие --required-attendee-key. Значение --required-attendee-key — числовой id участника, не логин.
  • «Без PIN» — отдельный флаг --no-pin-code, а не пустая строка в --pin-code.
  • --anonymous-access-expiration обязателен, только если --allow-anonymous true.

Повторяющиеся встречи в этой версии не поддерживаются — можно создать только разовое событие.

При сетевом сбое во время создания команда не повторяет запрос сама: если сеть оборвалась, неизвестно, ушло приглашение или нет, и автоматический повтор рискует создать дубль. Решение о повторной попытке — за вами; перед ней стоит проверить ktalk list-calendar, не появилась ли встреча уже.

Создание встречи ещё ни разу не выполнялось на боевом окружении — команда реализует задуманное поведение, но не проверена живым вызовом.

# Предпросмотр — без сети, без побочных эффектов
ktalk create-meeting-preview \
  --subject "Синк по проекту" \
  --start 2026-08-20T10:00:00 --end 2026-08-20T10:30:00 --timezone GMT+3 \
  --room-name "Переговорная 1" \
  --no-required-attendees \
  --enable-auto-recording false --allow-anonymous false \
  --no-pin-code

# Создание — только в интерактивном терминале, требует ввода "да"
ktalk create-meeting-confirm \
  --subject "Синк по проекту" \
  --start 2026-08-20T10:00:00 --end 2026-08-20T10:30:00 --timezone GMT+3 \
  --room-name "Переговорная 1" \
  --required-attendee-key 123 --required-attendee-key 456 \
  --enable-auto-recording false --allow-anonymous false \
  --no-pin-code

API

CLI работает с KTalk Web API через единственный (session token) режим авторизации (см. «Авторизация» выше) — query-параметр sessionToken, внутренний недокументированный контур API:

Эндпоинт Описание
GET /api/recordings Список записей
GET /api/recordings/{id} Детали записи
GET /api/recordings/{id}/transcript Транскрипт
GET /api/recordings/v2/{id}/summary Полное саммари (v2)
GET /api/recordings/{id}/summary/{type} Саммари по типу

Архив встреч (list-archive) недоступен: под session token у него нет и никогда не было рабочего пути (ADR-025) — команда отказывает до сети с явным сообщением.

OpenAPI спецификация talk.public.api-api-2.json включена как справочник, но содержит расхождения с реальным API (пути, формат авторизации, структура ответов). Пути, достижимые только под снятым режимом персонального ключа (X-Auth-Token), больше не применимы к этому CLI.

Реестр записей (ktalk)

Та же команда ktalk ведёт операционный реестр обработки записей на SQLite. Вся детерминированная механика (синхронизация списка записей, дедуп, смена статусов, рендер дашборда и markdown-зеркала, разовая миграция) живёт в коде, а не в рассуждениях модели.

SQLite — операционный source of truth. Markdown-файл registry.md — генерируемое read-only зеркало для git (ktalk export), руками не редактируется.

Путь к базе: флаг --db PATH > registry.db_path из .ktalk.toml проекта-хозяина > машинный дефолт централизованного хранилища (ADR-013; переменная KTALK_REGISTRY_DB снята в 4.0.0 и не читается, ADR-027).

ktalk auth-status, ktalk create-meeting-preview и ktalk create-meeting-confirm реестр не открывают вовсе — им он не нужен. В частности, auth-status работает даже если файла базы данных нет или он недоступен. Планирование встречи — отдельный раздел «Планирование встречи» выше.

Команда Назначение
ktalk sync [--days N] [--json] [--dry-run] Загрузить записи из KTalk и upsert'нуть их в реестр (новые — new, существующие — с обновлёнными не-статусными полями; статус ни одной записи не меняется). Без --days окно — от момента последней синхронизации минус 1 день запаса (первый запуск — 90 дней); --days N — явное переопределение нижней границы. Идемпотентно. --dry-run — сверить id с реестром без записи, ничего не пишет. В --json-ответе ключа expired больше нет (4.0.0): смены статуса как побочного эффекта чтения не происходит.
ktalk token set <значение|-> Записать session-токен в ~/.config/ktalk-mcp/token (0600). - — прочитать из stdin: pbpaste | ktalk token set -. Значение не печатается.
ktalk token status [--json] Есть ли файл токена, его права и маска значения.
ktalk auth-status [--json] Диагностика активной авторизации — жив ли токен. См. «Диагностика авторизации».
ktalk config set base-url <url> Записать адрес стенда в ~/.config/ktalk-mcp/config.toml (0644). См. «Конфигурация: адрес стенда».
ktalk config show [--json] Машинная конфигурация оператора (адрес, путь config.toml, статус файла токена) и резолвленный .ktalk.toml проекта-хозяина.
ktalk dashboard [--json] Дашборд: новые записи, статистика по статусам.
ktalk list [--status S] [--json] Список записей с фильтром по статусу.
ktalk show <id> [--json] Детали записи: участники, статус, пути, длительность.
ktalk mark-processing <id> Перевести в processing.
ktalk mark-done <id> --transcript P --protocol P [--type T] Завершить, проставить пути и processed_at.
ktalk mark-partial <id> [--transcript P] [--protocol P] Частичная обработка.
ktalk mark-skipped <id> Пропустить вручную.
ktalk set-vault-id <id> <ktalk_id> <vault_id> Привязать профиль к участнику.
ktalk export [--out PATH] [--full] Сгенерировать markdown-зеркало.
ktalk migrate <vault> [--dry-run] [--json] Разовый импорт из markdown-реестров.

Несколько фоновых агентов могут безопасно писать параллельно (WAL + busy_timeout

  • транзакция на операцию).

Разработка

git clone https://github.com/mdemyanov/ktalk-cli.git
cd ktalk-cli
uv sync

# Запуск тестов
uv run pytest -v

# Линтинг
uv run ruff check .

# Локальный запуск CLI (токен и адрес — файлами, см. «Авторизация»)
pbpaste | uv run ktalk token set -
uv run ktalk config set base-url https://your-domain.ktalk.ru
uv run ktalk auth-status

Пакет и плагин Claude Code

ktalk-cli работает и сам по себе, и как предусловие плагина Claude Code ktalk. Плагин не обращается к KTalk напрямую и не поднимает MCP-сервер — он вызывает эту же команду ktalk как единственную точку входа в контур.

Плагин пинует точную версию пакета (не нижний порог: «ровно эта версия», не «эта или новее») в собственном файле совместимости. Если что-то в интеграции с плагином ведёт себя не так, как описано в его документации, — первым делом сверьте версию:

ktalk --version    # см. «Проверка версии» в разделе «Установка»

Версия не совпадает с той, что требует плагин, — обновите пакет тем же способом, что при установке (uv tool upgrade ktalk-cli, см. «Установка»); не совпадает в другую сторону (пакет новее, чем ожидает плагин) — не откатывайте его самостоятельно, сверьтесь с тем, кто настраивал плагин.

Проблемы и вопросы

Нашли баг, некорректное поведение или неточность в документации — заведите issue в этом репозитории: https://github.com/mdemyanov/ktalk-cli/issues.

Лицензия

MIT