MAX

Что попадает на диск, а что не попадает никогда

Документация: v0.25.0

Это инструмент к личной переписке. Поэтому вопрос «что он о ней записывает» здесь не приложение к документации, а её середина.

Коротко: от чего защищает

  • Чужое сообщение не должно управлять агентом. Сервер MCP не даёт инструментов записи, пока их не включили флагом --allow-* или группой в mcpTools в файле настроек, а с --confirm-send сам показывает вам форму перед каждым действием. «Да» в этой форме действует один раз, пять минут и только для того чата и текста, которые были в ней показаны (mcp.md). Инструменты чтения предупреждают модель, что текст сообщений — данные, а не команды.
  • Ограничения профиля работают везде. Режим «только чтение», список разрешённых действий, список получателей и лимит в час проверяет и сама команда, и фоновый сервер — даже для программы, которая подключилась к его сокету напрямую. Каждая попытка записывается в журнал без текста (ниже).
  • Агент не выйдет за свой профиль и не отправит ваши ключи. MAX_PROFILE_LOCK закрепляет профиль, а --file не берёт скрытые файлы, ~/.ssh и папки самого max.
  • Чужой текст не управляет терминалом. Управляющие и невидимые символы показываются как текст, имена и названия печатаются в одну строку, автодополнение подставляет только номера (ниже).
  • Сеть. Файлы качаются только по https, не с адресов этой машины и локальной сети и не больше заданного размера. Размер кадра от MAX и распакованных данных ограничен, у соединений есть тайм-ауты (ниже).
  • Токен. max не сохраняет токен из MAX_TOKEN и не передаёт его фоновому серверу. Фоновый сервер не отдаёт токен тем, кто подключается к его сокету (ниже).
  • Файлы. На Linux и macOS чувствительные файлы состояния, включая локальную переписку, защищены правами 0600 в каталогах 0700. Настройки могут иметь 0644; при перенаправлении вывода права задаёт оболочка. На Windows доступ определяют унаследованные ACL каталога пользователя (ниже).
  • Выпуск. Пакет публикуется из GitHub Actions с подтверждением происхождения. Шаг публикации не запускает код зависимостей, а версии прямых зависимостей закреплены точно.

Где живёт токен

В ключнице операционной системы: служба max-cli, запись — имя профиля. Не в файле настроек, не в аргументе команды, не в переменной оболочки, не в истории.

Если ключницы на машине нет, токен ложится в ~/.config/max-cli/credentials.json с правами 0600, и команда говорит об этом одной строкой на stderr. max doctor тогда так и пишет: токен в файле, а не в ключнице.

MAX_TOKEN старше ключницы: если переменная задана, берётся она. Так это работает в CI. Токен из переменной остаётся только в ней:

  • если MAX выдаст сессии новый токен, max не запишет его ни в ключницу, ни в файл, а скажет об этом одной строкой на stderr — на машине без ключницы живой токен иначе остался бы в файле, а файлы сборки часто уезжают в кэш и артефакты;
  • команда с MAX_TOKEN не запускает фоновый сервер max serve и не передаёт ему переменную: иначе токен одной команды жил бы в фоновом процессе ещё четверть часа.

Токен бота для max bot лежит рядом, но отдельно: та же служба max-cli, запись bot:<профиль>, без ключницы — тот же файл с правами 0600. MAX_BOT_TOKEN старше ключницы, как MAX_TOKEN. max bot auth set сначала спрашивает у MAX, чей это токен, и только потом сохраняет его, поэтому опечатка не затирает рабочий токен. Токен из MAX_BOT_TOKEN он не сохраняет никогда.

В файле настроек секрета быть не может: в схеме нет поля, куда его положить — ни для токена, ни для телефона, ни для идентификатора чата.

Что ещё пишется на диск

ЧтоГдеПрава
состояние профиля: устройство, счётчик входов, viewerId~/.local/share/max-cli/profiles/<профиль>.json0600
настройки~/.config/max-cli/config.json0644
записи запусков — с --record, а неудачные всегда: слова команды, id, время, код ошибки; текстов нет~/.local/share/max-cli/runs/…каталог 0700, файлы 0600
журнал отправок — всегда: чат, время, id, длина, исход; текста нет~/.local/share/max-cli/sends/<профиль>.jsonlкаталог 0700, файлы 0600
список разрешённых получателей, если включён~/.local/share/max-cli/profiles/<профиль>.recipients.json0600
правила модерации групп — после первого chats rules set~/.local/share/max-cli/profiles/<профиль>.moderation.json0600
бот: чаты, которые он видел, журнал отправок, список получателей, отметка watch~/.local/share/max-cli/bots/…каталог 0700, файлы 0600
общая локальная копия сообщений — личного аккаунта, бота и tg; с текстами и расшифровками голосовых~/.local/share/cli-messaging/messages.dbкаталог 0700, файл 0600
сокет и журнал фонового сервера max serve~/.local/share/max-cli/profiles/<профиль>.sock, .serve.log0600
прежняя локальная копия профиля; больше не открывается~/.cache/max-cli/<профиль>.db и её -wal, -shmкаталог 0700, файлы 0600
выгрузка переписки — только max store export --outputкуда вы укажете0600
скачанные файлы из сообщений — только max messages downloadтекущий каталог или --output0600
отчёт о проблеме — только max doctor report createтекущий каталог или --output0600
модели распознавания речи — только после max models audio download~/.cache/cli-common/models/audio/…каталог 0700, файлы 0600

⚠ Общая локальная копия содержит тексты сообщений и расшифровки голосовых — это её назначение: отвечать без сети. max session end её не удаляет. max store clear --left --allow-dangerous удаляет только данные покинутых чатов; удаления всей общей копии команда не предлагает.

Старые файлы кэша профиля больше не открываются. Если они остались, max doctor показывает путь; их можно удалить отдельно, не затрагивая общую копию.

Тексты или содержимое переписки есть ещё в локальной копии бота, в выгрузке и в скачанных файлах; в списке чатов бота — названия чатов. Остальное из списка переписки не содержит.

Если компьютер попадёт в чужие руки

На Linux и macOS права 0600 закрывают файлы от других пользователей этой машины, но не от того, кто достанет диск. От этого защищает шифрование диска целиком: FileVault в macOS, LUKS в Linux, BitLocker в Windows. На Windows режимы 0600 и 0700 не задают ACL: доступ зависит от разрешений каталога пользователя и выбранных каталогов MAX_*_DIR. Числа прав в таблице относятся к Unix. Своего шифрования у локальной копии нет: встроенный в Node SQLite его не умеет, а ключ в ключнице не остановил бы программу, запущенную под вашим пользователем, — она читает ключницу так же, как max.

Чего инструмент не делает

  • Не отмечает прочитанным без просьбы. «Получить историю» и «отметить прочитанным» — разные операции протокола. Вторую отправляют только max chats mark-read и messages list --mark-read, и на то, что чтение её не отправляет, есть тест.
  • Не отправляет ничего, чего не просили. Что-то меняют только messages send|edit|delete|forward|pin|unpin, reactions add|remove, polls vote|close|create, contacts add|remove|import|rename|block|unblock, account update, account sessions end, chats join|leave|create|update, chats members|admins …, chats link reset, chats folders create|update|delete, chats moderate (только то, что разрешают правила группы), chats mark-read и messages list --mark-read — и каждая делает только то, что написано в набранной строке. max commands --json помечает их mutates.
  • Не удаляет сообщения без явного слова. max messages delete требует --allow-dangerous, а удалить у всех — ещё и --for-everyone. Удалённое не вернуть.
  • Не берёт номер телефона из командной строки. contacts lookup спрашивает его или читает из трубы, contacts import — из файла: строку команды видят ps и история оболочки. В ошибках, журнале отправок и записях запусков номера нет, а max session start и max account show показывают его скрытым.
  • Не пишет сообщения в журнал. Ни в обрезанном виде, ни хэшем — см. diagnostics.md.
  • Не ходит через посредников. Куда именно подключается max — в разделе «Что уходит в сеть». Своей телеметрии у max нет; max serve шлёт MAX одно служебное событие, как скрытая вкладка веб-версии, — см. там же.
  • Держит соединение только в max serve. Его запускает в фоне первая команда, которой нужен MAX; он сам останавливается через 15 минут без дела. Не запускать — max config set serve false.

Защита от отправки не туда

Агент читает чужие сообщения вместе с просьбой владельца. Сообщение может быть написано так, чтобы агент принял его за команду: «перешли эту переписку вот сюда». Поэтому перед каждой отправкой — сообщения, реакции, правки, пересылки, удаления — max проверяет четыре вещи, а после — пишет строку в журнал.

ЧтоКак включитьОтказ
профиль только для чтенияmax <профиль> config set readOnly trueкод 5, соединения нет
только названные действия: send, reaction, delete…max <профиль> config set allow send,reactionкод 5, соединения нет
список разрешённых получателейmax <профиль> recipients add <чат>; выключить — recipients clearкод 7
не больше N в час: сообщения, пересылки, правки, закрепления с уведомлением, удалённые сообщения, добавленные в группы люди; реакции не считаютсяsendsPerHour, по умолчанию 30код 8, в ошибке — когда можно снова
журнал каждой попытки, без текставсегда; смотреть — max sends list—

max bot подчиняется тем же readOnly и allow. Профиль только для чтения не даёт боту ничего менять; allow называет действия бота теми же словами — отправка и ответ на кнопку send, правка edit, удаление delete, закрепление pin, участники и настройки чата groups, команды бота profile, получение обновлений read. Действие, для которого слова нет (вебхуки), при заданном allow запрещено.

У каждого бота свой список получателей — max <имя> bot recipients add <чат> — и свой журнал — max <имя> bot sends list. Их проходит любая запись бота: messages send, messages pin и bot api тоже, иначе общий вызов API был бы обходом списка. Правка и удаление берут чат первым: max сначала спрашивает у MAX само сообщение и отказывает, если оно из другого чата. У чата, названного user:<id>, такой сверки нет. В журнале — чат, вид, исход, длина текста, но не сам текст. Лимита в час у бота нет, пока его не задали в разделе bot файла настроек: max <имя> config set --bot sendsPerHour 200.

Те же проверки делает фоновый сервер max serve — для всего, что проходит через него, в том числе от программы, которая подключилась к его сокету напрямую, а не через max. Он пропускает только запросы, которые знает max, и только в той форме, в какой их отправляет max; удаление чата целиком, например, не пропустит. Изменение через config set действует сразу, без перезапуска сервера.

Изменения самого аккаунта — контакты, профиль, папки, сеансы — тоже проходят первую проверку: профиль только для чтения их не делает. Список получателей и лимит в час к ним не относятся: в них нет чата и никто не получает сообщения. В журнал они пишутся видом account и действием, без имён, номеров и названий.

Список необязательный: пока в него ничего не добавлено, отправлять можно в любой чат. Пустой, но включённый список — «никуда». Когда он включён, chats create <название> <люди…> и chats members add принимают только людей, личный чат с которыми есть в списке. Новый участник группы старых сообщений не видит, пока не передан --history. Отложенное сообщение считается в лимит того часа, когда уйдёт. Две команды, запущенные разом, лимит не перепрыгнут: место под лимитом держится от проверки до ответа MAX. Очистка данных покинутых чатов журнал отправок не трогает.

⚠ Чего это не держит. Проверки стоят в самом max, и агент с доступом к оболочке может снять их сам: поменять настройку, выключить список. Они защищают от модели, которую уговорило прочитанное сообщение, а не от агента, который хочет их обойти. Против такого — только граница снаружи: песочница, отдельный пользователь ОС, запрет в правилах самого агента.

Что стоит знать, выбирая такую границу:

  • Профиль закрепляет MAX_PROFILE_LOCK, а не MAX_PROFILE. Первое слово команды главнее MAX_PROFILE: агенту с MAX_PROFILE=agent достаточно набрать max work messages send …. MAX_PROFILE_LOCK=agent такой вызов отклонит — но только там, где агент не может сам поменять окружение: в настройках MCP-клиента или в скрипте-обёртке. Агент с оболочкой снимет переменную. MCP-сервер профиль закрепляет при запуске.
  • --file не отправляет скрытые файлы, файлы из скрытых папок (например, ~/.ssh) и из папок самого max: там лежат ключи и токены. --allow-any-file снимает запрет — агенту этот флаг ставить не от себя. Остальное, что может прочитать ваш пользователь, отправить можно; в журнал попадает только вид и размер вложения.
  • Правило агента вида «спрашивать перед max messages send» не видит форму с профилем — max work messages send. Надёжнее ограничить сам профиль: readOnly, allow или список получателей — и не держать рядом профиль без ограничений с действующим входом.

Чужой текст на экране

Имена, названия чатов, имена файлов и тексты сообщений пишут другие люди. max не даёт им управлять вашим терминалом и не даёт подделать то, что вы видите:

  • управляющие символы — те, что перекрашивают, стирают строки, меняют заголовок окна или содержимое буфера обмена, — показываются как текст (\x1b), а не выполняются; так же — невидимые символы и символы смены направления текста;
  • имя, название, подпись вложения печатаются в одну строку: перевод строки в имени не начнёт поддельную строку переписки или таблицы;
  • если набранное название совпадает с одним чатом целиком, а с другими частично, max не выбирает сам, а показывает все;
  • автодополнение подставляет только номер чата или человека; название — только подсказка рядом;
  • выгрузка в Markdown и пути скачанных файлов проходят ту же очистку; из имени скачанного файла управляющие символы убираются совсем.

Вывод --json — данные: строки в нём как прислал MAX, экранированные по правилам JSON. Отдавая его в программу, которая печатает на терминал, очищайте сами.

Что видно другим на машине

Аргументы команды видны в ps любому процессу. Поэтому токен не передаётся аргументом — но текст сообщения передаётся:

max messages send 0 "текст"     # эта строка видна в ps и остаётся в истории оболочки

Если это важно, передавайте текст так, как передаётся токен, — не через командную строку, а через окружение скрипта, который вы контролируете.

Файлы состояния и сокет фонового сервера защищены правами 0600 и каталогами 0700. У других файлов могут быть иные права, например 0644 у настроек. При переносе файлов или перенаправлении вывода проверяйте права отдельно.

Что уходит в сеть

КудаКогда
wss://api.oneme.ru/websocket, заголовок Origin — https://web.max.ruкаждая команда, которой нужен MAX
серверы файлов MAX — адрес выдаёт сам MAXmessages send --file, messages download
https://web.max.ru во временном профиле Chromiumsession start qr-chrome, session start sms, `setup --method qr-chrome
Hugging Face и GitHub — файлы модели распознавания речитолько max models audio download; голос туда не уходит — он распознаётся на этом компьютере
https://platform-api2.max.ru — официальный Bot API, токен в заголовке Authorizationтолько команды max bot
реестр npm — узнать номер последней версииmax upgrade; и раз в сутки, когда команду запускает человек в терминале. Выключается updateCheck: false

max messages download качает только по https и не идёт по адресам этого компьютера и локальной сети, в том числе после перенаправления. Файл — не больше 4 ГиБ, голосовое для расшифровки — не больше 32 МиБ.

Запросы max bot честно называют себя max-cli/<версия>: бота MAX и так знает по токену. Сертификат platform-api2.max.ru подписан корневым сертификатом Минцифры, которого нет в Node; max добавляет его только в свои запросы к Bot API и ничего не меняет в системе.

Для личного аккаунта на проводе нет имени этого инструмента и собственного user-agent: user-agent и описание устройства взяты у веб-клиента MAX. Кадры тоже как у веб-клиента: тот же адрес, двоичный формат и сжатие. Телеметрию веб-клиента max serve повторяет так, как её шлёт скрытая вкладка: одно событие «показан список чатов» через 20 секунд после входа, и больше ничего. В нём только номер вашего аккаунта и время — ни сообщений, ни названий чатов. Одноразовые команды телеметрию не шлют. После входа max serve запрашивает то же, что вкладка: папки, баннеры, историю звонков, наборы стикеров и реакций — только чтение; ответы нигде не показываются и не сохраняются. Одноразовые команды этого не делают. Отличия остаются: вкладка запрашивает ещё контакты, истории и подписку на push-уведомления, а max — нет. Поэтому MAX может отличить max от веб-клиента.

Правила MAX и ваш аккаунт

max — не официальное приложение MAX. Пользовательское соглашение MAX (редакция от 09.09.2026, п. 4.3.7) не разрешает автоматические программы без согласия компании. Поэтому аккаунт, с которым работает max, может быть ограничен — и это аккаунт, к которому бывают привязаны госуслуги и связь с близкими.

Что стоит делать:

  • Пользуйтесь MAX как обычно — в браузере или на телефоне, параллельно с max. Аккаунт, который только отвечает на запросы max, выглядит иначе, чем аккаунт живого человека.
  • Не превращайте max в поток запросов. Чтение по делу, а не каждую минуту по расписанию.

При первом входе профиля через max setup или max session start это же говорится один раз, на stderr.

Только для себя

Инструмент сохраняет на вашем компьютере переписку и контакты других людей, включая тексты сообщений. Доступ к локальной базе даёт доступ к этим данным. Выгрузка (max store export), переданная другому человеку, передаёт и содержимое переписки; ссылки на фото в ней могут открываться без входа. Перед передачей проверьте содержимое и круг получателей. Эта страница описывает работу инструмента, а не подтверждает соблюдение законодательства для вашего сценария.

Отчёт о проблеме (max doctor report create) прикладывается к открытой задаче на GitHub — его увидят все. Текстов, имён и телефонов в нём нет, номера чатов и сообщений заменены метками; перед отправкой файл можно открыть и проверить.

Вход через браузер

session start qr-chrome и sms запускают браузер с временным профилем — отдельной папкой, а не вашим профилем с паролями и cookie. В ней живёт вошедший web.max.ru, поэтому папка удаляется на любом выходе: после входа, при закрытом окне, по --timeout и по Ctrl-C. Токен мы читаем через канал отладки между нашим процессом и браузером (--remote-debugging-pipe): сетевого порта нет, и другой пользователь машины к браузеру не подключится.

session start qr рисует QR-код в терминале — он остаётся в прокрутке, но через пару минут истекает. Если терминал узкий, код показывается со страницы на 127.0.0.1 со случайным адресом; ссылка кода не пишется ни в файл, ни текстом. Страница пропадает, когда команда завершается.

Каждый такой вход добавляет устройство в список сессий приложения MAX. Завершить его можно там же.

Протокол неофициальный

MAX не публикует API для пользовательских аккаунтов. Всё, что здесь знают о протоколе, либо измерено на живом соединении, либо прочитано в чужой обратной инженерии — и у каждой операции записано, откуда именно (protocol.md, колонка «Where it came from»).

Практический вывод один: это может перестать работать без предупреждения, и тогда команда скажет об этом строкой на stderr, а не покажет пустой список как ни в чём не бывало.

Если токен утёк

max session end        # забыть локально

Этого недостаточно: session end ничего не говорит серверу, и сессия остаётся живой. Отозвать её можно только там, где она заводилась, — в официальном клиенте, через список устройств.

max account sessions end --others --yes завершает все остальные сеансы сразу — и приложение на телефоне тоже, после него там придётся входить заново. Завершить один сеанс нельзя: MAX не даёт сеансу номера. Если MAX в ответ выдаст этому сеансу новый токен, max сохранит его в связку ключей раньше, чем скажет «готово».

Дальше

  • diagnostics.md — что именно записывается и что не записывается никогда
  • sessions.md — ключница, MAX_TOKEN, чем session end отличается от отзыва
  • mcp.md — что может агент через MCP-сервер и что включает каждый флаг

На этой странице