Перейти к основному содержимому

JSON-events схема

CLI переключается в JSON-lines режим автоматически когда запущен внутри AI-агента (Cursor, Claude Code) или с не-TTY stdout. Также можно включить явно: флаг --json или env LAYERO_JSON=1.

В этом режиме CLI:

  • Не задаёт вопросов — все интерактивные подтверждения пропускаются (для --prod всё равно нужен --yes)
  • На stdout печатает по одной строке {"event":"...", ...} за действие
  • Ошибки приходят со стабильным code и next_action
  • Каждое событие также содержит поле ts (ISO-8601 timestamp)
  • Каждая команда печатает события — с 0.10.0 и whoami, projects, orgs, link, hooks, logout, init
  • Код выхода различает классы ошибок — см. Коды выхода

События​

Каждая строка — самостоятельный JSON-объект. Парсите по event полю.

auth_required​

CLI начал device-flow логин. Покажите URL пользователю как кликабельную ссылку.

полетиппримечание
urlstringнапример https://app.layero.ru/cli?code=ABCD-1234
user_codestringнапример ABCD-1234 — также видно на странице подтверждения

CLI продолжит поллить каждые 2 секунды. Когда пользователь подтвердит — последует authorized. Истечение — error{code: "auth_expired" | "auth_timeout"}.

authorized​

Логин успешен.

полетип
userstring — username, email или user id

detected​

Как CLI видит папку. Это подсказка, а не решение: платформа определяет фреймворк заново по загруженным файлам, и догадка CLI в проект не записывается (с 0.11.0). В проект уходит только названное человеком: --type, --root, поля .layero/project.json, которые он вписал сам.

полетиппримечание
frameworkstringvite/nextjs/astro/…/static/generic; у сервера — имя его фреймворка (express, fastapi…)
build_cmdstring | nullnull — сборки нет (статика, приложение в контейнере) или её нечем выполнить
output_dirstring | nullnull — папка результата станет известна только после сборки
confidentbooleantrue — папку узнали: известный фреймворк, сервер или готовые файлы с index.html. false — не узнали: значения выше взяты по умолчанию, прочитайте hint
sourcesobjectоткуда каждое значение: framework, build_cmd, output_dir → layero.json, --type, .layero/project.json, project settings, package.json, framework config, framework default, detected, none
runtime_kindstring?приложение запускается в контейнере: node_web, python_web, ssr_next, …
hintstring?что CLI увидел вместо узнанного приложения: приложение в подпапке, фронт и бэк рядом, свой скрипт сборки, сервер без известного фреймворка
next_actionstring?один конкретный шаг: npx layero@latest deploy --root apps/web, текст layero.json и т. п.
candidatesstring[]?папки приложений, найденные ниже текущей
ssr_warningstring?Nuxt/SvelteKit соберутся сервером, а не статикой
layero_warningsstring[]?ключи layero.json, которые платформа не применит, с верным именем. Например, "type": "vite" не работает — нужно "framework": "vite" (с CLI 0.11.4)

framework, buildCommand и outputDirectory из layero.json здесь уже учтены (sources = layero.json).

plan​

Итог layero deploy --dry-run: как платформа соберёт папку, если выкатить сейчас. Ничего не упаковано, не загружено и не создано; вход не нужен. Порядок тот же, что у сборщика: layero.json → настройки проекта → детект.

полетиппримечание
framework, build_cmd, output_dir, confident, sources, hint, next_action, candidates, layero_warningsкак в detected, плюс настройки привязанного проекта (sources = project settings)
runtime_kindstring | nullтип контейнера, если приложение запускается в контейнере: node_web, python_web, ssr_next, …
rootstring | nullподпапка приложения (--root или настройка проекта)
projectobject | nullid, slug, project_type, repo привязанного проекта
project_settingsstringread, not linked или not read: … (нет входа)
creates_projectbooleanвыкатка создаст новый проект
replaces_live_sitebooleanвыкатка заменит живой сайт. false — только у проекта с подключённым репозиторием без --prod
prebuilt_dirstring?при --prebuilt

project_created​

Первый деплой в этой папке. Создан новый проект.

полетип
project_idstring
slugstring
organizationstring — slug организации

project_linked​

Деплой в существующий проект (cwd привязан через .layero/project.json).

полетип
project_idstring
slugstring

packing​

CLI упаковал директорию в tar.gz.

полетип
filesnumber
bytesnumber
sha256string

uploading​

Заливка архива в S3 началась. Без дополнительных полей.

uploaded​

Заливка успешна.

полетип
archive_keystring

prebuilt​

Деплой идёт с готовой сборкой (--prebuilt <dir>) — установка зависимостей и сборка на стороне платформы пропускаются.

полетип
dirstring — папка с артефактом

runtime_type_applied​

Проект определён как runtime-приложение, и тип проставлен автоматически — и при создании проекта, и при смене типа по --type. Тип, названный детектом CLI, платформа записывает как догадку и может уточнить по архиву; тип из --type — выбор человека.

полетип
project_typessr_next · node_web · python_web · streamlit · gradio · flask

runtime_type_apply_failed​

Тип определился, но проставить его не удалось. Деплой продолжается с прежним типом проекта.

полетип
errorstring

setup_applied​

Настройки проекта приняты. Записано только то, что названо явно (--type, свой .layero/project.json): чем собирать и куда класть результат, иначе решает сборщик по архиву на каждой сборке. Без полей.

repeated_failure_guard​

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

Дальше CLI либо спросит подтверждение (интерактивный терминал), либо завершится с кодом repeated_failure. Продолжить автоматически нельзя — это ровно тот цикл, который правило разрывает.

полетип
streaknumber — сколько отказов с этой ошибкой насчитано
thresholdnumber — порог, на котором срабатывает стоп
scope"project" | "owner" — где насчитано: в этом проекте или суммой по всем вашим проектам
failure_stagestring, опционально — стадия сборки
errorstring, опционально — текст ошибки

scope: "owner" отвечает на вопрос, который возникает первым: «я собирал здесь три раза, откуда десять?». Одна и та же ошибка считается и по всем проектам владельца сразу — перенос приложения в новый проект правило не обходит, потому что причина не в проекте.

deploy_started​

Бэкенд принял задачу.

полетип
deploy_idstring

stage​

Сменилась стадия сборки. Приходит перед первой строкой build_log этой стадии (с 0.11.0 стадия берётся из самих строк лога, а не из текущей стадии деплоя).

полетип
nameclone/install/build/upload/activate

build_log​

Строка лога сборки. Форвардить пользователю стоит только если содержит ошибку — в успешных билдах их много и они шумные.

Строки npm http fetch … и npm http cache … (по строке на каждый пакет) в JSON-режиме скрыты: вместо них приходит одна строка-пометка. Полный лог — npx layero@latest logs --deploy <deploy_id>.

полетип
linestring
streamstdout/stderr

ready​

Финальное событие. Деплой жив. Покажите url пользователю и завершите выполнение.

полетиппримечание
urlstringЖивой публичный адрес сайта — НЕ дашборд. Для обычного layero deploy CLI-проекта это production-адрес проекта (CLI-загрузки авто-промоутятся в apex). Для проекта с репозиторием, где CLI-загрузка не промоутится, — адрес окружения cli (--branch у deploy отклоняется, см. branch_unsupported). Адрес живой сразу; открывайте и показывайте пользователю именно его.
dashboard_urlstring?Страница управления проектом в дашборде (https://app.layero.ru/projects/<id>). Это НЕ сайт — не выдавайте её как ссылку на готовый сайт.
preview_urlstring?Legacy, больше не приходит. Отдельный per-deploy preview-хост в зоне *.preview.layero.ru. Существовал, чтобы дать ссылку, пока apex прогревался на CDN. Отдельной preview-зоны у layero.app нет, а на layero.ru пользовательских сайтов не осталось — поле не заполняется ни для одного проекта.
edge_readybool?true — адрес уже отвечает самим сайтом: перед ready CLI (с 0.11.0) опрашивает url, пока вместо сайта отвечает экран платформы (заголовок X-Layero-Screen), до 90 с. Так после ready по адресу уже не открывается заглушка «Здесь пока ничего нет». false — за это время приложение так и не ответило. Смотрите лог приложения: npx layero@latest logs --runtime.
screenstring?при edge_ready: false — какой экран платформы отвечал (starting, unavailable, …)
edge_eta_secondsnumber?Legacy, больше не приходит. Оценка остатка прогрева CDN. Распространять нечего — CDN перед пользовательскими сайтами нет.
deploy_idstring

Апекс переведён на указанный деплой. Приходит от layero promote и от layero deploy --promote.

полетип
urlstring — публичный адрес
deploy_idstring

data_api_enabled​

Итог layero data enable: у базы включён Data API.

полетиппримечание
orgstringslug организации
databasestringслаг или id базы
slugstringадрес базы в Data API: https://data.layero.ru/<slug>
public_keystring | nullпубличный ключ для сайта — полное значение, приходит один раз
secret_keystring | nullсекретный ключ — только с --with-secret; хранить на сервере, в код сайта не класть
reappliedbooleantrue — Data API у базы уже был включён и переприменён через --repair

data_keys​

Итог layero data keys list. Значений ключей в событии нет никогда — только префиксы.

полетиппримечание
orgstringslug организации
databasestringслаг или id базы
keysarrayключи: id, kind (public | secret), prefix, label, created_at, last_used_at, expires_at (string | null), in_build (boolean — ключ подставляется в сборку сайта), service (boolean)

data_key_issued​

Итог layero data keys issue. Полное значение ключа приходит один раз — сохраните его сразу.

полетиппримечание
orgstringslug организации
databasestringслаг или id базы
idstringid ключа — им ключ отзывают
kindstringpublic или secret
prefixstringначало ключа, по нему ключ узнают в списке
keystringполное значение ключа
expires_atstring | nullкогда ключ перестанет действовать; null — бессрочный

data_key_revoked​

Итог layero data keys revoke.

полетип
orgstring — slug организации
databasestring — слаг или id базы
idstring — id отозванного ключа

data_origins​

Итог layero data origins list: сайты, с которых браузер может обращаться к Data API.

полетиппримечание
orgstringslug организации
databasestringслаг или id базы
originsarrayдобавленные вручную: origin, note (string | null)
from_projectsstring[]адреса проектов организации — разрешены без добавления
localhost_allowedbooleanразрешены ли запросы с localhost

data_origin_added и data_origin_removed​

Итог layero data origins add и layero data origins remove.

полетип
orgstring — slug организации
databasestring — слаг или id базы
originstring — адрес сайта

data_methods​

Итог layero data methods: таблицы и функции базы с уровнем доступа по каждому методу. Уровни: closed — закрыто, visitor — любой посетитель, user — вошедшие, server — только сервер.

полетиппримечание
orgstringslug организации
databasestringслаг или id базы
tablesarrayschema, name, kind (table | view), rls (boolean | null), path, profile (string | null), shadowed_by (string | null), levels (GET, POST, PATCH, DELETE → уровень), writable (какие из POST, PATCH, DELETE таблица принимает)
functionsarrayschema, name, args, kind (function | procedure), signature, path (string | null — null, если по HTTP не вызывается), overloaded (boolean), level, public_only (boolean)
warningsstring[]всегда есть; по строке на таблицу, право на которую не работает: у роли нет USAGE на её схему, и шлюз таблицы не видит. В строке — что сделать. Пусто — предупреждений нет

data_grant​

Показ и итог layero data grant. Без --yes вне терминала событие приходит с applied: false, а следом — error с кодом confirmation_required или data_levels_blocked. После применения — applied: true, и current описывает состояние после.

полетиппримечание
orgstringslug организации
databasestringслаг или id базы
objectobjectkind (table | view | function | procedure), schema, name, args — только у функций
currentobjectметод → уровень сейчас; у функции — только POST
nextobjectметод → уровень после применения
sqlstring[]команды, которые выполнит применение
warningsstring[]предупреждения, включая причины из blocked
blockedstring[]почему применить нельзя; пусто — можно
appliedbooleanприменено ли
next_actionstringтолько когда нужно подтверждение — готовая команда повтора

data_probe​

Итог layero data probe: ответ шлюза на пробу метода Data API. Запрос настоящий, запись откатывается. Не откатываются номера последовательностей, внешние вызовы из базы, сессионные блокировки и суточная квота вызовов.

Событие приходит всегда, когда шлюз ответил. Код выхода — по одному правилу, по порядку:

  1. откат записи не подтверждён — ошибка data_probe_not_rolled_back;
  2. статус совпал с --expect — 0;
  3. шлюз ответил 5xx — ошибка data_probe_gateway_failed;
  4. статус не совпал с --expect — ошибка data_probe_unexpected_status;
  5. иначе 0, в том числе на отказ 4xx: 401, 403, 404 — ответ пробы, а не сбой.

Ошибка приходит событием error следом за data_probe.

полетиппримечание
orgstringslug организации
databasestringслаг или id базы
requestobjectmethod, path, as, user_id, query, schema — что ушло в пробу; schema в нижнем регистре, у функций и /whoami — null; тело не повторяется
statusnumberHTTP-статус ответа шлюза
elapsed_msnumberвремя запроса к шлюзу
callerstring | nullкем шлюз посчитал запрос: visitor, user, server; null — ключ или токен не приняты
rowsnumber | nullстрок в ответе
totalnumber | nullстрок, видимых роли, — из Content-Range
owner_totalnumber | nullстрок в таблице у владельца — знаменатель «N из M». null — не посчитали; total вместо него не подставляйте: это счёт самой роли
rollback_expectedbooleanоткат ожидался — у всего, кроме /whoami
rolled_backbooleanшлюз подтвердил откат
not_rolled_backbooleantrue — откат ожидался, ответ 200–399, а подтверждения нет: данные могли измениться. Следом придёт error с кодом data_probe_not_rolled_back
body_truncatedbooleanответ длиннее 64 КБ, в body только его начало
headersobjectтолько content-type, content-range, x-layero-caller, x-layero-key (префикс ключа), x-layero-user, x-layero-rolled-back
bodyanyтело ответа: JSON или строка

claimable​

Деплой без аккаунта (layero deploy --claim; только явным флагом). Платформа завела временный проект и выдала токен на него; сайт живёт час, адрес у него случайный, поисковикам он закрыт. Событие приходит до ready: после ready агент не читает, а без ссылки сайт исчезнет вместе со сроком.

полетиппримечание
project_idstring
slugstring
urlstringадрес сайта — тот же, что в ready. Пока сайт временный, браузеру он отвечает переходом на preview_url; для проверок и агентов открыт как есть
preview_urlstringссылка «для людей»: страница панели с сайтом в рамке и пометкой «временный сайт». Ею делятся
claim_urlstringссылка, по которой человек забирает проект в свой аккаунт. Принять заявку может только человек в панели — CLI и агент этого не делают
expires_atstringISO-8601 — когда сайт и токен перестанут действовать

Токен, код заявки и ссылка сохраняются в ~/.layero/config.json (файл доступен только вам); в .layero/project.json — только привязка папки: этот файл уходит в git, а код забора в публичном репозитории отдал бы сайт первому встречному (с CLI 0.11.8; код из project.json старых версий при следующей выкатке переезжает в конфиг). Повторный layero deploy в той же папке обновляет тот же сайт до истечения срока и снова печатает claimable с той же ссылкой. npx layero@latest diagnose и logs в этой папке работают с токеном песочницы — вход не нужен. Забор сайта в аккаунт сбрасывает переменные окружения, хуки деплоя и настройки сборки, заведённые без аккаунта: выложенные файлы остаются, следующая сборка берёт настройки из файлов проекта.

Песочница создаёт только новый проект. Если передан --project или папка привязана к проекту, заявки на который на этой машине нет, а токена нет, CLI начинает вход: событие auth_required с url и user_code. Так же — без --claim в новой папке: до 0.11.8 режим в агентской среде с --yes включался сам, и папка уходила в открытый интернет без решения человека. Токен песочницы из ~/.layero/config.json идёт только в свой проект.

claim_status​

Итог layero claim status [code]. Без кода — заявка проекта папки из ~/.layero/config.json (у папок старых версий CLI — из .layero/project.json).

полетип
codestring
statusstring — состояние заявки на сервере (unclaimed, claimed, expired)
claimedboolean
expires_atstring | null
urlstring | null — адрес сайта
claim_urlstring | null

claim_accept​

Итог layero claim accept [code]. В терминале CLI открывает claim_url в браузере, в агентском режиме — только печатает: подтвердить заявку должен человек, вошедший в панель.

полетип
codestring
claim_urlstring
openedboolean — открыт ли браузер

me​

Итог layero whoami.

полетип
idstring
usernamestring | null
emailstring | null
github_loginstring | null

logged_out​

Итог layero logout.

полетип
config_pathstring — удалённый файл с токеном

projects​

Итог layero projects list.

полетип
projectsarray — id, slug, name, organization, url (живой адрес), source_type (cli | github | git), repo (string | null — owner/repo подключённого репозитория), status

organizations​

Итог layero orgs list.

полетип
organizationsarray — id, slug, kind (personal | team), role (admin | member)

init_done​

Итог layero init (после detected).

полетип
frameworkstring
confidentboolean — как в detected
agent_docsarray — file (AGENTS.md, CLAUDE.md, .cursorrules), result (created | updated | unchanged)
project_jsoncreated | unchanged

С 0.11.0 init не записывает догадку детекта ни в .layero/project.json (там только analytics_enabled и env_vars), ни в AGENTS.md: фреймворк указан там, только если детект в нём уверен.

hooks, hook_created, hook_deleted​

Итоги layero hooks list, hooks create, hooks delete. Адрес хука — секрет: кто угодно с ним запускает сборку.

полетипсобытие
projectstring — id проектавсе три
hooksarray — id, name, branch (string | null), target (preview | production), url, last_triggered_at (string | null)hooks
id, name, branch, target, urlкак в спискеhook_created
idstringhook_deleted

sources​

Итог layero sources list: провайдеры, которые платформа умеет, и подключения организации. Токенов в событии нет — платформа их не отдаёт.

полетип
orgstring — slug организации
providersarray — id (gitverse, gitlab, gitflic, sourcecraft, …), title, self_hosted (boolean — принимает --base-url), webhook_supported (boolean — false у SourceCraft: автосборки на push там не будет), token_hint (string | null — где выпустить токен и с какими правами)
connectionsarray — id, provider, account (string | null — логин владельца токена), status (active | invalid), projects_count, token_expiry_state (ok | soon | today | expired | unknown), last_error (string | null)

source_connected​

Итог layero sources connect <provider> и шаг layero projects create --repo.

полетип
orgstring
connection_idstring — id подключения (у GitHub App — ключ аккаунта github:<installation>)
providerstring
accountstring | null

source_repos​

Итог layero sources repos <connection_id>.

полетип
orgstring
connection_idstring
reposarray — path (owner/repo, у GitLab — group/sub/project), name, default_branch, private, can_admin (boolean — хватит ли прав завести вебхук), updated_at (string | null)

webhook_installed и webhook_unavailable​

Шаг layero projects create --repo. Отдельным событием, а не полем: без вебхука push в репозиторий не собирается, и агент обязан сказать это человеку словами. Репозиторий при webhook_unavailable уже привязан — деплой по кнопке и по layero deploy работает, автосборка включится после ручной настройки вебхука по url.

полетипсобытие
projectstring — slugоба
urlstring — адрес вебхука; у GitHub App поля нет: там вебхук — часть установки, своего адреса у него нетоба
hintstring — почему не вышло и что сделатьwebhook_unavailable

setup_applied, deploy_started, setup_pending, setup_failed​

Завершение мастера в layero projects create --repo (с 0.10.2). Раньше команда останавливалась на привязке: проект оставался в pending_setup, и первая сборка ждала клика «Начать деплой» в панели. Теперь команда делает то же, что кнопка: берёт подсказку детекта, применяет её и запускает сборку.

событиеполясмысл
setup_appliedproject, framework, build_cmd (string | null), output_dir (string | null), layero_found (boolean)Мастер завершён. Фреймворк, команда и папка — то, что увидел детект, для сведения: в проект они не записаны (с CLI 0.11.4), сборщик определяет их по репозиторию на каждой сборке
deploy_startedproject, deploy_id, urlПервая сборка запущена; следить — layero deploys list --project <slug>
queuedwaited_sСборка ждёт свободный сборщик; печатается раз в 15 с до первого stage. Не ошибка — ждать дальше
setup_pendingproject, url, hint--no-deploy: проект оставлен в мастере, сборок не будет, пока настройку не завершат по url
setup_failedproject, reason, url, hintДетект, настройка или запуск сборки не удались. Проект создан, выход 0 — сказать человеку завершить в панели по url

environments​

Итог layero envs list. Окружение и ветка — одна сущность: у CLI-проекта оно одно (cli), у проекта с репозиторием — по ветке. Архивные и снятые с раздачи не входят.

полетип
projectstring — slug
environmentsarray — id, branch, url (адрес окружения), hostname, active_deploy_id (string | null), active_deploy_at (string | null), production (boolean — это production-ветка)

project_deleted​

Итог layero projects delete <slug> --yes. Очистка ресурсов (CDN, S3, сертификаты, вебхук) идёт в фоне; адрес и слаг освобождены сразу.

полетип
project_idstring
slugstring

error​

полетип
codestring — см. таблицу ниже
next_actionstring — конкретная команда / URL для разрешения
messagestring — человекочитаемое описание

Коды ошибок​

Список сверен с исходниками CLI: это все коды, которые он действительно выдаёт. Не изобретайте обработку кодов, которых здесь нет.

codeКогда происходитЧто делать (next_action)
auth_requiredНет токена ни в ~/.layero/config.json, ни в LAYERO_TOKENlayero login, либо задать LAYERO_TOKEN
auth_expiredВход больше не действует: либо user_code истёк (15 мин TTL) и пользователь не подтвердил, либо сохранённый токен протух (TTL 7 дней) или сессия отозвана — API ответил 401Запустить layero login ещё раз
auth_timeoutCLI поллил 15 минут, юзер так и не подтвердилЗапустить layero login ещё раз
plan_limitЛимит тарифа: API ответил 402 (например, проектов на free-тарифе больше, чем разрешено)Сменить тариф на app.layero.ru/billing или удалить ненужное
username_requiredУ аккаунта не выбрано имя (оно же адрес личной организации) — API отвечает 412. В интерактивном терминале login и deploy спрашивают имя сами, в агентском режиме спрашивать некогоlayero username <имя>
username_rejectedИмя занято, зарезервировано или не проходит по форматуВыбрать другое: строчные латинские буквы, цифры и дефис, 2–32 символа
oauth_unavailableПровайдер входа недоступенЭто на нашей стороне — попробовать позже
project_unknownКоманда вызвана вне каталога проекта и без --projectЗапустить из каталога проекта или передать --project <id|slug>
project_not_found--project указывает на несуществующий проектlayero projects list
cli_deploys_disabledАдмин выключил CLI-деплои в проектеВключить в Project Settings → CLI deploys, либо деплоить в другой проект
invalid_type--type с неизвестным значениемУбрать флаг (авто-детект) или передать валидный пресет — список в сообщении
invalid_choiceИнтерактивный prompt получил невалидный выбор в non-TTYПередать значение явным флагом
prebuilt_no_dirКаталог из --prebuilt не найденУказать явно: --prebuilt ./dist
prebuilt_no_indexВ каталоге --prebuilt нет index.htmlУказать папку со собранным index.html
deploy_not_startedСборка не стартовалаЗапустить layero deploy ещё раз; не помогло — npx layero@latest diagnose
deploy_watch_lostCLI потерял связь с логом сборки (несколько сбоев сети подряд). Сама сборка на платформе продолжаетсяНе запускать деплой заново. Итог — npx layero@latest deploys list --json, лог — npx layero@latest logs --deploy <id>
deploy_failedСборка не дошла до readynpx layero@latest diagnose --deploy <id> — команда из next_action, работает и в песочнице без аккаунта
repeated_failureПодряд идущие сборки падают с одной и той же ошибкой, и платформа отказалась выкатывать следующую вслепую. Текст ошибки — в message и в событии repeated_failure_guardПрочитать ошибку и устранить причину. Повтор без изменений даст тот же результат. Если причина уже устранена — layero deploy --confirm-repeated-failure
repeated_failure_declinedТо же, но в интерактивном терминале на вопрос «Всё равно выкатить?» ответили «нет»Исправить ошибку и запустить layero deploy заново
no_deploy / no_deploysУ проекта ещё нет деплоевСначала layero deploy
rollback_unsupportedУ деплоя нет раздаваемого артефакта: runtime-проект либо вычищенная по ретенции статикаПересобрать нужный коммит через layero deploy
rollback_noopЦель отката уже на живом адресе — например, второй layero rollback подряд. Ничего не изменено, выход 4Точечно — layero promote <sha>; список — layero deploys list
env_not_foundПеременной нетlayero env list
nothing_to_setlayero env set вызван без пары KEY=valuelayero env set KEY=value
bad_formatАргумент не разобранФормат — в сообщении
domain_not_foundДомена нет у проектаlayero domains list
domain_rejectedПлатформа отклонила доменПричина — в сообщении
forbiddenОперации не хватает scope у токена CI (layero_ci_*)Выпустить токен с нужным scope
org_unknownУ аккаунта несколько организаций, а команда не знает, в какой работатьПередать --org <slug>; список — layero orgs list
database_unknownВ организации нет базы с таким именем, слагом или id. У layero data enable --repair — база не указана через --db: переприменение снимает у ролей API права на схему public, и базу не угадываемlayero db list; завести — layero db create <имя>. Для --repair — layero data enable --db <база> --repair
sql_missinglayero db sql вызван без запросаПередать запрос следом за именем базы: layero db sql моя-база "select 1"
gb_not_supportedlayero db create --gb — объём базы так не выбирается. Флаг остался ради этого отказа: раньше он молча ничего не делалУ базы из тарифа объём задан тарифом, у выделенного инстанса — диском ступени
dedicated_needs_panellayero db create --cpu/--ram/--dedicated — выделенный инстанс из терминала не заказывается: у него есть цена и заморозка денег на карте, а подтвердить сумму в терминале негдеЗаказать в панели: адрес приходит в next_action
branch_without_envДля ветки ещё нет окруженияСначала задеплоить эту ветку
analytics_not_connectedАналитика не подключенаlayero analytics connect
no_runsНет прогонов замера скоростиlayero perf check
data_api_disabledlayero data … вызван для базы, у которой Data API не включёнlayero data enable --db <база>
data_key_kindlayero data keys issue --kind с неизвестным видом ключа--kind public — ключ для сайта, --kind secret — для сервера
data_key_expiry--expires-in с неподдерживаемым срокомДопустимые сроки — в next_action, либо never
data_key_unknownУ базы нет действующего ключа с таким id или префиксомlayero data keys list --db <база>
data_key_ambiguousПрефикс совпал с несколькими ключами базыПередать id ключа — список id в next_action
data_levels_missinglayero data grant вызван без единого уровняТаблица: --get visitor --post server …; функция: --call visitor
data_level_unknownУровень доступа не из спискаclosed — закрыто, visitor — любой посетитель, user — вошедшие, server — только сервер
data_levels_blockedПлатформа отказалась применять уровни: например, права выданы на отдельные колонки или схема принадлежит чужой роли. Причина — в message, изменения не отправлялисьИзменить запрос по тексту отказа; текущие уровни — layero data methods --db <база>
data_api_already_enabledlayero data enable --db <база> у базы, где Data API уже включён. Ничего не изменено: повторное включение сняло бы у ролей API права на схему publicКлючи — layero data keys list --db <база>, методы — layero data methods --db <база>; при --with-secret — выпуск секретного ключа layero data keys issue --db <база> --kind secret. Если роли или права на схему api испорчены вручную — layero data enable --db <база> --repair: вне терминала и с --json следом придёт confirmation_required с готовой командой --repair --yes
confirmation_requiredКоманда меняет доступ (отзыв ключа, удаление сайта, применение уровней, переприменение Data API — layero data enable --repair), а подтвердить её в агентском режиме некому. Ничего не изменено; план команд пришёл отдельным событиемПоказать план человеку и повторить с --yes — готовая команда в next_action
data_probe_methodМетод не из GET, POST, PATCH, DELETE; /whoami не методом GET; функция (/rest/v1/rpc/…) не методом GET или POST. Запрос не отправлялсяПодходящий метод — в next_action, для /whoami и функции — готовой командой
data_probe_pathВ пути пробы есть ?, косая черта в конце или нет имени таблицы или функции (/rest/v1/, /rest/v1/rpc/). Запрос не отправлялсяГотовая команда со всеми переданными флагами — в next_action: параметры из ? стали флагами --query, путь без косой черты. Для пути без имени — layero data methods --db <база>
data_probe_query--query не в виде имя=значение, имя пустое, одно имя указано дважды или задано и в пути после ?, и флагом --query--query select=id,title --query price=gt.100; несколько условий на одну колонку — одним параметром or=(…)
data_probe_bodyТело пробы не разобрано: не JSON, не объект и не массив, файл не читается, заданы и --body, и --body-file, тело у GET и DELETE, или число в теле не передаётся точно — например, 9007199254740993 ушло бы как 9007199254740992Объект или массив JSON в --body либо --body-file, только для POST и PATCH; большое число — строкой в кавычках
data_probe_as--as не из visitor, user, server либо --user без --as user--as visitor, --as user --user <id> или --as server
data_probe_user_required--as user без --user: не указано, от имени какого пользователя пробовать--user <id пользователя приложения>
data_probe_user_invalid--user — не UUID: платформа ждёт id пользователя приложенияВзять id в панели базы, в списке пользователей приложения
data_probe_schema--schema у таблицы не из api, public, app или у функции не api: функции шлюз зовёт только из api. Без этой проверки платформа молча проигнорировала бы флаг. У /whoami схема отбрасывается без отказа, пустая — как без флагаУ таблицы — --schema api, public или app; у функции — api или без флага. Без флага шлюз ищет таблицу в api, затем в public, затем в app
data_probe_expect--expect не разобран: нужен статус (200), класс (2xx) или список через запятую--expect 200, --expect 2xx, --expect 201,204
data_probe_rejectedПлатформа отказала в пробе до запроса к шлюзу: путь не метод базы, у базы не включён вход, тело больше 64 КБ, больше 50 параметров, шлюз ещё не умеет пробу с откатом. Причина — в message, запрос не выполнялся. Отказ самого шлюза (4xx) приходит не этим кодом, а событием data_probeПодсказка по случаю — в next_action
data_probe_gateway_failedШлюз не дал ответа: ответил 5xx (например, 503 с too_busy) или не ответил платформе вовсе. Если шлюз ответил, событие data_probe пришло перед ошибкой. Статус, указанный в --expect, этой ошибкой не бываетПовторить пробу позже
data_probe_unexpected_statusСтатус ответа шлюза не совпал с --expect. Событие data_probe пришло перед ошибкойСверить ответ пробы с уровнями доступа: layero data methods --db <база>
data_probe_not_rolled_backПроба записи прошла (ответ 200–399), а шлюз не подтвердил откат: данные могли измениться. Событие data_probe пришло перед ошибкой; --expect эту ошибку не снимаетПроверить данные базы; пробу записи не повторять, пока причина не найдена
branch_unsupportedlayero deploy --branch: архивная загрузка не попадает в ветку — платформа кладёт каждый архив в окружение cli, что бы ни передали. До 0.10.0 флаг принимался и молча игнорировался. Ничего не упаковано и не загруженоПревью-ветки есть только у проектов с репозиторием: подключить его — layero projects create --repo <provider>:<owner/repo> — и пушить в ветку. У проекта с репозиторием в next_action — имя репозитория, куда пушить
repo_format--repo не в виде <provider>:<owner/repo> или не переданlayero projects create --repo github:acme/site; провайдеры — layero sources list
account_not_foundВ организации нет подключения к этому провайдеру, либо оно не активно (токен отозван, установка App приостановлена)layero sources connect <provider> --token-stdin; GitHub — установить App в панели; адрес — в next_action
repo_not_foundРепозиторий не виден подключению: опечатка в пути или токену не хватает правДоступные пути — в next_action; полный список — layero sources repos <connection_id>
repo_already_importedРепозиторий уже привязан к проекту организацииlayero link <id> — привязать папку к нему
source_connect_failedПроект создан, а репозиторий к нему не привязался (провайдер не ответил или отказал). Проект удалён, если у токена хватило прав; иначе остался без репозитория — сказано в next_actionПроверить подключение (layero sources list) и повторить; лишний проект — layero projects delete <slug> --yes
provider_unknownlayero sources connect с провайдером не из спискаСписок — в next_action и в layero sources list; GitHub подключается установкой App
token_missinglayero sources connect без --token и без --token-stdin (или stdin пуст)echo "$PAT" | layero sources connect <provider> --token-stdin
source_rejectedПровайдер не принял токен (API ответил 502): неверный, отозван или без нужных правГде выпустить и с какими правами — в next_action (token_hint провайдера)
connection_not_foundlayero sources repos с id, которого нет в организацииlayero sources list
hook_not_foundlayero hooks delete с id, которого у проекта нет (уже удалён?)layero hooks list
claimable_unavailableДеплой без аккаунта на платформе не включён (API ответил 404/501/503), исчерпан лимит заявок (429) либо платформа не вернула код заявкиВойти: layero login — или LAYERO_TOKEN
sandbox_claimedПовторный layero deploy в папке песочницы, а сайт уже забрали в аккаунт: токен песочницы отозван. Токен и заявка забыты, привязка папки к проекту осталась — проект тот жеВойти тем аккаунтом, что забрал сайт (npx layero@latest login), и повторить тот же deploy
sandbox_expiredПовторный layero deploy в папке песочницы, а её срок (час) вышел и песочница удалена. Токен, заявка и привязка папки убраныНовый сайт без аккаунта — npx layero@latest deploy --claim; чтобы сайт жил дольше часа — войти и выкатить в аккаунт
claim_static_onlylayero deploy --claim (или авто-режим без входа) в папке серверного приложения — SSR, фуллстек, контейнер. Без аккаунта выкладываются только статика и SPA. Ничего не создано и не загруженоВойти (npx layero@latest login) и выкатить из аккаунта тем же deploy без --claim
claim_with_projectlayero deploy --claim --project <проект>: песочница создаёт новый проект и в существующий не выкатывает. Ничего не создано и не загруженоДля существующего проекта войти: layero login — и повторить без --claim; новый сайт без аккаунта — --claim без --project
claim_unknownlayero claim status/accept без кода и без заявки для проекта папки, либо заявка с таким кодом истекла или код неверныйПередать код; новый проект без аккаунта — layero deploy --claim
internalНепредвиденная ошибка CLI (сеть, неожиданное исключение)Перезапустить с --debug
Код деплоя собирается из статуса

Код неуспешного деплоя формируется как deploy_<status> по статусу сборки, а статусов у деплоя четыре: ready, building, failed, cancelled. Значит на практике встречаются ровно deploy_failed и deploy_cancelled — кодов deploy_error и deploy_timed_out не существует, не закладывайтесь на них.

Коды выхода​

С 0.10.0 код выхода различает классы ошибок — скрипту не нужно разбирать событие error, чтобы понять, кто виноват. Класс берётся из кода ошибки.

Код выходаКлассКоды error
0успех—
1прочееplan_limit, forbidden, confirmation_required, repeated_failure, cli_deploys_disabled, username_required и всё, что не попало в классы ниже
2нужен входauth_required, auth_expired, auth_timeout, sandbox_claimed
3не найденоsandbox_expired, project_unknown, project_not_found, org_unknown, database_unknown, env_not_found, domain_not_found, hook_not_found, connection_not_found, account_not_found, repo_not_found, claim_unknown, branch_without_env, no_deploy, no_deploys, no_runs, data_key_unknown
4неверный вводinvalid_type, invalid_choice, prebuilt_no_dir, prebuilt_no_index, bad_format, nothing_to_set, rollback_noop, sql_missing, branch_unsupported, claim_with_project, claim_static_only, provider_unknown, repo_format, token_missing, username_rejected, gb_not_supported, dedicated_needs_panel, data_key_kind, data_key_expiry, data_key_ambiguous, data_levels_missing, data_level_unknown, data_probe_method, data_probe_path, data_probe_query, data_probe_body, data_probe_as, data_probe_user_required, data_probe_user_invalid, data_probe_schema, data_probe_expect
5удалённая ошибкаdeploy_failed, deploy_cancelled, deploy_not_started, deploy_watch_lost, internal, oauth_unavailable, claimable_unavailable, data_probe_gateway_failed, любой deploy_<status> и http_5xx

Cold-start template для агента​

Минимальный поведенческий блок (положите в системный промпт):

If user asks to deploy via Layero:
1. Run: npx layero@latest deploy --dry-run --json
If "detected".confident is false → do what .next_action says first.
2. Run: npx layero@latest deploy --json
3. Parse each stdout line as JSON, route on .event:
- "auth_required" → render .url as clickable link, keep waiting
- "ready" → show .url (the live site) to user; it already answers
(.edge_ready true). Then stop.
- "error" → follow .next_action verbatim
4. Never run `git init`. Never run `npm install -g layero`.

Полный пример — Деплой из AI-агентов.