@plitzi/cli 0.38.7 → 0.38.8

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/README.md CHANGED
@@ -4,10 +4,10 @@ The command line for Plitzi.
4
4
 
5
5
  ```bash
6
6
  npx @plitzi/cli create my-site # a project that renders a space
7
- npx @plitzi/cli add plugin seat-picker legend # elements of your own, in the project you are in
7
+ npx @plitzi/cli plugin add seat-picker legend # elements of your own, in the project you are in
8
8
  npx @plitzi/cli create seat-picker --plugin # a plugin package any space can load
9
- npx @plitzi/cli pack plugin # a plugin built, and zipped the way the builder takes it
10
- npx @plitzi/cli upload plugin # that zip, on the space you work in, and installed there
9
+ npx @plitzi/cli plugin pack # a plugin built, and zipped the way the builder takes it
10
+ npx @plitzi/cli plugin upload # that zip, on the space you work in, and installed there
11
11
  ```
12
12
 
13
13
  ## What every command does the same way
@@ -21,10 +21,10 @@ npx @plitzi/cli upload plugin # that zip, on the space you work
21
21
  there, `-e, --environment` for which version of the space, `--width` for the widths a page is looked at (one, or
22
22
  several separated by commas), `--api` for the platform, `--json` for a tool or an agent.
23
23
  - **`--dry-run` says what it would do, and does none of it** — on every command that writes or sends: `create`,
24
- `add plugin`, `add runtime`, `pull`, `push`, `pack plugin`, `source`, `import`, `upload plugin`, `functions pull`/
25
- `push`, `runtime push`/`start`/`stop`/`size`/`vars`, `skills update`, `doctor --fix`. Each file it would write (`+` new, `~` replaced, `-`
24
+ `plugin add`, `runtime add`, `space pull`, `space push`, `plugin pack`, `source pack`, `page import`, `plugin upload`, `functions pull`/
25
+ `functions push`, `runtime push`/`start`/`stop`/`size`/`vars`, `skills update`, `doctor --fix`. Each file it would write (`+` new, `~` replaced, `-`
26
26
  removed), what it would install or run, what it would send and where. It still reads what it needs to say so — the
27
- project, the files it would send, the space it would pull, signing in for that. `upgrade` and `fix` only show until
27
+ project, the files it would send, the space it would pull, signing in for that. `upgrade` and `space fix` only show until
28
28
  `--write`.
29
29
 
30
30
  ## `create`
@@ -65,8 +65,8 @@ code (JSON, with the reason said, where one would not read back exactly), its fu
65
65
  runtime, and its files downloaded into `public/` with every CDN address rewritten — served by the project with nothing
66
66
  of Plitzi's. `.env` gets a signing key made for it and the names of the variables and credentials the space had, never
67
67
  their values. It signs in as you and needs a space you may change; the end of `create` says what came across
68
- differently. What the project was given is recorded in `.plitzi/space.json` — commit it — for [`pull`](#pull) and
69
- [`push`](#push). See `docs/en/projects-from-spaces.md`.
68
+ differently. What the project was given is recorded in `.plitzi/space.json` — commit it — for [`space pull`](#space-pull) and
69
+ [`space push`](#space-push). See `docs/en/projects-from-spaces.md`.
70
70
 
71
71
  ## The package manager
72
72
 
@@ -82,7 +82,7 @@ bundler — so the linker is pinned to the layout npm and pnpm already give it.
82
82
 
83
83
  ## Node runs the TypeScript
84
84
 
85
- Every script that runs TypeScript — `start`, `author`, `shot` — is plain `node`: Node 22.18+ strips the types
85
+ Every script that runs TypeScript — `start`, `author`, `page shot` — is plain `node`: Node 22.18+ strips the types
86
86
  itself, so nothing transpiles beside the server. (`tsx` did, and its loader thread cost a page server more memory
87
87
  than the server: ~270 MB to start where the same server starts in ~90.) The project's `tsconfig` holds it to what
88
88
  that needs — relative imports name their `.ts` file (`allowImportingTsExtensions`), type-only imports say so
@@ -114,7 +114,7 @@ when an install fails the CLI says which setting names it.
114
114
  again; it swaps a saved plugin where it is drawn, and restarts only for the server's own code.
115
115
  - **A plugin of the project's own.** `src/plugins/StatCard` is a React component the space renders through a
116
116
  `custom` element — the one thing about Plitzi a page of built-in elements cannot show. Every folder of
117
- `src/plugins` is registered by itself, under its name in camelCase, so `plitzi add plugin` is all a new one takes. Its props ARE the
117
+ `src/plugins` is registered by itself, under its name in camelCase, so `plitzi plugin add` is all a new one takes. Its props ARE the
118
118
  element's attributes, so a data source pointed at that element later reaches the component with no plumbing in
119
119
  between. Server-rendered in server mode (`action: 'compile'`), part of the bundle in client mode.
120
120
  - **A visual test.** The `visual` script starts the project, opens the page and asserts that every element the space
@@ -141,10 +141,10 @@ when an install fails the CLI says which setting names it.
141
141
  | `public/` | Served to anyone who asks, as it is — pictures, a favicon, and in client mode the data the browser fetches (`public/data/`). **It is on the internet**: never a secret, a key, a private document or data only some visitors may read | yes |
142
142
  | `src/data/` | Server mode: the project's own data — JSON its server reads for a provider (`query: '/data/<file>'`, `runtime: 'server'`) and never serves (`dataDir`). What a provider reads is in the page it renders: data a page must not carry is a server action's to read | yes |
143
143
  | `src/functions/` | Server mode: the project's own server code — tasks and `/fn/` routes (`defineFunctions`), built at boot | yes |
144
- | `vendor/plugins/` | The plugins the project runs as they were built, with no source (a project made from a space gets them), each folder with its `plugin-manifest.json`. The server runs them, and `author`, `check`, `fix` and `push` know every element type each provides | yes |
144
+ | `vendor/plugins/` | The plugins the project runs as they were built, with no source (a project made from a space gets them), each folder with its `plugin-manifest.json`. The server runs them, and `author`, `page check`, `space fix` and `space push` know every element type each provides | yes |
145
145
  | `tmp/` | What the project writes for itself while it runs: the plugins the server builds (`tmp/.sdk-plugins`), resized pictures, the port it took (`tmp/dev-server.json`), screenshots and test output. Rebuilt when missing | no |
146
146
  | `state/` | Server mode: what the server keeps for the space — its `kv` in `state/kv.json` (`createFileKv`): saved layouts, counters, cached answers. The deployment's state: kept across restarts, never rebuilt. `action.kv` in `src/config/serverOptions.ts` keeps it elsewhere (`createSqliteKv` for several processes, or a database) | no |
147
- | `.plitzi/` | What the CLI records about the project: the space it came from (`space.json`), the functions' working copy, the files `create` wrote — what `pull`, `push` and `upgrade` stand on | yes |
147
+ | `.plitzi/` | What the CLI records about the project: the space it came from (`space.json`), the functions' working copy, the files `create` wrote — what `space pull`, `space push` and `upgrade` stand on | yes |
148
148
 
149
149
  **`plitzi/` is the CLI's; `src/` is yours — but `src/main.ts`.** `plitzi/` holds `author.ts`, the types plugins import
150
150
  (`assets.d.ts`, server mode) or the page's base styles (`preflight.css`, client mode), and a `README.md` saying what
@@ -156,7 +156,7 @@ project keeps it — so a fix to the server arrives with `npm update`, not as a
156
156
  project is: it is the folder every script runs in, and both refuse to start anywhere else, naming what is missing
157
157
  (`package.json`, `src/`) — run them from the project's root. Nor do they start on a part where nothing reads it — a
158
158
  plugin folder with no `index.ts`, code in `src/plugin/`, `.env` in `src/` — naming every one at once (`doctor` says each
159
- with its fix). A plugin is declared by its folder: the server, `author` and `check` find every
159
+ with its fix). A plugin is declared by its folder: the server, `author` and `page check` find every
160
160
  `src/plugins/<Name>/declaration.ts` (`pluginDeclarations` from `@plitzi/sdk-authoring/node`). What the server does
161
161
  besides serving the space is the project's own, in files it reads: `src/config/serverOptions.ts` (handed to `serveProject` —
162
162
  `images`, `action.limits`, `action.kv`, `rsc`) and, with `--source local`, `src/actions/index.ts` (the space's server
@@ -179,43 +179,68 @@ in `src/data/products.json` read on the server as a typed source (`public/data/p
179
179
  in client mode), a catalog filtered by category, and a page per product — a file per part under `src/space/`. Both go
180
180
  with `--source local`.
181
181
 
182
- ## `check` and `shot`
182
+ ## `page check` and `page shot`
183
183
 
184
184
  ```bash
185
- plitzi check / --width 1440,390 # is the page whole? in text, per width; --json for a tool
186
- plitzi check /products --state --element catalog-count # and what it holds: state, sources, one element
187
- plitzi check / --ssr # and what the server's HTML lacks that the hydrated page has
188
- PLITZI_CHECK_PASSWORD=… plitzi check /studio --as maya # a page for signed-in visitors, signed in through /auth first
189
- plitzi shot /about --width 390 --scheme dark
190
- plitzi shot / --frames 4 --every 500 # what moves: a marquee, an autoplay
191
- plitzi shot / --compare https://example.com --width 1440 # beside another site: what differs, and how
185
+ plitzi page check / --width 1440,390 # is the page whole? in text, per width; --json for a tool
186
+ plitzi page check /products --state --element catalog-count # and what it holds: state, sources, one element
187
+ plitzi page check / --ssr # and what the server's HTML lacks that the hydrated page has
188
+ plitzi page check /enterprise --click site-footer-top # click one element: what it changed, or that nothing did
189
+ plitzi page check / --click news-send --fill news-email=ana@example.com # a form sent as a visitor fills it
190
+ PLITZI_CHECK_PASSWORD=… plitzi page check /studio --as maya # a page for signed-in visitors, signed in through /auth first
191
+ plitzi page shot /about --width 390 --scheme dark
192
+ plitzi page shot / --frames 4 --every 500 # what moves: a marquee, an autoplay
193
+ plitzi page shot / --compare https://example.com --width 1440 # beside another site: what differs, and how
192
194
  ```
193
195
 
194
196
  Both run on the project's own Playwright against its running server (`npm start`), and refuse a port that answers as
195
197
  another project. They wait for the page to settle — loaded, then half a second with nothing asked for — counting no
196
198
  stream that stays open, so a page with a realtime `channel` is checked like any other (`openPage` of
197
- `@plitzi/sdk-authoring`, which the generated `npm run visual` uses too). `check` reports every element the space owes the page that is missing or hidden (with why), broken
199
+ `@plitzi/sdk-authoring`, which the generated `npm run visual` uses too). `page check` reports every element the space owes the page that is missing or hidden (with why), broken
198
200
  images, sideways scroll, text in the colour behind it, console errors, refused requests and failed flows — and the
199
201
  page's data: a binding that reads a path its provider's answer lacks (with the keys it has) — none inside an element
200
202
  the page is not showing, which is not mounted — a provider that failed, and each list's rows, drawn and in its source
201
203
  (`feed 4 of 8 rows`, `hits not rendered (16 in its source)`; `--json`: `lists: { id: { rendered, source } }`). A page's state in a few hundred tokens, where a screenshot costs thousands.
204
+ `--element` adds, at rest, each property more than one of the element's classes sets: the value shown, the class it
205
+ comes from and what the others say — `border-radius: 999px, from ent-cta-pill (button-primary says 12px)` — or that
206
+ they all set it alike, so it stays without any one of them. That is said of the property alone: a class that shares
207
+ one may set others. A class is said to change nothing on the element only when every property it sets stays without
208
+ it, at rest at that width — and then with the other elements it is on: taking it off this element's `class` touches
209
+ none of them, changing the class itself changes them all (`--json`: `styles: { contested, inert, wornBy }`). Which
210
+ class wins is asked of the page (each taken off for a moment), so specificity, order and media are answered without a
211
+ picture.
212
+
213
+ `--click <id>` clicks one element once the page has settled, as a visitor does — brought into view first, which is
214
+ not the click's doing — and says what changed: the flows it ran and how each step ended, where the page went, what
215
+ scrolled, what is shown now and what no longer is, what the page said (a toast, an alert: `said: "Link copied"`), the
216
+ state. A form the browser held back is said with the field and the browser's reason (`the browser held the form back:
217
+ email — Please fill out this field.`), not as a click that ran nothing. A click that changed nothing says so in those
218
+ words, and a flow that ran and succeeded with nothing on the page changed is said as that too: a button whose flow
219
+ does nothing looks like one that works until it is clicked. A click that could not be made, or a flow that failed,
220
+ fails the check (`--json`: `clicked: { element, filled?, changes, failed, problem? }`).
221
+
222
+ `--fill <id>=<value>`, once per field, fills a field before the click as a visitor does — typed in, an option chosen, a
223
+ box ticked with `true` or `false` — so a form's flow is run with what it is for, not only refused empty. The id is the
224
+ field's element, or one that holds that one field (a `formControl`'s wrapper); one that holds several is refused with
225
+ their ids, and a field filled inside another element says whose it is. Without `--click` it is refused: nothing filled
226
+ is sent anywhere.
202
227
 
203
228
  `--scheme` is the space's own theme, set as a visitor's toggle sets it (the `theme` cookie); left out, the space's
204
- default, and `shot` names the file by the theme it was painted in. The dev tools' badge is hidden from both. A
205
- full-page `shot` is the whole page — the pane the SDK scrolls in unrolled, every lazy picture loaded, every arrival
229
+ default, and `page shot` names the file by the theme it was painted in. The dev tools' badge is hidden from both. A
230
+ full-page `page shot` is the whole page — the pane the SDK scrolls in unrolled, every lazy picture loaded, every arrival
206
231
  waiting for the scroll shown as it ends — in `tmp/shots/` unless `--out` says where.
207
232
 
208
- `shot --compare` writes the two pictures side by side and the differences in red. It compares each section where it
233
+ `page shot --compare` writes the two pictures side by side and the differences in red. It compares each section where it
209
234
  is on the other page, so a page 400 px longer is said once, with the section the drift starts at; then it pairs the
210
235
  texts both pages have and says what each does differently there — `h1 "Learn CSS" — font-size 68px → 60px · y +19px`.
211
236
  `--frames` compares pictures taken one after another and names what moved. A project `create` writes has them as
212
237
  `npm run check` and `npm run shot`.
213
238
 
214
- ## `fix`
239
+ ## `space fix`
215
240
 
216
241
  ```bash
217
- plitzi fix # what authoring would fix, as a diff of your own source
218
- plitzi fix --write # written, formatted as the project formats, and checked
242
+ plitzi space fix # what authoring would fix, as a diff of your own source
243
+ plitzi space fix --write # written, formatted as the project formats, and checked
219
244
  ```
220
245
 
221
246
  The fixes are the ones with a single reading (`fixSpace`'s: a key the element never reads, `'true'` where a boolean
@@ -224,12 +249,86 @@ by the line and column the element remembers — and only where the value is wri
224
249
  listed with where it is and why it was left. `--write` authors the space again in a fresh process and keeps the edits
225
250
  only if every fix is gone and no problem was added; a fix that would add one is put back and said.
226
251
 
227
- ## `lint`
252
+ ## `element where` and `element edit`
228
253
 
229
254
  ```bash
230
- plitzi lint # the space's source, eslint's way: each practice to change at its file and line
231
- plitzi lint --json # one object: { scope, notChecked, counts, findings }
232
- plitzi lint --max-warnings 0 # more warnings than that fail (exit 1); --strict: any warning does
255
+ plitzi element where hero-cta # by id: the file, the line and the call that writes it
256
+ plitzi element where navLink # every element wearing the class (`nav-link` or `navLink`)
257
+ plitzi element where "Get started" # every element showing the words
258
+ plitzi element where cta --by text # one reading only: id, class or text
259
+ plitzi element edit hero-cta --set content="Start free" # an attribute written in that call
260
+ plitzi element edit signup --set required=true --remove placeholder
261
+ plitzi element edit site-brand --every --set label="Home" # a helper's call that writes several elements: every one
262
+ ```
263
+
264
+ `element where` answers where the project's code writes an element — `src/space/pages/home.ts:42` and the call itself, or the
265
+ object a page or a layout is declared as — so
266
+ the call is edited instead of the files around it being read. It is asked of the code as it is now: the space is
267
+ authored again and each element's call read back, the way `space fix` finds it, so it follows an element wherever somebody
268
+ moved it, with nothing kept that could fall out of step. Ten matches at most, the call shown for the first three;
269
+ `--json` adds the element's attributes when it was asked for by id. A query is read as an id, then a class, then words —
270
+ the first that matches is answered, and any other that matched too is said with its count and the command for it
271
+ (`--by text`); `--by` reads it one way only. Words are every word an element says: its content, a `label`, `title`,
272
+ `alt` or `placeholder`, a binding's template, the words an instance hands its component. Asked for a class, it says
273
+ where the class is declared too — the `styles()` call — before who wears it; and an element written inside a
274
+ `LIST.map(item => …)` says which list it is repeated for and the file it is in. A space that does not author is said, with the
275
+ lines of `src/` holding the words instead.
276
+
277
+ `element edit` writes attributes in that call — `content` given as the factory's first argument (`text('Hi', { … })`) where it
278
+ is — keeping the kind each one has (a number stays a number; a new one is `true`/`false` or words), formats the file as
279
+ the project formats it, and authors the space again in a fresh process, read against the space before it: unless every
280
+ value asked for is there and nothing else in the space changed, the files go back to what they were, and what would
281
+ have changed besides is named. What it changed is printed, every line of it (`--json`: `effects`). An attribute a
282
+ binding computes is refused — the page shows the binding's value, never one written — and `element where` marks it `Bound`. A value that is a parameter of the helper the call is in (`heading(title, { … })` inside
283
+ `pageHead(id, title)`) is changed where the helper is handed it — `pageHead('about-head', 'About us')` — followed up
284
+ as far as the project's code hands it on, and only when the helper reads it once. A value read off a list the call is
285
+ repeated for (`QUESTIONS.map(item => button({ content: item.question }))`) is changed in the one entry of the list
286
+ that holds it, in whichever file the list is written. A component's instance is edited like any element: its
287
+ attributes are the props it hands the component, and `element where` finds the words it hands too. A page is edited by its
288
+ attributes as `element where` shows them — `seoPageTitle` is written as the page's `seoTitle`. A value read in more than one
289
+ place — a list entry a nav and a menu both draw — changes them all only with `--every`, every one named. A call that writes more than one
290
+ element — a helper called for each — is never changed unasked: `element where` says which elements it writes and the call that
291
+ leads to this one alone, and `element edit` refuses, naming them, unless `--every` says the change is for all of them. Any other
292
+ value written as anything but a literal — a variable, a template, props spread from elsewhere — is left to the author,
293
+ said with where it is. The same `element edit` refused again within a few minutes says so,
294
+ and that running it once more will not change the answer (kept in `tmp/refusals.json`).
295
+
296
+ ## `element remove`, `element move` and `verify`
297
+
298
+ ```bash
299
+ plitzi element remove ent-trust # the element's call taken out, with the styles and imports only it used
300
+ plitzi element move ent-faq --before ent-pricing # put before (or --after) a sibling of the same list of children
301
+ plitzi verify # author, lint:space, typecheck, lint, format and every page: what fails
302
+ plitzi verify --no-pages # the pages left out, said as such
303
+ ```
304
+
305
+ `element remove` and `element move` act on the call that writes the element — or, a section a helper builds and returns
306
+ (`body: [enterpriseFaq()]`), on the helper's call — and are checked as `element edit` is: the space authored again in a fresh
307
+ process and read against the one before. A removal may take the element and what it holds and nothing else; a move
308
+ may change only its parent's order, with the element beside the one it was moved by. Anything more and the file goes
309
+ back, what it would have changed named — and the space read again goes through the same gate `npm run author` does, so
310
+ a change that leaves it refused is never kept. A removal is refused before anything is written when another element's
311
+ flow acts on what it would take away (`site-search openModal → search-modal`), each said with where it is. What it took
312
+ is said once, by the outermost element, with how many it held. A `styles()` declared for the removed element alone goes with it, and its
313
+ factories' imports, named; a helper left with no caller is said, not deleted. A call written once for several
314
+ elements (a `map`), a page or a layout, and a move between two files are left to the author, said.
315
+
316
+ An element's own selector and its bindings are named after its place under its nearest id — not after its position
317
+ among its siblings — so a move renames nothing.
318
+
319
+ `verify` runs each check the project has a script for, as its package manager runs one, then opens every page with
320
+ no parameter in its path at 1440 and 390 px (the server must be up: `npm start`). Only what fails is printed, with the
321
+ last lines it said, and the first failure ends the run — one broken file fails every step after it the same way — the
322
+ rest said as not run until it passes (`--keep-going` runs them anyway); a page the browser was sent away from — one for signed-in visitors — is said as not checked, never
323
+ as passing — said on its own line, without failing the run, since a space with pages for signed-in visitors always
324
+ has some (`plitzi page check <path> --as <username>` opens one). Exit 1 when anything failed.
325
+
326
+ ## `space lint`
327
+
328
+ ```bash
329
+ plitzi space lint # the space's source, eslint's way: each practice to change at its file and line
330
+ plitzi space lint --json # one object: { scope, notChecked, counts, findings }
331
+ plitzi space lint --max-warnings 0 # more warnings than that fail (exit 1); --strict: any warning does
233
332
  ```
234
333
 
235
334
  How the space in `src/space/` is written — what only its source can say, and what grows hard to read and to change as
@@ -261,14 +360,14 @@ lint's own codes:
261
360
  `// plitzi-lint-disable <codes>` for the whole file.
262
361
 
263
362
  It is not whether the space authors — what it refuses and warns of is `npm run author`'s — nor a page as it renders
264
- (`check`), nor the project around the space (`doctor`); every report says so (`notChecked`). Exit code 1 while anything
363
+ (`page check`), nor the project around the space (`doctor`); every report says so (`notChecked`). Exit code 1 while anything
265
364
  is an error; with `--strict` a warning too, with `--max-warnings <n>` more than n of them.
266
365
 
267
- ## `import`
366
+ ## `page import`
268
367
 
269
368
  ```bash
270
- plitzi import https://example.com/pricing # into src/imported
271
- plitzi import https://example.com/ --out src/home --width 1440,390
369
+ plitzi page import https://example.com/pricing # into src/imported
370
+ plitzi page import https://example.com/ --out src/home --width 1440,390
272
371
  ```
273
372
 
274
373
  A page you own or may reuse, measured in the project's own Playwright as a place to start writing from — never a copy
@@ -303,11 +402,16 @@ plitzi explain class-and-css # a problem's code: what was wrong, what to writ
303
402
  plitzi explain content-attribute # a suggestion's code: what is written the long way, and the short one
304
403
  plitzi explain bindTemplate # a helper: how it is written, what it is for, an example
305
404
  plitzi explain motion # the arrivals, triggers and loops the SDK plays
405
+ plitzi explain pageFamily # any other export of @plitzi/sdk-authoring: its signature and its doc's first line
306
406
  plitzi explain --list steps # every one of a kind: elements, steps, triggers, codes, transformers, helpers
307
407
  ```
308
408
 
309
409
  What a name means when authoring, from the catalogues the checks themselves read — the answer to a question that would
310
- otherwise be a search through the SDK's types. `--json` answers in one object; over MCP it is `plitzi://explain/{name}`.
410
+ otherwise be a search through the SDK's types. A name no catalogue holds — `pageFamily`, `styles`, `SpaceSpec` — is any
411
+ export of `@plitzi/sdk-authoring`, answered from the `.d.ts` the project installed, so it is the version the project
412
+ runs. An element of the project's own — `src/plugins/<Name>/` — is explained by its type the same way: what it takes
413
+ (each attribute at its default), fires and answers, and the `custom({ … renderType })` that places it, which `plugin
414
+ add` prints too. `--json` answers in one object; over MCP it is `plitzi://explain/{name}`.
311
415
 
312
416
  ## `doctor`
313
417
 
@@ -322,7 +426,7 @@ plitzi doctor --strict # warnings fail too — for a CI that keeps the p
322
426
  Whether the project is whole as the CLI sets it up, read from what it is now rather than from what the CLI once wrote:
323
427
  a developer may change any file, and the checks are what each part must be for the project to install, start, build and
324
428
  push. It is the CLI's check of the project, not of the space: what the space authors to and warns of is `npm run
325
- author`'s, how it is written `lint`'s, and how a page renders `check`'s. Exit code 1 while anything is an error (with `--strict`, a warning).
429
+ author`'s, how it is written `space lint`'s, and how a page renders `page check`'s. Exit code 1 while anything is an error (with `--strict`, a warning).
326
430
 
327
431
  Each finding has an area, a stable `code`, the file and its `fix`; the report ends with **what to run next** — the few
328
432
  commands (`plitzi upgrade --write`, an install, `doctor --fix`) that clear most of the list, by how many each fixes.
@@ -345,7 +449,7 @@ area would only say what the move fixes — and `upgrade` writes no file until i
345
449
  **Where each part lives** is one check (`checkProjectLayout`, `@plitzi/sdk-shared/project/layout`) said by three: the
346
450
  server refuses to start on its errors, listing every one (and prints its warnings while developing — a plugin folder
347
451
  added broken while `start:dev` runs is said there, and the server goes on), `npm run author` and the CLI's checks
348
- (`check`, `push`, `fix`) refuse to author, and `doctor` says each with its fix under `layout`. `lint` says in one line
452
+ (`page check`, `space push`, `space fix`) refuse to author, and `doctor` says each with its fix under `layout`. `space lint` says in one line
349
453
  that there are some. Its codes, each with what it means, are `PROJECT_LAYOUT_CODES`: errors — a plugin folder with no
350
454
  `index.ts` (or `index.tsx`), or both; a JavaScript entry; a folder name that is no element type (`story-editor` →
351
455
  `StoryEditor`), two folders of one type, a plugin also built in `vendor/plugins/`; a plugin's `functions/`,
@@ -365,7 +469,7 @@ did you mean `index.ts`, `src/plugins/`? — and one that differs only in case s
365
469
  | `config` | `tsconfig.json` reads `src/` and `plitzi/` and sets what Node's type stripping needs; `tsconfig.build.json` writes the file `start:prod` runs; `.gitignore` keeps `.env` out (and `node_modules`, `tmp`, `dist`, `state`) and `.plitzi/` in; `.env` not in git; the signing secret, as long as the project's own server wants it; a cloud project's key |
366
470
  | `sources` | what Node runs as written — `src/main.ts`, `src/config/`, `src/actions/`, `src/space/`, `src/runtime/`, `plitzi/author.ts`, the plugins' declarations, and all they import: every relative import a file that is there, with its extension; JSON imported `with { type: 'json' }`; no JSX; every package declared (a devDependency, in what production runs, is said); what the server loads by name exported (`space`, `actions`, the runtime's default) |
367
471
  | `plugins` | each folder of `src/plugins/` the server can build: its entry builds and exports its component, its packages declared; its `declaration.ts` loads and its `type` is the folder's (`StatCard` → `statCard`) |
368
- | `data` | every JSON file of `src/data/` and `public/data/` parses — what the server answers with and `push` sends |
472
+ | `data` | every JSON file of `src/data/` and `public/data/` parses — what the server answers with and `space push` sends |
369
473
  | `functions` | `src/functions/` built by the project's own `@plitzi/sdk-server` (`buildFunctions`), as every runner builds them |
370
474
  | `records` | `.plitzi/space.json`, `scaffold.json` and `functions.json` readable, and of the same space |
371
475
  | `skills` | `.claude/skills/plitzi-*` as the packages installed write them |
@@ -412,7 +516,7 @@ today's command, one the project changed is left and said. A file the CLI no lon
412
516
  Node reads `.env` — is removed the same way once the `main.ts` that read it is the CLI's; one the project changed is
413
517
  said and left, unless `--take` names it (`.plitzi/scaffold.json` records the files and the scripts, and the package
414
518
  manager the files were written for — what a project not installed yet has no lockfile to say). In a project made from
415
- a space, a file the space gave over one of the CLI's would be the space's, and `upgrade` would leave it to `plitzi pull` —
519
+ a space, a file the space gave over one of the CLI's would be the space's, and `upgrade` would leave it to `plitzi space pull` —
416
520
  none does: `serveProject` runs whatever the space brought, from where it lands. `update` is the same
417
521
  command, and `plitzi skills update` is `upgrade skills --write`. `npm run author` says when the authoring skill is
418
522
  older than the `@plitzi/sdk-authoring` installed.
@@ -425,14 +529,16 @@ plitzi data describe src/data/products.json --json # { shape, example }
425
529
  ```
426
530
 
427
531
  The fields of a JSON file, their types and which rows have them — `price?: number (in 812 of 879)` — so a page can
428
- be bound to half a megabyte of data after reading twenty lines of it.
532
+ be bound to half a megabyte of data after reading twenty lines of it. An object keyed by data — slugs, ids — is one
533
+ shape, said once: `{ [key]: … } (500 keys: "first-post", …)`. A file written a letter off is offered the nearest one
534
+ beside it.
429
535
 
430
- ## `pull`
536
+ ## `space pull`
431
537
 
432
538
  ```bash
433
- plitzi pull # the space's changes in, yours kept
434
- plitzi pull --force # where a file changed on both sides, the space's copy wins
435
- plitzi pull --environment production --revision latest # follow another version from now on
539
+ plitzi space pull # the space's changes in, yours kept
540
+ plitzi space pull --force # where a file changed on both sides, the space's copy wins
541
+ plitzi space pull --environment production --revision latest # follow another version from now on
436
542
  ```
437
543
 
438
544
  In a project `create --from` wrote: a file the space changed and you did not is written, one you changed and the space
@@ -441,15 +547,15 @@ write **nothing** and name them. Both sides are compared as the project's Pretti
441
547
  `package.json` only gains the packages the space's code now asks for. It follows the version the project was made from —
442
548
  the draft, an environment's latest, or a pinned revision.
443
549
 
444
- ## `push`
550
+ ## `space push`
445
551
 
446
552
  ```bash
447
- plitzi push # at a terminal: tick what goes up — what changed is ticked already
448
- plitzi push space functions # only these: space, functions, data, runtime, plugins, files
449
- plitzi push space --force # replace the draft even though it was edited in the builder since
553
+ plitzi space push # at a terminal: tick what goes up — what changed is ticked already
554
+ plitzi space push space functions # only these: space, functions, data, runtime, plugins, files
555
+ plitzi space push space --force # replace the draft even though it was edited in the builder since
450
556
  ```
451
557
 
452
- The way back of `pull`: the project put on the space it works with, as its **draft**. With nobody at the terminal it
558
+ The way back of `space pull`: the project put on the space it works with, as its **draft**. With nobody at the terminal it
453
559
  sends what changed since the project last had the space. Each part goes up as its own command sends it, in the order
454
560
  that names come before what names them:
455
561
 
@@ -467,17 +573,17 @@ The draft is never replaced unseen: when it was edited in the builder since the
467
573
  is refused — pull first, or `--force`. A project that never had the space (one not made with `create --from`) may take a
468
574
  space nobody has worked on yet; one that holds work asks for `--force` too. Always the space the CLI is connected to,
469
575
  which must be the one the project came from, and never a published environment: publish in the builder. Afterwards
470
- `.plitzi/space.json` records what was sent, so `pull` keeps working — on a project that started on its own too.
576
+ `.plitzi/space.json` records what was sent, so `space pull` keeps working — on a project that started on its own too.
471
577
 
472
578
  The space goes back with its files where Plitzi serves them: a path to a file of `public/assets/` (`/assets/a.png`) —
473
- one `create --from` or `pull` wrote, or one the `files` part put on the CDN — is sent as that file's CDN address. Only
579
+ one `create --from` or `space pull` wrote, or one the `files` part put on the CDN — is sent as that file's CDN address. Only
474
580
  `public/assets/` goes to the CDN: the rest of `public/` is the project's own server's. What would not reach Plitzi is
475
581
  said before anything is sent, with what to do: a provider reading a file `src/data/` does not hold, a file of
476
582
  `public/assets/` the space names that is not on its CDN yet, and one of `public/` outside `assets/`.
477
583
 
478
- ## `add plugin`
584
+ ## `plugin add`
479
585
 
480
- Adds elements of your own to the project you are in — one, several at once (`add plugin seat-picker legend`), or one at
586
+ Adds elements of your own to the project you are in — one, several at once (`plugin add seat-picker legend`), or one at
481
587
  a time as the need comes. Each is a folder, written the way Plitzi's own elements are (`@plitzi/sdk-elements`): the
482
588
  component, its `declaration.ts` (its `type`, the events it fires, the actions it answers to, and the element the builder
483
589
  adds), its `Settings.tsx` panel for the builder, and the `index.ts` that puts them together — what the folder is built
@@ -497,7 +603,7 @@ A name that would make a built-in element's type (`button`, `form`) is refused:
497
603
  Told its shape, it writes that shape rather than the counter it writes otherwise — one element at a time:
498
604
 
499
605
  ```bash
500
- plitzi add plugin ticker --prop interval:number=5000 --prop paused:boolean --trigger onTick:count --callback reset --headless
606
+ plitzi plugin add ticker --prop interval:number=5000 --prop paused:boolean --trigger onTick:count --callback reset --headless
501
607
  ```
502
608
 
503
609
  `--prop name:type=default` (string, number or boolean) is an attribute: in the props, the declaration's defaults and
@@ -512,14 +618,14 @@ Prettier writes them.
512
618
  routes answer under `/fn/plugins/<type>/` (`usePluginRoute(type)` in the component names them), its tasks are steps
513
619
  `<type>.<action>`, and it runs with a plugin's own corner of `kv`, none of the space's credentials or channels. In a
514
620
  server-mode project or a plugin package (which gets `@plitzi/sdk-server` for the types); a project that renders in the
515
- browser alone has nothing to run it, and is refused. `pack plugin` carries it as `functions.source.json`, and the
621
+ browser alone has nothing to run it, and is refused. `plugin pack` carries it as `functions.source.json`, and the
516
622
  platform builds and keeps it privately when the plugin is uploaded — see
517
623
  [functions § a plugin's server half](../../docs/en/functions.md#10-a-plugins-server-half).
518
624
 
519
625
  ## `create --plugin`
520
626
 
521
627
  A plugin package: elements any space can load, with a Vite preview to write them in. It builds nothing itself —
522
- `pack plugin` does, for every plugin — so it carries no bundler config and no build dependency.
628
+ `plugin pack` does, for every plugin — so it carries no bundler config and no build dependency.
523
629
 
524
630
  ```bash
525
631
  plitzi create seat-picker --plugin # asks the name, what the builder shows, what it is for, who publishes it
@@ -535,14 +641,14 @@ Its scripts: `start` (every element inside a space, rendered by the SDK in the b
535
641
  replacement), `visual` (a browser checks each element renders, answers a click, and leaves the page whole),
536
642
  `typecheck`, `lint` and `format`.
537
643
 
538
- ## `pack plugin`
644
+ ## `plugin pack`
539
645
 
540
646
  The one place a plugin is built — from a plugin package, or from element folders of any project:
541
647
 
542
648
  ```bash
543
- plitzi pack plugin # in a plugin package: every element it holds
544
- plitzi pack plugin src/plugins/SeatPicker # an element of a self-hosted project
545
- plitzi pack plugin src/plugins/SeatPicker src/plugins/Legend # several in one plugin, the first its main
649
+ plitzi plugin pack # in a plugin package: every element it holds
650
+ plitzi plugin pack src/plugins/SeatPicker # an element of a self-hosted project
651
+ plitzi plugin pack src/plugins/SeatPicker src/plugins/Legend # several in one plugin, the first its main
546
652
  ```
547
653
 
548
654
  It writes one ES module (esbuild; React and the SDK kept out — the page provides them; images, fonts and any file
@@ -558,27 +664,27 @@ what a manifest is written from. `--out` moves the build, `--no-zip` leaves the
558
664
  version the manifest carries (the project's own by default).
559
665
 
560
666
  Beside the zip it writes the plugin's **source** (`<name>.source.json.gz`): every file of the project its elements import
561
- — followed with the project's own TypeScript, `import type` included — and the packages they need. `upload plugin`
667
+ — followed with the project's own TypeScript, `import type` included — and the packages they need. `plugin upload`
562
668
  keeps it on the space, which is what `create --from` brings back. `--source-root` names the project those paths are
563
669
  relative to, when the elements are not a project of their own. A file outside it, a credentials file or a credential
564
670
  in the code keeps it from being written — said, and never stopping the build.
565
671
 
566
- ## `pack source`
672
+ ## `source pack`
567
673
 
568
674
  ```bash
569
- plitzi pack source src/runtime/index.ts --kind runtime --name runtime -o runtime.source.json.gz
675
+ plitzi source pack src/runtime/index.ts --kind runtime --name runtime -o runtime.source.json.gz
570
676
  ```
571
677
 
572
- What `upload plugin` and `runtime push` keep, written to a file to look at: the closure of the entries named, gzipped.
678
+ What `plugin upload` and `runtime push` keep, written to a file to look at: the closure of the entries named, gzipped.
573
679
 
574
680
 
575
- ## `login`, `space` and `upload plugin`
681
+ ## `login`, `space use` and `plugin upload`
576
682
 
577
683
  ```bash
578
684
  plitzi login # sign in, in your browser
579
- plitzi space # choose the space to work in, in your browser
685
+ plitzi space use # choose the space to work in, in your browser
580
686
  plitzi whoami # who you are signed in as, and the space; --json for a tool
581
- plitzi upload plugin # the zip pack plugin left, on that space
687
+ plitzi plugin upload # the zip pack plugin left, on that space
582
688
  plitzi logout # the session revoked on the platform, and forgotten here
583
689
  ```
584
690
 
@@ -588,17 +694,17 @@ social sign-in work without it knowing. What it keeps is the session and a way t
588
694
  and it shows among your account's devices, where it can be ended like any other.
589
695
 
590
696
  **One space at a time.** The space is chosen on the same grant screen an AI connector's is, and the CLI works in that
591
- one until `plitzi space` chooses another — which replaces the connection, and revokes the one before. No command takes a
697
+ one until `plitzi space use` chooses another — which replaces the connection, and revokes the one before. No command takes a
592
698
  space of its own: an upload goes to the space `plitzi whoami` names, so a plugin meant for a staging space cannot end
593
699
  up in the live one because of a flag.
594
700
 
595
- `upload plugin` takes the zip named, or the one `pack plugin` left in the project (the newest, when there are several —
701
+ `plugin upload` takes the zip named, or the one `plugin pack` left in the project (the newest, when there are several —
596
702
  asked at a terminal). It is checked for its `plugin-manifest.json` before anything is sent. Without a connection, or
597
703
  without a space, the browser opens for what is missing, so the first upload is one command too. It goes on one of the
598
704
  space's public buckets — `--bucket <identifier>` (narrowed to one CDN with `--cdn <identifier>`), or asked when there
599
705
  are several; a private bucket is refused, since no page could load from it — and is installed, as the builder does when
600
706
  a zip is dropped under Resources: added, or the plugin already there moved to the new version with its settings kept. The
601
- source `pack plugin` wrote beside the zip goes up after it, into the space's private bucket.
707
+ source `plugin pack` wrote beside the zip goes up after it, into the space's private bucket.
602
708
 
603
709
  `--api` (or `PLITZI_API_URL`) points it at another platform, a self-hosted or local one; the CLI trusts the
604
710
  certificate authorities the system trusts, as the browser beside it does.
@@ -621,11 +727,11 @@ connection kept open, memory that outlives a request, Node and its packages (`do
621
727
  **Its code lives in a project of yours** — a folder, usually a repository — and nowhere else: the builder shows how a
622
728
  runtime runs and sets its variables, but it does not hold its code and cannot change it. The project has
623
729
  `src/runtime/index.ts` (or `--entry`), whose default export is `defineRuntime(…)`, and `@plitzi/sdk-server` installed:
624
- `plitzi add runtime` writes it in a project from `plitzi create` in server mode, whose `src/main.ts` runs it too —
730
+ `plitzi runtime add` writes it in a project from `plitzi create` in server mode, whose `src/main.ts` runs it too —
625
731
  `/hello` answers on `npm start` — and whose `start:dev` restarts on it; `examples/self-hosting/10-runtime` is the smallest one to start
626
732
  from, and it runs as a server of its own too.
627
733
 
628
- `push` packs the module with the project's own `@plitzi/sdk-server` — the module and every package it imports, bar
734
+ `runtime push` packs the module with the project's own `@plitzi/sdk-server` — the module and every package it imports, bar
629
735
  `@plitzi/*` and React, which the platform provides — and sends it to the space `plitzi whoami` names. It becomes the
630
736
  draft's runtime, which starts on it; **publishing the space** from the builder takes it to the published site. A
631
737
  runtime is part of the plans that carry it; on another, the push is refused and says so. The source it was
@@ -649,8 +755,8 @@ plitzi functions dev seismic.feed --params '{}' --watch # on this mac
649
755
  ```
650
756
 
651
757
  A space's own server code — tasks its actions run as steps, routes under `/fn/` — and `src/functions/` is a working copy
652
- of it: `.plitzi/functions.json` keeps what was pulled, so `pull` refuses to overwrite what is not pushed (`--force`
653
- throws it away) and `push` refuses when the space moved on since. A problem comes back as
758
+ of it: `.plitzi/functions.json` keeps what was pulled, so `functions pull` refuses to overwrite what is not pushed (`--force`
759
+ throws it away) and `functions push` refuses when the space moved on since. A problem comes back as
654
760
  `src/functions/<file>:<line> <message>`. `dev` runs with the project's own `@plitzi/sdk-server` (`isolated-vm` and
655
761
  `core-js` beside it); credentials come from `PLITZI_FUNCTIONS_CREDENTIALS`. See `docs/en/functions.md`.
656
762