Для ИИ-агентов
Управляйте `openemail` из Claude Code, Codex или задания CI: вход без участия человека, справка как данные, пробные запуски, недостающие scope и коды подтверждения.
Встроенное руководство
openemail agents выводит короткое руководство в Markdown для ИИ-агента вроде Claude Code или Codex или для скрипта в CI: как войти без человека, читать вывод, находить команды, безопасно что-то менять и листать списки, что делать, когда не хватает кода подтверждения или scope, и пять готовых рецептов. openemail agent это та же команда.
openemail agentsopenemail agents --json | jq -r '.recipes[].commands[]'С --json руководство становится одним документом с schemaVersion, title, intro, sections из { id, title, points }, exitCodes и recipes из { id, title, commands }. Вместо того чтобы вставлять эти правила в каждый промпт, один раз скажите агенту в файле инструкций, который ваш проект ему уже даёт, запускать openemail agents перед работой с CLI.
Вход без участия человека
- Используйте API-ключ. Задайте
OPENEMAIL_API_KEYили передайте--api-keyодной команде. Создайте его в разделе «Настройки → API-ключи» (openemail open api-keys) только с теми scope, которые нужны агенту. Ключ никогда не открывает браузер и никогда не требует кода подтверждения. - Или используйте повторно вход через браузер, который человек один раз выполнил на этой машине через
openemail login, и выберите его через--profile <name>. CLI сама обновляет свои токены. - Без терминала ничего не спрашивается. Под
--json,--no-inputилиCI, либо без подключённого терминала, значение, которое CLI спросила бы, приводит к остановке с кодом выхода2, и называется флаг, который нужно передать. - Вход через браузер должен одобрить человек, поэтому
openemail loginбез участия человека останавливается с кодом выхода2и кодомunattended, прежде чем что-либо зарегистрировать, и указывает наopenemail login --with-token. openemail whoami --jsonпоказывает рабочее пространство, вид входа и егоscopes.
Чтение вывода
Передавайте --json каждой команде. Тогда stdout содержит ровно один JSON-документ или один объект на строку с --ndjson, а ход работы остаётся в stderr. Сбой выводит одну строку {"error":{...}} в stderr: ветвитесь по коду выхода и по её code, показывайте next человеку и никогда не разбирайте message, формулировка которого может измениться. Страница «Скрипты» перечисляет каждое поле и каждый код выхода.
Команды как данные
--help --json выводит справку одним JSON-документом, построенным из того же реестра команд, по которому CLI разбирает аргументы, поэтому он всегда соответствует установленной версии. Это работает на корне, на группе или на команде, а openemail help <command> --json выводит то же самое.
openemail send --help --jsonopenemail domains delete --help --json | jq '.commands[0] | {scopes, destructive}'openemail help domains --json | jq -r '.commands[0].subcommands[].command'openemail --help --json | jq -r '.commands[].command'Документ
schemaVersionnumber- Меняется, когда поле меняет смысл
cli, versionstring- Всегда `openemail`, и версия, которая его вывела
pathstring[]- Запрошенная команда, пустой для корня
commandsobject[]- Для корня каждая команда верхнего уровня, иначе запрошенная, каждая со своими подкомандами
globalFlagsobject[]- Флаги, которые принимает каждая команда, в том же виде, что и флаги команды
subcommandAliasesobject- Каждый общий псевдоним, например `ls` или `rm`, и глаголы, которые он заменяет
exitCodesobject[]- Каждый код выхода в виде `{ code, name, meaning }`
Команда
namestring- Последнее слово команды
commandstring- Вся команда, например `openemail domains delete`
path, aliasesstring[]- Слова после `openemail`, которые ведут к ней, и её другие имена
summary, descriptionstring- Что она делает, одной строкой и полностью
usagestring[]- Как её вызвать
categorystring | null- Её раздел в `openemail --help` для команды верхнего уровня, иначе `null`
group, runnable, hiddenboolean- Есть ли у неё подкоманды, запускается ли она сама по себе и не скрывает ли её справка
authstring- Вход, который ей нужен: `required`, `browser` только для входа через браузер, `optional` или `none`
scopesstring[]- Scope API, которые нужны каждому её запуску
destructiveboolean- Спрашивает ли она сначала подтверждение, на которое отвечает `--yes`
argumentsobject[]- `name`, `description`, `required` и `variadic` каждого аргумента
flagsobject[]- `name`, `short`, `kind`, `required`, `repeatable`, `choices`, `placeholder`, `description` и `hidden` каждого флага
notes, examplesobject[]- Дополнительные блоки справки в виде `{ title, lines }` и примеры в виде `{ command, note }`
resourceobject | null- Для команды ресурса метод SDK и вызов REST за ней, иначе `null`
subcommandsobject[]- Команды внутри группы, в том же виде
Ресурс
namespacestring- Пространство имён SDK, например `domains`
sdkMethodstring- Метод SDK, например `openemail.domains.delete`
sdkMethodAllstring | null- Для списка метод `listAll`, который обходит `--all --json`
httpMethod, httpPathstring- Вызов REST, например `DELETE` и `/domains/{id}`
scopesstring[]- Scope, которые нужны методу
authstring- `apiKey`, либо `none` и `inboxToken` для метода, который не отправляет API-ключ
returnsobject- `{ shape, type }`: форма ответа, например `object` или `page`, и его тип в SDK
paginatesboolean- Возвращает ли он одну страницу списка
Всё дерево занимает около мегабайта, почти целиком это 198 команд ресурсов, поэтому запрашивайте нужную команду или фильтруйте дерево через jq. Текст сохраняет обратные кавычки и не содержит кодов цвета, а скрытые команды вроде security включены с hidden, равным true.
Пробные запуски
--dry-run работает на всех командах, кроме mcp serve. Чтение выполняется как обычно, затем первый запрос, который что-то изменил бы, выводится вместо отправки, и команда завершается с кодом 0, больше ничего не делая. Подтверждения пропускаются, раз ничего не отправляется, так что агент может увидеть, что сделала бы разрушительная команда, не передавая --yes.
openemail domains delete <domain-id> --dry-runopenemail send --from [email protected] --to [email protected] --subject "Hi" --text "Hello" --dry-run --json{ "dryRun": true, "request": { "method": "POST", "url": "https://api.openemail.uk/emails", "headers": { "accept": "application/json", "authorization": "Bearer [redacted]", "content-type": "application/json", "idempotency-key": "58e6fb61-ad2e-401e-b141-7a0546c7c749", "user-agent": "openemail-cli/0.0.1 openemail-sdk/0.0.5" }, "body": { "from": "[email protected]", "to": [ "[email protected]" ], "subject": "Hi", "text": "Hello" }, "raw": null }}- Изменение это любой запрос, кроме
GETиHEAD, вызов инструмента MCP, а также запросы входа и выхода уloginиlogout. Обновление токенов иdocs askвсё равно выполняются. - План показывает метод, полный URL, заголовки со значением
Authorization, урезанным доBearer [redacted], и JSON-тело, в котором секретные поля, например ключ Resend, скрыты. Загрузка файла показывает только его размер и тип содержимого. - Изменение, которое остаётся на этой машине, например
profile use,login --with-tokenили удаление сохранённого API-ключа, выводит{"dryRun":true,"local":{"action","profile"}}и ничего не сохраняет. - Команда, которая выводит прочитанное перед первым изменением, показывает это первым:
readвыводит цепочку, а затем запрос, который отметил бы её прочитанной. Передайте--no-mark-read, чтобы убрать второе. mcp serveотклоняет--dry-runс кодом выхода2, потому что что отправлять, решает его клиент. Вместо этого просмотрите один вызов инструмента черезopenemail mcp call <tool> --dry-run.
Недостающие scope
Каждая команда знает scope API, которые ей нужны всегда, и её справка их перечисляет. Когда сохранённому входу не хватает одного из них, команда один раз запрашивает у API текущий список, поэтому доступ, выданный на сайте после входа, учитывается сразу. Если scope всё ещё не хватает, она останавливается с кодом выхода 4 и кодом insufficient_scope, прежде чем что-либо спросить или отправить запрос:
{"error":{"type":"cli_error","code":"insufficient_scope","message":"This sign-in does not have the emails:send permission, which openemail send needs.","hint":null,"next":"Give this app more access in Account settings, Connected apps (openemail open apps, then Edit access), or run openemail login --force and choose more access.","status":null,"requestId":null,"param":null,"docUrl":null,"exitCode":4}}- Для входа через браузер
nextсоветует дать приложению больше доступа в разделе «Аккаунт → Командная строка» (openemail open cli, затем «Изменить доступ») или запуститьopenemail login --forceи выбрать больше доступа. Входу через браузер никогда не выдаютсяkeys:writeиkeys:manage, поэтому для них он указывает на API-ключ. - Для API-ключа
nextсоветует взять ключ, у которого есть этот scope. - Ключ из
--api-keyилиOPENEMAIL_API_KEYзаранее не проверяется, решает API. Когда API отклоняет вызов из-за недостающего scope, ошибка несёт тот жеnext.
Коды подтверждения
API-ключу никогда не нужен код подтверждения. Входу через браузер он нужен перед чувствительным изменением, например добавлением вебхука, созданием правила, изменением участника или удалением домена, а агент не может его ввести. Поэтому до запуска агента человек либо запускает openemail verify в терминале с тем же профилем, либо выбирает для этого входа «Разрешить изменения на 60 минут» в разделе «Аккаунт → Командная строка». Любой из вариантов покрывает следующие 60 минут.
openemail verifyopenemail verify --status --jsonverify --status --json сообщает агенту, подтверждён ли профиль, в elevated, и до какого времени, в elevatedUntil. Без подтверждения изменение останавливается с кодом выхода 4 и кодом step_up_required, и ничего не меняется:
{"error":{"type":"cli_error","code":"step_up_required","message":"This action needs a verification code, and there is no interactive terminal to ask for one.","hint":null,"next":"Run openemail verify in an interactive terminal first, then run this again within 60 minutes. An API key never needs a code.","status":403,"requestId":"req_9Qm4tV","param":null,"docUrl":"https://openemail.uk/docs/api/errors#step_up_required","exitCode":4}}Через MCP
Агент, который говорит на MCP, может вместо этого использовать MCP-сервер OpenEmail. openemail mcp config --client claude-code, или codex, cursor и другие клиенты из его списка, выводит настройку, а openemail mcp serve это локальный мост, который использует вход через браузер этой CLI. API-ключи не могут достучаться до MCP-сервера. Подробности на странице «ИИ и MCP».
Рецепты
openemail inbox --unread --limit 20 --jsonopenemail inbox --unread --json | jq -r '.items[].id'openemail read CAHk7pQ2x9LmZ4 --no-mark-read --jsonopenemail send --from [email protected] --to [email protected] --subject "Weekly report" --body-file report.md --idempotency-key weekly-report-39 --jsonopenemail domains create --domain example.com --dry-run --jsonopenemail domains create --domain example.com --jsonopenemail whoami --json | jq '.scopes'