@zitadel/cli 0.1.0-alpha.12 → 0.1.0-alpha.14

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.
Files changed (43) hide show
  1. package/README.md +137 -57
  2. package/SKILLS.md +26 -13
  3. package/dist/commands/apply.mjs +6 -4
  4. package/dist/commands/apply.mjs.map +1 -1
  5. package/dist/commands/doctor.mjs +89 -12
  6. package/dist/commands/doctor.mjs.map +1 -1
  7. package/dist/commands/eject.mjs +4 -4
  8. package/dist/commands/logs.mjs +2 -2
  9. package/dist/commands/plan.mjs +6 -4
  10. package/dist/commands/plan.mjs.map +1 -1
  11. package/dist/commands/reset.mjs +2 -2
  12. package/dist/commands/schemas/list.mjs +134 -0
  13. package/dist/commands/schemas/list.mjs.map +1 -0
  14. package/dist/commands/setup.mjs +130 -15
  15. package/dist/commands/setup.mjs.map +1 -1
  16. package/dist/commands/start.mjs +4 -4
  17. package/dist/commands/status.mjs +3 -3
  18. package/dist/commands/stop.mjs +3 -3
  19. package/dist/{docker-Djz6BLp9.mjs → docker-D7BSD5C9.mjs} +3 -3
  20. package/dist/{docker-Djz6BLp9.mjs.map → docker-D7BSD5C9.mjs.map} +1 -1
  21. package/dist/{docker-guidance-D-33g1uV.mjs → docker-guidance-mcTT3_0E.mjs} +2 -2
  22. package/dist/{docker-guidance-D-33g1uV.mjs.map → docker-guidance-mcTT3_0E.mjs.map} +1 -1
  23. package/dist/environment-BQF7LeCz.mjs +17 -0
  24. package/dist/environment-BQF7LeCz.mjs.map +1 -0
  25. package/dist/{oclif-BoUVygsZ.mjs → oclif-Bm-FkF6z.mjs} +66 -13
  26. package/dist/oclif-Bm-FkF6z.mjs.map +1 -0
  27. package/dist/{orca-DU8myWGm.mjs → orca-CpXj_XsA.mjs} +46 -94
  28. package/dist/orca-CpXj_XsA.mjs.map +1 -0
  29. package/dist/{ports-B09RjuHx.mjs → ports-CxBKS1ga.mjs} +1 -1
  30. package/dist/{ports-B09RjuHx.mjs.map → ports-CxBKS1ga.mjs.map} +1 -1
  31. package/dist/{processes-Cw8TO1SY.mjs → processes-BVqYsxT8.mjs} +1 -1
  32. package/dist/{processes-Cw8TO1SY.mjs.map → processes-BVqYsxT8.mjs.map} +1 -1
  33. package/dist/{project-B1qVQMKS.mjs → project-Dk7V0xka.mjs} +3 -3
  34. package/dist/{project-B1qVQMKS.mjs.map → project-Dk7V0xka.mjs.map} +1 -1
  35. package/dist/{sync-CzruNz8K.mjs → sync-nSLnVhKK.mjs} +128 -107
  36. package/dist/sync-nSLnVhKK.mjs.map +1 -0
  37. package/dist/user-schema-DDz5-lX5.mjs +13 -0
  38. package/dist/user-schema-DDz5-lX5.mjs.map +1 -0
  39. package/oclif.manifest.json +106 -1
  40. package/package.json +5 -4
  41. package/dist/oclif-BoUVygsZ.mjs.map +0 -1
  42. package/dist/orca-DU8myWGm.mjs.map +0 -1
  43. package/dist/sync-CzruNz8K.mjs.map +0 -1
package/README.md CHANGED
@@ -42,9 +42,12 @@ scaffolds also replace the starter `app/page.tsx` with links to sign in, create
42
42
  an account, and profile. Setup writes `.env.local` and `.zitadel/`, and installs
43
43
  dependencies with the detected package manager. Pass `--skip-install` to install
44
44
  them yourself. The project's default user schema and login flow are provisioned
45
- server-side at creation time, so the CLI does not scaffold or upload them. Open
46
- the dev server URL printed by your framework, register a user, log out, log back
47
- in, and end on the signed-in profile page.
45
+ from versioned local defaults; setup writes editable copies into
46
+ `.zitadel/schemas/default-human-user.json` and
47
+ `.zitadel/flows/default-login.json`, uploads them through the schema and flow
48
+ APIs, then seeds `.zitadel/state.json` so `zitadel plan` is immediately empty.
49
+ Open the dev server URL printed by your framework, register a user, log out,
50
+ log back in, and end on the signed-in profile page.
48
51
 
49
52
  For a reproducible tester report, use the exact alpha train from the GitHub
50
53
  Release:
@@ -60,6 +63,14 @@ registration/login, and optional passkey setup after password registration.
60
63
  Users who skip passkey setup can still sign in with password; users who add a
61
64
  passkey can sign in with either credential.
62
65
 
66
+ Repo config is authoritative: edit `zitadel.json`, `.zitadel/schemas/*.json`,
67
+ or `.zitadel/flows/*.json`, then re-run `zitadel plan` and `zitadel apply`.
68
+ Server-provisioned defaults remain a fallback for non-CLI project creation, but
69
+ CLI-created projects are authored from local files first.
70
+ Templates are not supported until the server exposes template storage and APIs.
71
+ Flow create, read, list, update, and delete are available; the server enforces
72
+ flow lifecycle rules such as draft-only edits.
73
+
63
74
  For agent scripts, pass `--non-interactive --json` and capture stdout and stderr
64
75
  separately. The CLI contract is one parseable JSON object on stdout; terminals
65
76
  and agent UIs may display stderr package-manager progress together with stdout.
@@ -88,6 +99,7 @@ and agent UIs may display stderr package-manager progress together with stdout.
88
99
  * [`zitadel logs`](#zitadel-logs)
89
100
  * [`zitadel plan`](#zitadel-plan)
90
101
  * [`zitadel reset`](#zitadel-reset)
102
+ * [`zitadel schemas list`](#zitadel-schemas-list)
91
103
  * [`zitadel search`](#zitadel-search)
92
104
  * [`zitadel setup`](#zitadel-setup)
93
105
  * [`zitadel start`](#zitadel-start)
@@ -103,19 +115,22 @@ Validate and upload repo config to the platform.
103
115
 
104
116
  ```
105
117
  USAGE
106
- $ zitadel apply [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug]
107
- [--telemetry] [-e development|preview|production]
118
+ $ zitadel apply [--json] [-c <value>] [-s <value>] [-n] [-f]
119
+ [--dry-run] [--verbose] [--debug] [--telemetry] [-e
120
+ development|preview|production]
108
121
 
109
122
  FLAGS
110
123
  -c, --cwd=<value> Project directory to operate on.
111
124
  -e, --environment=<option> Target environment (default: development).
112
125
  <options: development|preview|production>
113
126
  -f, --force Overwrite protected files on conflict.
114
- -n, --non-interactive Disable prompts. Required when scripting or running as an agent.
127
+ -n, --non-interactive Disable prompts. Required when scripting or
128
+ running as an agent.
115
129
  -s, --server=<value> Override the resolved server URL.
116
130
  --debug Debug logging.
117
131
  --dry-run Preview without mutating files or the platform.
118
- --[no-]telemetry Send anonymous usage analytics. Disable with --no-telemetry.
132
+ --[no-]telemetry Send anonymous usage analytics. Disable with
133
+ --no-telemetry.
119
134
  --verbose Verbose logging.
120
135
 
121
136
  GLOBAL FLAGS
@@ -162,8 +177,9 @@ List all zitadel commands.
162
177
 
163
178
  ```
164
179
  USAGE
165
- $ zitadel commands [--json] [-c id|plugin|summary|type... | --tree] [--deprecated] [-x | ] [--hidden]
166
- [--no-truncate | ] [--sort id|plugin|summary|type | ]
180
+ $ zitadel commands [--json] [-c id|plugin|summary|type... | --tree]
181
+ [--deprecated] [-x | ] [--hidden] [--no-truncate | ] [--sort
182
+ id|plugin|summary|type | ]
167
183
 
168
184
  FLAGS
169
185
  -c, --columns=<option>... Only show provided columns (comma-separated).
@@ -191,13 +207,15 @@ Verify local runtime and project state.
191
207
 
192
208
  ```
193
209
  USAGE
194
- $ zitadel doctor [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug]
195
- [--telemetry] [--fix] [--image <value>] [--port <value>] [--runtime binary|docker]
210
+ $ zitadel doctor [--json] [-c <value>] [-s <value>] [-n] [-f]
211
+ [--dry-run] [--verbose] [--debug] [--telemetry] [--fix] [--image <value>]
212
+ [--port <value>] [--runtime binary|docker]
196
213
 
197
214
  FLAGS
198
215
  -c, --cwd=<value> Project directory to operate on.
199
216
  -f, --force Overwrite protected files on conflict.
200
- -n, --non-interactive Disable prompts. Required when scripting or running as an agent.
217
+ -n, --non-interactive Disable prompts. Required when scripting or running as
218
+ an agent.
201
219
  -s, --server=<value> Override the resolved server URL.
202
220
  --debug Debug logging.
203
221
  --dry-run Preview without mutating files or the platform.
@@ -206,7 +224,8 @@ FLAGS
206
224
  --port=<value> [default: 8080] Local HTTP port.
207
225
  --runtime=<option> Local runtime backend.
208
226
  <options: binary|docker>
209
- --[no-]telemetry Send anonymous usage analytics. Disable with --no-telemetry.
227
+ --[no-]telemetry Send anonymous usage analytics. Disable with
228
+ --no-telemetry.
210
229
  --verbose Verbose logging.
211
230
 
212
231
  GLOBAL FLAGS
@@ -222,17 +241,19 @@ Remove managed files and local Zitadel state.
222
241
 
223
242
  ```
224
243
  USAGE
225
- $ zitadel eject [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug]
226
- [--telemetry]
244
+ $ zitadel eject [--json] [-c <value>] [-s <value>] [-n] [-f]
245
+ [--dry-run] [--verbose] [--debug] [--telemetry]
227
246
 
228
247
  FLAGS
229
248
  -c, --cwd=<value> Project directory to operate on.
230
249
  -f, --force Overwrite protected files on conflict.
231
- -n, --non-interactive Disable prompts. Required when scripting or running as an agent.
250
+ -n, --non-interactive Disable prompts. Required when scripting or running as
251
+ an agent.
232
252
  -s, --server=<value> Override the resolved server URL.
233
253
  --debug Debug logging.
234
254
  --dry-run Preview without mutating files or the platform.
235
- --[no-]telemetry Send anonymous usage analytics. Disable with --no-telemetry.
255
+ --[no-]telemetry Send anonymous usage analytics. Disable with
256
+ --no-telemetry.
236
257
  --verbose Verbose logging.
237
258
 
238
259
  GLOBAL FLAGS
@@ -271,19 +292,21 @@ Show local Zitadel server logs.
271
292
 
272
293
  ```
273
294
  USAGE
274
- $ zitadel logs [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug]
275
- [--telemetry] [--follow] [--tail <value>]
295
+ $ zitadel logs [--json] [-c <value>] [-s <value>] [-n] [-f]
296
+ [--dry-run] [--verbose] [--debug] [--telemetry] [--follow] [--tail <value>]
276
297
 
277
298
  FLAGS
278
299
  -c, --cwd=<value> Project directory to operate on.
279
300
  -f, --force Overwrite protected files on conflict.
280
- -n, --non-interactive Disable prompts. Required when scripting or running as an agent.
301
+ -n, --non-interactive Disable prompts. Required when scripting or running as
302
+ an agent.
281
303
  -s, --server=<value> Override the resolved server URL.
282
304
  --debug Debug logging.
283
305
  --dry-run Preview without mutating files or the platform.
284
306
  --follow Follow logs.
285
307
  --tail=<value> [default: 200] Number of lines to show.
286
- --[no-]telemetry Send anonymous usage analytics. Disable with --no-telemetry.
308
+ --[no-]telemetry Send anonymous usage analytics. Disable with
309
+ --no-telemetry.
287
310
  --verbose Verbose logging.
288
311
 
289
312
  GLOBAL FLAGS
@@ -299,19 +322,22 @@ Validate config without mutation and preview the sync diff.
299
322
 
300
323
  ```
301
324
  USAGE
302
- $ zitadel plan [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug]
303
- [--telemetry] [-e development|preview|production]
325
+ $ zitadel plan [--json] [-c <value>] [-s <value>] [-n] [-f]
326
+ [--dry-run] [--verbose] [--debug] [--telemetry] [-e
327
+ development|preview|production]
304
328
 
305
329
  FLAGS
306
330
  -c, --cwd=<value> Project directory to operate on.
307
331
  -e, --environment=<option> Target environment (default: development).
308
332
  <options: development|preview|production>
309
333
  -f, --force Overwrite protected files on conflict.
310
- -n, --non-interactive Disable prompts. Required when scripting or running as an agent.
334
+ -n, --non-interactive Disable prompts. Required when scripting or
335
+ running as an agent.
311
336
  -s, --server=<value> Override the resolved server URL.
312
337
  --debug Debug logging.
313
338
  --dry-run Preview without mutating files or the platform.
314
- --[no-]telemetry Send anonymous usage analytics. Disable with --no-telemetry.
339
+ --[no-]telemetry Send anonymous usage analytics. Disable with
340
+ --no-telemetry.
315
341
  --verbose Verbose logging.
316
342
 
317
343
  GLOBAL FLAGS
@@ -327,17 +353,19 @@ Delete the local Zitadel server runtime and data.
327
353
 
328
354
  ```
329
355
  USAGE
330
- $ zitadel reset [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug]
331
- [--telemetry]
356
+ $ zitadel reset [--json] [-c <value>] [-s <value>] [-n] [-f]
357
+ [--dry-run] [--verbose] [--debug] [--telemetry]
332
358
 
333
359
  FLAGS
334
360
  -c, --cwd=<value> Project directory to operate on.
335
361
  -f, --force Overwrite protected files on conflict.
336
- -n, --non-interactive Disable prompts. Required when scripting or running as an agent.
362
+ -n, --non-interactive Disable prompts. Required when scripting or running as
363
+ an agent.
337
364
  -s, --server=<value> Override the resolved server URL.
338
365
  --debug Debug logging.
339
366
  --dry-run Preview without mutating files or the platform.
340
- --[no-]telemetry Send anonymous usage analytics. Disable with --no-telemetry.
367
+ --[no-]telemetry Send anonymous usage analytics. Disable with
368
+ --no-telemetry.
341
369
  --verbose Verbose logging.
342
370
 
343
371
  GLOBAL FLAGS
@@ -347,6 +375,39 @@ DESCRIPTION
347
375
  Delete the local Zitadel server runtime and data.
348
376
  ```
349
377
 
378
+ ## `zitadel schemas list`
379
+
380
+ List revisions of a user-schema by objectType.
381
+
382
+ ```
383
+ USAGE
384
+ $ zitadel schemas list -t <value> [--json] [-c <value>] [-s <value>]
385
+ [-n] [-f] [--dry-run] [--verbose] [--debug] [--telemetry] [-e
386
+ development|preview|production]
387
+
388
+ FLAGS
389
+ -c, --cwd=<value> Project directory to operate on.
390
+ -e, --environment=<option> Target environment (default: development).
391
+ <options: development|preview|production>
392
+ -f, --force Overwrite protected files on conflict.
393
+ -n, --non-interactive Disable prompts. Required when scripting or
394
+ running as an agent.
395
+ -s, --server=<value> Override the resolved server URL.
396
+ -t, --object-type=<value> (required) Filter revisions by objectType (e.g.
397
+ human-user).
398
+ --debug Debug logging.
399
+ --dry-run Preview without mutating files or the platform.
400
+ --[no-]telemetry Send anonymous usage analytics. Disable with
401
+ --no-telemetry.
402
+ --verbose Verbose logging.
403
+
404
+ GLOBAL FLAGS
405
+ --json Format output as json.
406
+
407
+ DESCRIPTION
408
+ List revisions of a user-schema by objectType.
409
+ ```
410
+
350
411
  ## `zitadel search`
351
412
 
352
413
  Search for a command.
@@ -358,7 +419,8 @@ USAGE
358
419
  DESCRIPTION
359
420
  Search for a command.
360
421
 
361
- Once you select a command, hit enter and it will show the help for that command.
422
+ Once you select a command, hit enter and it will show the help for that
423
+ command.
362
424
  ```
363
425
 
364
426
  _See code: [@oclif/plugin-search](https://github.com/oclif/plugin-search/blob/v1.2.50/src/commands/search.ts)_
@@ -369,25 +431,32 @@ Create a Zitadel project and scaffold local auth.
369
431
 
370
432
  ```
371
433
  USAGE
372
- $ zitadel setup [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug]
373
- [--telemetry] [--framework next|nuxt|react|vue|solid|svelte|qwik|angular] [--renderer react|web-component]
374
- [--dev-port <value>] [--skip-install]
434
+ $ zitadel setup [--json] [-c <value>] [-s <value>] [-n] [-f]
435
+ [--dry-run] [--verbose] [--debug] [--telemetry] [--framework
436
+ next|nuxt|react|vue|solid|svelte|qwik|angular] [--renderer
437
+ react|web-component] [--dev-port <value>] [--skip-install]
375
438
 
376
439
  FLAGS
377
440
  -c, --cwd=<value> Project directory to operate on.
378
441
  -f, --force Overwrite protected files on conflict.
379
- -n, --non-interactive Disable prompts. Required when scripting or running as an agent.
442
+ -n, --non-interactive Disable prompts. Required when scripting or running
443
+ as an agent.
380
444
  -s, --server=<value> Override the resolved server URL.
381
445
  --debug Debug logging.
382
- --dev-port=<value> Dev-server port; also the issuer origin registered with Zitadel. Defaults to the detected
383
- port. Use distinct ports to run several scaffolded apps side by side.
446
+ --dev-port=<value> Dev-server port; also the issuer origin registered
447
+ with Zitadel. Defaults to the detected port. Use
448
+ distinct ports to run several scaffolded apps side
449
+ by side.
384
450
  --dry-run Preview without mutating files or the platform.
385
451
  --framework=<option> Framework to target.
386
- <options: next|nuxt|react|vue|solid|svelte|qwik|angular>
452
+ <options:
453
+ next|nuxt|react|vue|solid|svelte|qwik|angular>
387
454
  --renderer=<option> Renderer (default: react).
388
455
  <options: react|web-component>
389
- --skip-install Do not install dependencies after setup updates package.json.
390
- --[no-]telemetry Send anonymous usage analytics. Disable with --no-telemetry.
456
+ --skip-install Do not install dependencies after setup updates
457
+ package.json.
458
+ --[no-]telemetry Send anonymous usage analytics. Disable with
459
+ --no-telemetry.
391
460
  --verbose Verbose logging.
392
461
 
393
462
  GLOBAL FLAGS
@@ -408,13 +477,15 @@ Start a local Zitadel server.
408
477
 
409
478
  ```
410
479
  USAGE
411
- $ zitadel start [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug]
412
- [--telemetry] [--image <value>] [--port <value>] [--runtime binary|docker]
480
+ $ zitadel start [--json] [-c <value>] [-s <value>] [-n] [-f]
481
+ [--dry-run] [--verbose] [--debug] [--telemetry] [--image <value>] [--port
482
+ <value>] [--runtime binary|docker]
413
483
 
414
484
  FLAGS
415
485
  -c, --cwd=<value> Project directory to operate on.
416
486
  -f, --force Overwrite protected files on conflict.
417
- -n, --non-interactive Disable prompts. Required when scripting or running as an agent.
487
+ -n, --non-interactive Disable prompts. Required when scripting or running as
488
+ an agent.
418
489
  -s, --server=<value> Override the resolved server URL.
419
490
  --debug Debug logging.
420
491
  --dry-run Preview without mutating files or the platform.
@@ -422,7 +493,8 @@ FLAGS
422
493
  --port=<value> [default: 8080] Local HTTP port.
423
494
  --runtime=<option> Local runtime backend.
424
495
  <options: binary|docker>
425
- --[no-]telemetry Send anonymous usage analytics. Disable with --no-telemetry.
496
+ --[no-]telemetry Send anonymous usage analytics. Disable with
497
+ --no-telemetry.
426
498
  --verbose Verbose logging.
427
499
 
428
500
  GLOBAL FLAGS
@@ -438,17 +510,19 @@ Summarize the local Zitadel server and project state.
438
510
 
439
511
  ```
440
512
  USAGE
441
- $ zitadel status [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug]
442
- [--telemetry]
513
+ $ zitadel status [--json] [-c <value>] [-s <value>] [-n] [-f]
514
+ [--dry-run] [--verbose] [--debug] [--telemetry]
443
515
 
444
516
  FLAGS
445
517
  -c, --cwd=<value> Project directory to operate on.
446
518
  -f, --force Overwrite protected files on conflict.
447
- -n, --non-interactive Disable prompts. Required when scripting or running as an agent.
519
+ -n, --non-interactive Disable prompts. Required when scripting or running as
520
+ an agent.
448
521
  -s, --server=<value> Override the resolved server URL.
449
522
  --debug Debug logging.
450
523
  --dry-run Preview without mutating files or the platform.
451
- --[no-]telemetry Send anonymous usage analytics. Disable with --no-telemetry.
524
+ --[no-]telemetry Send anonymous usage analytics. Disable with
525
+ --no-telemetry.
452
526
  --verbose Verbose logging.
453
527
 
454
528
  GLOBAL FLAGS
@@ -464,18 +538,21 @@ Stop the local Zitadel server.
464
538
 
465
539
  ```
466
540
  USAGE
467
- $ zitadel stop [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug]
468
- [--telemetry] [--all]
541
+ $ zitadel stop [--json] [-c <value>] [-s <value>] [-n] [-f]
542
+ [--dry-run] [--verbose] [--debug] [--telemetry] [--all]
469
543
 
470
544
  FLAGS
471
545
  -c, --cwd=<value> Project directory to operate on.
472
546
  -f, --force Overwrite protected files on conflict.
473
- -n, --non-interactive Disable prompts. Required when scripting or running as an agent.
547
+ -n, --non-interactive Disable prompts. Required when scripting or running as
548
+ an agent.
474
549
  -s, --server=<value> Override the resolved server URL.
475
- --all Stop all discovered CLI-managed local Zitadel runtime processes.
550
+ --all Stop all discovered CLI-managed local Zitadel runtime
551
+ processes.
476
552
  --debug Debug logging.
477
553
  --dry-run Preview without mutating files or the platform.
478
- --[no-]telemetry Send anonymous usage analytics. Disable with --no-telemetry.
554
+ --[no-]telemetry Send anonymous usage analytics. Disable with
555
+ --no-telemetry.
479
556
  --verbose Verbose logging.
480
557
 
481
558
  GLOBAL FLAGS
@@ -491,17 +568,19 @@ Remove managed files and local Zitadel state.
491
568
 
492
569
  ```
493
570
  USAGE
494
- $ zitadel uninstall [--json] [-c <value>] [-s <value>] [-n] [-f] [--dry-run] [--verbose] [--debug]
495
- [--telemetry]
571
+ $ zitadel uninstall [--json] [-c <value>] [-s <value>] [-n] [-f]
572
+ [--dry-run] [--verbose] [--debug] [--telemetry]
496
573
 
497
574
  FLAGS
498
575
  -c, --cwd=<value> Project directory to operate on.
499
576
  -f, --force Overwrite protected files on conflict.
500
- -n, --non-interactive Disable prompts. Required when scripting or running as an agent.
577
+ -n, --non-interactive Disable prompts. Required when scripting or running as
578
+ an agent.
501
579
  -s, --server=<value> Override the resolved server URL.
502
580
  --debug Debug logging.
503
581
  --dry-run Preview without mutating files or the platform.
504
- --[no-]telemetry Send anonymous usage analytics. Disable with --no-telemetry.
582
+ --[no-]telemetry Send anonymous usage analytics. Disable with
583
+ --no-telemetry.
505
584
  --verbose Verbose logging.
506
585
 
507
586
  GLOBAL FLAGS
@@ -529,7 +608,8 @@ GLOBAL FLAGS
529
608
  FLAG DESCRIPTIONS
530
609
  --verbose Show additional information about the CLI.
531
610
 
532
- Additionally shows the architecture, node version, operating system, and versions of plugins that the CLI is using.
611
+ Additionally shows the architecture, node version, operating system, and
612
+ versions of plugins that the CLI is using.
533
613
  ```
534
614
 
535
615
  _See code: [@oclif/plugin-version](https://github.com/oclif/plugin-version/blob/2.2.46/src/commands/version.ts)_
package/SKILLS.md CHANGED
@@ -64,11 +64,14 @@ layer, not the envelope.
64
64
  ## Commands
65
65
 
66
66
  - `setup` — create a Zitadel project and scaffold local auth (routes,
67
- middleware, `.zitadel/**`, env templates). The project's default user schema
68
- and login flow are provisioned server-side at creation, so setup neither
69
- scaffolds nor uploads them. Agents must pass `--framework` when scaffolding
70
- into a fresh directory; interactive humans can omit it and choose from the
71
- prompt. Flags: `--framework next|react|vue|angular|nuxt|solid|svelte|qwik`, `--renderer
67
+ middleware, `.zitadel/**`, env templates). Setup writes the versioned local
68
+ default user schema and login flow into
69
+ `.zitadel/schemas/default-human-user.json` and
70
+ `.zitadel/flows/default-login.json`, uploads them through the schema and flow
71
+ APIs, then seeds `.zitadel/state.json` so `plan` is immediately empty. Agents
72
+ must pass `--framework` when scaffolding into a fresh directory; interactive
73
+ humans can omit it and choose from the prompt. Flags:
74
+ `--framework next|react|vue|angular|nuxt|solid|svelte|qwik`, `--renderer
72
75
  react|web-component` (selects the Next.js auth-page renderer; accepted for any
73
76
  framework and recorded in `zitadel.json` branding, but only Next varies its
74
77
  generated templates by it), `--dev-port` (dev-server port, also the issuer
@@ -76,6 +79,10 @@ layer, not the envelope.
76
79
  apps side by side), `--skip-install`.
77
80
  - `plan` — validate config and preview the sync diff without mutating anything.
78
81
  - `apply` — validate and upload repo config to the platform.
82
+ - `schemas list` — inspect the revision history of a user-schema, filtered by
83
+ `--object-type` (e.g. `human-user`). Non-interactive/`--json` prints one row
84
+ per revision (newest first); interactive adds a picker that fetches and
85
+ pretty-prints the selected revision body.
79
86
  - `doctor` — verify generated app files and local state once `zitadel.json`
80
87
  exists. The default local runtime is the `@zitadel/server` npm binary;
81
88
  Docker checks apply only when using `--runtime docker` or `--image`.
@@ -158,11 +165,17 @@ exercises fresh-app setup plus registration, logout, and login across the
158
165
  supported frameworks.
159
166
 
160
167
  Repo config is authoritative: edit `zitadel.json` or files under `.zitadel/`,
161
- then re-run `plan` and `apply`. Managed files carry a marker comment; `eject`
162
- removes only files that still carry it, preserving anything the user replaced.
163
- For app-local development, `--server local` resolves through
164
- `.zitadel/local/runtime.json` and requires a healthy `npx @zitadel/cli@alpha start`
165
- runtime. Runtime-only `.zitadel/local/**` state does not block fresh
166
- same-directory scaffolding. `setup` installs dependencies with the detected
167
- package manager by default; pass `--skip-install` when the agent or host
168
- workflow will install dependencies separately.
168
+ then re-run `plan` and `apply`. Schema and flow files are synced from
169
+ `.zitadel/schemas/*.json` and `.zitadel/flows/*.json`; templates are not
170
+ supported until the server exposes template storage and APIs. Server-provisioned
171
+ defaults remain a fallback for non-CLI project creation, but CLI-created
172
+ projects are authored from local files first. Flow create, read, list, and
173
+ update are available, while the server enforces lifecycle rules such as
174
+ draft-only edits. Managed files carry a marker comment; `eject` removes only
175
+ files that still carry it, preserving anything the user replaced. For app-local
176
+ development, `--server local` resolves through `.zitadel/local/runtime.json` and
177
+ requires a healthy
178
+ `npx @zitadel/cli@alpha start` runtime. Runtime-only `.zitadel/local/**` state
179
+ does not block fresh same-directory scaffolding. `setup` installs dependencies
180
+ with the detected package manager by default; pass `--skip-install` when the
181
+ agent or host workflow will install dependencies separately.
@@ -1,6 +1,7 @@
1
- import { t as BaseCommand } from "../oclif-BoUVygsZ.mjs";
2
- import { o as readZitadelSecret } from "../project-B1qVQMKS.mjs";
3
- import { a as makeSyncers, i as runSyncLoop, n as summarizePlan, o as environmentSchema, r as buildSyncPlan, t as renderPlan } from "../sync-CzruNz8K.mjs";
1
+ import { t as BaseCommand } from "../oclif-Bm-FkF6z.mjs";
2
+ import { o as readZitadelSecret } from "../project-Dk7V0xka.mjs";
3
+ import { a as runSyncLoop, n as summarizePlan, r as buildSyncPlan, s as makeSyncers, t as renderPlan } from "../sync-nSLnVhKK.mjs";
4
+ import { t as environmentSchema } from "../environment-BQF7LeCz.mjs";
4
5
  import { Flags } from "@oclif/core";
5
6
  import { createZitadelClient } from "@zitadel/api/client";
6
7
  import { consola as consola$1 } from "consola";
@@ -51,10 +52,11 @@ var Apply = class Apply extends BaseCommand {
51
52
  this.recordTelemetry({
52
53
  creates: summary.creates,
53
54
  updates: summary.updates,
55
+ revisions: summary.revisions,
54
56
  deletes: summary.deletes,
55
57
  total: summary.total
56
58
  });
57
- consola$1.success(`Plan: ${summary.creates} create${summary.creates === 1 ? "" : "s"}, ${summary.updates} update${summary.updates === 1 ? "" : "s"}, ${summary.deletes} delete${summary.deletes === 1 ? "" : "s"}`);
59
+ consola$1.success(`Plan: ${summary.creates} create${summary.creates === 1 ? "" : "s"}, ${summary.updates} update${summary.updates === 1 ? "" : "s"}, ${summary.revisions} new revision${summary.revisions === 1 ? "" : "s"}, ${summary.deletes} delete${summary.deletes === 1 ? "" : "s"}`);
58
60
  return this.emit({
59
61
  status: "ok",
60
62
  data: summary,
@@ -1 +1 @@
1
- {"version":3,"file":"apply.mjs","names":[],"sources":["../../src/commands/apply.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { consola } from \"consola\";\n\nimport { createZitadelClient } from \"@zitadel/api/client\";\n\nimport { BaseCommand, type JsonEnvelope } from \"../lib/oclif\";\nimport { environmentSchema } from \"../lib/environment\";\nimport { buildSyncPlan, makeSyncers, renderPlan, runSyncLoop, summarizePlan } from \"../lib/sync\";\nimport { readZitadelSecret } from \"../lib/project\";\n\n/**\n * `zitadel apply` — validate and upload repo config to the platform.\n *\n * Runs the sync loop to convergence, or (with `--dry-run`) previews the diff\n * without mutating. All validation — structural shape and `${VAR}` / `*_env`\n * reference presence — happens inside the sync engine ({@link buildSyncPlan}),\n * so an invalid or under-configured file fails with `E_VALIDATION` before any\n * platform call.\n */\nexport default class Apply extends BaseCommand {\n static override description = \"Validate and upload repo config to the platform.\";\n static override flags = {\n environment: Flags.string({\n char: \"e\",\n description: \"Target environment (default: development).\",\n options: [...environmentSchema.options],\n }),\n };\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Apply);\n await this.toMeta(flags);\n const { cwd, source, env, dryRun, isTTY } = this.meta;\n\n const secret = await readZitadelSecret(cwd);\n consola.info(`Project ${secret.project_id}`);\n consola.info(`Server ${source}`);\n const client = createZitadelClient({\n baseUrl: source,\n token: secret.project_secret,\n });\n const syncers = makeSyncers({ client, projectId: secret.project_id, env });\n\n if (!dryRun) {\n consola.start(\"Syncing schemas and flows to Zitadel\");\n await runSyncLoop(cwd, syncers);\n consola.success(\"Sync complete\");\n return this.emit({ status: \"ok\", data: { synced: true } });\n }\n\n consola.start(\"Building plan (dry run)\");\n const plan = await buildSyncPlan(cwd, syncers, true);\n const summary = summarizePlan(plan);\n this.recordTelemetry({\n creates: summary.creates,\n updates: summary.updates,\n deletes: summary.deletes,\n total: summary.total,\n });\n consola.success(\n `Plan: ${summary.creates} create${summary.creates === 1 ? \"\" : \"s\"}, ` +\n `${summary.updates} update${summary.updates === 1 ? \"\" : \"s\"}, ` +\n `${summary.deletes} delete${summary.deletes === 1 ? \"\" : \"s\"}`,\n );\n return this.emit({\n status: \"ok\",\n data: summary,\n pretty: renderPlan(plan, isTTY),\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmBA,IAAqB,QAArB,MAAqB,cAAc,YAAY;CAC7C,OAAgB,cAAc;CAC9B,OAAgB,QAAQ,EACtB,aAAa,MAAM,OAAO;EACxB,MAAM;EACN,aAAa;EACb,SAAS,CAAC,GAAG,kBAAkB,QAAQ;EACxC,CAAC,EACH;CAED,MAAM,MAA6B;EACjC,MAAM,EAAE,UAAU,MAAM,KAAK,MAAM,MAAM;AACzC,QAAM,KAAK,OAAO,MAAM;EACxB,MAAM,EAAE,KAAK,QAAQ,KAAK,QAAQ,UAAU,KAAK;EAEjD,MAAM,SAAS,MAAM,kBAAkB,IAAI;AAC3C,YAAQ,KAAK,aAAa,OAAO,aAAa;AAC9C,YAAQ,KAAK,aAAa,SAAS;EAKnC,MAAM,UAAU,YAAY;GAAE,QAJf,oBAAoB;IACjC,SAAS;IACT,OAAO,OAAO;IACf,CACmC;GAAE,WAAW,OAAO;GAAY;GAAK,CAAC;AAE1E,MAAI,CAAC,QAAQ;AACX,aAAQ,MAAM,uCAAuC;AACrD,SAAM,YAAY,KAAK,QAAQ;AAC/B,aAAQ,QAAQ,gBAAgB;AAChC,UAAO,KAAK,KAAK;IAAE,QAAQ;IAAM,MAAM,EAAE,QAAQ,MAAM;IAAE,CAAC;;AAG5D,YAAQ,MAAM,0BAA0B;EACxC,MAAM,OAAO,MAAM,cAAc,KAAK,SAAS,KAAK;EACpD,MAAM,UAAU,cAAc,KAAK;AACnC,OAAK,gBAAgB;GACnB,SAAS,QAAQ;GACjB,SAAS,QAAQ;GACjB,SAAS,QAAQ;GACjB,OAAO,QAAQ;GAChB,CAAC;AACF,YAAQ,QACN,SAAS,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC9D,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC1D,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,MAC5D;AACD,SAAO,KAAK,KAAK;GACf,QAAQ;GACR,MAAM;GACN,QAAQ,WAAW,MAAM,MAAM;GAChC,CAAC"}
1
+ {"version":3,"file":"apply.mjs","names":[],"sources":["../../src/commands/apply.ts"],"sourcesContent":["import { Flags } from \"@oclif/core\";\nimport { consola } from \"consola\";\n\nimport { createZitadelClient } from \"@zitadel/api/client\";\n\nimport { BaseCommand, type JsonEnvelope } from \"../lib/oclif\";\nimport { environmentSchema } from \"../lib/environment\";\nimport { buildSyncPlan, makeSyncers, renderPlan, runSyncLoop, summarizePlan } from \"../lib/sync\";\nimport { readZitadelSecret } from \"../lib/project\";\n\n/**\n * `zitadel apply` — validate and upload repo config to the platform.\n *\n * Runs the sync loop to convergence, or (with `--dry-run`) previews the diff\n * without mutating. All validation — structural shape and `${VAR}` / `*_env`\n * reference presence — happens inside the sync engine ({@link buildSyncPlan}),\n * so an invalid or under-configured file fails with `E_VALIDATION` before any\n * platform call.\n */\nexport default class Apply extends BaseCommand {\n static override description = \"Validate and upload repo config to the platform.\";\n static override flags = {\n environment: Flags.string({\n char: \"e\",\n description: \"Target environment (default: development).\",\n options: [...environmentSchema.options],\n }),\n };\n\n async run(): Promise<JsonEnvelope> {\n const { flags } = await this.parse(Apply);\n await this.toMeta(flags);\n const { cwd, source, env, dryRun, isTTY } = this.meta;\n\n const secret = await readZitadelSecret(cwd);\n consola.info(`Project ${secret.project_id}`);\n consola.info(`Server ${source}`);\n const client = createZitadelClient({\n baseUrl: source,\n token: secret.project_secret,\n });\n const syncers = makeSyncers({\n client,\n projectId: secret.project_id,\n env,\n });\n\n if (!dryRun) {\n consola.start(\"Syncing schemas and flows to Zitadel\");\n await runSyncLoop(cwd, syncers);\n consola.success(\"Sync complete\");\n return this.emit({ status: \"ok\", data: { synced: true } });\n }\n\n consola.start(\"Building plan (dry run)\");\n const plan = await buildSyncPlan(cwd, syncers, true);\n const summary = summarizePlan(plan);\n this.recordTelemetry({\n creates: summary.creates,\n updates: summary.updates,\n revisions: summary.revisions,\n deletes: summary.deletes,\n total: summary.total,\n });\n consola.success(\n `Plan: ${summary.creates} create${summary.creates === 1 ? \"\" : \"s\"}, ` +\n `${summary.updates} update${summary.updates === 1 ? \"\" : \"s\"}, ` +\n `${summary.revisions} new revision${summary.revisions === 1 ? \"\" : \"s\"}, ` +\n `${summary.deletes} delete${summary.deletes === 1 ? \"\" : \"s\"}`,\n );\n return this.emit({\n status: \"ok\",\n data: summary,\n pretty: renderPlan(plan, isTTY),\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAmBA,IAAqB,QAArB,MAAqB,cAAc,YAAY;CAC7C,OAAgB,cAAc;CAC9B,OAAgB,QAAQ,EACtB,aAAa,MAAM,OAAO;EACxB,MAAM;EACN,aAAa;EACb,SAAS,CAAC,GAAG,kBAAkB,QAAQ;EACxC,CAAC,EACH;CAED,MAAM,MAA6B;EACjC,MAAM,EAAE,UAAU,MAAM,KAAK,MAAM,MAAM;AACzC,QAAM,KAAK,OAAO,MAAM;EACxB,MAAM,EAAE,KAAK,QAAQ,KAAK,QAAQ,UAAU,KAAK;EAEjD,MAAM,SAAS,MAAM,kBAAkB,IAAI;AAC3C,YAAQ,KAAK,aAAa,OAAO,aAAa;AAC9C,YAAQ,KAAK,aAAa,SAAS;EAKnC,MAAM,UAAU,YAAY;GAC1B,QALa,oBAAoB;IACjC,SAAS;IACT,OAAO,OAAO;IACf,CAEO;GACN,WAAW,OAAO;GAClB;GACD,CAAC;AAEF,MAAI,CAAC,QAAQ;AACX,aAAQ,MAAM,uCAAuC;AACrD,SAAM,YAAY,KAAK,QAAQ;AAC/B,aAAQ,QAAQ,gBAAgB;AAChC,UAAO,KAAK,KAAK;IAAE,QAAQ;IAAM,MAAM,EAAE,QAAQ,MAAM;IAAE,CAAC;;AAG5D,YAAQ,MAAM,0BAA0B;EACxC,MAAM,OAAO,MAAM,cAAc,KAAK,SAAS,KAAK;EACpD,MAAM,UAAU,cAAc,KAAK;AACnC,OAAK,gBAAgB;GACnB,SAAS,QAAQ;GACjB,SAAS,QAAQ;GACjB,WAAW,QAAQ;GACnB,SAAS,QAAQ;GACjB,OAAO,QAAQ;GAChB,CAAC;AACF,YAAQ,QACN,SAAS,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC9D,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,IAAI,IAC1D,QAAQ,UAAU,eAAe,QAAQ,cAAc,IAAI,KAAK,IAAI,IACpE,QAAQ,QAAQ,SAAS,QAAQ,YAAY,IAAI,KAAK,MAC5D;AACD,SAAO,KAAK,KAAK;GACf,QAAQ;GACR,MAAM;GACN,QAAQ,WAAW,MAAM,MAAM;GAChC,CAAC"}
@@ -1,15 +1,16 @@
1
- import { C as isObject, E as ZitadelError, a as DEFAULT_LOCAL_SERVER_PORT, b as publicCliCommand, c as checkLocalServerHealth, l as defaultLocalServerImageForCliVersion, m as readRuntimeMetadata, p as localServerUrl, s as assertLocalStateWritable, t as BaseCommand } from "../oclif-BoUVygsZ.mjs";
2
- import { i as issuerFromPort, t as createOrca } from "../orca-DU8myWGm.mjs";
3
- import { a as readZitadelConfig, i as readRendererId, o as readZitadelSecret, r as readDevelopmentIssuer, t as hasZitadelConfig } from "../project-B1qVQMKS.mjs";
4
- import { n as listenersForPort } from "../ports-B09RjuHx.mjs";
5
- import { d as assertServerPackageAvailable, o as imageAvailable, r as dockerAvailable } from "../docker-Djz6BLp9.mjs";
6
- import { n as dockerUnavailableMessage, t as dockerRuntimeGuidance } from "../docker-guidance-D-33g1uV.mjs";
7
- import { t as discoverManagedRuntimeProcesses } from "../processes-Cw8TO1SY.mjs";
1
+ import { C as isObject, E as ZitadelError, a as DEFAULT_LOCAL_SERVER_PORT, b as publicCliCommand, c as checkLocalServerHealth, l as defaultLocalServerImageForCliVersion, m as readRuntimeMetadata, p as localServerUrl, s as assertLocalStateWritable, t as BaseCommand } from "../oclif-Bm-FkF6z.mjs";
2
+ import { i as issuerFromPort, t as createOrca } from "../orca-CpXj_XsA.mjs";
3
+ import { a as readZitadelConfig, i as readRendererId, o as readZitadelSecret, r as readDevelopmentIssuer, t as hasZitadelConfig } from "../project-Dk7V0xka.mjs";
4
+ import { t as SCHEMAS_DIR } from "../user-schema-DDz5-lX5.mjs";
5
+ import { n as listenersForPort } from "../ports-CxBKS1ga.mjs";
6
+ import { d as assertServerPackageAvailable, o as imageAvailable, r as dockerAvailable } from "../docker-D7BSD5C9.mjs";
7
+ import { n as dockerUnavailableMessage, t as dockerRuntimeGuidance } from "../docker-guidance-mcTT3_0E.mjs";
8
+ import { t as discoverManagedRuntimeProcesses } from "../processes-BVqYsxT8.mjs";
9
+ import { chmod, readFile, readdir, stat, writeFile } from "node:fs/promises";
10
+ import { join } from "node:path";
8
11
  import { Flags } from "@oclif/core";
9
12
  import consola from "consola";
10
- import { join } from "node:path";
11
- import { chmod, readFile, stat, writeFile } from "node:fs/promises";
12
- import "@zitadel/api/generated/endpoints/zitadelNextGen.zod";
13
+ import { schemaConfigSchema } from "@zitadel/config/schemas";
13
14
  //#region src/commands/doctor/checks/types.ts
14
15
  /**
15
16
  * Base class for checks: subclasses declare `name`, `path`, and a success
@@ -150,8 +151,8 @@ var FrameworkCheck = class extends AbstractSanityCheck {
150
151
  * Reconstructs a {@link PatchContext} from the on-disk project (config, secret)
151
152
  * plus fresh framework detection, so a patcher repair can rebuild its plan.
152
153
  * Used by the dependency check's `fix`, which reclaims the framework-specific
153
- * SDK package via `patcher.repair`. The user schema and flow definition are
154
- * server-owned and no longer scaffolded locally, so nothing here reads them.
154
+ * SDK package via `patcher.repair`. Schema and flow config are user-editable
155
+ * sync resources, not patcher inputs, so nothing here reads them.
155
156
  */
156
157
  async function loadPatchContext(cwd, orca, cliVersion) {
157
158
  const config = await readZitadelConfig(cwd);
@@ -235,6 +236,81 @@ var ProjectMatchCheck = class extends AbstractSanityCheck {
235
236
  }
236
237
  };
237
238
  //#endregion
239
+ //#region src/lib/json-dir.ts
240
+ /**
241
+ * Read every `*.json` file under `absDir` and return each body as a plain
242
+ * object. Files are read in lexical filename order so the result is
243
+ * deterministic for downstream hashing and diffs. Each file is parsed by
244
+ * `JSON.parse`; this function does **not** apply any schema validation —
245
+ * unknown keys, forward-compatible fields, and `${VAR}` placeholders survive
246
+ * intact. Callers that need a typed shape pass the result through their
247
+ * resource's Zod schema.
248
+ *
249
+ * Returns an empty array when the directory is missing. Throws `E_VALIDATION`
250
+ * `ZitadelError` on invalid JSON or when a file's root value is not an object.
251
+ *
252
+ * @param absDir - Absolute path to the directory to scan.
253
+ */
254
+ async function readJsonDir(absDir) {
255
+ let entries;
256
+ try {
257
+ entries = await readdir(absDir);
258
+ } catch (error) {
259
+ if (typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT") return [];
260
+ throw error;
261
+ }
262
+ const result = [];
263
+ for (const entry of entries.filter((name) => name.endsWith(".json")).sort()) {
264
+ const abs = join(absDir, entry);
265
+ let raw;
266
+ try {
267
+ raw = JSON.parse(await readFile(abs, "utf8"));
268
+ } catch {
269
+ throw new ZitadelError("E_VALIDATION", `${entry} is not valid JSON`);
270
+ }
271
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) throw new ZitadelError("E_VALIDATION", `${entry} must contain a JSON object at the root`);
272
+ result.push(raw);
273
+ }
274
+ return result;
275
+ }
276
+ //#endregion
277
+ //#region src/commands/doctor/checks/schema.ts
278
+ /**
279
+ * Verifies local schema config files round-trip through the canonical
280
+ * `schemaConfigSchema` from `@zitadel/config/schemas` — the same Zod the
281
+ * sync engine validates with, so doctor and `apply` can never disagree
282
+ * about a file. The union enforces the `kind` discriminator
283
+ * (`user-schema` / `schema-url`) and the `metaSchema`/`x-auth-methods`/etc.
284
+ * fields the platform requires.
285
+ */
286
+ var SchemaCheck = class extends AbstractSanityCheck {
287
+ name = "schema";
288
+ path = SCHEMAS_DIR;
289
+ summary = "User schemas are valid Zitadel schema bodies";
290
+ /**
291
+ * An empty `.zitadel/schemas/` is a warning, not a failure: projects
292
+ * created before editable config existed were seeded server-side and have
293
+ * no local schema files, and there is no safe auto-fix that could invent
294
+ * them. Only invalid files fail the check.
295
+ */
296
+ async run(ctx) {
297
+ if ((await readJsonDir(join(ctx.cwd, ".zitadel/schemas"))).length === 0) return {
298
+ name: this.name,
299
+ status: "warn",
300
+ message: `No schema files found in ${SCHEMAS_DIR} — this project predates editable schema config or setup was interrupted. New projects scaffold editable defaults via \`zitadel setup\`.`,
301
+ path: this.path
302
+ };
303
+ return super.run(ctx);
304
+ }
305
+ async verify(ctx) {
306
+ const schemas = await readJsonDir(join(ctx.cwd, SCHEMAS_DIR));
307
+ for (const schema of schemas) {
308
+ const result = schemaConfigSchema.safeParse(schema);
309
+ if (!result.success) throw new Error(result.error.issues.map((issue) => `${issue.path.join(".") || "/"} ${issue.message}`).join("; "));
310
+ }
311
+ }
312
+ };
313
+ //#endregion
238
314
  //#region src/commands/doctor/checks/index.ts
239
315
  /** Every diagnostic the `doctor` command runs, in display order. */
240
316
  const SANITY_CHECKS = [
@@ -244,6 +320,7 @@ const SANITY_CHECKS = [
244
320
  new GitignoreCheck(),
245
321
  new EnvExampleCheck(),
246
322
  new FrameworkCheck(),
323
+ new SchemaCheck(),
247
324
  new DependencyCheck(),
248
325
  new ProjectMatchCheck()
249
326
  ];