CLI tools

Личный аккаунт: как пользоваться

This page is in Russian.

Эта страница — про ваш личный аккаунт. Бот, который работает через официальный Bot API, — на bot.md.

Каждая команда делает одно дело, печатает результат и завершается. Подключение к MAX держит только max serve: его запускает в фоне первая команда, которой нужен MAX, и он сам останавливается через 15 минут без дела.

max [профиль] [опции] <ресурс> <действие> [аргументы]

Полный список команд и опций — commands.md, он собирается из самой программы.

Первая минута

max session start qr     # QR-код в терминале, токен уйдёт в ключницу
max chats list           # ваши чаты

Больше для чтения ничего не нужно.

Вход

Проще всего — max session start qr: в терминале появится QR-код, вы отсканируете его приложением MAX, и токен ляжет в ключницу. Все способы входа — docs/sessions.md. Без способа max session start импортирует токен, полученный в официальном клиенте, и кладёт его в ключницу операционной системы.

max session start
MAX token: ▏               # ввод не отображается

Токен не передаётся аргументом, и это не придирка: аргумент виден в ps любому процессу на машине и остаётся в истории оболочки. Поэтому он либо спрашивается у терминала без эха, либо читается из трубы:

pass show max/token | max session start

Для CI и разовых запусков есть MAX_TOKEN — он старше ключницы, то есть если переменная задана, берётся она:

MAX_TOKEN="$(cat /path/to/token)" max chats list

Проверить, кто вы:

max account show                # номер телефона — только последние 4 цифры
max account show --show-phone   # номер целиком

Забыть сессию на этой машине:

max session end

session end стирает токен локально и ничего не говорит серверу MAX: сессия, открытая в браузере, продолжает жить. Это видно и в ответе — revokedOnServer: false.

Профиль — первое слово

Несколько аккаунтов живут рядом. Профиль называется первым словом, а не флагом:

max chats list              # профиль default
max personal chats list     # профиль personal

Правило простое: первое слово — это профиль, если оно не совпадает с именем команды. Поэтому профиль нельзя назвать chats — при создании такое имя будет отвергнуто, с объяснением.

Для целой сессии оболочки удобнее переменная:

export MAX_PROFILE=personal
max chats list

У каждого профиля свой токен, своё состояние и свой кэш.

Чтение

max chats list                      # все чаты
max chats list --limit 5            # первые пять
max chats list --unread             # только чаты с непрочитанным
max chats show "Иван Петров"        # один чат: вид, непрочитанное, последнее сообщение, участники
max contacts list                   # люди, с кем есть личный чат
max contacts show @ivan             # один человек и общие с ним чаты
max messages list 0                 # сообщения чата по id
max messages list "Иван Петров"     # или по имени чата
max messages list 0 --limit 50

Чат адресуется id или частью названия. Если часть названия подходит к двум чатам, команда откажется угадывать и покажет кандидатов: отправить не в тот разговор — необратимо.

Человек в contacts show адресуется так же: id, @username или часть имени, и двух подходящих команда тоже не угадывает. Найти можно любого, кого знает локальная копия, — и участника группы, который контактом не считается. В ответе — имя, @username и чаты, общие с ним, свежие сверху. Команда только читает; найти человека не значит ему написать.

chats show отвечает одним объектом: поля строки из chats list и members — кто в чате, кроме вас. У канала members — null: MAX присылает четырёх подписчиков из тысяч, и выдать их за состав канала значило бы соврать.

Непрочитанное во всех чатах и то, что пришло с прошлой проверки:

max inbox                               # непрочитанное — по счётчику MAX, у каждого сообщения чат
max inbox --new                         # что пришло с прошлой проверки, каждое сообщение один раз
max inbox --new --jsonl                 # то же для скрипта: одно сообщение на строку
max inbox --since 2026-09-24T09:00      # разовый взгляд с этого времени

max inbox ничего не помечает прочитанным, поэтому отвечает одно и то же, пока сообщения не прочитаны в приложении. Для запуска по расписанию — --new: место, где остановились, хранится в профиле и сдвигается, только когда вывод напечатан. Первый --new смотрит на последние 24 часа. --since это место не двигает. Свои сообщения не показываются. Больше --limit в одном чате (по умолчанию 20) — показаны самые новые, а в stderr — команда, которой прочитать остальное. За один запуск читается не больше 20 чатов; остальные названы в stderr и в skipped.

Одно сообщение и то, что было вокруг него — чат и id сообщения обязательны (id выдуманные):

max messages show -1000 100000000000000001
max messages context -1000 100000000000000001 --before-n 3 --after-n 3

В ленте искомое помечено ◀, в JSON — "anchor": true. Если такого сообщения нет — удалено или чат не тот — это ошибка «не найдено», а не соседнее сообщение. --before-id у messages list работает для любого id: время отправки зашито в сам id. Сообщение можно назвать и одной ссылкой msg:… из вывода messages search — тогда id после неё не нужен.

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

max messages download -1000 100000000000000001 --output ~/Downloads

У файла остаётся его имя, у остального — <id сообщения>-<номер>.<расширение>. Существующий файл не перезаписывается: команда остановится с ошибкой и назовёт его. Видео сохраняется как самый крупный MP4; звонки, ссылки и стикеры не скачиваются, и об этом будет строка в stderr. Сохранённые файлы доступны только владельцу (права 600).

Голосовые в текст

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

max models audio list                # какие модели есть, какие скачаны, какая по умолчанию (*)
max models audio download gigaam-v3  # 233 МБ, один раз
max messages transcribe "Иван Петров" 100000000000000001
МодельЯзыкиРазмер5 минут речи
gigaam-v3 — по умолчаниюрусский — лучше всех с русским233 МБ~40 с
gigaam-v3-ctcрусский — чуть быстрее, хуже с заглавными буквами226 МБ~36 с
parakeet-v325: болгарский, хорватский, чешский, датский, нидерландский, английский, эстонский, финский, французский, немецкий, греческий, венгерский, итальянский, латышский, литовский, мальтийский, польский, португальский, румынский, словацкий, словенский, испанский, шведский, русский, украинский671 МБ~60 с

Время — на ноутбуке с Ryzen AI 9 HX 470 в один поток. Другую модель можно взять на один раз — --model parakeet-v3 — или насовсем, строкой "transcribeModel": "parakeet-v3" в разделе defaults файла настроек. Каждый скачанный файл сверяется с контрольной суммой, записанной в max; не совпало — файл не устанавливается.

Текст сохраняется в локальной копии: повторный вызов отвечает сразу, без сети и без модели. Пока идёт распознавание, соединение с MAX уже закрыто. Памяти нужно около 700 МБ (parakeet-v3 — 1,3 ГБ).

Расшифровать сразу все голосовые в чате или во входящих:

max messages list "Иван Петров" --transcribe
max inbox --transcribe

--transcribe слушает только показанные голосовые, у которых ещё нет текста; --model выбирает модель на один раз. Сначала max скачивает все нужные записи, потом закрывает соединение и только тогда запускает модель. Текст печатается под голосовым со значком 🎤, в --json — полем transcript. Что расшифровать не удалось, перечислено в unheard, причина — строкой в stderr; сообщения всё равно печатаются. Если модель не скачана, команда назовёт, как её скачать, но сама не скачивает. Модели лежат в ~/.cache/cli-common/models/audio — одна копия для max и tg.

Уже расшифрованные голосовые показывают текст и без флага: он лежит на этом компьютере. С --offline новые голосовые не расшифровываются — записи не скачать без сети.

Чтение ничего не помечает прочитанным. Протокол разделяет «получить историю» и «отметить прочитанным», и без просьбы вторая операция не отправляется; на это есть тест. Отметить чат прочитанным можно явно — собеседник это увидит:

max chats mark-read "Иван Петров"                  # до последнего сообщения
max chats mark-read "Иван Петров" --until 100000000000000001   # до этого сообщения включительно
max messages list "Иван Петров" --mark-read        # прочитать и отметить показанное

Отметка проходит те же проверки, что отправка: профиль только для чтения и список получателей её не пропустят, в лимит сообщений в час она не считается. С --offline — отказ.

Обзор: кто кому что должен

max review                                   # всё за последние 3 дня
max review --since 2026-09-23T09:00          # с конца прошлого обзора
max review --since 2026-09-23T09:00 --transcribe --json

Все сообщения — и ваши, и чужие — во всех чатах, где что-то было с --since. Нужно, чтобы понять, что вы обещали, чего ждёте от других и что осталось неясным; разбирать их — дело ваше или агента. Ничего не отмечает прочитанным.

Команда заканчивает строкой в stderr: с какого по какой момент прочитано. Следующий обзор начинайте с этого --since, тогда ничего не потеряется между двумя обзорами. Если обзор неполный — чатов слишком много, чат обрезан или голосовое не расшифровано, — команда так и скажет, и границу лучше не сдвигать.

--transcribe расшифровывает голосовые, у которых ещё нет текста: медленно, до минуты на пять минут речи, и только если модель уже скачана (Голосовые в текст). Без флага в ответе будет текст уже расшифрованных, а остальные — в списке unheard.

Вопросы без ответа

max review --unanswered                      # вопросы, на которые сутки никто не ответил
max review --chat "Соседи" --unanswered 4    # в одной группе, без ответа 4 часа

--unanswered [часы] оставляет только вопросы, которые ждут ответа — ваш или админов группы. Вопрос — сообщение со знаком «?» или ответ на ваше сообщение или сообщение админа. Он считается отвеченным, если вы или админ ответили на него, или заговорили первыми после того, кто спросил. Вопросы моложе заданного часа (по умолчанию 24) не показываются: на них ещё не успели ответить.

Кто админ, MAX сообщает при входе, но только для чатов, где недавно что-то было. Если для группы этого нет, команда так и скажет, и ответом будут считаться только ваши сообщения. Ответ, пришедший после конца обзора, команда не видит. --chat ограничивает обзор одним чатом, и с --unanswered, и без.

Страницы

У chats list и contacts list — три опции страниц; у messages list, inbox, sends list, runs list — только --limit, у chats members list и chats events — ни одной:

max contacts list --limit 5             # по пять в странице
max contacts list --limit 5 --page 2    # шестой по десятый
max contacts list --all                 # всё, без страниц
max contacts list --order name          # по алфавиту вместо «кто писал последним»

--all вместе с --page — отказ, а не тихая победа одного из них. --limit можно записать в файл настроек; --page и --all — нельзя, номер страницы в файле нужен ровно один раз и потом мешает.

⚠ Номер страницы на живом списке может повторить или пропустить строку. Сверху самое свежее, поэтому сообщение, пришедшее между первой страницей и второй, сдвигает кого-то через границу. Так устроен любой постраничный вывод; здесь об этом написано, а не обойдено.

У сообщений страниц нет — у них есть --before-id, потому что история и так привязана ко времени, и листать её назад можно точно, а не приблизительно:

max messages list 0 --limit 20
max messages list 0 --before-id 116762160362694583        # id самой старой строки, которую вы видите
max messages list 0 --before-time 2026-09-20T01:00:00Z    # работает и когда того сообщения уже нет
max messages list 0 --after-id 116762160362694583         # что пришло после этого сообщения
max messages list 0 --after-time 2026-09-20T01:00:00Z     # или после этого времени

--after-id и --after-time — чтение вперёд: --limit сообщений после указанной точки, от старых к новым, а подсказка на stderr называет следующую страницу: --after-id <id последней строки>. Из четырёх опций годится одна: две вместе — отказ, это разные начальные точки, а не отрезок между ними.

Сама точка в ответ не попадает ни с --before-id, ни с --after-id: MAX отдаёт и её, а эта программа отбрасывает, чтобы следующая страница не начиналась с последней строки предыдущей. С --offline годится только --before-id, и только с id сообщения, которое есть в локальной копии.

Время — в ISO 8601 или как «столько назад»: 30m, 2h, 1d (--after-time 7d — за последнюю неделю). Если id не находится в локальной копии — а удалённое сообщение выглядит именно так, его уже нет и в истории, которую отдаёт MAX, — команда скажет об этом и назовёт второй способ.

Найти чат, потом писать в него

max chats list --search иван             # чаты, в названии которых есть «иван»
max chats list --search work --kind group # только группы
max chats list --unread --kind dialog    # личные чаты, где есть непрочитанное
max contacts list --search петров        # люди по имени или @username
max messages search "договор"            # по тексту сообщений, которые уже прочитаны
max messages search "договор" --chat 42  # в одном чате

Искомое — не меньше трёх символов: по двум буквам совпадёт половина списка, и это не ответ. chats list с --search, --kind или --unread смотрит 200 самых свежих чатов и скажет, если были старше; с --offline — все сохранённые.

Найдя нужный чат, дальше обращайтесь к нему по id — он в выводе, и он не меняется:

max messages list 42 --limit 20
max messages send 42 "текст"

Часть названия там тоже принимается — и в max messages search --chat: поиск идёт по локальной копии и не подключается к MAX, а имя ищется среди сохранённых чатов. В поиске каждое слово должно встретиться как слово или его начало (квартир найдёт «квартира»); --regex — одно регулярное выражение без учёта регистра.

Кто считается контактом

max contacts list отвечает людьми, с которыми есть личный чат, свежий разговор сверху. Остальные участники ваших групп тоже сохраняются — с именами и с тем, какие чаты у вас общие, — но контактами не считаются и в этом списке не появляются.

Адресной книги здесь нет: у MAX нет операции, которая бы её отдала, поэтому доступны только люди из чатов, в которых вы состоите. Контакты держатся свежими сами: каждая команда входит в аккаунт, а каждый вход просит у MAX только то, что изменилось с прошлого раза.

max contacts sync     # забыть, где остановились, и забрать список заново

Это ремонт, а не обычный путь. Он нужен, если локальная копия разъехалась или её обнулило обновление схемы. Ответ — только числа: ни имени, ни телефона, ни описания.

Отправка

max messages send 0 "текст"
max messages send "Иван Петров" "текст"

Подтверждения отправка не просит: адресат и текст уже написаны в строке, которую вы набрали.

Текст из трубы

Оставьте последний аргумент — и тело прочитается со стандартного ввода:

echo "текст" | max messages send 0
max messages send 0 <<'EOF'
первая строка

третья
EOF
cat письмо.txt | max messages send 0

Так пишется многострочное сообщение, которое аргументом не передать вовсе, и так текст не попадает ни в ps, ни в историю оболочки — то же правило, по которому токен не принимается аргументом. Переносы строк сохраняются все, кроме одного в самом конце: его добавляет echo, и без этого почти каждое сообщение заканчивалось бы пустой строкой.

⚠ Если ввод — терминал, команда откажет, а не будет ждать. max messages send 0 без текста — это забытый аргумент, а не приглашение печатать; команда, которая молча ждёт, неотличима от зависшей.

Если ответ не пришёл, команда отвечает outcome_unknown (код возврата 14) — не «отправлено» и не «ошибка», потому что сообщение могло уйти. В сообщении об ошибке будет --send-id — номер, с которым попытку можно повторить, не рискуя вторым сообщением:

max messages send 0 "текст" --send-id 1789784741828

MAX не создаёт второго сообщения, если повтор пришёл с тем же cid.

Отправить позже

max messages send 0 "напоминание" --at-time 2026-09-25T09:00   # местное время
max messages send 0 "напоминание" --at-time 2h                # или через 30m, 2h, 1d
max messages scheduled 0                                       # что ждёт отправки в этом чате

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

  • Ответ — сообщение в очереди, с полем scheduledFor. Когда оно уйдёт, у него будет другой id.
  • С --silent — отказ: приложение MAX всегда присылает отложенное с уведомлением.
  • Защиты отправки (только чтение, список получателей, лимит в час) считают сообщение сейчас, в момент постановки в очередь.
  • Если ответа нет, повтора не будет: outcome_unknown советует проверить очередь, а --send-id с --at-time не принимается. Схлопывает ли MAX повтор отложенного, не проверено.
  • Отменить или изменить — в приложении MAX. max удаление не отправляет.

Ответ и реакция

max messages send 0 "да" --reply-to 100000000000000001   # ответ на сообщение в том же чате
max reactions add 0 100000000000000001 👍                 # реакция; прежняя ваша заменяется

Реакцию видит собеседник, как и ответ. Снять свою реакцию: max reactions remove 0 100000000000000001.

При чтении реакции печатаются под сообщением — 👍 3 🔥 1 (you: 🔥); в JSON это поле reactions: {counts: [{reaction, count}], mine, total}. null значит «не спрашивали»: с --offline или если MAX не ответил — тогда в stderr одна строка о причине.

Правка, пересылка, закрепление

max messages edit 0 100000000000000001 "новый текст"          # только своё; вложения остаются
max messages forward 0 100000000000000001 --to "Коллеги"      # переслать одно сообщение в другой чат
max messages pin 0 100000000000000001                         # закрепить, без уведомления участникам
max messages pin 0 100000000000000001 --notify                # закрепить и уведомить
max messages unpin 0 100000000000000001                       # открепить; в чате MAX закреплено одно сообщение

Правку видит собеседник, и старый текст он мог уже прочитать. MAX разрешает править своё сообщение 7 суток. Пересланное сообщение не правится. Пересылка — это новое сообщение: она проходит те же проверки, что отправка, и считается в sendsPerHour. Правка и закрепление с --notify тоже считаются; тихое закрепление проходит проверки, но в лимит не идёт. Если пересылка ответила outcome_unknown, повторяйте её только с --send-id из ошибки — MAX оставит одну копию. Повтор без него будет второй копией.

Закрепить можно только в группе или канале — в личном чате и в «Избранном» MAX не закрепляет, и команда отказывает сразу.

Удаление

max messages delete 0 100000000000000001 --allow-dangerous                   # только у вас
max messages delete 0 100000000000000001 100000000000000002 --allow-dangerous # несколько, до 10
max messages delete 0 100000000000000001 --for-everyone --allow-dangerous    # у всех в чате

Удаление нельзя отменить, поэтому без --allow-dangerous команда отказывает и ничего не спрашивает. По умолчанию сообщение пропадает только у вас; у собеседника оно остаётся. С --for-everyone оно пропадает у всех — это собеседник уже не вернёт.

Удаление проходит те же проверки, что отправка. Каждое удалённое сообщение считается в sendsPerHour, как одна отправка, и за раз можно удалить не больше 10: много удалений подряд похоже на автоматизацию, за которую MAX блокирует аккаунт. Удалённое пропадает и из локального кэша, и из поиска.

Опросы

max polls create 0 "Обед?" "Да" "Нет" --multiple     # опрос отдельным сообщением
max polls show 0 100000000000000001                  # варианты с id и сколько за каждый
max polls vote 0 100000000000000001 1                # голос за вариант с id 1
max polls vote 0 100000000000000001 --retract        # снять голос, если опрос это разрешает
max polls close 0 100000000000000001                 # закрыть свой опрос; открыть снова нельзя

При чтении опрос печатается под сообщением: вопрос, варианты с id в [скобках] — его и берёт polls vote, — число голосов и ✓ у вашего. В JSON это поле poll у вложения: {id, question, answers: [{id, text, votes, mine}], total, multiple, anonymous, revote, closed, quiz}. Опрос версии новее известной печатается одной строкой без вариантов. polls show и ответы polls vote|close — общий с tg вид: {chatId, messageId, question, answers: [{id, text, voters, chosen}], closed, multiple, anonymous, voters}; у vote и close он в поле poll рядом с operationId. С --revote в опросе, созданном polls create, можно переголосовать.

web.max.ru опросы не показывает: вместо опроса там надпись «Обновите MAX…». Кто читает чат в браузере, ваш опрос не увидит — только в приложении на телефоне или компьютере.

Голос видят другие участники, если опрос не анонимный. Команда отказывает сама, не спрашивая MAX, как отказывает веб-клиент: опрос закрыт; несколько вариантов там, где можно один; второй голос там, где переголосовать нельзя; варианта с таким id нет. Голос, закрытие и новый опрос проходят те же проверки, что отправка: голос — как реакция, закрытие — как правка, новый опрос — как сообщение. В sendsPerHour считаются новый опрос и закрытие; голос, как и реакция, — нет. Голос не повторяется сам. Для агентов: max_polls_vote и max_polls_create в max mcp — только с --allow-send, max_polls_close — только с polls в настройке mcpTools (mcp.md).

Контакты, профиль, папки

max contacts lookup                         # спросит номер; или: echo "+7…" | max contacts lookup
max contacts add 20000002                   # id из lookup, или часть известного имени
max contacts remove 20000002
max contacts rename 20000002 "Соседка" "Анна" # своё имя для человека; он его не видит
max contacts block 20000002                 # больше не сможет вам писать
max contacts unblock 20000002
max contacts import книжка.csv              # строка: номер, запятая или табуляция, имя
max account update --description "о себе"   # имя остаётся прежним
max account update --photo портрет.png      # новое фото профиля
max account sessions list                   # где ещё выполнен вход
max account sessions end --others --yes     # выйти везде, кроме этого сеанса — и на телефоне
max chats folders list
max chats folders create "Работа" --chat -1000 --chat "Проект"
max chats folders update "Работа" --title "Офис" --add -2000 --remove -1000
max chats folders delete "Офис"             # чаты остаются

Номер телефона не пишется в строку команды — её видят ps и история оболочки. Добавленный человек, с которым нет диалога, в contacts list не появится (там только те, с кем есть переписка); его видно через contacts show <id>. Заблокировать можно и того, кого нет в контактах. Короткого имени (@имя) у личного аккаунта MAX не даёт: любое отклоняется как «This name is unavailable». Название папки — не длиннее 20 знаков: длиннее MAX не принимает, и max откажет сам, ничего не отправляя. import отправляет в MAX номера других людей.

Фото, видео, файлы и голосовые

max messages send 0 "отчёт" --file отчёт.pdf
max messages send 0 "с дачи" --file ролик.mp4          # видео, которое смотрят прямо в чате
max messages send 0 --file ролик.mp4 --as-file       # то же видео файлом для скачивания
max messages send 0 --photo снимок.png                # фото
max messages send 0 --voice заметка.ogg              # голосовое сообщение

С --file .jpg .jpeg .png .webp .gif уходят фотографией, .mp4 .mov .webm .mkv — видео, остальное — файлом. С --as-file файл из --file уходит файлом, видео тоже. --photo берёт только .jpg .png .webp. В сообщении одно вложение из --file и одно из --photo; видео и файл — только сами по себе, и команда откажет до загрузки. Текст необязателен. Если загрузка не удалась, ничего не отправлено. Несколько файлов в одном сообщении max сейчас не отправляет. --no-preview в MAX не работает: собственный клиент MAX так не умеет, и команда откажет.

--voice отправляет голосовое: с полоской громкости и длительностью, как записанное в телефоне. Оно уходит одно — без текста, файла и фото рядом. Файл должен быть в формате Ogg Opus, в каком голосовые записывает сам MAX; другой звук сначала переведите:

ffmpeg -i запись.m4a -ac 1 -ar 48000 -c:a libopus -b:a 32k заметка.ogg

Файл из скрытой папки или скрытый файл (например, из ~/.ssh) и файлы из папок самого max не отправляются: там лежат ключи и токены. Если такой файл действительно нужен — --allow-any-file.

С --md текст размечается — и в send, и в edit: **жирный**, _курсив_ или *курсив*, ~~зачёркнутый~~, `код`. Без флага звёздочки и подчёркивания уходят как есть. _ и * внутри слова не считаются разметкой (file_name останется file_name), а \* оставляет знак буквально.

max messages send 0 "встреча **в 15:00**, не _в 14_" --md

Группы и каналы

Сценарии для админа группы, все правила и ограничения — groups.md.

max chats inspect https://max.ru/join/…          # что за ссылкой; не вступает
max chats join https://max.ru/join/…             # вступить в группу или канал
max chats leave "Семья"                          # выйти
max chats create "Поход" "Аня" 20000002          # создать группу с людьми (имя или id)
max chats create "Новости" --channel            # закрытый канал; люди входят по ссылке-приглашению
max chats members list "Поход"                   # все участники: когда заведён аккаунт, когда был в сети
max chats members add "Поход" "Боря"             # без старых сообщений; с ними — --history
max chats members remove "Поход" "Боря"
max chats admins add "Поход" "Аня" --can members,pin
max chats admins remove "Поход" "Аня"              # снять права; участником остаётся
max chats update "Поход" --title "Поход-2026" --description "в июле"
max chats show "Поход"                           # настройки группы — в поле settings
max chats update "Поход" --all-can-pin off       # поменять одну
max chats link show "Поход"                      # ссылка-приглашение, если вам её видно
max chats link reset "Поход"                     # новая ссылка; старая перестаёт работать
max chats events "Поход"                         # кто вступил, вышел, кого добавили и удалили — за 7 дней
max chats events "Поход" --event add,remove --since 2026-09-01T00:00

Всё это видят другие люди: вступление, выход, добавление, новое название. Кроме inspect, settings без флагов, events и members list — они только читают. Действия идут через те же проверки, что отправка: профиль только для чтения откажет, список получателей пустит только в свои чаты, а в журнал отправок попадает действие без названий и ссылок. create и members add считаются в лимит отправок в час по одному на каждого человека — им приходит сообщение. Если список получателей включён, людей можно звать, только если личный чат с каждым есть в списке. Ничего не повторяется при сбое: повтор create — вторая группа.

events берёт служебные сообщения из истории чата: кто что сделал и с кем. События называются так, как их называет MAX: new — чат создан, add — добавили, remove — удалили, pin — закрепили. Другие названия команда покажет как есть. За один запуск читается до 2000 сообщений, начиная с самых старых; если их больше, команда подскажет, с какого места продолжить.

members list спрашивает список у MAX, поэтому работает и для каналов, и для больших групп: chats show показывает только тех, кого видела локальная копия. У каждого — роль (owner, admin, member; её нет, если MAX не прислал при входе, кто в группе админ), когда заведён аккаунт в MAX (registeredAt: совсем новый аккаунт в группе стоит проверить) и когда человек был в сети (lastSeenAt; пусто, если он это скрыл). За один запуск — до 5000 человек.

Удалить участника можно, стереть его сообщения — нет. Удалить чат целиком — тоже нет, намеренно. Права админа для --can: read, members, admins, info, pin, link, post, edit, delete. read — читать все сообщения группы, как переключатель «Read messages» в приложении; без него бот в группе не видит ни одного сообщения. link — менять ссылку-приглашение.

Правила модерации

max chats rules show "Поход"                          # правила группы; без них — значения по умолчанию
max chats rules set "Поход" invites delete            # приглашения в чужие чаты — удалять
max chats rules set "Поход" newAccount.days 3         # аккаунт моложе трёх дней — отметить
max chats rules set "Поход" trusted 30000003,30000004 # этих людей правила не трогают
max chats rules set "Поход" consent.delete confirm    # перед удалением — спрашивать
max chats rules unset "Поход" consent.delete          # вернуть значение по умолчанию

Правила хранятся на этом компьютере, в файле рядом с настройками профиля; команда называет его в ответе. Первое set для группы записывает все правила сразу, со значениями по умолчанию, так что в файле видно всё, что можно поменять. Файл можно править и руками — rules show скажет, если в нём ошибка.

По умолчанию ни одно правило ничего не делает, только отмечает (report). Что правило может делать сверх этого: delete — удалить сообщение, remove — удалить человека. Отдельно, для каждого действия, — насколько вы его разрешаете (consent.delete, consent.remove): forbid — никогда, flag — только с --allow-dangerous (по умолчанию), confirm — спрашивать каждый раз, allow — без вопросов.

Проверка группы

max chats check "Поход"                       # что нового нарушает правила; делает то, что разрешено
max chats check "Поход" --dry-run             # только показать
max chats check "Поход" --allow-dangerous     # сделать и то, что стоит на уровне flag
max chats check "Поход" --since 2026-09-20T00:00

Проверка смотрит, что появилось в группе с прошлой проверки (в первый раз — за сутки): сообщения, кто вступил в группу. Каждое сообщение она сверяет с правилами: заблокированный автор, приглашение в другой чат, ссылка, пересланное, флуд. Вступивших — со списками и возрастом аккаунта. Вас, админов и людей из trusted правила не трогают.

Что делать с найденным, решают правила группы и уровень согласия для каждого действия. По умолчанию всё только отмечается. На каждую строку ответа — что нашлось, кто, по какому правилу, какое действие и чем кончилось: reported — отмечено, done — сделано, planned — не сделано, ждёт флага или вашего ответа (рядом — команда, которой это сделать руками), forbidden — запрещено правилами, declined — вы ответили «нет», refused — не пустили проверки профиля или лимит в час, skipped — не дошла очередь.

За одну проверку — не больше 10 действий (--max-actions). Удаления считаются в лимит отправок в час; упёрлась в лимит — остальное откладывается. Если что-то осталось не сделанным, следующая проверка начнёт с первого такого сообщения. Удалённый человек может вернуться по ссылке: забанить через этот аккаунт нельзя.

Заявок на вступление в MAX нет: группа либо открытая, либо в неё входят по ссылке-приглашению.

Для скриптов и агентов

max chats list --json

--json — это ровно одно значение JSON на stdout и больше ничего: ни спиннера, ни галочки, ни предупреждения. То же самое происходит само, когда stdout не терминал, то есть в трубе и в CI.

Любой список отвечает одним объектом, всегда одним и тем же — и у бота тоже. У списка без страниц page — 1, limit — сколько пришло, hasMore — false:

{ "items": [ … ], "page": 1, "limit": 20, "hasMore": true }

--all и --offline отвечают тем же объектом — --all с page: 1 и hasMore: false. Форма не говорит, откуда взялись строки: об этом уже говорят код возврата и диагностика, а тому, кто разбирает ответ, ветвиться на две формы незачем.

hasMore — это «есть ли ещё страница», а не сколько всего: считать строки, которых MAX не присылал, — второй вопрос со своей ценой. Для чатов и контактов он точен, они посчитаны в локальной копии; ⚠ для сообщений это утверждение о нашей копии, а не о чате — полная страница назад и есть единственное свидетельство, что за ней что-то есть.

В терминале вместо объекта по-прежнему таблица, а строчка про следующую страницу уходит на stderr: stdout несёт данные в любом режиме, а подсказка листателя — не данные.

--jsonl — по объекту на строку, без обёртки: удобно для потока и для jq. Есть ли ещё страница, в этом режиме говорит только строчка на stderr.

max messages list -1000 --jsonl | jq 'select(.senderId == "111")'

Как выглядит переписка

max messages list и max messages search в терминале печатают ленту, а не таблицу:

── 3 января 2026 ──

10:05:12  Анна
          созвонимся в четверг?

10:09:03  вы
          ↳ Анна: созвонимся в четверг?
          Договорились.
          📎 photo
          edited 10:09:30

Время местное, разделитель — при смене дня. вы — ваши сообщения, собеседник без имени — его id. ↳ — на что это ответ, ↪ — чьё сообщение переслано. 📎 — вложение; в терминале с цветом это ссылка, без цвета — адрес рядом.

-v добавляет id сообщения, отправителя, чата и адреса вложений; -vv — всё, что известно о сообщении. Версия — max -V.

Ошибка уходит на stderr, а stdout остаётся пустым — так отказ невозможно принять за результат:

{"error":{"code":"authentication_error","message":"no session for profile \"default\" — run `max session start`"}}

Ветвиться надо по коду возврата, а не по тексту: текст меняется, код — нет. Вся таблица — в commands.md, а самые частые: 4 — нет сессии, 6 — не найдено, 9 — таймаут, 14 — исход неизвестен.

if ! max messages send 0 "текст" --json > /dev/null; then
  case $? in
    14) echo "могло уйти, повторять только с тем же --send-id" ;;
    4)  echo "нужен max session start" ;;
  esac
fi

Локальная копия и новые сообщения

Что max хранит у вас, как держать это свежим (max serve, max watch), как скачать историю чата и выгрузить её в файл — archive.md.

Что команда делала

По умолчанию записывается только запуск, который кончился ошибкой (diagnostics.md). Две отдельные вещи включают диагностику:

max chats list --trace      # показать, ничего не сохраняя
max chats list --record       # сохранить, ничего не показывая

--trace печатает по строке на запрос — на stderr, поэтому --json рядом не ломается:

→ session.login     op 19  seq 2  871 B
← session.login     op 19  seq 2  213ms  48.0 kB  25 chats  6 contacts

--record кладёт то же самое в каталог запуска и хранит 30 дней:

max runs list                 # что делалось, новое сверху
max runs show <id>            # один запуск: чем кончился и куда ходил
max runs path <id>            # каталог, для jq и grep

В записи нет содержимого. Операция, опкод, номер запроса, идентификаторы, байты и длительности — да. Название чата, имя человека, текст сообщения, номер телефона, токен — никогда, ни в обрезанном виде, ни в виде хэша.

Настройки

Необязательный файл ~/.config/max-cli/config.json:

{
  "defaultProfile": "personal",
  "profiles": {
    "personal": { "limit": 50, "timeoutMs": 20000, "color": true, "record": false, "keepRunsForDays": 30 }
  }
}

Порядок, в котором решается любая настройка: флаг → переменная окружения → файл → встроенное значение. В файле профиль сильнее общих defaults, а разделы personal и bot задают значения отдельно для личного аккаунта и для ботов (max config set --personal …, --bot …). Все поля, defaultProfile и mcpTools в том числе, — configuration.md. Опечатка в имени поля — ошибка с именем поля, а не молчаливое значение по умолчанию.

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

Что профилю можно

allow — список действий, которые профилю разрешены. Без него разрешено всё, как раньше.

max work config set allow send,reaction      # только писать и ставить реакции
max work config unset allow                  # снова всё
max config set --defaults allow send          # для всех профилей, у которых нет своего списка

Имена: send — отправить (текст, файлы, ответ, отложенное), forward, reaction, edit, pin, read — отметить прочитанным, delete, groups — всё с группами и каналами, contacts, profile — свой профиль, folders, sessions — завершить другие сеансы. Звёздочки нет: чтобы разрешить delete или sessions, их надо назвать.

Список профиля заменяет список из defaults, а не добавляется к нему. Пустой список — ничего, как readOnly; readOnly сильнее любого списка. Отказ — код 5, до подключения к MAX, и в ошибке готовая команда, которая это действие разрешит. Удаление всё равно требует --allow-dangerous.

Дальше

  • commands.md — полный справочник, собранный из программы
  • configuration.md — файл настроек целиком
  • installation.md — установка, обновление, куда что ложится

On this page