layero 0.9.5 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Layero platform
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,70 +1,93 @@
1
1
  # layero
2
2
 
3
- CLI for [Layero](https://layero.ru) — publish a local directory with one command. **No git or GitHub required.**
4
-
5
- ## For AI agents (Cursor, Claude Code, Aider…)
6
-
7
- If you're an agent reading this: the user asked you to deploy their site with Layero. Do exactly this — no git repo, no GitHub setup, no dashboard visits required:
8
-
9
- ```bash
10
- npx layero@latest init # scaffolds .layero/ + adds a block to AGENTS.md
11
- npx layero@latest login # one-time: prints a URL, user clicks once
12
- npx layero@latest deploy --json # ships current dir, streams JSON events to stdout
13
- ```
14
-
15
- `layero deploy` prints `{"event":"ready","url":"https://..."}` on success. Show the URL to the user. That's the whole job.
16
-
17
- **If the user has no code yet** and wants a landing page built from scratch, this CLI is the wrong tool. Layero runs a remote MCP server for that — `https://mcp.layero.ru/mcp` (Streamable HTTP), registered as `ru.layero/layero` in the official MCP registry. It builds the page from a two-or-three-question brief and deploys it. Install it with `claude plugin marketplace add LayeroInfra/layero-agents && claude plugin install layero@layero-claude`, `codex mcp add layero --url https://mcp.layero.ru/mcp --bearer-token-env-var LAYERO_TOKEN`, or one click in Cursor from [land.layero.app](https://land.layero.app). Details: [docs.layero.ru/en/plugin/intro](https://docs.layero.ru/en/plugin/intro).
3
+ CLI for [Layero](https://layero.ru) — hosting with build servers in Russia.
4
+ Deploy a directory or connect a repository with one command; every command
5
+ speaks JSON for AI agents and CI.
6
+
7
+ Source: [github.com/LayeroInfra/cli](https://github.com/LayeroInfra/cli)
8
+ (public mirror of the `cli/` directory of the platform monorepo).
9
+ Docs: [docs.layero.ru/cli](https://docs.layero.ru/cli/).
10
+
11
+ ## For AI agents (Cursor, Claude Code, Codex, Aider…)
12
+
13
+ The canonical agent skill lives in
14
+ [LayeroInfra/layero-agents](https://github.com/LayeroInfra/layero-agents):
15
+ `npx skills add LayeroInfra/layero-agents`, or for Claude Code
16
+ `claude plugin marketplace add LayeroInfra/layero-agents && claude plugin install layero@layero`.
17
+ Agent docs: [docs.layero.ru/agents](https://docs.layero.ru/agents/).
18
+
19
+ Three paths — pick by situation:
20
+
21
+ 1. **The user has a repository** (GitHub, GitVerse, GitLab, GitFlic,
22
+ SourceCraft): connect it, then push to a branch = preview, push to `main`
23
+ = production.
24
+ ```bash
25
+ npx layero@latest projects create --repo github:owner/repo --json
26
+ ```
27
+ 2. **The user has a directory with code**: the CLI packs it, the platform
28
+ builds it. No git repository is needed for this path.
29
+ ```bash
30
+ npx layero@latest deploy --json
31
+ ```
32
+ 3. **The site is already on Layero**: `diagnose`, `logs`, `rollback`,
33
+ `envs list`, `domains`, `env`, `analytics`, `data` — or the MCP server
34
+ `https://mcp.layero.ru/mcp` (`npx -y add-mcp https://mcp.layero.ru/mcp`).
35
+
36
+ `layero deploy --json` prints `{"event":"ready","url":"https://…"}` on
37
+ success. Show `url` to the user as-is. Not logged in? The command starts the
38
+ browser device flow itself and prints `auth_required` with a `url` — render
39
+ it as a link and keep waiting. No account at all? `--claim` (see below).
18
40
 
19
41
  ## Install
20
42
 
21
43
  ```bash
22
- # Recommended (project-local):
23
- npm install -D layero
24
- # or one-shot:
25
- npx layero@latest deploy
26
-
27
- # System-wide (advanced; needs sudo on most setups):
28
- npm install -g layero
44
+ npx layero@latest deploy # one-shot, always the current version
45
+ npm install -D layero # project-local
29
46
  ```
30
47
 
31
- Requires Node.js ≥ 20.
48
+ Requires Node.js ≥ 20. Do not `npm install -g layero`: without `@latest` a
49
+ bare `npx layero` call then runs the globally installed copy for years.
32
50
 
33
51
  ## Quick start
34
52
 
35
53
  ```bash
36
- layero login # device-flow: prints a URL + code, you sign in once (email code or Yandex ID)
54
+ layero login # device flow: prints a URL + code, sign in once (email code or Yandex ID)
37
55
  cd my-site
38
- layero deploy # auto-detects framework, packs, uploads, builds, ships
56
+ layero deploy # detects the framework, packs, uploads, builds, ships
39
57
  ```
40
58
 
41
59
  The first `layero deploy` in a directory creates a project and links it via
42
- `./.layero/project.json`. Subsequent runs reuse the same project — re-edit code,
43
- re-run `layero deploy`.
60
+ `./.layero/project.json`. Later runs reuse the same project.
44
61
 
45
62
  > **A plain `layero deploy` is not a preview.** For a project created from the
46
- > CLI, direct uploads auto-promote: every run replaces what visitors see at the
47
- > project's public address the same `ready.url` the previous run printed.
48
- > `--prod` matters only for projects with a connected git repository, where it
49
- > targets the production environment. Isolated previews come from pushing to a
50
- > branch of a connected repo, nothing else: `--branch` is accepted and silently
51
- > ignored for direct uploads.
63
+ > CLI, direct uploads auto-promote: every run replaces what visitors see at
64
+ > `ready.url`. `--branch` is **refused** with `branch_unsupported` (exit 4):
65
+ > archive uploads always land in the reserved `cli` environment, so the flag
66
+ > cannot give you a preview. Isolated previews come from pushing a branch of
67
+ > a connected repository `layero projects create --repo …`.
52
68
 
53
69
  ## Commands
54
70
 
55
71
  | Command | Description |
56
72
  |---|---|
57
- | `layero init` | Scaffold `.layero/project.json` + write a deploy block into `AGENTS.md` / `CLAUDE.md` / `.cursorrules` so future agent sessions know how to ship. |
58
- | `layero login` | Authenticate via browser. |
59
- | `layero logout` | Remove the saved auth token. |
60
- | `layero whoami` | Show current account. |
61
- | `layero projects list` | List projects on your account. |
62
- | `layero link <id_or_slug>` | Link cwd to an existing project. |
63
- | `layero deploy` | Auto-detect framework, pack cwd, build, ship. |
64
- | `layero deploys list` | List recent deploys. |
65
- | `layero rollback` | Re-activate the previous successful deploy. |
66
- | `layero hooks list/create/delete` | Manage deploy hooks (URL tokens that trigger builds from CMS / cron / external CI). |
67
- | `layero token` | Manage the auth token directly. |
73
+ | `layero init` | Scaffold `.layero/project.json` and write a Layero block into `AGENTS.md` / `CLAUDE.md` / `.cursorrules` (compact index; full skill in `layero-agents`). |
74
+ | `layero login` / `logout` / `whoami` | Browser device-flow sign-in, sign-out, current account. |
75
+ | `layero deploy` | Pack the current directory, build on the platform, publish. `--claim` — without an account. |
76
+ | `layero projects list` | Projects on your account with addresses. |
77
+ | `layero projects create --repo <provider>:<owner/repo>` | Create a project from a repository of a connected provider. Events: `project_created`, `source_connected`, `webhook_installed` \| `webhook_unavailable`. |
78
+ | `layero projects delete <slug> --yes` | Delete a project. Irreversible; needs a token with scope `admin`. |
79
+ | `layero sources list` | Git providers the platform supports and the organization's connections. |
80
+ | `layero sources connect <provider> --token-stdin` | Connect a provider by personal access token (read from stdin so it never lands in shell history). |
81
+ | `layero sources repos <connection_id>` | Repositories visible to a connection. |
82
+ | `layero envs list` | Environments (branches) of a project with their addresses. |
83
+ | `layero deploys list` / `rollback` / `promote` | Deploy history, roll back, pin the apex. |
84
+ | `layero diagnose` / `logs` | Why a deploy is in its state; build and runtime logs. |
85
+ | `layero claim status` / `claim accept <code>` | Claimable project: status of the claim, open the claim page. |
86
+ | `layero domains …` / `env …` / `analytics …` / `perf …` | Custom domains, environment variables, Yandex Metrika, performance checks. |
87
+ | `layero db …` / `data …` | Postgres databases and the Data API. |
88
+ | `layero hooks list/create/delete` | Deploy hooks — URL tokens that trigger builds from CMS / cron / external CI. |
89
+ | `layero token create <name>` | Long-lived token for CI and agents (`--scope read,deploy,admin`). |
90
+ | `layero link <id_or_slug>` | Link the current directory to an existing project. |
68
91
 
69
92
  Run `layero <cmd> --help` for full options.
70
93
 
@@ -72,29 +95,48 @@ Run `layero <cmd> --help` for full options.
72
95
 
73
96
  - `--type <preset>` — framework override: `vite`, `vitepress`, `next`,
74
97
  `astro`, `cra`, `sveltekit`, `nuxt`, `gatsby`, `docusaurus`, `eleventy`
75
- (alias `11ty`), `hugo`, `static`. **Optional** auto-detected from
76
- `package.json` and config files when omitted.
98
+ (alias `11ty`), `hugo`, `static`; runtime kinds `node_web`, `python_web`,
99
+ `flask`, `streamlit`, `gradio`, `ssr_next` (aliases `express`, `fastapi`,
100
+ `django`, …). **Optional** — auto-detected when omitted.
77
101
  - `--prebuilt [dir]` — ship an already-built artifact instead of building
78
- remotely. Without an argument, picks the first existing of
79
- `dist/`, `build/`, `public/`, `out/`, `_site/`, `.output/public/`,
80
- `docs/.vitepress/dist/`, `.vitepress/dist/`. With `--prebuilt ./my-out`
81
- uses that explicit path. Use this for CI flows that build in the
82
- pipeline, Webflow / Framer exports, or whenever you don't want the
83
- platform to run install/build for you.
84
- - `--root <dir>` — monorepo: tell the builder the app lives in a
85
- subdirectory of the repo (e.g. `--root apps/web`). Saved on the
86
- project; future GitHub-push and hook triggers use the same value.
87
- CLI auto-detect honours it: framework signals are looked up inside
88
- `<cwd>/<root>` so a `package.json` workspace at the repo root
89
- doesn't shadow the real app's stack.
102
+ remotely. Without an argument, picks the first existing of `dist/`,
103
+ `build/`, `public/`, `out/`, `_site/`, `.output/public/`,
104
+ `docs/.vitepress/dist/`, `.vitepress/dist/`.
105
+ - `--root <dir>` monorepo: the app lives in a subdirectory (`--root apps/web`).
90
106
  - `--name <name>` — project name (only on first deploy).
91
107
  - `--project <id_or_slug>` — deploy into an existing project, ignoring
92
- `./.layero/project.json` (useful for CI).
93
- - `--prod` — target the production environment of a repository-linked project. **Redundant for CLI projects**: a project created by `layero deploy` auto-promotes to its apex on every deploy, so a plain `deploy` already replaces the live site. `--branch` does **not** help here: it is accepted and silently ignored, because every archive upload is filed under the reserved `cli` environment. A publish that leaves the live address alone does not exist for a CLI project — it is done by connecting a repository and pushing to a branch.
94
- - `--branch <name>` deploy to a specific branch's environment.
95
- - `--org <slug>` — Layero organization for first-time project creation.
108
+ `./.layero/project.json` (use this in CI, not `--name`).
109
+ - `--prod` — target the production environment of a repository-linked
110
+ project. Redundant for CLI projects: they auto-promote on every deploy.
111
+ - `--branch <name>` — **refused** (`branch_unsupported`, exit 4), see above.
112
+ - `--claim` — deploy without an account: a temporary project for 72 hours
113
+ plus a `claim_url` for a human to take it over. Turns on by itself when
114
+ there is no token, the run is non-interactive (an agent, not CI) and
115
+ `--yes` is passed. In CI a missing `LAYERO_TOKEN` stays an error.
116
+ - `--org <slug>` — organization for first-time project creation.
96
117
  - `--yes` / `-y` — non-interactive mode.
97
- - `--json` — emit JSON-lines events on stdout (for agents and CI).
118
+ - `--json` — JSON-lines events on stdout (for agents and CI).
119
+
120
+ ## Deploy without an account (`--claim`)
121
+
122
+ ```bash
123
+ npx layero@latest deploy --claim --json
124
+ ```
125
+
126
+ The platform creates a temporary project and a token for it; the CLI deploys
127
+ with that token and prints, before `ready`:
128
+
129
+ ```
130
+ {"event":"claimable","url":"https://swift-fox.layero.app","claim_url":"https://app.layero.ru/claim?code=…","expires_at":"…"}
131
+ ```
132
+
133
+ The site lives for 72 hours. A human opens `claim_url`, signs in and takes
134
+ the project into their account — the CLI cannot accept a claim by itself.
135
+ The claim code is saved in `.layero/project.json`; the temporary token stays
136
+ in `~/.layero/config.json`, so `layero deploy` in the same directory keeps
137
+ updating the same site until the claim expires or is accepted.
138
+ `layero claim status` shows where things stand; `layero claim accept` opens
139
+ the page in a browser (in agent mode it prints the link).
98
140
 
99
141
  ## Framework auto-detection
100
142
 
@@ -120,8 +162,7 @@ Run `layero <cmd> --help` for full options.
120
162
 
121
163
  Auto-detection above is a default, not a decision. Drop a `layero.json` at the
122
164
  root of the repository and Layero uses what you set there instead — for the
123
- CLI, the dashboard and pushes alike. It travels with your code, so it can
124
- differ per branch, and it beats any dashboard setting.
165
+ CLI, the dashboard and pushes alike. It beats any dashboard setting.
125
166
 
126
167
  ```json title="layero.json"
127
168
  {
@@ -134,25 +175,30 @@ differ per branch, and it beats any dashboard setting.
134
175
  }
135
176
  ```
136
177
 
137
- Every field is optional; `{}` is valid and means "decide everything yourself".
138
- Short names (`install`, `build`, `output`, `node`, `start`) work too and are not
139
- deprecated. A field declared here is shown in the dashboard with a badge instead
140
- of an edit button — an edit there would be undone by the next build.
178
+ Every field is optional; `{}` is valid. An error in the file never fails a
179
+ build: unreadable values become warnings in the build log.
180
+ Full reference: https://docs.layero.ru/deploys/layero-json
141
181
 
142
- An error in the file never fails a build: unreadable values become warnings in
143
- the build log.
182
+ ## Repositories: `sources` and `projects create`
144
183
 
145
- Full reference: https://docs.layero.ru/deploys/layero-json
184
+ ```bash
185
+ layero sources list # providers + connections
186
+ echo "$GITVERSE_TOKEN" | layero sources connect gitverse --token-stdin
187
+ layero sources repos <connection_id>
188
+ layero projects create --repo gitverse:acme/site --branch main --json
189
+ ```
146
190
 
147
- ## Deploy hooks webhook URLs that trigger builds
191
+ GitHub is connected by installing the Layero GitHub App in the dashboard; the
192
+ other providers take a personal access token. `projects create` validates the
193
+ repository against the connection, creates the project and installs the
194
+ webhook. If the provider refuses the webhook (token permissions, or
195
+ SourceCraft, which has no outgoing webhooks), the CLI says so with
196
+ `webhook_unavailable` and the URL to register by hand — the repository is
197
+ connected either way, only push-triggered builds wait for the webhook.
148
198
 
149
- When something *other than you* should kick a build — a headless CMS
150
- publishing content, a cron job, an external CI pipeline — create a
151
- deploy hook. You get back an opaque URL; whoever POSTs to it fires a
152
- deploy.
199
+ ## Deploy hooks webhook URLs that trigger builds
153
200
 
154
201
  ```bash
155
- # Inside a linked project directory:
156
202
  layero hooks create strapi-content # preview-target, default branch
157
203
  layero hooks create publish --prod # production-target hook
158
204
  layero hooks create staging --branch=dev # explicit branch
@@ -160,64 +206,37 @@ layero hooks list
160
206
  layero hooks delete <id> # revoke immediately
161
207
  ```
162
208
 
163
- The created URL looks like `https://api.layero.ru/hooks/<token>`. Paste
164
- it into Strapi / Sanity / Contentful / Decap CMS / GitHub Actions / a
165
- cron job — any tool that can POST to a URL. Token = credential; rotate
166
- by `delete` + `create`. There is no per-token rate limit yet; rely on
167
- the platform's natural in-flight-commit dedup if the same commit gets
168
- fired more than once.
209
+ The URL (`https://api.layero.ru/hooks/<token>`) is a credential: anyone who
210
+ has it can start a build. Rotate with `delete` + `create`.
169
211
 
170
212
  ## Bring-your-own-build (`--prebuilt`)
171
213
 
172
- If you already build your site yourself — in CI, via a desktop tool like
173
- Webflow/Framer, or because you want a guaranteed deterministic artifact —
174
- skip the platform's install/build entirely:
175
-
176
214
  ```bash
177
- # Auto-pick the output directory:
178
- layero deploy --prebuilt
179
-
180
- # Or point at a specific one:
181
- layero deploy --prebuilt ./dist
182
- layero deploy --prebuilt ./build/static
215
+ layero deploy --prebuilt # auto-pick the output directory
216
+ layero deploy --prebuilt ./dist # or point at a specific one
183
217
  ```
184
218
 
185
- What changes: only the files inside the directory you point at are
186
- uploaded (no source-tree filters like `.gitignore` apply). The platform
187
- ships them verbatim no detect, no install, no build. Smaller archive,
188
- faster deploys, no surprises from the platform's package-manager defaults.
189
-
190
- ⚠️ The flip side of ignoring `.gitignore`: `--prebuilt .` at your project
191
- root publishes **everything there** except the built-in denylist, including
192
- drafts you hid via `.gitignore` (verified on a live deploy — such a file comes
193
- back with a 200). Secrets are still safe: `.env`, `.env.*`, `.git`,
194
- `node_modules` and the rule files are excluded on this path too, nested
195
- directories included. Even so, name the directory explicitly rather than
196
- using `.`.
197
-
198
- Override anything by editing `.layero/project.json` after the first `layero init`.
219
+ Only the files inside that directory are uploaded and shipped verbatim — no
220
+ detect, no install, no build. `.gitignore` is **not** applied on this path
221
+ (`.env*`, `.git`, `node_modules` and the rule files are still excluded), so
222
+ name the directory explicitly rather than using `.`.
199
223
 
200
224
  ## In CI
201
225
 
202
226
  `layero login` opens a browser — there isn't one on a runner, so a pipeline
203
- authenticates with a long-lived token instead. Create it at
204
- [app.layero.ru/settings/cli](https://app.layero.ru/settings/cli) and pass it
205
- through the environment:
227
+ authenticates with a long-lived token. Create it with `layero token create ci`
228
+ or at [app.layero.ru/settings/cli](https://app.layero.ru/settings/cli):
206
229
 
207
230
  ```bash
208
- LAYERO_TOKEN=... npx layero@latest deploy --prod --yes
231
+ LAYERO_TOKEN=... npx layero@latest deploy --project <slug> --json --yes
209
232
  ```
210
233
 
211
- `LAYERO_TOKEN` is read **before** `~/.layero/config.json`, deliberately: on a
212
- developer machine that is already signed in to a different account, the
213
- opposite order would silently deploy to the wrong place. `--yes` skips the
214
- confirmation prompt that would otherwise wait forever with nobody to answer it.
234
+ `LAYERO_TOKEN` is read **before** `~/.layero/config.json`. `--yes` skips the
235
+ confirmation that would otherwise wait forever. `--project`, not `--name`:
236
+ `--name` only names a project on creation, and a clean checkout without
237
+ `.layero/project.json` would create a new project on every run.
215
238
 
216
- The token is account-scoped, like a login session, so create a separate one per
217
- repository — then a leak is contained to that repository. Revoke on the same
218
- page; running builds start failing immediately.
219
-
220
- On GitHub Actions there is an official action that wraps the above:
239
+ On GitHub Actions there is an official action:
221
240
 
222
241
  ```yaml
223
242
  - uses: LayeroInfra/deploy-action@v1
@@ -226,85 +245,102 @@ On GitHub Actions there is an official action that wraps the above:
226
245
  prod: true
227
246
  ```
228
247
 
229
- Note that if the repository is already linked to a Layero project, a push
230
- builds it automatically — a pipeline would only duplicate that work. Reach for
231
- CI when the build itself needs secrets or private dependencies the platform
232
- does not have, then ship the result with `prebuilt: dist`.
233
-
248
+ If the repository is already connected to a Layero project, a push builds it
249
+ automatically — reach for CI only when the build itself needs secrets the
250
+ platform does not have, then ship the result with `--prebuilt`.
234
251
  Full guide: <https://docs.layero.ru/cli/github-actions>
235
252
 
236
253
  ## Agent / JSON mode
237
254
 
238
- `layero` auto-switches to non-interactive + structured-output mode when any of these is true:
255
+ `layero` switches to non-interactive, structured output when any of these holds:
239
256
 
240
- - `--json` flag passed
241
- - `LAYERO_JSON=1` env var
242
- - `CURSOR_AGENT`, `CLAUDECODE`, `LAYERO_AGENT` env vars set
257
+ - `--json` flag or `LAYERO_JSON=1`
258
+ - `CURSOR_AGENT`, `CLAUDECODE`, `LAYERO_AGENT` env vars
243
259
  - `CI=1` (non-interactive only; JSON-lines requires explicit opt-in)
244
260
  - stdout is not a TTY
245
261
 
246
- Event types emitted on stdout:
262
+ Every command emits events — one JSON object per line on stdout:
247
263
 
248
264
  ```
249
265
  {"event":"auth_required","url":"…","user_code":"…"}
250
266
  {"event":"authorized","user":"…"}
251
- {"event":"project_created","project_id":"…","slug":"…","organization":"…"}
252
- {"event":"project_linked","project_id":"…","slug":""}
267
+ {"event":"me","id":"…","username":"…","email":"…"}
268
+ {"event":"projects","projects":[{"slug":"…","url":"https://…","repo":null,…}]}
269
+ {"event":"organizations","organizations":[{"slug":"…","kind":"personal","role":"admin"}]}
270
+ {"event":"project_created","project_id":"…","slug":"…","organization":"…","url":"…","repo":"…","branch":"…"}
271
+ {"event":"project_linked","project_id":"…","slug":"…","url":"…"}
272
+ {"event":"source_connected","org":"…","connection_id":"…","provider":"…","account":"…"}
273
+ {"event":"webhook_installed","project":"…","url":"…"} | {"event":"webhook_unavailable","project":"…","url":"…","hint":"…"}
274
+ {"event":"sources","org":"…","providers":[…],"connections":[…]}
275
+ {"event":"source_repos","org":"…","connection_id":"…","repos":[…]}
276
+ {"event":"environments","project":"…","environments":[{"branch":"main","url":"https://…","production":true,…}]}
253
277
  {"event":"detected","framework":"…","build_cmd":"…","output_dir":"…","confident":true}
254
278
  {"event":"packing","files":N,"bytes":N,"sha256":"…"}
255
- {"event":"uploading"}
256
- {"event":"uploaded","archive_key":"…"}
257
- {"event":"setup_applied"}
279
+ {"event":"uploading"} {"event":"uploaded","archive_key":"…"}
258
280
  {"event":"deploy_started","deploy_id":"…"}
259
281
  {"event":"build_log","line":"…","stream":"…"}
260
282
  {"event":"stage","name":"…"}
261
- {"event":"ready","url":"…","preview_url":"…","dashboard_url":"…","edge_ready":false,"edge_eta_seconds":N,"deploy_id":"…"}
262
- {"event":"promoted","url":"…","deploy_id":"…"}
283
+ {"event":"claimable","project_id":"…","slug":"…","url":"…","claim_url":"","expires_at":"…"}
284
+ {"event":"ready","url":"…","dashboard_url":"…","deploy_id":"…"}
285
+ {"event":"hooks","project":"…","hooks":[…]} {"event":"hook_created",…} {"event":"hook_deleted",…}
286
+ {"event":"project_deleted","project_id":"…","slug":"…"}
287
+ {"event":"claim_status","code":"…","status":"…","claimed":false,"expires_at":"…","url":"…","claim_url":"…"}
288
+ {"event":"claim_accept","code":"…","claim_url":"…","opened":false}
289
+ {"event":"logged_out","config_path":"…"}
263
290
  {"event":"error","code":"…","next_action":"…","message":"…"}
264
291
  ```
265
292
 
266
- On `ready`, `url` is the **live public site** — reachable the moment the event
267
- arrives. Show it as-is and never rebuild the hostname from a template: project
268
- addresses live in the `layero.app` zone, organizations that have not migrated
269
- yet still use the older `<org>-<project>.layero.ru` scheme, and a guessed host
270
- will be wrong for one of the two. `dashboard_url` is the management page, not
271
- the site.
272
-
273
- `preview_url`, `edge_ready` and `edge_eta_seconds` are legacy fields from the
274
- era when user sites sat behind a CDN that needed warming. They no longer do —
275
- sites are served straight from the platform edge. `preview_url` is `null` for
276
- projects in the `layero.app` zone. **Do not gate on `edge_ready`**: waiting for
277
- it means waiting for something that will not arrive.
278
-
279
- Not logged in? `deploy` starts the device-flow itself (`auth_required`).
293
+ On `ready`, `url` is the **live public site** — show it as-is and never
294
+ rebuild the hostname from a template. `dashboard_url` is the management page,
295
+ not the site. `preview_url`, `edge_ready` and `edge_eta_seconds` are legacy
296
+ fields; do not wait for them.
280
297
 
281
298
  Errors carry a stable `code` (`auth_required`, `auth_expired`, `auth_timeout`,
282
299
  `project_unknown`, `project_not_found`, `cli_deploys_disabled`, `invalid_type`,
283
- `prebuilt_no_dir`, `prebuilt_no_index`, `deploy_not_started`, `deploy_failed`,
284
- `internal`, and a few command-specific ones) plus a `next_action` hint, so your
285
- agent can react without parsing prose. The failure code is assembled as
286
- `deploy_<status>` and a deploy only has `ready`, `building`, `failed` and
287
- `cancelled` — so `deploy_error` and `deploy_timed_out` do not exist.
300
+ `prebuilt_no_dir`, `prebuilt_no_index`, `branch_unsupported`,
301
+ `deploy_not_started`, `deploy_failed`, `internal`, and command-specific ones)
302
+ plus a `next_action` hint. The failure code is assembled as `deploy_<status>`
303
+ and a deploy only has `ready`, `building`, `failed` and `cancelled` — so
304
+ `deploy_error`, `deploy_timed_out` and `not_logged_in` do not exist.
305
+ Full reference: <https://docs.layero.ru/cli/json-events>
306
+
307
+ ### Exit codes
308
+
309
+ | Code | Class | Error codes |
310
+ |---|---|---|
311
+ | 0 | success | |
312
+ | 1 | other | `plan_limit`, `forbidden`, `confirmation_required`, `repeated_failure`, … |
313
+ | 2 | sign-in needed | `auth_required`, `auth_expired`, `auth_timeout` |
314
+ | 3 | not found | `project_unknown`, `project_not_found`, `org_unknown`, `hook_not_found`, `connection_not_found`, `claim_unknown`, … |
315
+ | 4 | invalid input | `invalid_type`, `prebuilt_no_dir`, `prebuilt_no_index`, `branch_unsupported`, `repo_format`, `token_missing`, `bad_format`, … |
316
+ | 5 | remote failure | `deploy_failed`, `deploy_cancelled`, `deploy_not_started`, `internal`, 5xx from the platform |
288
317
 
289
318
  ## Ignore rules
290
319
 
291
- `layero deploy` honours `.gitignore` and `.layeroignore`. The following are
292
- always excluded: `node_modules`, `.git`, `dist`, `build`, `.next`, `.env*`,
293
- `.DS_Store`, and the rule files themselves (`.gitignore`, `.layeroignore`)
294
- they have no business being on the web, and they list exactly the filenames
295
- you chose to hide. Maximum archive size is 200 MB.
320
+ `layero deploy` honours `.gitignore` and `.layeroignore`. Always excluded:
321
+ `node_modules`, `.git`, `dist`, `build`, `.next`, `.env*`, `.DS_Store`, and
322
+ the rule files themselves. Maximum archive size is 200 MB.
296
323
 
297
324
  ## Config
298
325
 
299
- - Auth token: `~/.layero/config.json` (chmod 600).
326
+ - Auth token: `~/.layero/config.json` (chmod 600). Claim tokens of temporary
327
+ projects live there too, keyed by project.
300
328
  - Per-project link: `./.layero/project.json` — `project_id`, `slug`,
301
- `organization_slug`, `apex_hostname` are managed by the CLI;
329
+ `organization_slug`, `apex_hostname`, `claim` are managed by the CLI;
302
330
  `framework_hint`, `build_cmd`, `output_dir`, `analytics_enabled`,
303
331
  `env_vars` are user-editable and override auto-detection.
304
332
 
333
+ ## Contributing
334
+
335
+ The package is developed in the `cli/` directory of the platform monorepo and
336
+ mirrored to [LayeroInfra/cli](https://github.com/LayeroInfra/cli) on every
337
+ release (`git subtree push --prefix=cli https://github.com/LayeroInfra/cli main`,
338
+ `make cli-mirror`). Issues and pull requests are welcome on the mirror.
339
+ `npm test` runs the unit tests; `npm run build` compiles with `tsc`.
340
+
305
341
  ## Links
306
342
 
307
- - Website: https://layero.ru
308
- - Docs: https://docs.layero.ru
343
+ - Docs: https://docs.layero.ru/cli/
344
+ - For agents: https://docs.layero.ru/agents/ · skill: https://github.com/LayeroInfra/layero-agents
345
+ - Source: https://github.com/LayeroInfra/cli · issues: https://github.com/LayeroInfra/cli/issues
309
346
  - Support: https://docs.layero.ru/contacts/
310
- - MCP server / IDE plugin: https://docs.layero.ru/en/plugin/intro