Repository navigation
diagnostics
Эта страница нужна, когда команда упала, зависла или идёт слишком долго и хочется понять почему. Прочитав её, вы сможете видеть запросы команды по ходу работы, сохранить запись о запуске, проверить установку и отправить отчёт о проблеме, в котором нет текста сообщений.
Слова, которые здесь встречаются:
-
Запуск — один вызов
max, от старта до выхода. - Запись запуска — каталог, где хранится, что делал один запуск: команда, итог и по строке на каждый запрос к MAX. Текстов сообщений, имён и названий в нём нет никогда.
-
max personal doctorпроверяет установку: версию, вход, настройки и локальную копию. -
Отчёт о проблеме — один файл JSON из ответа
max personal doctorи неудачного запуска. Его прикладывают к задаче на GitHub.
| Задача | Команда | Что сохраняется |
|---|---|---|
| Видеть каждый запрос по ходу работы | max … --trace |
ничего, только вывод в stderr |
| Сохранить запись одного запуска | max … --record |
запись запуска |
| Найти неудачный запуск позже | max personal runs list |
неудачный запуск сохраняется сам |
| Сохранять каждый запуск | max personal config set record true |
запись каждого запуска |
| Проверить установку |
max personal doctor, max personal doctor --online
|
ничего |
| Составить отчёт о проблеме | max personal doctor report create |
один файл, который вы отправляете |
max personal chats list --trace→ session.init op 6 seq 1 432 B
← session.init op 6 seq 1 89ms 335 B 38 reg-country-code
→ session.login op 19 seq 2 871 B
← session.login op 19 seq 2 202ms 48.0 kB 25 chats 6 contacts
→ contacts.info op 32 seq 3 154 B 3 contacts
← contacts.info op 32 seq 3 91ms 6.5 kB 10 contacts
→ — что спросили, ← — что пришло, • — ответ, который не уходил в сеть. Дальше по строке:
операция, опкод протокола, номер запроса в соединении, названные идентификаторы, длительность,
размер кадра и сколько чего вернулось.
Всё это идёт в stderr, поэтому рядом с --json ничего не ломается:
max personal chats list --json --trace > chats.json # данные в файл, диагностика на экранВ терминале — строки выше. В трубе — по одному объекту JSON на строку, по тому же правилу, что и для данных:
max personal chats list --json --trace 2>&1 >/dev/null | jq -c 'select(.event == "response")'--trace сильнее --quiet: флаг, который вы дописали сами, срабатывает всегда.
У max <имя> bot … одна строка на HTTP-запрос к Bot API: операция, идентификаторы из адреса
(чат, сообщение, человек, комментарий), HTTP-код, время, размер ответа.
max shop bot messages list -100 --trace→ getMyInfo
← getMyInfo 200 143ms 211 B
→ getMessages chat -100
← getMessages 200 chat -100 187ms 6.2 kB
Отказ показывает код ошибки и ключ MAX, например 404 not_found not.found, но не текст
ответа. Загрузка файла (--file, uploads put) — отдельная пара строк upload.image,
upload.video и так далее: размер, HTTP-код, время. Адреса загрузки и имени файла в ней нет: адрес
сам работает как пропуск.
max personal chats list --record
max personal runs list # что делалось, новое сверху
max personal runs show <id> # один запуск: чем кончился и куда ходил
max personal runs path <id> # каталог, для jq и grepКаталог запуска:
~/.local/share/max-cli/runs/2026-09-19/20260919T234428Z-chats-list-9df39e/
run.json что это было, когда, какой профиль, сколько длилось, чем кончилось
events.jsonl по объекту JSON на запрос, без единого управляющего символа
Каталог — 0700, оба файла — 0600. run.json пишется дважды: как только запуск начался, со
статусом running, и в конце — с итогом. Поэтому каталога с событиями, но без описания запуска, не
бывает.
Итог записывается на любом пути — в том числе когда команда упала, не успев подключиться:
{ "run_id": "…", "command": "chats list", "profile": "default", "status": "failed",
"requests": 0, "error_code": "authentication_error", "duration_ms": 12 }Если команда кончилась ошибкой, её запуск сохраняется и без --record — с пометкой
"kept_because_failed": true в run.json. Это касается любой команды и любой ошибки: неверного
флага, неизвестной команды, проверки до начала работы, команд, которые в MAX не ходят (models,
server, watch, upgrade). В записи — только слова команды, например messages list, без того,
что было написано после них.
Полностью удачный запуск без --record записи не оставляет; частичный результат сохраняется по умолчанию. Поэтому у отчёта о проблеме всегда есть что
приложить. --no-record или "record": false в настройках отключают и это.
Удачные запросы поиска и статистики хранят свою историю, отдельно от записей запусков. В ней параметры запросов, но не найденные сообщения. Как ею управлять — в разделе сохранённые поиски и история.
max personal config set record true # этот профиль
max personal chats list --no-record # но не этот запускТо же в файле настроек:
{ "profiles": { "default": { "record": true } } }Тогда пишется каждый запуск. По умолчанию полностью удачный запуск не записывается, пока не попросили:
каталог с тем, кого и когда вы читали, был бы дневником вашей жизни, о котором никто не просил.
--no-record или "record": false отключают и запись запусков, и историю поиска.
30 дней, или keep_runs_for_days в настройках. Старое удаляется только тогда,
когда что-то записывается: инструменту, который ничего не пишет, незачем ходить по этому каталогу.
Удаляется днями целиком, по имени каталога, поэтому ничего не нужно открывать, чтобы решить.
| Записывается | Не записывается никогда |
|---|---|
| операция, опкод, номер запроса | название чата |
идентификатор чата, номер отправки (send), идентификатор сообщения |
имя человека |
| сколько байт ушло и пришло | текст сообщения |
| сколько миллисекунд занял ответ | номер телефона |
| сколько чатов, контактов, сообщений вернулось | токен |
код ошибки и короткий ключ ошибки MAX вида login.token
|
текст ошибки, пришедший от MAX |
предупреждение — кодом, например reactions_unread
|
текст предупреждения |
| при падении — тип ошибки и строки кода, где оно случилось | текст ошибки при падении |
версия, среда (node или bun), система |
путь к домашнему каталогу |
Ни в обрезанном виде, ни хэшем. Событие собирается из полей, названных по именам, а не
фильтрованием копии запроса: поле, которого никто не предвидел, в журнал попасть не может. У
session.login есть поле token — и ни одна ветка в коде до него не дотягивается.
Идентификаторы, наоборот, в записи есть. Идентификатор чата — число, бесполезное без сессии, к которой он относится. И только он делает диагностику полезной: любая настоящая жалоба — про один конкретный разговор.
Текст ошибки MAX не записывается по той же причине: отказ сервера может цитировать то, что ему
послали, а послано могло быть и сообщение. Записывается только ключ — строчные латинские буквы,
цифры, точки и дефисы, как proto.payload. Если MAX ответил чем-то другим, не пишется ничего.
То же верно и для отчёта, собранного из запуска.
max personal doctor # никуда не подключается
max personal doctor --online # ещё и входит в MAX один раз; ничего не отправляетБез --online он печатает, не подключаясь к MAX, то, от чего зависит любая команда:
- есть ли токен и откуда, какая запись в ключнице и не сдвинули ли её переменные окружения (сам токен не печатается никогда — только «есть» и «откуда»);
- сколько было входов и когда последний; все профили на этой машине — личный аккаунт, бот или оба;
- общее хранилище: в ответе
--jsonполеitem.store— путь, схема и число сохранённых чатов и сообщений. Проверка не создаёт и не обновляет хранилище.item.legacy_cacheтолько указывает, есть ли старый файл локальной копии; если он есть,doctorподсказывает путь для ручного удаления; - каталог запусков;
- какой версией веб-клиента MAX
maxпредставляется, и дату, когда её прочитали. Если этой дате больше 60 дней,max personal doctorпредупредит: MAX может перестать принимать старую версию, и тогда поможет обновлениеmax; - чем запущен
max(Node или Bun, и где), каким менеджером пакетов поставлен, какую командуmaxнайдёт новый терминал, грузятся ли ключница и SQLite, скачана ли модель речи. Если каталог с командойmaxне наPATH,max personal doctorпечатает точные команды, которые его туда добавят: на Windows — для PowerShell, на Linux и macOS — строкуexport; - пауза входа после отказа MAX за слишком частые входы, если она есть.
У профиля бота max <имя> doctor показывает токен бота (откуда он), сколько чатов бот видел и где
лежат файлы профиля: состояние, кеш, записи запусков, файлы ботов, журнал отправок и общее
хранилище сообщений.
--online — один вход, один чат из списка, затем сервер MCP запускается так, как его запускает
клиент, и отвечает списком инструментов. Ничего не отправляет и ничего не отмечает прочитанным.
Вход засчитывается в лимит MAX на входы, поэтому при ошибке он не повторяется. Если какая-то часть
не прошла, код возврата — не 0. Если у профиля есть токен бота, --online ещё спрашивает у Bot
API, чей это токен, и печатает имя и id бота. Если личного токена нет, вход в MAX не делается.
max personal doctor report create # о последнем неудачном запуске
max personal doctor report create --run <id> # об этом запускеКоманда пишет файл JSON — то, что показывает max personal doctor, и запуск — и печатает ссылку на новую
задачу в github.com/WireCatLabs/max-cli/issues. Прочитайте
файл, прежде чем отправлять. Текстов сообщений в нём нет, а номера чатов и сообщений заменены
метками. Что ещё в нём есть — в разделе как сообщить о проблеме.
Если неудачного запуска нет, запустите упавшую команду ещё раз: её ошибка сохранится сама.
Записи — это JSON, поэтому на вопросы о них отвечает jq. max personal runs list --json отвечает
{ items, page: { limit, has_more } }, а items — это run.json запусков, новые сверху:
# какие запуски закончились плохо
max personal runs list --json | jq '.items[] | select(.status=="failed") | {run_id, command, error_code}'
# сколько времени ушло на вход в последних запусках
for id in $(max personal runs list --json | jq -r '.items[].run_id'); do
jq -r 'select(.operation=="session.login" and .event=="response") | "\(.duration_ms)ms"' \
"$(max personal runs path "$id" --json | jq -r .item.path)/events.jsonl"
donemax personal runs show печатает те же события таблицей, без служебных полей, которые повторяются в каждой
строке: иначе таблица уезжает за правый край экрана раньше, чем доходит до длительностей. Файл
целиком, со служебными полями, лежит в каталоге, который печатает max personal runs path.
max personal runs search --error-code rate_limited --json
max personal runs search --status partial --since-time 2026-10-01 --jsonruns search ищет буквальный текст в метаданных и безопасных диагностических событиях;
--operation, --profile, --since-time, --limit и --page уточняют поиск. Одна страница — до 100
запусков; в запуске возвращается до 100 совпавших событий, events_truncated сообщает о сокращении.
Ошибка отдельного файла или страницы истории создаёт частичную запись status: "partial" с
неудачными ID, этапами и кодами. Текст сообщений и текст отказа сервера в неё не копируются.
Запись сохраняется по умолчанию, если её явно не выключили. Поиск сам не создаёт новый запуск.
В MCP вызовите max_read с command: "runs search"; поля arguments: query, status, error_code, operation, since_time, limit,
page. Он читает только записи активного профиля, не подключается к MAX и не открывает сырые
журналы фоновых заданий. Полный результат частичной команды называет неудачные элементы и коды их ошибок;
диагностическая запись сохраняет только безопасные идентификаторы и коды.