@zitadel/cli 0.2.0 → 0.4.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/README.md +224 -72
- package/dist/index.mjs +2083 -872
- package/dist/index.mjs.map +1 -1
- package/dist/lib/oclif/help.mjs +3 -2
- package/dist/lib/oclif/help.mjs.map +1 -1
- package/dist/skills/zitadel/SKILL.md +111 -0
- package/dist/skills/zitadel-cli/SKILL.md +635 -0
- package/dist/skills/zitadel-cli/references/driving-login-ui.md +124 -0
- package/dist/skills/zitadel-components/SKILL.md +152 -0
- package/dist/skills/zitadel-sdk-angular/SKILL.md +149 -0
- package/dist/skills/zitadel-sdk-next/SKILL.md +174 -0
- package/dist/skills/zitadel-sdk-nuxt/SKILL.md +149 -0
- package/dist/skills/zitadel-sdk-qwik/SKILL.md +136 -0
- package/dist/skills/zitadel-sdk-qwik-router/SKILL.md +126 -0
- package/dist/skills/zitadel-sdk-react/SKILL.md +149 -0
- package/dist/skills/zitadel-sdk-solid/SKILL.md +144 -0
- package/dist/skills/zitadel-sdk-solid-start/SKILL.md +149 -0
- package/dist/skills/zitadel-sdk-svelte/SKILL.md +137 -0
- package/dist/skills/zitadel-sdk-sveltekit/SKILL.md +147 -0
- package/dist/skills/zitadel-sdk-tanstack-start/SKILL.md +150 -0
- package/dist/skills/zitadel-sdk-vue/SKILL.md +147 -0
- package/dist/{skills-hint-CBoak9HL.mjs → skills-hint-C8oe8cCo.mjs} +1502 -191
- package/dist/skills-hint-C8oe8cCo.mjs.map +1 -0
- package/oclif.manifest.json +286 -69
- package/package.json +10 -6
- package/skills/zitadel-cli/SKILL.md +106 -9
- package/skills/zitadel-cli/references/driving-login-ui.md +16 -1
- package/dist/skills-hint-CBoak9HL.mjs.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zitadel/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Agent-friendly Zitadel CLI",
|
|
5
5
|
"homepage": "https://github.com/zitadel/nextgen/tree/main/apps/cli#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -106,13 +106,16 @@
|
|
|
106
106
|
"description": "View login flows."
|
|
107
107
|
},
|
|
108
108
|
"policies": {
|
|
109
|
-
"description": "View policies."
|
|
109
|
+
"description": "View and test policies."
|
|
110
110
|
},
|
|
111
111
|
"env": {
|
|
112
112
|
"description": "Show and bind environments."
|
|
113
113
|
},
|
|
114
114
|
"api": {
|
|
115
115
|
"description": "Call any operation of the Zitadel API."
|
|
116
|
+
},
|
|
117
|
+
"skills": {
|
|
118
|
+
"description": "Give coding agents the Zitadel skills."
|
|
116
119
|
}
|
|
117
120
|
}
|
|
118
121
|
},
|
|
@@ -127,9 +130,9 @@
|
|
|
127
130
|
"@oclif/plugin-search": "^1.2.50",
|
|
128
131
|
"@oclif/plugin-version": "^2.2.46",
|
|
129
132
|
"@oclif/plugin-which": "^3.2.55",
|
|
130
|
-
"@zitadel/api": "0.
|
|
131
|
-
"@zitadel/config": "0.
|
|
132
|
-
"@zitadel/server": "0.
|
|
133
|
+
"@zitadel/api": "0.4.0",
|
|
134
|
+
"@zitadel/config": "0.4.0",
|
|
135
|
+
"@zitadel/server": "0.4.0",
|
|
133
136
|
"ajv": "^8.20.0",
|
|
134
137
|
"consola": "^3.4.2",
|
|
135
138
|
"magicast": "^0.5.3",
|
|
@@ -148,7 +151,8 @@
|
|
|
148
151
|
"@types/wrap-ansi": "^3.0.0",
|
|
149
152
|
"@vitest/coverage-v8": "^4.1.11",
|
|
150
153
|
"@zitadel/api-mock": "0.0.0",
|
|
151
|
-
"@zitadel/sdk-next": "0.
|
|
154
|
+
"@zitadel/sdk-next": "0.4.0",
|
|
155
|
+
"@zitadel/vitest-config": "0.0.0",
|
|
152
156
|
"msw": "^2.14.6",
|
|
153
157
|
"oclif": "^4.17.46",
|
|
154
158
|
"tsdown": "^0.23.0",
|
|
@@ -47,6 +47,13 @@ by declared range or installed release, with `E_UNSUPPORTED_PROJECT_SHAPE`
|
|
|
47
47
|
left the project untouched. The message names the minimum and the hint says to
|
|
48
48
|
upgrade, so upgrade the app and rerun rather than retrying.
|
|
49
49
|
|
|
50
|
+
The CLI ships this skill and the other Zitadel skills. `skills add` puts the
|
|
51
|
+
ones of the version that runs it into the project's `.agents/skills/`, and into
|
|
52
|
+
`.claude/skills/` when Claude Code is installed or the project has a `.claude/`
|
|
53
|
+
folder, replacing older copies. After moving the app to a newer CLI, run it
|
|
54
|
+
with that version so the skills describe it. It talks to no server and asks
|
|
55
|
+
nothing; `data.skills` and `data.directories` say what it added where.
|
|
56
|
+
|
|
50
57
|
## Using the CLI
|
|
51
58
|
|
|
52
59
|
- **Drive it non-interactively.** Always pass `--non-interactive --json` (short:
|
|
@@ -71,7 +78,10 @@ upgrade, so upgrade the app and rerun rather than retrying.
|
|
|
71
78
|
`--help` output is bounded too — read it in full rather than `head`-ing it, or
|
|
72
79
|
you will miss flags further down.
|
|
73
80
|
- **Working directory.** Add `--cwd <path>` when operating outside the current
|
|
74
|
-
working directory.
|
|
81
|
+
working directory. A relative `--env-file` path is still read from the
|
|
82
|
+
current directory, not from `--cwd` (`--cwd app --env-file app/.env.ci`):
|
|
83
|
+
Node reads `--env-file` itself before the CLI starts and exits 9 with
|
|
84
|
+
`node: <path>: not found`, and no envelope, when the file is not there.
|
|
75
85
|
- **Server and project.** A command that talks to a project reads
|
|
76
86
|
`ZITADEL_URL`, `ZITADEL_PROJECT_ID` and `ZITADEL_PROJECT_SECRET`, each from the
|
|
77
87
|
first source that has it: `--server` (the URL only), `--env-file <path>`, the
|
|
@@ -93,6 +103,9 @@ upgrade, so upgrade the app and rerun rather than retrying.
|
|
|
93
103
|
`deploy` yourself. `data.deployment` carries the `release_id`,
|
|
94
104
|
`content_hash`, `deployment_id` and `origins` when a person accepted, and is
|
|
95
105
|
null otherwise — a failed deploy is a warning, never a failed `env add`.
|
|
106
|
+
`ZITADEL_URL` and `--server` are the server's origin: the API lives under
|
|
107
|
+
`/api/v1` there, which the CLI adds (and drops from a URL that already ends
|
|
108
|
+
in it).
|
|
96
109
|
- **Origins.** `zitadel origin add <url> --kind primary|preview`, `origin list`
|
|
97
110
|
and `origin rm <url>` manage the URLs a project serves: a `primary` origin is
|
|
98
111
|
where the app is served, a `preview` pattern (it may hold a `*`) is where
|
|
@@ -134,8 +147,9 @@ upgrade, so upgrade the app and rerun rather than retrying.
|
|
|
134
147
|
- **Calling an operation no command covers.** `zitadel api <operation>` calls
|
|
135
148
|
any operation of the API with the resolved server and `.zitadel/secret`.
|
|
136
149
|
Name it by its `operationId` (`queryUsers`, as the API reference and
|
|
137
|
-
`@zitadel/api` spell it) or by its path (`/users/query
|
|
138
|
-
|
|
150
|
+
`@zitadel/api` spell it) or by its path as the spec has it (`/users/query`,
|
|
151
|
+
which the server serves at `/api/v1/users/query`; a path copied with the
|
|
152
|
+
prefix works too, and `-X` picks the method where a path has several). Path parameters follow as arguments, in
|
|
139
153
|
path order; a `project_id` left out is the project's own. `-F name=value`
|
|
140
154
|
(or `name:=json`) sets a query parameter when the operation declares one by
|
|
141
155
|
that name, else a dot path into the body, typed by the operation's schema;
|
|
@@ -198,6 +212,11 @@ over reading `<resource> --help` one at a time. A `list` verb's envelope carries
|
|
|
198
212
|
you pass `--all`, so a "how many …?" question is one `list --all --json` call:
|
|
199
213
|
read the count, do not page and tally.
|
|
200
214
|
|
|
215
|
+
To find the users still on an older revision of a schema, filter on the
|
|
216
|
+
schema's object type and exclude the newest revision's URL:
|
|
217
|
+
`users list --filter schema_object_type=equals:<type> --filter
|
|
218
|
+
schema=not_equals:<newest-url> --all --json`.
|
|
219
|
+
|
|
201
220
|
## Reading the envelope
|
|
202
221
|
|
|
203
222
|
Each invocation prints one JSON object:
|
|
@@ -230,12 +249,28 @@ Each invocation prints one JSON object:
|
|
|
230
249
|
`--origin`, which selects targets but never authorizes a preview deploy. A CI
|
|
231
250
|
build other than Vercel or Netlify must set `ZITADEL_ENV=preview`, or it is
|
|
232
251
|
skipped too. `preview list` and `preview rm <url>` read and end live previews.
|
|
252
|
+
- `deploy` and `preview` record `-m` on the release and the deployment. Omitted,
|
|
253
|
+
they use a GitHub pull request's title, Vercel's commit message, or a clean
|
|
254
|
+
worktree's commit subject; with none, a non-interactive `deploy` fails. A
|
|
255
|
+
blank `-m` is refused. A release keeps the message of
|
|
256
|
+
the run that first built its content, usually the pull request's `preview`.
|
|
257
|
+
`deployment rollback -m` records why on the rollback.
|
|
258
|
+
- `deployment get <id>` emits the deployment as the API serves it; on a
|
|
259
|
+
terminal it also shows the variables the deployment froze, secrets masked.
|
|
260
|
+
Read them as JSON with `variable resolve`.
|
|
233
261
|
- `deployment rollback` emits `data.release_id` (the release live again),
|
|
234
262
|
`data.origins` and `data.pointers`, the `{kind, handle, revision_id}`
|
|
235
263
|
revisions that release pins; the `schema` one is what new registrations use.
|
|
236
264
|
Users keep their schema revision and attributes: a rollback does not migrate
|
|
237
265
|
them back. Without `data.pointers`, a warning says the release could not be
|
|
238
266
|
read.
|
|
267
|
+
- `deploy --dry-run` and `deploy` emit `data.diff`, the git diff the terminal
|
|
268
|
+
shows, against the live release's commit (`diff.against`): `diff.files` holds
|
|
269
|
+
one `{path, status, previous_path?, patch}` per changed file (`status` is
|
|
270
|
+
`added`, `modified`, `deleted`, `renamed` or `copied`; `patch` is its unified
|
|
271
|
+
diff), including rapid same-size edits and untracked configuration files.
|
|
272
|
+
Review it before you deploy. `files` is `[]` when nothing changed and
|
|
273
|
+
`null` when there is nothing to diff against, with `diff.note` saying why.
|
|
239
274
|
- A write verb's `--dry-run` reports what it would send without calling the
|
|
240
275
|
platform, so you can preview a mutation before making it.
|
|
241
276
|
- `api` emits the response body as `data`, exactly as the API reference
|
|
@@ -254,13 +289,18 @@ Common error codes point at their own fix in `next_commands`:
|
|
|
254
289
|
- `E_LOCAL_SERVER_NOT_RUNNING`: start the local runtime, then retry with
|
|
255
290
|
`--server local`.
|
|
256
291
|
- `E_NOT_FOUND`: an HTTP 404 — a missing resource, an operation the server's
|
|
257
|
-
version does not have (`details.body.code` is `req.not_found
|
|
292
|
+
version does not have (`details.body.code` is `req.not_found`; a server
|
|
293
|
+
from before the API moved under `/api/v1` answers every call so), or a
|
|
258
294
|
`--server` that is not a Zitadel platform API. Follow `next_commands`.
|
|
259
295
|
- `E_PORT_IN_USE`: the requested local runtime port already has a listener; stop
|
|
260
296
|
that process or choose another port.
|
|
261
297
|
|
|
262
298
|
In human mode the output follows the terminal (TTY table, or tab-separated lines
|
|
263
|
-
when piped or `--plain`); `--json` is unaffected and remains the contract.
|
|
299
|
+
when piped or `--plain`); `--json` is unaffected and remains the contract. A
|
|
300
|
+
human run lists its next steps under `Next:` after its result (`setup` shows
|
|
301
|
+
them in its summary box instead); where stdout is data a script reads (a piped
|
|
302
|
+
or `--plain` list, a resource's created or updated JSON) they go to stderr, so
|
|
303
|
+
stdout holds only that data.
|
|
264
304
|
|
|
265
305
|
Text the server returns is escaped before it is printed, in `--json` as in human
|
|
266
306
|
mode, so a stored value cannot drive the reader's terminal. Control, format and
|
|
@@ -360,12 +400,50 @@ npx @zitadel/cli@latest doctor --non-interactive --json
|
|
|
360
400
|
npx @zitadel/cli@latest deploy -m "<why this release changes>" --non-interactive --json
|
|
361
401
|
```
|
|
362
402
|
|
|
403
|
+
`setup` commits the project it scaffolds: `git init` first when the directory
|
|
404
|
+
is not yet a repository, then one commit, `chore: scaffold the project with
|
|
405
|
+
zitadel setup`. A release records the commit it was built from and `deploy`
|
|
406
|
+
diffs `.zitadel/` against it, so without this the first release carries no
|
|
407
|
+
commit and the next deploy reports no diff.
|
|
408
|
+
|
|
409
|
+
Then setup deploys `.zitadel/` to the app's origin, so the sign-in it asks you
|
|
410
|
+
to verify is served the release it built. `data.deployment` carries the
|
|
411
|
+
`release_id`, `content_hash`, `deployment_id` and `origins`, and is null on
|
|
412
|
+
`--dry-run` or when the deploy failed. A failed deploy is a warning, never a
|
|
413
|
+
failed setup, and `data.next_commands` then leads with the `deploy` that fixes
|
|
414
|
+
it.
|
|
415
|
+
|
|
416
|
+
Setup refuses with `E_CONFLICT` when the repository already has uncommitted
|
|
417
|
+
work, untracked files included, which `details.untracked` lists separately
|
|
418
|
+
from `details.modified`. The commit covers the project directory, so it can
|
|
419
|
+
only tell its own files from yours when the tree starts clean. It never
|
|
420
|
+
commits `.env*` files (other than `.env.example`), `.zitadel/secret` or
|
|
421
|
+
`.zitadel/local/`, whatever their case. Commit or stash
|
|
422
|
+
first, then rerun. Only what `start` leaves is exempt: `.zitadel/local/` and
|
|
423
|
+
the `.gitignore` line that ignores it. A connection under `.zitadel/idps/` is
|
|
424
|
+
yours and is not exempt. During a merge, rebase, cherry-pick, revert or bisect,
|
|
425
|
+
or on a detached HEAD, setup refuses with `E_CONFLICT` before it writes
|
|
426
|
+
anything, naming what stops the commit.
|
|
427
|
+
|
|
428
|
+
Setup deploys nothing, and it does not need to: a project with no release
|
|
429
|
+
resolves the newest revisions, which are the ones setup just uploaded, so
|
|
430
|
+
sign-in already runs on `.zitadel/`. Deploying pins them into a release, which
|
|
431
|
+
is what the server will require once that fallback goes (#1616). The publish
|
|
432
|
+
step says so and names the command. `data.git` reports what setup did:
|
|
433
|
+
`initialized` when it ran `git init`, even if the commit then failed, and the
|
|
434
|
+
`commit`, or null. `--no-git` skips both the refusal
|
|
435
|
+
and the commit, and nothing prompts, so this is the same interactively and in
|
|
436
|
+
CI.
|
|
437
|
+
|
|
363
438
|
`setup` scaffolds into an empty directory, or patches an existing app project
|
|
364
439
|
where it detects a framework. What `start` leaves in a directory —
|
|
365
440
|
`.zitadel/local/` and the `.gitignore` line that ignores it — still counts as
|
|
366
441
|
empty, so the golden path runs `setup` right after `start` in the same
|
|
367
|
-
directory.
|
|
368
|
-
|
|
442
|
+
directory. A `--cwd` that does not exist yet counts as empty too: setup creates
|
|
443
|
+
it with the app, and removes it again when setup fails before the app is kept.
|
|
444
|
+
A `--cwd` that is a file fails with `E_VALIDATION`. Any other non-empty
|
|
445
|
+
directory stops setup with a hint to pass `--force`. Pass it only for a
|
|
446
|
+
directory whose contents may be replaced: files
|
|
369
447
|
the new app also has, such as `package.json`, are overwritten. Without a
|
|
370
448
|
terminal `setup` cannot ask which framework to scaffold, so pass `--framework`;
|
|
371
449
|
the error lists the choices in `details.frameworks`. `setup --dry-run` creates
|
|
@@ -401,7 +479,11 @@ server and its port, but runs its project checks in the working directory, so ru
|
|
|
401
479
|
it from the app. When that server is unhealthy it suggests `start` and
|
|
402
480
|
`reset --force` with `--cwd` set to the directory that holds it (when that path needs
|
|
403
481
|
shell quoting the commands are left out, the hint names the directory, and
|
|
404
|
-
`doctor --json` returns the argument lists in `details.suggested_args` to run as they are).
|
|
482
|
+
`doctor --json` returns the argument lists in `details.suggested_args` to run as they are).
|
|
483
|
+
The hint says the server is the parent's and that `reset --force` deletes the data in that
|
|
484
|
+
directory, and it adds a plain `start`, which gives the working directory a server of its own
|
|
485
|
+
because `start` does not look in parents; a healthy parent server is reported in the `runtime`
|
|
486
|
+
check as started in the parent folder. A
|
|
405
487
|
local server is healthy once its `/readyz` answers, which takes its database
|
|
406
488
|
answering too: `start` waits for that, and the commands that read a server
|
|
407
489
|
treat one whose database does not answer as unhealthy. `stop`,
|
|
@@ -511,6 +593,21 @@ missing or outdated (after an upgrade that changed a dialect), and
|
|
|
511
593
|
`doctor --fix` writes the current ones, unless the project pins a newer
|
|
512
594
|
`@zitadel/*` version (run that version's `doctor --fix`) or a symlink is on
|
|
513
595
|
the path; `deploy --dry-run` validates without them either way.
|
|
596
|
+
`deploy`, `preview` and `release create`, `--dry-run` included, check the
|
|
597
|
+
shape of `.zitadel/` locally before anything is written, and fail with
|
|
598
|
+
`E_VALIDATION` listing each problem by field and by the schema's or flow's
|
|
599
|
+
handle (a policy by its file). The server still applies its own release rules
|
|
600
|
+
when the build is submitted, such as handles being unique, so a passing dry run
|
|
601
|
+
does not promise the release is accepted.
|
|
602
|
+
|
|
603
|
+
An SPA's dev proxy (`vite.config.*`, Angular's `proxy.conf.cjs`) keeps the
|
|
604
|
+
app's session in a cookie of its own project, `zitadel_session_<project id>`
|
|
605
|
+
on `http://localhost` and `__Host-zitadel_session_<project id>` over https.
|
|
606
|
+
`doctor` fails (`managed-files`, `outdated managed config wiring`) on the
|
|
607
|
+
session-cookie hooks a CLI wrote before these names: the server no longer
|
|
608
|
+
reads the cookies they keep. `doctor --fix` replaces hooks that are as the CLI
|
|
609
|
+
wrote them; ones changed by hand must be updated by hand, which the failure
|
|
610
|
+
says. Browsers signed in before the change sign in again.
|
|
514
611
|
|
|
515
612
|
## Claiming a project
|
|
516
613
|
|
|
@@ -535,4 +632,4 @@ Load on demand:
|
|
|
535
632
|
|
|
536
633
|
- [`references/driving-login-ui.md`](references/driving-login-ui.md) — driving the
|
|
537
634
|
`<zitadel-login>` component in a browser, and the authoritative repo-config
|
|
538
|
-
workflow (schemas, flows, branding, policies).
|
|
635
|
+
workflow (schemas, flows, branding, policies and their tests).
|
|
@@ -94,7 +94,22 @@ which applies the next time a password is set. A setting left out is off, and
|
|
|
94
94
|
the deployed release carries, so deploying without the file switches it off
|
|
95
95
|
there; a password set through the API, or before the first deploy, uses the
|
|
96
96
|
newest revision, which only `"config": {}` switches off. `policies list` and
|
|
97
|
-
`policies get <id|operation>` read them back.
|
|
97
|
+
`policies get <id|operation>` read them back. A policy's cases live beside it
|
|
98
|
+
in `<operation>.test.json` (`.zitadel/meta/policy-test.json`): each names an
|
|
99
|
+
`input` in the operation's terms (`{"password": "…"}`), optional `facts` the
|
|
100
|
+
operation would look up (`self_service`, `history_matches`), and the expected
|
|
101
|
+
decision (`allowed`, optionally `code` and exactly the `violations`). The
|
|
102
|
+
decision and rules hold in the login too; `code` is the API's answer, and a
|
|
103
|
+
flow shows each rule as `error.x-auth-methods#password_<rule>` instead.
|
|
104
|
+
`policies test [operation]` evaluates every case on the server against the
|
|
105
|
+
sibling policy file, or with `--release <id>` against the revision that
|
|
106
|
+
release pins; a missing policy is tested as none. It fails with `E_VALIDATION`
|
|
107
|
+
(exit 3) when a case does not hold, `data`/`details` carrying `source`,
|
|
108
|
+
`operations[].cases[]` (`name`, `passed`, `expected`, `actual`), `passed` and
|
|
109
|
+
`failed`; with no test files it is `skipped` (`no-policy-tests`). `deploy`
|
|
110
|
+
never carries test files. Until #2331, a release that pins no flow is tested
|
|
111
|
+
with a warning: its sign-ins use the newest revisions instead. Write cases from
|
|
112
|
+
what the user wants enforced; never invent expectations for them. `setup` writes and publishes
|
|
98
113
|
the password policy with a `min_length` of 15; pass `--password-min-length <n>`
|
|
99
114
|
only when the user asks for another value (`0` sets none). Managed files carry
|
|
100
115
|
a marker comment; `eject` removes only
|