@kici-dev/compiler 0.5.0 → 0.6.1

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 (73) hide show
  1. package/dist/cli.js +46 -8
  2. package/dist/commands/approve.d.ts +12 -0
  3. package/dist/commands/approve.js +5 -2
  4. package/dist/commands/compile.js +4 -2
  5. package/dist/commands/doctor.js +2 -2
  6. package/dist/commands/endpoints.js +4 -6
  7. package/dist/commands/feedback.d.ts +53 -0
  8. package/dist/commands/feedback.js +142 -0
  9. package/dist/commands/held-run-client.d.ts +21 -1
  10. package/dist/commands/held-run-client.js +34 -15
  11. package/dist/commands/hook.js +22 -20
  12. package/dist/commands/index.d.ts +4 -0
  13. package/dist/commands/index.js +3 -1
  14. package/dist/commands/init.d.ts +9 -2
  15. package/dist/commands/init.js +43 -16
  16. package/dist/commands/login.js +1 -1
  17. package/dist/commands/orchestrators.js +3 -2
  18. package/dist/commands/reject.d.ts +12 -0
  19. package/dist/commands/reject.js +5 -2
  20. package/dist/commands/report/collect.d.ts +82 -0
  21. package/dist/commands/report/collect.js +234 -0
  22. package/dist/commands/report/identity.d.ts +48 -0
  23. package/dist/commands/report/identity.js +49 -0
  24. package/dist/commands/report/index.d.ts +63 -0
  25. package/dist/commands/report/index.js +119 -0
  26. package/dist/commands/report/upload.d.ts +38 -0
  27. package/dist/commands/report/upload.js +64 -0
  28. package/dist/commands/run-hold-watch.js +2 -2
  29. package/dist/commands/run.js +6 -3
  30. package/dist/commands/runs/show.js +80 -1
  31. package/dist/commands/types.js +51 -8
  32. package/dist/execution/sdk-alias.js +4 -2
  33. package/dist/fixtures/compiler.js +2 -1
  34. package/dist/format.js +3 -3
  35. package/dist/generators/secrets-dts.d.ts +8 -2
  36. package/dist/generators/secrets-dts.js +3 -2
  37. package/dist/hooks/installer.js +2 -1
  38. package/dist/llm-context/llms-architecture.txt +35 -13
  39. package/dist/llm-context/llms-cli-remote.txt +2347 -0
  40. package/dist/llm-context/llms-cli.txt +284 -2470
  41. package/dist/llm-context/llms-features-execution.txt +2028 -0
  42. package/dist/llm-context/llms-features.txt +298 -1483
  43. package/dist/llm-context/llms-full.txt +6153 -4639
  44. package/dist/llm-context/llms-getting-started.txt +292 -12
  45. package/dist/llm-context/llms-patterns.txt +176 -1
  46. package/dist/llm-context/llms-providers.txt +11 -27
  47. package/dist/llm-context/llms-sdk-runtime.txt +25 -4
  48. package/dist/llm-context/llms-sdk.txt +31 -1
  49. package/dist/llm-context/llms.txt +33 -18
  50. package/dist/local-plane/paths.d.ts +15 -0
  51. package/dist/local-plane/paths.js +22 -1
  52. package/dist/local-plane/plane-manager.js +2 -2
  53. package/dist/local-plane/port-holder.js +1 -1
  54. package/dist/local-plane/postgres.d.ts +3 -16
  55. package/dist/local-plane/postgres.js +10 -15
  56. package/dist/lockfile/generator.d.ts +12 -0
  57. package/dist/lockfile/generator.js +47 -14
  58. package/dist/postinstall.js +2 -1
  59. package/dist/remote/config.d.ts +2 -15
  60. package/dist/remote/config.js +2 -16
  61. package/dist/remote/dashboard-client.d.ts +39 -0
  62. package/dist/remote/dashboard-client.js +41 -0
  63. package/dist/remote/oauth.js +7 -5
  64. package/dist/remote/uploader.js +2 -2
  65. package/dist/templates/package-json.js +1 -1
  66. package/dist/test-runner/dry-run.js +4 -2
  67. package/dist/test-runner/git-detector.js +2 -1
  68. package/dist/test-runner/job-executor.js +2 -1
  69. package/dist/test-runner/payload-builder.js +11 -17
  70. package/dist/types.d.ts +33 -3
  71. package/dist/validation/validator.js +23 -6
  72. package/package.json +16 -11
  73. package/sbom.spdx.json +953 -901
@@ -1,577 +1,6 @@
1
- # KiCI CLI and authoring
1
+ # KiCI CLI: authoring on your own machine
2
2
 
3
- This bundle covers: Running the CLI: compile, test, run local/remote, auth, hooks, lock-file drift.
4
-
5
- ## Drive KiCI from your coding agent
6
-
7
- Source: https://docs.kici.dev/user/ai-agents/
8
-
9
- KiCI ships a hosted **MCP server** so a coding agent (Claude Code, or any MCP
10
- client) can drive your CI directly: trigger runs, read a structured result,
11
- fetch the failing step's logs, cancel, and re-run — all under an agent identity
12
- you control, org-scoped, and audited. There are no per-tool tokens to configure:
13
- point the agent at one URL with one credential and it's done.
14
-
15
- The MCP exposes only what you can already do yourself through the `kici` CLI and
16
- the dashboard. It is not a new privileged surface — every tool maps to an
17
- existing user-facing operation and is gated by the same permissions your role
18
- grants.
19
-
20
- ## 1. Mint an agent credential
21
-
22
- The MCP accepts an **agent-kind credential** — and only an agent-kind one. It
23
- can be either of two kinds:
24
-
25
- - An **agent personal access token (PAT)** that you own — it acts as you, with
26
- your provenance. The token is `kici_pat_…`.
27
- - An **agent org API key** that belongs to your organization — a
28
- provenance-carrying service account, independent of any one person. The key is
29
- `kici_sk_…`.
30
-
31
- Both drive the MCP identically. A non-agent token of either kind (a plain user
32
- PAT, a plain org API key) is refused at the door.
33
-
34
- **Option A — an agent PAT.** Mint one with the `kici` CLI (log in first with
35
- `kici login`):
36
-
37
- ```bash
38
- kici pat create --agent --name "claude-code"
39
- ```
40
-
41
- The `--name` value is the **agent label**. It is recorded on every action the
42
- agent takes, so your audit log shows exactly which agent did what (and on whose
43
- behalf). The token is printed once — save it now; it cannot be retrieved later.
44
-
45
- **Option B — an agent org API key.** Create one from the dashboard's
46
- **Settings → API keys** tab: set the key's kind to **Agent** and give it an
47
- agent name (the agent label). The same key can also be minted with
48
- `kici-platform-admin user api-key create --org <id> --agent --agent-label <label>`.
49
- Reach for an org agent key when the agent should act as a shared service account
50
- rather than as a single user — for example, a long-lived CI bot that outlives any
51
- individual's membership.
52
-
53
- Whichever you pick, the credential carries provenance, not extra authority. Its
54
- effective permissions are the matrix it was minted with, and that matrix can
55
- never exceed the permissions of the person who created it — so you can scope an
56
- agent credential **below** your own access (for example, read-only) and the agent
57
- is held to that smaller set. Powerful operator capabilities (secret rotation,
58
- agent and peer management, draining) are intentionally **not** exposed here. See
59
- [the agent safety model](https://docs.kici.dev/user/ai-agents/#6-the-agent-safety-model) for how scoping and
60
- confinement work.
61
-
62
- ## 2. Point your coding agent at the MCP server
63
-
64
- KiCI's hosted MCP server lives at one fixed URL:
65
-
66
- ```
67
- https://api.kici.dev/api/v1/mcp
68
- ```
69
-
70
- Configure your MCP client with that URL and your agent credential (the agent PAT
71
- or the agent org key) as a Bearer credential. For Claude Code:
72
-
73
- ```bash
74
- claude mcp add --transport http kici https://api.kici.dev/api/v1/mcp \
75
- --header "Authorization: Bearer <your-agent-credential>"
76
- ```
77
-
78
- That's the entire setup. The agent can now call the tools below.
79
-
80
- ## 3. What the agent can do
81
-
82
- **Read**
83
-
84
- - `list_runs` — recent runs in your organization.
85
- - `get_run` — the structured, provenance-tagged result of a run: the typed job
86
- graph, per-step statuses and exit codes, durations, and a derived failure
87
- category.
88
- - `get_step_logs` — the log lines for a specific step.
89
- - `list_workflows` — your registered workflows, optionally filtered by
90
- `triggerType`, `repo`, or `stale` (only those not triggered within a duration
91
- like `30d`).
92
- - `list_orgs` — the organizations you belong to. Use it to discover the `orgId`
93
- to pass to the other tools when you're a member of more than one.
94
- - `list_secrets` — the secret scopes in your organization and the **key names**
95
- each holds. Secret values are never returned — only the names.
96
- - `list_orchestrators` — the connected orchestrator clusters your runs execute
97
- on (cluster name, routing keys, version, scaler backends, health).
98
- - `get_diagnostics` — your organization's execution metrics over the last 24
99
- hours (run count, success rate, average duration, queued and running jobs)
100
- plus per-orchestrator connection health.
101
-
102
- **Drive**
103
-
104
- - `trigger_run` — run a registered workflow ("run now").
105
- - `rerun_run` — re-run a completed run.
106
- - `cancel_run` — cancel an in-progress run.
107
- - `approve_run` — approve a held approval gate for a run (name the run, plus
108
- `job`/`step` to disambiguate when it has multiple holds). Requires
109
- `runs:write` **and** the permission matching the hold's type — `ci_trust:write`
110
- for a security hold, `contexts:admin` for a wait-timer hold, `contexts:write`
111
- otherwise. That is the same rule the dashboard and the `kici` CLI answer to,
112
- so an agent cannot release a hold a person with the same grants could not.
113
- Grant agent credentials accordingly.
114
- - `reject_run` — reject a held approval gate; a `reason` is required. Gated
115
- identically to `approve_run`.
116
- - `cancel_runs_by_branch` — cancel all in-progress runs on a branch (bounded —
117
- up to 100 per call; a `truncated` flag tells the agent to re-invoke).
118
-
119
- The tools cover the same developer operations you can drive yourself with the
120
- `kici` CLI. Operations that are purely local to your machine (scaffolding,
121
- compiling, running a workflow locally) or that mint credentials are
122
- intentionally not exposed — the agent works against your deployed CI, not your
123
- filesystem.
124
-
125
- If you belong to a single organization, the org is resolved automatically. If
126
- you belong to several, pass an `orgId` argument to any tool (use `list_orgs` to
127
- find it).
128
-
129
- ### Limits and pagination
130
-
131
- The MCP server applies a few bounds so an agent loop can't overwhelm the shared
132
- infrastructure. They are agent-visible — your agent gets a clear tool error and
133
- should back off or page, never a silent truncation:
134
-
135
- - **Per-token request limits.** Each agent token has its own ceiling, refreshed
136
- every minute: **120 reads/minute** (listing and fetching runs, step logs, and
137
- workflows) and **20 run actions/minute** (cancel, re-run, trigger, approve,
138
- reject, cancel-by-branch). The two
139
- budgets are independent. An over-limit call returns a tool error telling the
140
- agent which kind of operation was throttled and how many seconds to wait
141
- before retrying.
142
- - **Paginated step logs.** `get_step_logs` returns log lines in pages. Pass a
143
- `limit` to bound a page (capped server-side) and follow the returned
144
- `nextCursor` (as `cursor` on the next call) to read more. A large step log is
145
- paged, never silently cut off — when `nextCursor` is null you've reached the
146
- end.
147
- - **Bounded run results.** `get_run` returns the structured run result, which is
148
- naturally bounded by workflow size. For a pathologically large run it returns a
149
- tool error directing the agent to inspect specific steps with `get_step_logs`
150
- instead.
151
-
152
- ## 4. Why the structured result is agent-safe
153
-
154
- Every tool returns a machine-first shape designed for an agent to reason over
155
- without being misled by repository content. Each field that comes from your repo,
156
- a contributor, or a process's output — workflow and job names, refs, error
157
- messages, log lines, job outputs — is delivered **fenced** as untrusted data:
158
- wrapped in a per-response, randomly-named delimiter (`⟦u:<nonce>⟧…⟦/u:<nonce>⟧`),
159
- with the result prefixed by a notice that fenced text is data, never instructions.
160
- KiCI-generated values (ids, statuses, exit codes, durations, the derived failure
161
- category) are left plain. So an agent can keep user-controlled content out of its
162
- instruction channel by treating anything inside a fence as data only. See
163
- [Untrusted content and prompt injection](https://docs.kici.dev/user/ai-agents/#7-untrusted-content-and-prompt-injection)
164
- for the full model.
165
-
166
- Secret values are never returned — only the names of the secret keys a step
167
- accessed.
168
-
169
- ## 5. The audit guarantee
170
-
171
- Because the MCP accepts only an agent-kind credential, **every action that flows
172
- through it is agent-attributed by construction** — there is no path that produces
173
- an untagged, human-looking action. Each read and each drive operation is recorded
174
- in your orchestrator's access log under the acting identity plus the agent label,
175
- so you always have a complete trail of what your agent did.
176
-
177
- Inspect that trail with `kici-admin access-log list --json` (or
178
- `kici-admin access-log show <id>` for one entry). The acting identity depends on
179
- which credential you used:
180
-
181
- - An **agent PAT** keeps `actor_type` as `user` and `actor_id` as your own
182
- identity — the agent provenance rides in the actor metadata as `agentLabel`
183
- (the `--name` you minted the PAT with) and `agentPatId`.
184
- - An **agent org key** keeps `actor_type` as `api_key` and `actor_id` as the key
185
- — the same `agentLabel` provenance rides in its actor metadata.
186
-
187
- Either way the label is stored in a dedicated `agent_label` column on every such
188
- row, so you can filter the access log down to just agent activity:
189
-
190
- ```bash
191
- # Every action a specific agent took, by its label:
192
- kici-admin access-log list --agent-label "claude-code"
193
-
194
- # Every agent-attributed action, across all agents:
195
- kici-admin access-log list --agent-only
196
- ```
197
-
198
- In the dashboard, agent-driven activity is visually distinguished: the
199
- [Activity](https://docs.kici.dev/user/dashboard/activity-and-dlq/#activity) log renders an **agent badge**
200
- on every agent-attributed row, and a run's **Triggered by** shows the same badge
201
- when an agent triggered or cancelled it — so an agent's footprint is obvious at a
202
- glance, not buried in metadata.
203
-
204
- ## 6. The agent safety model
205
-
206
- KiCI treats a coding agent as a **least-privilege principal with its own token**,
207
- not as an unscoped extension of you. Three properties make the agent
208
- "confined and audited by construction":
209
-
210
- **Least-privilege, capped at the creator.** An agent token is scoped when you
211
- mint it. Leave the scope open and it inherits your role; narrow it and the agent
212
- is held to that smaller set — its effective permissions are always the
213
- **minimum** of your role and the token's scope. A token can never grant more than
214
- you hold, so an agent cannot escalate beyond its creator.
215
-
216
- **Repository scope comes along too.** If your role is restricted to a set of
217
- repositories, an agent token you mint is restricted to the same set. Runs
218
- outside it are simply not there: they are filtered out of `list_runs`,
219
- `cancel_runs_by_branch` skips them, and naming one directly answers "not found"
220
- — the same answer a run id that does not exist gets, so an agent cannot use the
221
- tools to discover which repositories it is missing. Your organization's audit
222
- log records the real reason. One thing to know when you choose which credential
223
- to give an agent: this inheritance applies to a **personal** agent token. An
224
- **organization** agent API key has no minting user's role to inherit from, so it
225
- reaches every repository in the organization within its permission level — reach
226
- for a personal agent token when repository scoping is what you want.
227
-
228
- **Fail-closed denial, on every surface the token is used.** The scope is enforced
229
- wherever the token acts — the MCP tools the agent drives **and** any direct API
230
- call made with the raw token. When the agent attempts something outside its
231
- scope (driving a run with a read-only token, reading members it wasn't granted),
232
- the action is **refused fail-closed**: it does not run, nothing is changed, and a
233
- clear "insufficient permission" error comes back. There is no fallback path that
234
- quietly lets a denied action through.
235
-
236
- **Every decision is audited — allowed and denied alike.** Allowed actions are
237
- recorded in your access log under your identity plus the agent label, exactly as
238
- described in [the audit guarantee](https://docs.kici.dev/user/ai-agents/#5-the-audit-guarantee). **Denials are audited
239
- too:** each refused action lands a row in your organization's audit log carrying
240
- the agent label and the permission that was required, so a confined agent's
241
- attempts are as visible as its successes. You can see both what your agent did
242
- and what it was stopped from doing.
243
-
244
- **Execution stays confined.** Beyond authorization, the workloads an agent
245
- triggers run under the same execution guardrails as any other run — label-based
246
- routing decides where a job runs, and privileged (root) execution is gated and
247
- verified, refused fail-closed when the guarantee can't be met.
248
-
249
- Together these mean you can hand an agent a deliberately narrow token, point it
250
- at KiCI, and trust that it can do exactly what you granted — no more — with a
251
- complete, tamper-evident trail of every allow and every deny.
252
-
253
- ## 7. Untrusted content and prompt injection
254
-
255
- A run carries content KiCI does not vouch for — log lines, workflow and repository
256
- names, error text, contributor names. An agent reading a run must treat that content
257
- as **data**, never as instructions, or a crafted log line ("ignore previous
258
- instructions and …") could hijack the agent.
259
-
260
- KiCI defends this structurally:
261
-
262
- - **Provenance tagging.** Every user- or process-controlled value is marked untrusted
263
- at the API boundary; KiCI's own values (run ids, statuses, exit codes, commit hashes)
264
- are trusted.
265
- - **Fencing at the agent boundary.** When the MCP server returns a result, every
266
- untrusted value is wrapped in a per-response, randomly-named fence
267
- (`⟦u:<nonce>⟧…⟦/u:<nonce>⟧`) and the result is prefixed with a notice that fenced
268
- text is data, never instructions. The fence name is random per response, so injected
269
- content cannot forge a closing fence to break out.
270
- - **No mutation.** KiCI never rewrites your log content — it fences and labels it. The
271
- agent sees the true bytes inside the fence.
272
-
273
- ### Safe integration pattern
274
-
275
- An agent (or harness) consuming KiCI reads should treat anything inside a fence as
276
- opaque data: quote it, summarize it, search it — but never execute it, follow it, or
277
- let it redirect a tool call. Any action taken off the back of a read (re-run, cancel,
278
- trigger) should be a deliberate decision from the trusted skeleton (statuses, exit
279
- codes, the failure category), not from fenced content.
280
-
281
- ### Sandboxing actions
282
-
283
- Actions an agent drives through KiCI run under the agent's own least-privilege identity
284
- and are audited; combine the fencing contract with that confinement so that even if a
285
- log line tries to provoke an action, the action is bounded by the agent token's scope.
286
-
287
- ---
288
-
289
- ## CLI authentication
290
-
291
- Source: https://docs.kici.dev/user/cli-auth/
292
-
293
- The KiCI CLI supports three authentication methods: browser-based OAuth (default), device authorization flow (for headless environments), and API key paste (for CI/CD pipelines).
294
-
295
- ## Authentication methods
296
-
297
- ### Browser OAuth (default)
298
-
299
- The default `kici login` flow:
300
-
301
- 1. Opens your default browser to the KiCI identity provider
302
- 2. You authenticate in the browser
303
- 3. The CLI receives a token via localhost callback
304
- 4. A personal access token (PAT) is created and stored locally
305
-
306
- ```bash
307
- kici login
308
- ```
309
-
310
- The CLI auto-detects headless environments (SSH sessions, CI runners, containers) and switches to device flow automatically. On WSL, `kici login` opens your Windows browser when Windows interop is reachable; if it is not (interop disabled, or the Windows drive not mounted), the CLI falls back to the device flow rather than waiting for a browser that cannot open.
311
-
312
- ### Device flow (headless)
313
-
314
- For environments without a browser (SSH, remote servers):
315
-
316
- ```bash
317
- kici login --device
318
- ```
319
-
320
- This displays a URL and a code. Open the URL on any device, enter the code, and authenticate. The CLI polls for completion.
321
-
322
- ### API key paste
323
-
324
- For CI/CD pipelines and automated environments, paste an API key directly:
325
-
326
- ```bash
327
- kici login --token kici_sk_abc123...
328
- ```
329
-
330
- The API key (starts with `kici_sk_`) is passed directly as the flag value and stored in your local config file.
331
-
332
- ## kici logout
333
-
334
- Revoke your PAT and clear local authentication:
335
-
336
- ```bash
337
- kici logout
338
- ```
339
-
340
- This:
341
-
342
- 1. Revokes the PAT on the server (preventing further use)
343
- 2. Clears auth fields from the local config file
344
- 3. Preserves non-auth settings (active org, default clusters, Platform endpoint)
345
-
346
- ## Organization management
347
-
348
- ### List organizations
349
-
350
- ```bash
351
- kici org list
352
- ```
353
-
354
- Shows all organizations you belong to, with your role in each. The active organization is marked with an asterisk.
355
-
356
- ### Switch active organization
357
-
358
- ```bash
359
- kici org use <name-or-id>
360
- ```
361
-
362
- Name matching is case-insensitive. You can also use the organization ID directly.
363
-
364
- The active organization is both the scope for org-scoped commands (`kici runs list`, `kici diagnostics`, `kici secrets list`, …) **and** the default target for `kici run remote`. After `kici login` and `kici org use <org>`, `kici run remote` dispatches to that org through the Platform — that is the complete path to a remote run. Override the target for a single run with `kici run remote --org <id>`.
365
-
366
- If an organization has more than one connected orchestrator cluster, set its default cluster once with `kici orchestrators use <name>` (list them with `kici orchestrators list`). `kici run remote` then targets that cluster unless you pass `--orchestrator <name>`. With a single connected orchestrator the cluster is selected automatically.
367
-
368
- ### Show current organization
369
-
370
- ```bash
371
- kici org current
372
- ```
373
-
374
- Displays the currently active organization name and ID.
375
-
376
- ## Auth status
377
-
378
- `kici org current` shows your current login state and active organization:
379
-
380
- ```bash
381
- kici org current
382
- ```
383
-
384
- It reports whether you are logged in and which organization is active. PAT
385
- expiry and the full list of your tokens are managed from the dashboard (see
386
- "Dashboard management" below).
387
-
388
- ## Personal access tokens
389
-
390
- Personal access tokens (PATs) are created automatically when you log in via OAuth. You can also create and manage PATs through the dashboard.
391
-
392
- ### How PATs work
393
-
394
- - **User-scoped**: PATs work across all organizations you belong to
395
- - **120-day default expiry**: Configurable when creating from the dashboard
396
- - **Named per machine**: Each login creates a PAT named after the machine hostname
397
- - **Permission inheritance**: PATs inherit your effective role permissions in each org
398
-
399
- ### PATs vs API keys
400
-
401
- | | Personal access tokens | API keys |
402
- | ---------- | ---------------------- | --------------- |
403
- | Scope | User (cross-org) | Organization |
404
- | Prefix | `kici_pat_` | `kici_sk_` |
405
- | Created by | CLI login or dashboard | Dashboard |
406
- | Expiry | 120 days (default) | No expiry |
407
- | Use case | Developer CLI access | CI/CD pipelines |
408
-
409
- ### Dashboard management
410
-
411
- Create, view, and revoke PATs from the dashboard:
412
-
413
- 1. Click your avatar in the sidebar
414
- 2. Select **Account settings**
415
- 3. Navigate to the **Personal access tokens** tab
416
-
417
- From here you can:
418
-
419
- - Create PATs with custom names and expiry periods
420
- - View active PATs with their prefixes and expiry dates
421
- - Revoke PATs that are no longer needed
422
-
423
- ## Reaching the Platform API directly
424
-
425
- The Platform exposes a versioned REST API under `/api/v1/*`. The same endpoints back the dashboard SPA, the `kici` CLI, and any third-party automation. There is no separate "public" surface — the dashboard's API is the API.
426
-
427
- ### Base URL
428
-
429
- | Deployment | Base URL pattern |
430
- | ----------- | ------------------------------------------------------------------------- |
431
- | KiCI Cloud | `https://<your-platform-host>/api/v1/` |
432
- | Self-hosted | `https://<orchestrator-host>/<deployment-slug>/api/v1/` (slug is optional |
433
- | | — `KICI_BASE_PATH` may add a prefix when the Platform is reverse-proxied) |
434
-
435
- `/api/v1/*` requires authentication (see below). `/health`, `/metrics`, and `/ws` (WebSocket) sit outside that prefix and have their own access posture (`/metrics` is meant for Prometheus scrape, not public exposure).
436
-
437
- ### Authentication
438
-
439
- Every request to `/api/v1/*` carries an `Authorization: Bearer <token>` header. The Platform routes on the prefix:
440
-
441
- | Prefix | Token type | Created via | Scope |
442
- | ----------- | ----------------------------- | --------------------------------------- | ---------------- |
443
- | `kici_pat_` | Personal access token | `kici login` or dashboard | User (cross-org) |
444
- | `kici_sk_` | User API key | Dashboard → Settings → API keys | Org |
445
- | `kici_sa_` | Service account key | Dashboard → Settings → Service accounts | Org |
446
- | (other) | OIDC JWT or opaque OIDC token | OIDC login (browser SPA) | User (cross-org) |
447
-
448
- JWT and opaque OIDC tokens are validated against the configured OIDC issuer (JWKS for JWTs, the issuer's UserInfo endpoint for opaque ones). All `kici_*` tokens are validated by SHA-256 hash lookup against the Platform DB. See [RBAC: authentication methods](https://docs.kici.dev/architecture/security/rbac/#authentication-methods) for the full model.
449
-
450
- > **Note:** `kici_ok_` keys are **not** for the HTTP API — they authenticate orchestrator-to-Platform WebSocket connections only. Use `kici_sk_` (or `kici_pat_`) for HTTP calls.
451
-
452
- ### Permissions
453
-
454
- Tokens authenticate; RBAC authorizes. Every org-scoped route runs `orgContextMiddleware` (verifies you are a member of the target org) followed by `requirePermission(resource, level)`. The 18 resources and 5 levels are documented in [RBAC](https://docs.kici.dev/architecture/security/rbac/#permission-model). User API keys carry their own permission matrix bounded above by the creator's effective permissions; PATs inherit the user's role permissions (or are capped further by their `scopes` field).
455
-
456
- ### Configurable surfaces
457
-
458
- The dashboard is a browser SPA on top of the same `/api/v1/*` surface, so anything you can configure in the dashboard you can configure over HTTP. The mounted route groups include:
459
-
460
- - **Auth & identity:** `/cli/exchange-token`, `/pats`, `/user`, `/identity-links`, `/github-oauth`, `/invites`, `/invites/pending`, `/invites/:inviteId/{accept,decline}`
461
- - **Org & membership:** `/orgs`, `/orgs/:customerId`, `/orgs/:customerId/{members,roles,api-keys,orchestrator-keys,service-accounts,billing,trust-policies}`
462
- - **Workflows & runs:** `/orgs/:customerId/{runs,registrations,workflows,held-runs,contexts,secrets,global-workflows}`
463
- - **Webhooks & event log:** `/orgs/:customerId/{sources,webhook-endpoints,event-log}`
464
- - **Diagnostics & activity:** `/orgs/:customerId/{diagnostics,activity,access-log}`
465
-
466
- The full route tree is the source of truth — every method, request schema, and response schema is enumerated server-side. There is currently no auto-generated OpenAPI spec; the typed `DashboardApiType` export is the canonical contract for TypeScript clients.
467
-
468
- ### Calling the API
469
-
470
- Two short examples — adapt the base URL and token to your deployment.
471
-
472
- **curl (PAT or API key):**
473
-
474
- ```bash
475
- TOKEN="$(grep -E '^pat=' ~/.kici/config | cut -d= -f2)" # or paste a kici_sk_…
476
- ORG="<your-org-id>"
477
- curl -sS \
478
- -H "Authorization: Bearer $TOKEN" \
479
- "https://<orchestrator-host>/<deployment-slug>/api/v1/orgs/$ORG/runs?limit=5" | jq
480
- ```
481
-
482
- **Browser console (after dashboard login):**
483
-
484
- ```js
485
- const ns = Object.keys(localStorage).find((k) => k.startsWith('oidc.user:'));
486
- const { access_token } = JSON.parse(localStorage.getItem(ns));
487
- const res = await fetch('/<deployment-slug>/api/v1/orgs/<your-org-id>/runs?limit=5', {
488
- headers: { Authorization: `Bearer ${access_token}` },
489
- });
490
- console.log(await res.json());
491
- ```
492
-
493
- ### Rate limits and body size
494
-
495
- There is currently no per-token rate limit on `/api/v1/*`. A single global body-size cap applies to webhook ingress and dashboard API requests alike.
496
-
497
- ### Audit trail
498
-
499
- Every `/api/v1/*` mutation that touches tenant-plane data is recorded in the upstream tenant-plane audit log, stamped with the actor (user, API key, service account, or upstream operator on a break-glass support read). Reads on customer data go through the orchestrator over the WebSocket proxy and land in the orchestrator's `access_log` table. See [Audit log](https://docs.kici.dev/operator/security/audit-log/) for the orchestrator schema and the dashboard's "Activity" page for the federated view.
500
-
501
- ## Token storage
502
-
503
- The CLI stores authentication data in `~/.kici/config` with `0600` permissions (owner read/write only). The config file contains:
504
-
505
- - PAT token
506
- - PAT expiry date
507
- - Active organization ID
508
- - Per-org default orchestrator clusters
509
- - Platform endpoint URL
510
-
511
- ## Troubleshooting
512
-
513
- ### Browser doesn't open
514
-
515
- If `kici login` can't open a browser:
516
-
517
- - Copy the authorization URL the CLI prints under `If it does not open, visit:` and open it in any browser — the CLI keeps waiting for the callback for up to 5 minutes (see [Browser callback never arrives](https://docs.kici.dev/user/cli-auth/#browser-callback-never-arrives) if it never lands)
518
- - Use `kici login --device` for the device flow
519
- - Or set the `KICI_BROWSER_CMD` environment variable to your browser command (e.g., `KICI_BROWSER_CMD='firefox {url}'`)
520
-
521
- ### Browser callback never arrives
522
-
523
- If the browser opens and you complete sign-in, but `kici login` keeps waiting:
524
-
525
- - The CLI is waiting on a callback to `127.0.0.1`. A corporate firewall, an unusual loopback policy, or a WSL `portproxy` rule can block it.
526
- - After 90 seconds of waiting the CLI prints a reminder that `kici login --device` needs no callback. It is safe to ignore if you are still signing in. After 5 minutes it gives up with `Authentication timed out after 5 minutes`.
527
- - Retry with `kici login --device` — the device flow needs no local callback.
528
- - If you must keep the browser flow, set `KICI_CALLBACK_PORT` to a fixed port your firewall allows.
529
-
530
- ### Callback port already in use
531
-
532
- If `KICI_CALLBACK_PORT` names a port something else is already listening on, `kici login` stops immediately and names the port instead of hanging or crashing.
533
-
534
- It deliberately does **not** pick another port for you. A fixed port is something you set on purpose — usually because a firewall rule or a WSL `portproxy` entry allows exactly that one — so binding somewhere else would hand the browser a callback URL nothing can reach, and you would wait out the full 5-minute timeout instead of seeing a clear error.
535
-
536
- Two ways forward:
537
-
538
- - Free the port (stop whatever holds it) or point `KICI_CALLBACK_PORT` at a different free port your firewall allows.
539
- - Run `kici login --device` — the device flow needs no local callback at all.
540
-
541
- A port below 1024 fails the same way, with a permissions message rather than an "in use" one: those ports need elevated privileges. Pick a port above 1024. A value that is not a port number at all — non-numeric, negative, or above 65535 — is rejected before the login starts, naming the value you set.
542
-
543
- ### Device flow timeout
544
-
545
- This is the device flow's own expiry, not the browser flow's callback timeout above.
546
-
547
- The device flow has a 5-minute timeout. If it expires:
548
-
549
- - Run `kici login --device` again to get a new code
550
- - Ensure you're using the correct URL displayed by the CLI
551
-
552
- ### Expired PAT
553
-
554
- If you see "Personal access token has expired":
555
-
556
- - Run `kici login` to create a new PAT
557
- - The old expired PAT is automatically superseded
558
-
559
- ### "Not a member" errors
560
-
561
- If authenticated commands return 403:
562
-
563
- - Check your active org: `kici org current`
564
- - List available orgs: `kici org list`
565
- - Switch to the correct org: `kici org use <name>`
566
-
567
- ### Connection refused
568
-
569
- If the CLI can't reach the server:
570
-
571
- - Verify the endpoint: check `~/.kici/config` for the correct URL
572
- - Test connectivity: `curl <your-platform-url>/health`
573
-
574
- ---
3
+ This bundle covers: Running the CLI locally: compile, test, run local, hooks, lock-file drift, common failures.
575
4
 
576
5
  ## CLI reference
577
6
 
@@ -605,7 +34,7 @@ The full command reference is split by area:
605
34
  - [Authoring & local dev](https://docs.kici.dev/user/cli/authoring-and-local/) — `compile`, `preview`, `local`, `fixture`, `types`, `workflows`, `hook`, `docs`
606
35
  - [Runs & approvals](https://docs.kici.dev/user/cli/runs-and-approvals/) — `run`, `runs`, `reject`, `approve`
607
36
  - [Account & org](https://docs.kici.dev/user/cli/account-and-org/) — `login`, `logout`, `init`, `org`, `pat`, `secrets`, `admin`, `orchestrators`, `endpoints`
608
- - [Notifications & diagnostics](https://docs.kici.dev/user/cli/notifications-and-diagnostics/) — `notifications`, `verify-attestation`, `diagnostics`, `doctor`
37
+ - [Notifications & diagnostics](https://docs.kici.dev/user/cli/notifications-and-diagnostics/) — `notifications`, `verify-attestation`, `diagnostics`, `doctor`, `report`, `feedback`
609
38
 
610
39
  Each area page carries a `## Guide` section (worked examples and command-by-command narrative) and a `## Reference` section (the always-current generated signature list for that area's commands).
611
40
 
@@ -1166,6 +595,7 @@ Step entries carry their own capability flags, so the orchestrator can reason ab
1166
595
 
1167
596
  | Flag | Meaning |
1168
597
  | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
598
+ | `hasOutputs` | The step declares an output schema, so the run has typed outputs to record for it. Present on every step entry. |
1169
599
  | `hasCheck` | The step declares an idempotent `check` facet, so a run can be dispatched in check mode. See [idempotent steps and check mode](https://docs.kici.dev/user/idempotent-steps/). |
1170
600
  | `hasWhenInSync` | The step declares a `whenInSync` facet that produces its outputs when `check` reports no drift. |
1171
601
  | `hasRules` | The step has conditional rules (evaluated agent-side). |
@@ -1787,7 +1217,7 @@ export const pushMain = fixture('push-main', {
1787
1217
 
1788
1218
  Source: https://docs.kici.dev/user/workflow-patterns/
1789
1219
 
1790
- Practical patterns for building real-world KiCI workflows in TypeScript. The patterns are organised across five pages -- start with [Basic CI](https://docs.kici.dev/user/patterns/basic/) if you're new, or jump to [Integrations](https://docs.kici.dev/user/patterns/integrations/) if you're wiring up a non-GitHub forge or a generic webhook.
1220
+ Practical patterns for building real-world KiCI workflows in TypeScript. The patterns are organised across seven pages -- start with [Basic CI](https://docs.kici.dev/user/patterns/basic/) if you're new, or jump to [Integrations](https://docs.kici.dev/user/patterns/integrations/) if you're wiring up a non-GitHub forge or a generic webhook.
1791
1221
 
1792
1222
  | Page | Covers |
1793
1223
  | ---------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
@@ -1795,6 +1225,8 @@ Practical patterns for building real-world KiCI workflows in TypeScript. The pat
1795
1225
  | [Conditionals & matrix](https://docs.kici.dev/user/patterns/conditionals-matrix/) | Conditional execution with rules, matrix builds (static + dynamic), and dynamic job generation. |
1796
1226
  | [Integrations](https://docs.kici.dev/user/patterns/integrations/) | Workflow chaining, generic webhooks, Stripe handlers, self-hosted git forges (Forgejo / Gitea / Gogs), plain GitHub repo webhooks (no GitHub App). |
1797
1227
  | [Scheduling & events](https://docs.kici.dev/user/patterns/scheduling-and-events/) | Nightly cron, workflow-complete-triggered deploys, custom event chaining. |
1228
+ | [Git credentials](https://docs.kici.dev/user/patterns/git-credentials/) | Declaring named git credentials from the secrets backend, and pushing from a job (including to the job's own repository). |
1229
+ | [Host restart](https://docs.kici.dev/user/patterns/host-restart/) | `restartHost()` and `waitForHostAlive()` -- reboot the host a workflow runs on and resume in a second job pinned to the same host. |
1798
1230
  | [Pattern reference](https://docs.kici.dev/user/patterns/reference/) | Step context, the examples repository, and GitHub check run output -- cross-cutting reference shared by every pattern above. |
1799
1231
 
1800
1232
  ## See also
@@ -1808,2125 +1240,507 @@ Practical patterns for building real-world KiCI workflows in TypeScript. The pat
1808
1240
 
1809
1241
  ---
1810
1242
 
1811
- ## kici: account & org
1243
+ ## kici: authoring & local dev
1812
1244
 
1813
- Source: https://docs.kici.dev/user/cli/account-and-org/
1245
+ Source: https://docs.kici.dev/user/cli/authoring-and-local/
1814
1246
 
1815
1247
  ## Guide
1816
1248
 
1817
- ### kici login
1818
-
1819
- Authenticate with KiCI via browser-based OAuth (default) or API key (`--token`).
1820
-
1821
- By default, `kici login` opens your browser for OIDC authentication using PKCE. In headless environments (SSH, CI, containers), it automatically switches to the RFC 8628 device authorization flow where you visit a URL and enter a code.
1822
-
1823
- The browser flow completes by receiving a callback on `127.0.0.1`. If that callback is blocked, pass `--device` to use the device flow instead — it needs no local callback. See [CLI authentication](https://docs.kici.dev/user/cli-auth/#browser-callback-never-arrives) for the full troubleshooting steps.
1824
-
1825
- After OAuth, the CLI exchanges the OIDC token for a personal access token (PAT) stored in the config directory (`~/.kici/config` by default, overridable with `KICI_CONFIG_DIR`).
1249
+ ### kici compile
1826
1250
 
1827
- `kici login` targets the hosted KiCI Platform by default. To authenticate against another KiCI environment (staging, or a testing OIDC provider, for example), pass `--platform-endpoint` / `--oidc-issuer` or set `KICI_PLATFORM_URL` / `KICI_OIDC_ISSUER`. Login persists the platform endpoint and OIDC issuer it authenticated against alongside the PAT, so a saved PAT always matches its endpoint. Because the config describes one environment at a time, **switching the endpoint resets the active organization and default clusters** — re-run `kici org use <name>` after switching environments.
1251
+ Compile workflows from `.kici/workflows/` to `kici.lock.json`.
1828
1252
 
1829
1253
  ```bash
1830
- kici login [options]
1254
+ kici compile [options]
1831
1255
  ```
1832
1256
 
1833
- **Environment variables:**
1834
-
1835
- | Variable | Default | Description |
1836
- | --------------------- | -------------------------------------------- | ---------------------------------------------------------------------- |
1837
- | `KICI_PLATFORM_URL` | `https://api.kici.dev` | Platform API base URL (override to target another KiCI environment) |
1838
- | `KICI_OIDC_ISSUER` | `https://auth.kici.dev/realms/kici-internal` | OIDC issuer URL (override to target another KiCI environment) |
1839
- | `KICI_OIDC_CLIENT_ID` | `kici-cli` | OIDC client ID (override to target another KiCI environment) |
1840
- | `KICI_BROWSER_CMD` | uses `open` package | Custom browser command with `{url}` placeholder, or `none` to suppress |
1841
- | `KICI_CALLBACK_PORT` | random | Fixed port for OAuth PKCE callback server |
1842
- | `KICI_CONFIG_DIR` | `~/.kici` | Override config directory |
1843
-
1844
1257
  **Examples:**
1845
1258
 
1846
1259
  ```bash
1847
- # Browser-based OAuth login (default)
1848
- kici login
1849
-
1850
- # Force device flow (for SSH/headless)
1851
- kici login --device
1852
-
1853
- # Legacy API key login
1854
- kici login --token kici_sk_abc123...
1260
+ # Compile all workflows
1261
+ kici compile
1855
1262
 
1856
- # Log in against another KiCI environment (e.g. a testing instance)
1857
- kici login --platform-endpoint https://platform.example.com \
1858
- --oidc-issuer https://auth.example.com/realms/kici-internal
1263
+ # Validate and type-check (CI-friendly, no file writes)
1264
+ kici compile --check
1859
1265
 
1860
- # Suppress browser opening (print authorize URL to stdout)
1861
- KICI_BROWSER_CMD=none kici login
1266
+ # Watch mode for development
1267
+ kici compile --watch
1862
1268
 
1863
- # Use custom browser command
1864
- KICI_BROWSER_CMD='firefox {url}' kici login
1269
+ # Custom .kici directory location
1270
+ kici compile --kici-dir packages/app/.kici
1865
1271
 
1866
- # Fixed callback port and custom config directory
1867
- KICI_CALLBACK_PORT=19876 KICI_CONFIG_DIR=/tmp/kici-test kici login
1272
+ # Verbose output for debugging
1273
+ kici compile --verbose
1868
1274
  ```
1869
1275
 
1870
- **Headless detection:** The CLI checks, in order:
1871
-
1872
- 1. SSH session — `SSH_CONNECTION`, `SSH_CLIENT`, or `SSH_TTY` set.
1873
- 2. CI — `CI`, `GITHUB_ACTIONS`, or `GITLAB_CI` set to anything other than the explicit opt-outs `0` and `false` (any case), so exporting `CI=0` on a desktop keeps the browser flow. An opt-out cancels that one marker only — `CI=false GITHUB_ACTIONS=true` still selects the device flow, and `GITHUB_ACTIONS=false` opts that marker out without affecting `CI`. See [Environment variables](https://docs.kici.dev/user/env-vars/#how-ci-is-interpreted) for the full convention.
1874
- 3. Container — `container` or `DOCKER_CONTAINER` set, or the `/run/.containerenv` / `/.dockerenv` sentinel files present.
1875
- 4. WSL — an interactive desktop, so **not** headless, but only when Windows interop is reachable: the browser flow opens your Windows browser and the localhost callback is normally reachable through WSL's localhost forwarding (a `portproxy` rule or firewall policy can still block it — pass `--device` if it does). When interop is unreachable (it is disabled, or the Windows drive is not mounted) no Windows browser can be launched, so WSL counts as headless and the device flow is used. The same applies when the interop check does not answer within a couple of seconds — the signature of a hung Windows drive mount — so a wedged mount falls back to the device flow instead of stalling the login.
1876
- 5. Linux without a display server — neither `DISPLAY` nor `WAYLAND_DISPLAY` set.
1877
-
1878
- The first match wins, so an SSH session into WSL, or a container running on a WSL host, stays on the device flow.
1879
-
1880
- ### kici logout
1276
+ **Exit codes:**
1881
1277
 
1882
- Revoke your personal access token on the server and clear local credentials.
1278
+ | Code | Meaning |
1279
+ | ---- | --------------------------- |
1280
+ | 0 | Compilation successful |
1281
+ | 1 | Compilation failed (errors) |
1883
1282
 
1884
- If the server is unreachable, local credentials are still cleared (the PAT will expire automatically). Non-auth config fields (active org, default clusters, etc.) are preserved.
1283
+ The `--check` flag is useful in CI pipelines and pre-commit hooks. It validates that workflows are syntactically and semantically correct **and** runs a `tsc --noEmit` type-check over `.kici/workflows/**`, so type-broken workflows are caught at compile time instead of shipping silently. No lock file or other files are written.
1885
1284
 
1886
- ```bash
1887
- kici logout
1888
- ```
1285
+ The type-check requires `.kici/tsconfig.json` and a `typescript` dependency — both are scaffolded by `kici init`. In a JavaScript-only workspace (`kici init --mjs`, which has no `tsconfig.json`), the type-check is skipped with a notice and validation still runs. When the type-check finds errors, `kici compile --check` prints each one in `file:line:column error [E120]: message` form and exits non-zero.
1889
1286
 
1890
- **Examples:**
1287
+ Compile and validation errors carry the real `file:line:column` of the offending job or step (anchored to the job's first step location), so you can jump straight to the source instead of a generic line 1.
1891
1288
 
1892
- ```bash
1893
- # Log out and revoke PAT
1894
- kici logout
1895
- ```
1289
+ **Auto-type regeneration:** When authenticated (via `kici login`), `kici compile` automatically refreshes `.kici/types/secrets.d.ts` after each successful compilation. This keeps type declarations in sync with your orchestrator's secret contexts. The type regeneration is non-blocking -- if the orchestrator is unreachable, compilation still succeeds with a warning. The `--check` flag skips type regeneration since no files are written.
1896
1290
 
1897
- ### kici init
1291
+ ### kici preview
1898
1292
 
1899
- Initialize a `.kici/` directory with default workflow templates.
1293
+ Preview which workflows match a trigger event (dry-run, no execution). Useful for verifying trigger configurations during development.
1900
1294
 
1901
1295
  ```bash
1902
- kici init [options]
1296
+ kici preview [event] [options]
1903
1297
  ```
1904
1298
 
1905
1299
  **Examples:**
1906
1300
 
1907
1301
  ```bash
1908
- # Interactive initialization
1909
- kici init
1910
-
1911
- # Overwrite existing setup
1912
- kici init --force
1913
-
1914
- # Skip dependency install (faster, install manually later)
1915
- kici init --skip-install
1916
-
1917
- # Force a specific package manager (default: detect from your repo)
1918
- kici init --package-manager pnpm
1919
-
1920
- # JavaScript mode (no TypeScript)
1921
- kici init --mjs
1922
-
1923
- # Integrate into the surrounding workspace (workflows can import sibling packages)
1924
- kici init --workspace
1925
-
1926
- # Force a self-contained .kici/ even inside a workspace
1927
- kici init --standalone
1302
+ # Preview which workflows match a push event
1303
+ kici preview push
1928
1304
 
1929
- # Skip writing the AGENTS.md LLM authoring context file
1930
- kici init --no-agents-md
1305
+ # Preview PR trigger matching
1306
+ kici preview pr:open
1931
1307
 
1932
- # Scaffold a workflow registries entry for a private npm registry
1933
- kici init --private-registry https://npm.pkg.github.com/ \
1934
- --private-registry-scope @my-org \
1935
- --private-registry-secret production:GITHUB_PACKAGES_TOKEN
1936
- ```
1308
+ # Preview with branch override
1309
+ kici preview push --branch develop
1937
1310
 
1938
- **What it creates:**
1311
+ # Filter to specific workflow
1312
+ kici preview push --workflow ci
1939
1313
 
1940
- ```
1941
- .kici/
1942
- workflows/
1943
- hello-world.ts # Minimal push workflow
1944
- pr-checks.ts # Comprehensive PR workflow
1945
- tests/
1946
- push-test.ts # Sample test fixture
1947
- types/ # Directory for generated type declarations (kici types)
1948
- package.json # Dependencies (@kici-dev/sdk)
1949
- tsconfig.json # TypeScript configuration (includes types/**/*.d.ts)
1950
- AGENTS.md # LLM authoring context (skip with --no-agents-md)
1951
- .kiciignore # Default exclusion patterns for test uploads
1314
+ # Simulate changed files for path-filtered triggers
1315
+ kici preview push --files src/index.ts --files README.md
1952
1316
  ```
1953
1317
 
1954
- `AGENTS.md` is written by default (the interactive prompt defaults to yes, and CI / non-interactive runs write it). An existing `.kici/AGENTS.md` is never overwritten, so hand edits survive a re-run.
1318
+ **Exit codes:**
1955
1319
 
1956
- In interactive mode (TTY), `kici init` prompts you to:
1320
+ | Code | Meaning |
1321
+ | ---- | ------------------------------------------ |
1322
+ | 0 | Preview completed (including zero matches) |
1323
+ | 1 | Error |
1957
1324
 
1958
- 1. Select which workflow templates to include
1959
- 2. Optionally install a pre-commit hook
1325
+ **Migration from the old `test` command:** The dry-run preview command was renamed from `test` to `preview`. If you were using the old `test` command with a fixture name for remote fixture execution, use `kici run remote <fixture-name>` instead. For local workflow execution, use `kici run <event> --local`.
1960
1326
 
1961
- **Host-OS runsOn:** the scaffolded workflows target `kici:os:<your OS>` — `kici init` detects the host operating system (like it detects the default branch) and writes `kici:os:linux`, `kici:os:macos`, or `kici:os:windows` so your very first `kici run push --local` dispatches on this machine. A workflow authored on one OS and run locally on another prints a hint naming the OS it wants versus the host it found.
1327
+ ### kici local
1962
1328
 
1963
- **First run:** in interactive mode, after setup `kici init` offers to run the scaffolded workflow immediately (`kici run push --local`), defaulting to No. It is skipped in CI, non-interactive shells, `--mjs`, and `--skip-install` (where dependencies are not installed yet).
1329
+ Manage the **local dev plane** the warm, per-user orchestrator (plus its own local PostgreSQL) that [`kici run <event> --local`](https://docs.kici.dev/user/cli/runs-and-approvals/#kici-run-event---local) dispatches through. You rarely need these commands directly: a local run boots the plane on demand and reuses it afterwards. Reach for them to inspect the plane, stop it, read its log, or switch it between offline and Platform-connected mode.
1964
1330
 
1965
- **Package manager:** the dependency install step uses the package manager detected for your repo — the `packageManager` field in the nearest `package.json` (Corepack convention), then a lockfile in the project root (`pnpm-lock.yaml` → pnpm, `yarn.lock` → yarn, `package-lock.json` → npm), then the package manager that invoked `kici` (`pnpm dlx` / `yarn dlx` / `npx`), defaulting to npm. Pass `--package-manager <npm|pnpm|yarn>` to override detection, or `--skip-install` to set up the files and install later yourself.
1331
+ ```bash
1332
+ kici local up [--offline | --connected] # Start, or reuse an already-running plane
1333
+ kici local status [--json] # Port, pid, PostgreSQL backend, attachment mode, readiness
1334
+ kici local down # Stop the orchestrator and its PostgreSQL, verifying the port is freed
1335
+ kici local logs # Print the orchestrator log file path
1336
+ kici local attach # Attach to the Platform (hybrid mode)
1337
+ kici local detach # Return the plane to offline (independent) mode
1338
+ kici local trust-root <file> # Export the dev-signed trust root for offline verification
1339
+ ```
1966
1340
 
1967
- **Standalone vs workspace integration:** by default `kici init` scaffolds a self-contained `.kici/` with its own `package.json`. When run inside a pnpm, npm, or yarn workspace, it offers an **integrate** option (or pass `--workspace`): `.kici/` joins the workspace, `@kici-dev/sdk` is added to your workspace-root `package.json`, and your workflows can `import` your other workspace packages (e.g. shared build or deploy utilities). In this mode there is no `.kici/package.json` — the workspace root manages dependencies, and the root install resolves the SDK. Your workflows resolve sibling packages through the workspace-root `node_modules`: under npm and yarn every workspace member is hoisted there automatically, while pnpm links only your root's declared dependencies, so under pnpm add the package you want to import to your workspace-root `dependencies` (this is how KiCI's own repository imports its packages from workflows). Pass `--standalone` to force the self-contained layout even inside a workspace. In CI / non-interactive runs the default is standalone; use `--workspace` to opt in explicitly. `--workspace` and `--standalone` are mutually exclusive, and `--workspace` errors if no workspace is found at or above the current directory.
1341
+ The plane runs in one of two modes:
1968
1342
 
1969
- **Development mode:** When `KICI_DEV=true` or `package.json` has `"kici": { "development": true }`, the generated `package.json` uses prerelease-compatible version ranges (`>=0.0.1-0`) so npm resolves Verdaccio's prerelease builds.
1343
+ - **Independent (offline)** the default for a plane that has never been attached. Identity tokens and attestations are signed by a local dev key under the clearly non-production issuer `kici-local`.
1344
+ - **Hybrid (attached)** — `kici local attach` mints an org-scoped key with your logged-in credentials and reboots the plane connected to the Platform, so local runs get real Platform-minted identity and attestation. `kici local up` honors a durable attachment record: an attached plane comes back up hybrid, and falls back to offline with a warning when the Platform is unreachable.
1970
1345
 
1971
- ### kici org
1346
+ `--offline` forces an independent boot without clearing the attachment record (only `detach` clears it); `--connected` requires an attached, reachable Platform and fails otherwise.
1972
1347
 
1973
- Manage organization context. Requires a PAT (run `kici login` first).
1348
+ `kici local down` reports success only once the plane port is verified free. If a process still holds it — including a plane left behind by an interrupted boot — the command exits non-zero and names the holder, so a failed teardown is never mistaken for a clean one. A holder that does not identify as a KiCI plane orchestrator is reported and left alone, never stopped.
1974
1349
 
1975
- #### kici org list
1350
+ `kici local status` reports a plane whose process is alive but whose readiness probe fails — for example when its PostgreSQL has stopped — as running but not ready, together with its readiness checks, rather than as not running. When the holder is a KiCI plane orchestrator that this config directory did not start — a plane belonging to another `KICI_CONFIG_DIR`, or one whose record here was lost — status names it as such rather than as not ready, since its readiness is never probed, and points at `kici local down`, which does reclaim it. When the port is held by a process that is not a KiCI plane orchestrator, `kici local status` names that holder instead and points at `KICI_LOCAL_ORCH_PORT`, because `kici local down` will not stop it.
1976
1351
 
1977
- List organizations you belong to. The active org is marked with a star (`*`).
1352
+ Pass `--json` for machine-readable output. It prints one object and exits 0 for
1353
+ every state, including when the plane is stopped — the state is in the payload,
1354
+ not the exit code:
1978
1355
 
1979
1356
  ```bash
1980
- kici org list
1357
+ $ kici local status --json
1358
+ {"state":"ready","running":true,"pid":3768093,"port":4319,
1359
+ "url":"http://127.0.0.1:4319","pgKind":"embedded","stampVersion":3,
1360
+ "mode":"independent"}
1981
1361
  ```
1982
1362
 
1983
- **Example output:**
1984
-
1985
- ```
1986
- Organizations:
1987
-
1988
- * Personal (owner) abc123def456
1989
- My team (admin) xyz789ghi012
1990
- ```
1991
-
1992
- #### kici org use
1993
-
1994
- Switch the active organization by name (case-insensitive) or ID.
1995
-
1996
- ```bash
1997
- kici org use <name>
1998
- ```
1999
-
2000
- **Examples:**
2001
-
2002
- ```bash
2003
- # Switch by name
2004
- kici org use "My team"
2005
-
2006
- # Switch by ID
2007
- kici org use xyz789ghi012
2008
- ```
2009
-
2010
- #### kici org current
2011
-
2012
- Show the current active organization.
2013
-
2014
- ```bash
2015
- kici org current
2016
- ```
2017
-
2018
- ### kici pat create
2019
-
2020
- Mint a personal access token under your own identity. Pass `--agent` to mint an
2021
- **agent-kind** PAT — the credential a coding agent points the KiCI MCP server at.
2022
-
2023
- ```bash
2024
- kici pat create --agent --name "claude-code"
2025
- ```
2026
-
2027
- - `--agent` marks the token as agent-kind. An agent PAT inherits your
2028
- permissions unchanged (it carries provenance, not extra authority) and is the
2029
- **only** credential the MCP server accepts.
2030
- - `--name <label>` sets the token name. For an agent PAT this is the **agent
2031
- label** recorded on every action the agent takes — required with `--agent`.
2032
- - `--expires-in-days <n>` overrides the default expiry.
2033
-
2034
- The token is printed once — save it immediately; it cannot be retrieved later.
2035
- See [Drive KiCI from your coding agent](https://docs.kici.dev/user/ai-agents/) for the full setup.
2036
-
2037
- **Prerequisites:** authenticate via `kici login` first.
2038
-
2039
- ### kici secrets list
2040
-
2041
- List secret contexts available for test runs. Shows context names and key names (not values).
2042
-
2043
- ```bash
2044
- kici secrets list
2045
- ```
2046
-
2047
- Each context corresponds to a context configured on the orchestrator. The output lists every context whose `allowLocalExecution` flag is `true` (the gate that lets CLI-initiated test runs resolve secrets through that context), along with the secret key names reachable from the context's bound scopes.
2048
-
2049
- Only key names are shown — secret values are never returned over this endpoint.
2050
-
2051
- **Prerequisites:** authenticate via `kici login` and select an active organization with `kici org use <name>`.
2052
-
2053
- ### kici admin
2054
-
2055
- Operator-facing commands for running instances.
2056
-
2057
- #### kici admin drain-worker
2058
-
2059
- Trigger graceful drain on a worker instance. Sends a POST request to the worker's `/drain` endpoint.
2060
-
2061
- ```bash
2062
- kici admin drain-worker [options]
2063
- ```
2064
-
2065
- **Examples:**
2066
-
2067
- ```bash
2068
- # Drain a local worker
2069
- kici admin drain-worker --url http://localhost:10143
2070
-
2071
- # Drain a remote worker
2072
- kici admin drain-worker --url http://worker-2.internal:10143
2073
- ```
2074
-
2075
- **Exit codes:**
2076
-
2077
- | Code | Meaning |
2078
- | ---- | ----------------------------------- |
2079
- | 0 | Drain request accepted |
2080
- | 1 | Error (unreachable or request fail) |
2081
-
2082
- ### kici endpoints
2083
-
2084
- List all webhook entrypoints for the current project. Reads the compiled lock file and displays webhook URLs grouped by type (git provider, generic webhooks, scheduled, event-driven).
2085
-
2086
- ```bash
2087
- kici endpoints [options]
2088
- ```
2089
-
2090
- **Prerequisites:** Run `kici compile` first to generate the lock file.
2091
-
2092
- **Examples:**
2093
-
2094
- ```bash
2095
- # List all webhook entrypoints
2096
- kici endpoints
2097
-
2098
- # Custom .kici directory
2099
- kici endpoints --kici-dir packages/app/.kici
2100
- ```
2101
-
2102
- ## Reference
2103
-
2104
- <!-- BEGIN GENERATED: kici-account-and-org (do not edit; run the doc generator) -->
2105
-
2106
- ### `kici admin`
2107
-
2108
- Operator-facing commands for running instances
2109
-
2110
- Synopsis: `kici admin`
2111
-
2112
- ### `kici admin drain-worker`
2113
-
2114
- Trigger graceful drain on a worker instance
2115
-
2116
- Synopsis: `kici admin drain-worker [options]`
2117
-
2118
- **Options**
2119
-
2120
- | Option | Default | Description |
2121
- | ------------- | ------- | -------------------------------------------- |
2122
- | `--url <url>` | | Worker URL (e.g., http://worker-host:<port>) |
2123
-
2124
- ### `kici endpoints`
2125
-
2126
- List all webhook entrypoints for the current project
2127
-
2128
- Synopsis: `kici endpoints [options]`
2129
-
2130
- **Options**
2131
-
2132
- | Option | Default | Description |
2133
- | ------------------- | ------- | ----------------------- |
2134
- | `--kici-dir <path>` | `.kici` | Path to .kici directory |
2135
-
2136
- ### `kici init`
2137
-
2138
- Initialize .kici/ directory with default workflows
2139
-
2140
- Synopsis: `kici init [options]`
2141
-
2142
- **Options**
2143
-
2144
- | Option | Default | Description |
2145
- | ---------------------------------- | ---------------------- | --------------------------------------------------------------------------------------------------- |
2146
- | `--force` | `false` | Overwrite existing .kici/ directory |
2147
- | `--skip-install` | `false` | Create files without installing dependencies |
2148
- | `--package-manager <npm | pnpm | yarn>` | | Force a package manager for the install step (default: auto-detect) |
2149
- | `--mjs` | `false` | JavaScript-only mode (no TypeScript, no dependencies) |
2150
- | `--workspace` | `false` | Integrate .kici/ into the detected pnpm/npm/yarn workspace so workflows can import sibling packages |
2151
- | `--standalone` | `false` | Force a self-contained .kici/ even inside a workspace |
2152
- | `--no-agents-md` | | Skip writing .kici/AGENTS.md (LLM authoring context) |
2153
- | `--private-registry <url>` | | Scaffold a workflow registries: entry pointing at <url> |
2154
- | `--private-registry-scope <scope>` | | Optional npm package scope (e.g. @my-org) for the private registry |
2155
- | `--private-registry-secret <ref>` | `production:NPM_TOKEN` | Qualified secret reference (env:NAME) the private registry token comes from |
2156
- | `--use-verdaccio-local` | `false` | |
2157
-
2158
- ### `kici login`
2159
-
2160
- Authenticate with KiCI via browser OAuth (default) or API key (--token)
2161
-
2162
- Synopsis: `kici login [options]`
2163
-
2164
- **Options**
2165
-
2166
- | Option | Default | Description |
2167
- | --------------------------- | ------- | ----------------------------------------------------------------------------------- |
2168
- | `--token <key>` | | API key for direct authentication (legacy) |
2169
- | `--device` | | Force device authorization flow (for headless/SSH environments) |
2170
- | `--platform-endpoint <url>` | | Platform relay URL |
2171
- | `--oidc-issuer <url>` | | OIDC issuer URL (defaults to the hosted KiCI IdP unless a flag/env selects another) |
2172
- | `--routing-key <key>` | | Routing key for webhook source identification |
2173
- | `--no-attach` | | Skip the post-login prompt to attach the local dev plane |
2174
-
2175
- ### `kici logout`
2176
-
2177
- Revoke PAT and clear local credentials
2178
-
2179
- Synopsis: `kici logout`
2180
-
2181
- ### `kici orchestrators`
2182
-
2183
- Inspect the org's orchestrator clusters and pick a default for run remote
2184
-
2185
- Synopsis: `kici orchestrators`
2186
-
2187
- ### `kici orchestrators list`
2188
-
2189
- List the connected orchestrator clusters for the active org
2190
-
2191
- Synopsis: `kici orchestrators list [options]`
2192
-
2193
- **Options**
2194
-
2195
- | Option | Default | Description |
2196
- | ------------ | ------- | ---------------------------------------------- |
2197
- | `--org <id>` | | Target organization (overrides the active org) |
2198
-
2199
- ### `kici orchestrators use`
2200
-
2201
- Set the per-org default orchestrator cluster for run remote
2202
-
2203
- Synopsis: `kici orchestrators use <name> [options]`
2204
-
2205
- **Arguments**
2206
-
2207
- | Argument | Required | Variadic | Description |
2208
- | -------- | -------- | -------- | ------------------------- |
2209
- | `name` | yes | no | Orchestrator cluster name |
2210
-
2211
- **Options**
2212
-
2213
- | Option | Default | Description |
2214
- | ------------ | ------- | ---------------------------------------------- |
2215
- | `--org <id>` | | Target organization (overrides the active org) |
2216
-
2217
- ### `kici org`
2218
-
2219
- Manage organizations
2220
-
2221
- Synopsis: `kici org`
2222
-
2223
- ### `kici org current`
2224
-
2225
- Show current active organization
2226
-
2227
- Synopsis: `kici org current`
2228
-
2229
- ### `kici org list`
2230
-
2231
- List organizations you belong to
2232
-
2233
- Synopsis: `kici org list`
2234
-
2235
- ### `kici org use`
2236
-
2237
- Switch active organization
2238
-
2239
- Synopsis: `kici org use <name>`
2240
-
2241
- **Arguments**
2242
-
2243
- | Argument | Required | Variadic | Description |
2244
- | -------- | -------- | -------- | ----------------------- |
2245
- | `name` | yes | no | Organization name or ID |
2246
-
2247
- ### `kici pat`
2248
-
2249
- Manage personal access tokens
2250
-
2251
- Synopsis: `kici pat`
2252
-
2253
- ### `kici pat create`
2254
-
2255
- Mint a personal access token (use --agent for a coding-agent token)
2256
-
2257
- Synopsis: `kici pat create [options]`
2258
-
2259
- **Options**
2260
-
2261
- | Option | Default | Description |
2262
- | ----------------------- | ------- | ---------------------------------------------- |
2263
- | `--name <name>` | | Token name (defaults to the agent label) |
2264
- | `--agent` | `false` | Mint an agent-kind PAT for the KiCI MCP server |
2265
- | `--expires-in-days <n>` | | Custom expiry in days |
2266
-
2267
- ### `kici secrets`
2268
-
2269
- Manage secrets
2270
-
2271
- Synopsis: `kici secrets`
2272
-
2273
- ### `kici secrets list`
2274
-
2275
- List test-available secret contexts
2276
-
2277
- Synopsis: `kici secrets list`
2278
- <!-- END GENERATED: kici-account-and-org -->
2279
-
2280
- ---
2281
-
2282
- ## kici: authoring & local dev
2283
-
2284
- Source: https://docs.kici.dev/user/cli/authoring-and-local/
2285
-
2286
- ## Guide
2287
-
2288
- ### kici compile
2289
-
2290
- Compile workflows from `.kici/workflows/` to `kici.lock.json`.
2291
-
2292
- ```bash
2293
- kici compile [options]
2294
- ```
2295
-
2296
- **Examples:**
2297
-
2298
- ```bash
2299
- # Compile all workflows
2300
- kici compile
2301
-
2302
- # Validate and type-check (CI-friendly, no file writes)
2303
- kici compile --check
2304
-
2305
- # Watch mode for development
2306
- kici compile --watch
2307
-
2308
- # Custom .kici directory location
2309
- kici compile --kici-dir packages/app/.kici
2310
-
2311
- # Verbose output for debugging
2312
- kici compile --verbose
2313
- ```
2314
-
2315
- **Exit codes:**
2316
-
2317
- | Code | Meaning |
2318
- | ---- | --------------------------- |
2319
- | 0 | Compilation successful |
2320
- | 1 | Compilation failed (errors) |
2321
-
2322
- The `--check` flag is useful in CI pipelines and pre-commit hooks. It validates that workflows are syntactically and semantically correct **and** runs a `tsc --noEmit` type-check over `.kici/workflows/**`, so type-broken workflows are caught at compile time instead of shipping silently. No lock file or other files are written.
2323
-
2324
- The type-check requires `.kici/tsconfig.json` and a `typescript` dependency — both are scaffolded by `kici init`. In a JavaScript-only workspace (`kici init --mjs`, which has no `tsconfig.json`), the type-check is skipped with a notice and validation still runs. When the type-check finds errors, `kici compile --check` prints each one in `file:line:column error [E120]: message` form and exits non-zero.
2325
-
2326
- Compile and validation errors carry the real `file:line:column` of the offending job or step (anchored to the job's first step location), so you can jump straight to the source instead of a generic line 1.
2327
-
2328
- **Auto-type regeneration:** When authenticated (via `kici login`), `kici compile` automatically refreshes `.kici/types/secrets.d.ts` after each successful compilation. This keeps type declarations in sync with your orchestrator's secret contexts. The type regeneration is non-blocking -- if the orchestrator is unreachable, compilation still succeeds with a warning. The `--check` flag skips type regeneration since no files are written.
2329
-
2330
- ### kici preview
2331
-
2332
- Preview which workflows match a trigger event (dry-run, no execution). Useful for verifying trigger configurations during development.
2333
-
2334
- ```bash
2335
- kici preview [event] [options]
2336
- ```
2337
-
2338
- **Examples:**
2339
-
2340
- ```bash
2341
- # Preview which workflows match a push event
2342
- kici preview push
2343
-
2344
- # Preview PR trigger matching
2345
- kici preview pr:open
2346
-
2347
- # Preview with branch override
2348
- kici preview push --branch develop
2349
-
2350
- # Filter to specific workflow
2351
- kici preview push --workflow ci
2352
-
2353
- # Simulate changed files for path-filtered triggers
2354
- kici preview push --files src/index.ts --files README.md
2355
- ```
2356
-
2357
- **Exit codes:**
2358
-
2359
- | Code | Meaning |
2360
- | ---- | ------------------------------------------ |
2361
- | 0 | Preview completed (including zero matches) |
2362
- | 1 | Error |
2363
-
2364
- **Migration from the old `test` command:** The dry-run preview command was renamed from `test` to `preview`. If you were using the old `test` command with a fixture name for remote fixture execution, use `kici run remote <fixture-name>` instead. For local workflow execution, use `kici run <event> --local`.
2365
-
2366
- ### kici local
2367
-
2368
- Manage the **local dev plane** — the warm, per-user orchestrator (plus its own local PostgreSQL) that [`kici run <event> --local`](https://docs.kici.dev/user/cli/runs-and-approvals/#kici-run-event---local) dispatches through. You rarely need these commands directly: a local run boots the plane on demand and reuses it afterwards. Reach for them to inspect the plane, stop it, read its log, or switch it between offline and Platform-connected mode.
2369
-
2370
- ```bash
2371
- kici local up [--offline | --connected] # Start, or reuse an already-running plane
2372
- kici local status [--json] # Port, pid, PostgreSQL backend, attachment mode, readiness
2373
- kici local down # Stop the orchestrator and its PostgreSQL, verifying the port is freed
2374
- kici local logs # Print the orchestrator log file path
2375
- kici local attach # Attach to the Platform (hybrid mode)
2376
- kici local detach # Return the plane to offline (independent) mode
2377
- kici local trust-root <file> # Export the dev-signed trust root for offline verification
2378
- ```
2379
-
2380
- The plane runs in one of two modes:
2381
-
2382
- - **Independent (offline)** — the default for a plane that has never been attached. Identity tokens and attestations are signed by a local dev key under the clearly non-production issuer `kici-local`.
2383
- - **Hybrid (attached)** — `kici local attach` mints an org-scoped key with your logged-in credentials and reboots the plane connected to the Platform, so local runs get real Platform-minted identity and attestation. `kici local up` honors a durable attachment record: an attached plane comes back up hybrid, and falls back to offline with a warning when the Platform is unreachable.
2384
-
2385
- `--offline` forces an independent boot without clearing the attachment record (only `detach` clears it); `--connected` requires an attached, reachable Platform and fails otherwise.
2386
-
2387
- `kici local down` reports success only once the plane port is verified free. If a process still holds it — including a plane left behind by an interrupted boot — the command exits non-zero and names the holder, so a failed teardown is never mistaken for a clean one. A holder that does not identify as a KiCI plane orchestrator is reported and left alone, never stopped.
2388
-
2389
- `kici local status` reports a plane whose process is alive but whose readiness probe fails — for example when its PostgreSQL has stopped — as running but not ready, together with its readiness checks, rather than as not running. When the holder is a KiCI plane orchestrator that this config directory did not start — a plane belonging to another `KICI_CONFIG_DIR`, or one whose record here was lost — status names it as such rather than as not ready, since its readiness is never probed, and points at `kici local down`, which does reclaim it. When the port is held by a process that is not a KiCI plane orchestrator, `kici local status` names that holder instead and points at `KICI_LOCAL_ORCH_PORT`, because `kici local down` will not stop it.
2390
-
2391
- Pass `--json` for machine-readable output. It prints one object and exits 0 for
2392
- every state, including when the plane is stopped — the state is in the payload,
2393
- not the exit code:
2394
-
2395
- ```bash
2396
- $ kici local status --json
2397
- {"state":"ready","running":true,"pid":3768093,"port":4319,
2398
- "url":"http://127.0.0.1:4319","pgKind":"embedded","stampVersion":3,
2399
- "mode":"independent"}
2400
- ```
2401
-
2402
- `state` is one of `stopped`, `ready`, `unready`, `foreign-kici`,
2403
- `foreign-unknown`. The key set is fixed: the plane's admin token is never part
2404
- of it, so the output is safe to log. Every key is always present, but only
2405
- `state`, `running` and `mode` always carry a value — the rest are `null`
2406
- whenever the plane cannot supply them (for `stopped` that is all of them, and
2407
- `stampVersion` is populated only for `ready`), so read them defensively
2408
- (`jq -r '.pid // empty'`).
2409
-
2410
- A local run also fails fast when no agent claims it: if no scaler label set matches the job's `runsOn`, or the agent cannot start, the run gives up within a short acceptance window (2 minutes by default, overridable with `KICI_LOCAL_ACCEPTANCE_TIMEOUT_MS`) and names the plane log instead of waiting out the full no-progress timeout.
2411
-
2412
- **Verifying an offline-signed bundle:** export the plane's trust root, then pass it to the verifier:
2413
-
2414
- ```bash
2415
- kici local trust-root ./local-trust-root.json
2416
- kici verify-attestation ./dist/app.tgz \
2417
- --bundle ./app.tgz.kici.json \
2418
- --trust-root ./local-trust-root.json
2419
- ```
2420
-
2421
- For the plane's on-disk layout, port selection, PostgreSQL backends, and reset behavior, see [Local dev plane](https://docs.kici.dev/operator/orchestrator/local-dev-plane/).
2422
-
2423
- ### kici fixture
2424
-
2425
- Generate a fixture template for an event type. Useful for creating custom test payloads.
2426
-
2427
- ```bash
2428
- kici fixture <event> [options]
2429
- ```
2430
-
2431
- **Valid events:** `pr:open`, `pr:sync`, `pr:close`, `pr:reopen`, `push`, `tag`, `comment`, `review`, `review_comment`, `release`, `dispatch`, `create`, `delete`, `status`, `workflow_run`, `fork`, `star`, `watch`, `kici_event`, `workflow_complete`, `job_complete`, `generic_webhook`, `schedule`, `lifecycle` (many support `:action` suffixes, e.g. `comment:edited`, `release:published`, `lifecycle:workflow_complete`). `webhook:<source>` is a shorthand alias for `generic_webhook:<source>`.
2432
-
2433
- **Examples:**
2434
-
2435
- ```bash
2436
- # Print fixture to stdout
2437
- kici fixture pr:open
2438
-
2439
- # Write fixture to file
2440
- kici fixture pr:open --output fixtures/pr-open.json
2441
-
2442
- # Generate push fixture
2443
- kici fixture push --output fixtures/push.json
2444
- ```
2445
-
2446
- Use generated fixtures as reference when writing test fixture files in `.kici/tests/`:
2447
-
2448
- ```bash
2449
- kici fixture pr:open --output fixtures/pr-open-reference.json
2450
- # Use the generated JSON as reference when writing .kici/tests/pr-open.ts
2451
- ```
2452
-
2453
- ### kici types
2454
-
2455
- Generate TypeScript declaration files from orchestrator environment metadata. The generated `.d.ts` file augments the SDK's `KnownSecretKeys` and `ContextSecrets` interfaces, providing compile-time autocomplete and type checking for secret key names.
2456
-
2457
- ```bash
2458
- kici types [options]
2459
- ```
2460
-
2461
- **Prerequisites:** Must be authenticated via `kici login`.
2462
-
2463
- **Output:** `.kici/types/secrets.d.ts`
2464
-
2465
- **Examples:**
2466
-
2467
- ```bash
2468
- # Generate types from orchestrator
2469
- kici types
2470
-
2471
- # Use custom .kici directory
2472
- kici types --kici-dir packages/app/.kici
2473
- ```
2474
-
2475
- **How it works:**
2476
-
2477
- 1. Fetches all environment metadata (environment names and secret key names) from the orchestrator
2478
- 2. Generates a `.d.ts` file that augments `@kici-dev/sdk`'s `KnownSecretKeys` and `ContextSecrets` interfaces
2479
- 3. Writes the file to `.kici/types/secrets.d.ts`
2480
-
2481
- After generating types, `ctx.secrets.get('MY_KEY')` and `ctx.secrets.expose('DB_HOST')` gain autocomplete and type checking in your IDE.
2482
-
2483
- **Git workflow:** Commit the generated `.kici/types/secrets.d.ts` so team members get type checking without needing orchestrator access. Run `kici types` to refresh when environments change.
2484
-
2485
- **Auto-regeneration:** `kici compile` automatically runs `kici types` after successful compilation when authenticated. See the [kici compile](https://docs.kici.dev/user/cli/authoring-and-local/#kici-compile) section for details.
2486
-
2487
- **Escape hatch:** For dynamic keys not in the generated types, use a cast: `(ctx.secrets as any).DYNAMIC_KEY`.
2488
-
2489
- ### kici workflows list
2490
-
2491
- List permanently registered workflows on the orchestrator.
2492
-
2493
- ```bash
2494
- kici workflows list [options]
2495
- ```
2496
-
2497
- **Examples:**
2498
-
2499
- ```bash
2500
- # List all registered workflows
2501
- kici workflows list
2502
-
2503
- # JSON output for scripting
2504
- kici workflows list --json
2505
-
2506
- # Show workflows not updated in 30 days
2507
- kici workflows list --stale 30d
2508
-
2509
- # Filter by trigger type
2510
- kici workflows list --trigger-type push
2511
-
2512
- # Filter by repository
2513
- kici workflows list --repo my-org/my-repo
2514
- ```
2515
-
2516
- ### kici hook install
2517
-
2518
- Install a pre-commit hook that runs `kici compile` before each commit.
2519
-
2520
- ```bash
2521
- kici hook install [options]
2522
- ```
2523
-
2524
- **Examples:**
2525
-
2526
- ```bash
2527
- # Auto-detect hook tool (husky, lint-staged, etc.)
2528
- kici hook install
2529
-
2530
- # Force raw git hook
2531
- kici hook install --git
2532
- ```
2533
-
2534
- The command auto-detects existing hook tools in your project:
2535
-
2536
- - **Husky**: Adds to `.husky/pre-commit`
2537
- - **lint-staged**: Adds to lint-staged configuration
2538
- - **Raw git**: Writes `.git/hooks/pre-commit`
2539
-
2540
- If multiple tools are detected, you are prompted to choose.
2541
-
2542
- ### kici docs
2543
-
2544
- Open the KiCI documentation site in the default browser. With the `llm` subcommand, print the LLM-friendly documentation bundle that ships with `@kici-dev/compiler` — pipe it into a coding agent's context buffer to brief the agent on authoring conventions without an internet round-trip.
2545
-
2546
- ```bash
2547
- kici docs # open https://kici.dev/docs/
2548
- kici docs --no-open # print the URL instead of opening a browser
2549
- kici docs llm # print the llms.txt index (a router over the task bundles)
2550
- kici docs llm sdk # print the SDK task bundle
2551
- kici docs llm full # print llms-full.txt (every page in one file)
2552
- kici docs llm sdk --out sdk-context.md # write a bundle to a file
2553
- ```
2554
-
2555
- **Examples:**
2556
-
2557
- ```bash
2558
- # Open the docs site in your browser
2559
- kici docs
2560
-
2561
- # Pipe just the SDK bundle into a coding agent (small, task-scoped context)
2562
- kici docs llm sdk | claude -- "Read this and help me author a deploy workflow"
2563
-
2564
- # Save the router index for offline reference
2565
- kici docs llm --out kici-llms-index.txt
2566
- ```
2567
-
2568
- Bundles are regenerated from `docs/` every time `@kici-dev/compiler` is built, so they always match your installed CLI version. The index lists each task bundle — `getting-started`, `sdk`, `sdk-runtime`, `cli`, `patterns`, `features`, `providers`, `architecture` — with its size and a one-line purpose; pass the bundle id as the topic. Every cross-reference link inside a bundle is an absolute `docs.kici.dev` URL. The same files are published online following the [llms.txt convention](https://llmstxt.org/).
2569
-
2570
- ## Reference
2571
-
2572
- <!-- BEGIN GENERATED: kici-authoring-and-local (do not edit; run the doc generator) -->
2573
-
2574
- ### `kici compile`
2575
-
2576
- Compile workflows from .kici/workflows/ to kici.lock.json
2577
-
2578
- Synopsis: `kici compile [options]`
2579
-
2580
- **Options**
2581
-
2582
- | Option | Default | Description |
2583
- | ------------------- | ------- | ---------------------------------------------------------------------------------- |
2584
- | `--check` | `false` | Validate workflows and type-check sources (tsc --noEmit) without writing lock file |
2585
- | `--kici-dir <path>` | `.kici` | Path to .kici directory |
2586
- | `--verbose` | `false` | Detailed output |
2587
- | `--watch` | `false` | Watch for changes and recompile |
2588
-
2589
- ### `kici docs`
2590
-
2591
- Open the KiCI documentation site in the default browser
2592
-
2593
- Synopsis: `kici docs [options]`
2594
-
2595
- **Options**
2596
-
2597
- | Option | Default | Description |
2598
- | ----------- | ------- | ----------------------------------------------- |
2599
- | `--no-open` | | Print the docs URL instead of opening a browser |
2600
-
2601
- ### `kici docs llm`
2602
-
2603
- Print KiCI LLM docs bundles. No topic prints the llms.txt index; <topic> prints a task bundle (e.g. sdk, cli, patterns, features, providers, architecture, getting-started); "full" prints the complete bundle.
2604
-
2605
- Synopsis: `kici docs llm [topic] [options]`
2606
-
2607
- **Arguments**
2608
-
2609
- | Argument | Required | Variadic | Description |
2610
- | -------- | -------- | -------- | ----------- |
2611
- | `topic` | no | no | |
2612
-
2613
- **Options**
2614
-
2615
- | Option | Default | Description |
2616
- | -------------- | ------- | -------------------------------------------- |
2617
- | `--out <path>` | | Write the bundle to a file instead of stdout |
2618
-
2619
- ### `kici fixture`
2620
-
2621
- Generate fixture template for event type
2622
-
2623
- Synopsis: `kici fixture <event> [options]`
2624
-
2625
- **Arguments**
2626
-
2627
- | Argument | Required | Variadic | Description |
2628
- | -------- | -------- | -------- | ------------------------------------------------------------------------------------------ |
2629
- | `event` | yes | no | Event to generate fixture for (e.g., pr:open, push, schedule, lifecycle:workflow_complete) |
2630
-
2631
- **Options**
2632
-
2633
- | Option | Default | Description |
2634
- | ----------------- | ------- | ------------------------------- |
2635
- | `--output <path>` | | Write to file instead of stdout |
2636
-
2637
- ### `kici hook`
2638
-
2639
- Manage pre-commit hooks
2640
-
2641
- Synopsis: `kici hook`
2642
-
2643
- ### `kici hook install`
2644
-
2645
- Install kici compile pre-commit hook
2646
-
2647
- Synopsis: `kici hook install [options]`
2648
-
2649
- **Options**
2650
-
2651
- | Option | Default | Description |
2652
- | ------- | ------- | ---------------------------------------- |
2653
- | `--git` | `false` | Use raw git hook (.git/hooks/pre-commit) |
2654
-
2655
- ### `kici local`
2656
-
2657
- Manage the local dev orchestrator plane
2658
-
2659
- Synopsis: `kici local`
2660
-
2661
- ### `kici local attach`
2662
-
2663
- Attach the local dev plane to the Platform (hybrid)
2664
-
2665
- Synopsis: `kici local attach`
2666
-
2667
- ### `kici local detach`
2668
-
2669
- Detach the local dev plane from the Platform (offline)
2670
-
2671
- Synopsis: `kici local detach`
2672
-
2673
- ### `kici local down`
2674
-
2675
- Stop the local dev plane
2676
-
2677
- Synopsis: `kici local down`
2678
-
2679
- ### `kici local logs`
2680
-
2681
- Print the local dev plane orchestrator log path
2682
-
2683
- Synopsis: `kici local logs`
2684
-
2685
- ### `kici local status`
2686
-
2687
- Show local dev plane status and control commands
2688
-
2689
- Synopsis: `kici local status [options]`
2690
-
2691
- **Options**
2692
-
2693
- | Option | Default | Description |
2694
- | -------- | ------- | ---------------------------------------------------- |
2695
- | `--json` | `false` | Emit machine-readable JSON (exits 0 for every state) |
2696
-
2697
- ### `kici local trust-root`
2698
-
2699
- Export the offline dev-signed identity trust root ({ issuer, jwks }) to a file
2700
-
2701
- Synopsis: `kici local trust-root <file>`
2702
-
2703
- **Arguments**
2704
-
2705
- | Argument | Required | Variadic | Description |
2706
- | -------- | -------- | -------- | ---------------------------------------------------- |
2707
- | `file` | yes | no | Output path for the { issuer, jwks } trust-root JSON |
2708
-
2709
- ### `kici local up`
2710
-
2711
- Start (or reuse) the local dev plane
2712
-
2713
- Synopsis: `kici local up [options]`
2714
-
2715
- **Options**
2716
-
2717
- | Option | Default | Description |
2718
- | ------------- | ------- | ---------------------------------------------------------------------------- |
2719
- | `--offline` | `false` | Force the independent (offline) plane (does not clear the attachment record) |
2720
- | `--connected` | `false` | Force the connected/hybrid plane (requires an attached, reachable Platform) |
2721
-
2722
- ### `kici preview`
2723
-
2724
- Preview which workflows match a trigger event (no execution)
2725
-
2726
- Synopsis: `kici preview [event] [options]`
2727
-
2728
- **Arguments**
2729
-
2730
- | Argument | Required | Variadic | Description |
2731
- | -------- | -------- | -------- | ----------------------------------------------------- |
2732
- | `event` | no | no | Event type to preview (e.g., push, pr:open, schedule) |
2733
-
2734
- **Options**
2735
-
2736
- | Option | Default | Description |
2737
- | --------------------------- | ------- | ------------------------------------------------------------ |
2738
- | `--branch <name>` | | Override target branch for trigger matching (default: main) |
2739
- | `--sha <hash>` | | Override commit SHA |
2740
- | `--workflow <name>` | | Filter to specific workflow in display |
2741
- | `--job <name>` | | Filter to specific job in display |
2742
- | `--debug` | `false` | Verbose internals |
2743
- | `--kici-dir <path>` | `.kici` | Path to .kici directory |
2744
- | `--files <path>` | | Simulate changed file path for trigger matching (repeatable) |
2745
- | `--secret <key=value>` | | Inject flat secret (repeatable) |
2746
- | `--context <ctx.key=value>` | | Inject context secret (repeatable) |
2747
-
2748
- ### `kici types`
2749
-
2750
- Generate TypeScript declarations for secret contexts
2751
-
2752
- Synopsis: `kici types [options]`
2753
-
2754
- **Options**
2755
-
2756
- | Option | Default | Description |
2757
- | ------------------- | ------- | ----------------------- |
2758
- | `--kici-dir <path>` | `.kici` | Path to .kici directory |
2759
-
2760
- ### `kici workflows`
2761
-
2762
- Manage workflow registrations
2763
-
2764
- Synopsis: `kici workflows`
2765
-
2766
- ### `kici workflows list`
2767
-
2768
- List permanently registered workflows
2769
-
2770
- Synopsis: `kici workflows list [options]`
2771
-
2772
- **Options**
2773
-
2774
- | Option | Default | Description |
2775
- | ----------------------- | ------- | ------------------------------------------ |
2776
- | `--json` | `false` | Output as JSON |
2777
- | `--stale <duration>` | | Filter stale registrations (e.g., 30d, 7d) |
2778
- | `--trigger-type <type>` | | Filter by trigger type |
2779
- | `--repo <repo>` | | Filter by repository |
2780
-
2781
- <!-- END GENERATED: kici-authoring-and-local -->
2782
-
2783
- ---
2784
-
2785
- ## kici: notifications & diagnostics
2786
-
2787
- Source: https://docs.kici.dev/user/cli/notifications-and-diagnostics/
2788
-
2789
- ## Guide
2790
-
2791
- ### kici notifications
2792
-
2793
- Manage your organization's notification configuration — channels, subscriptions, and the Slack-identity roster — programmatically, under your PAT against the hosted Platform's org-scoped API. Requires a PAT (run `kici login` first) and an active org (`kici org use <name>`, or pass `--org <id>` to any subcommand). These are the same operations the dashboard Notifications tab performs.
2794
-
2795
- Every `list` supports `--json` for machine-readable output.
2796
-
2797
- #### kici notifications channels
2798
-
2799
- Manage the destinations a notification is delivered to (Slack or email).
2800
-
2801
- ```bash
2802
- # List channels
2803
- kici notifications channels list
2804
- kici notifications channels list --json
2805
-
2806
- # Add a Slack channel
2807
- kici notifications channels add --type slack --name "alerts" \
2808
- --connection <connectionId> --slack-channel <slackChannelId>
2809
-
2810
- # Add an email channel
2811
- kici notifications channels add --type email --name "email" \
2812
- --from-name "KiCI CI" --reply-to ci@example.com
2813
-
2814
- # Remove a channel
2815
- kici notifications channels remove <channelId>
2816
- ```
2817
-
2818
- #### kici notifications subscriptions
2819
-
2820
- Manage which runs notify which channel, with optional literal `--mentions` and digest accumulation.
2821
-
2822
- ```bash
2823
- # List subscriptions
2824
- kici notifications subscriptions list
2825
-
2826
- # Notify a channel on any failure across the org
2827
- kici notifications subscriptions add --channel <channelId> --on-status failed
2828
-
2829
- # Scope to a repo, mention people, and accumulate a digest over 30s
2830
- kici notifications subscriptions add --channel <channelId> \
2831
- --on-status failed --repo-glob 'my-org/*' \
2832
- --mentions U012ABCDEF,U345GHIJKL --accumulate-for 30000
2833
-
2834
- # Remove a subscription
2835
- kici notifications subscriptions remove <subscriptionId>
2836
- ```
2837
-
2838
- Key options for `add`: `--level <run|job>` (default `run`), `--scope <org|team|user|actor>` (default `org`; `--scope-id` is required for `team`/`user`), `--on-status <csv>` (required), `--repo-glob` / `--workflow-glob` / `--job-glob`, `--mentions <csv>`, `--recipient-override <csv>`, `--on-failure-class <csv>`, `--accumulate-for <ms>`.
2839
-
2840
- #### kici notifications roster
2841
-
2842
- Manage the Slack-identity roster used for best-effort actor tagging — mapping the person who triggered a run to a Slack member id.
2843
-
2844
- `roster add` requires the `notifications:admin` permission — it is the admin editor for the shared roster. To connect **your own** Slack account (no admin needed), use **Connect Slack** on the dashboard's personal Notifications tab, which runs Sign in with Slack; there is no CLI equivalent because the flow is browser-based.
2845
-
2846
- ```bash
2847
- # List roster entries
2848
- kici notifications roster list
2849
-
2850
- # Admin: map a contributor to their Slack member id (by id, email, or @handle)
2851
- kici notifications roster add --connection <connectionId> \
2852
- --subject-kind git_login --subject octocat \
2853
- --input-form email --value octocat@example.com
2854
-
2855
- # Remove a roster entry (admins; or your own connected entry)
2856
- kici notifications roster remove <entryId>
2857
- ```
2858
-
2859
- ### kici verify-attestation
2860
-
2861
- Verify a KiCI build-provenance attestation bundle offline. A bundle is the signed package a workflow step produces via `ctx.attestProvenance(...)`: a DSSE-wrapped SLSA in-toto statement, the ephemeral public key that signed it, and the KiCI identity token that anchors the build context. For the end-to-end attest → verify → view journey, see the [build provenance guide](https://docs.kici.dev/user/provenance/). Verification establishes the full chain — the identity token verifies against the trusted issuer's JWKS, the DSSE signature verifies against the bundled key, and the statement's build context must match the token's claims (a mismatch is a hard failure). When an `[artifact]` is given, its SHA-256 digest is also matched against the attestation subject.
2862
-
2863
- On success the output prints the **origin org** (the customer's public org id — the authoritative "who built this" the platform vouches for) and a **source marker**. A `kici run remote` attestation is flagged unmistakably: its `repository`/`ref`/`sha` are caller-supplied from a local working-tree overlay, not a triggered VCS commit, so a verifier must treat those coordinates as org-asserted rather than VCS-verified. A normal triggered run carries the ordinary `triggered` source marker. See the [build provenance guide](https://docs.kici.dev/user/provenance/) for the full trust model.
2864
-
2865
- ```bash
2866
- kici verify-attestation [artifact] --bundle <path-or-url> [--trust-root <url-or-file>] [options]
2867
- ```
2868
-
2869
- **Trust root:** `--trust-root` defaults to your **configured orchestrator** — the orchestrator you `kici login` against, which owns the provenance signing key and publishes its own JWKS (see [Which trust root do I use?](https://docs.kici.dev/user/provenance/#which-trust-root-do-i-use)), so the common case needs no flag. When no orchestrator is configured, the default falls back to the hosted KiCI platform's provenance issuer so historical platform-signed bundles still verify. The verifier never trusts the issuer named inside the token; supplying it out-of-band is what prevents a forged bundle from self-attesting. To override the default, pass `--trust-root` in one of two forms:
2870
-
2871
- - **Online — an HTTPS issuer URL.** The verifier fetches `<url>/.well-known/openid-configuration`, reads its `issuer` and `jwks_uri`, and fetches the JWKS. The token's `iss` is pinned to the discovery document's `issuer`.
2872
- - **Offline — a self-contained trust-root file.** A local JSON file with the issuer and JWKS inlined, so no network access is needed (air-gapped verification):
2873
-
2874
- ```json
2875
- {
2876
- "issuer": "https://platform.example/issuer",
2877
- "jwks": {
2878
- "keys": [
2879
- { "kty": "EC", "crv": "P-256", "x": "...", "y": "...", "alg": "ES256", "kid": "..." }
2880
- ]
2881
- }
2882
- }
2883
- ```
2884
-
2885
- **Examples:**
2886
-
2887
- ```bash
2888
- # Default: verify against your configured orchestrator (no --trust-root needed)
2889
- kici verify-attestation ./dist/app.tgz --bundle ./app.tgz.kici.json
2890
-
2891
- # Override: verify a bundle against a specific issuer, digest-checking the artifact
2892
- kici verify-attestation ./dist/app.tgz \
2893
- --bundle ./app.tgz.kici.json \
2894
- --trust-root https://platform.example/issuer
2895
-
2896
- # Offline / air-gapped: verify against a self-contained trust-root file
2897
- kici verify-attestation ./dist/app.tgz \
2898
- --bundle ./app.tgz.kici.json \
2899
- --trust-root ./kici-trust-root.json
2900
-
2901
- # Machine-readable result for scripting
2902
- kici verify-attestation --bundle ./app.tgz.kici.json \
2903
- --trust-root https://platform.example/issuer --json
2904
- ```
2905
-
2906
- **Attestation origin marker.** On a PASS, the command surfaces when the identity
2907
- token was minted relative to the build. A normal attestation prints no marker
2908
- (the token was minted live). A **deferred** attestation prints an `ATTESTATION:
2909
- deferred` line — the build facts were sealed at build time and the token was
2910
- minted later, after a transient platform outage, bound to the frozen statement
2911
- by its hash. An **offline-backfill** attestation prints an `ATTESTATION:
2912
- offline-backfill` line — the run was ingested while the platform was down, so its
2913
- run/job rows were backfilled before the token was minted. Both still verify
2914
- (PASS); the marker discloses the temporal gap, and the organization id remains
2915
- the authoritative anchor.
2916
-
2917
- **Exit codes:**
2918
-
2919
- | Code | Meaning |
2920
- | ---- | ----------------------------------------------------------------------------------------- |
2921
- | 0 | Verified — signature, identity, build context (and digest, if checked) all pass |
2922
- | 1 | Not verified, or an error (missing `--bundle`, unreadable bundle, unreachable trust root) |
2923
-
2924
- ### kici diagnostics
2925
-
2926
- Show the orchestrators, scalers, and agents serving your organization — the
2927
- terminal equivalent of the dashboard Infrastructure page. Reads the same
2928
- org-scoped data the dashboard does, so it needs `kici login` and an active org
2929
- (`kici org use <name>`).
2930
-
2931
- The output has three parts: a one-line header (runs in the last 24h, success
2932
- rate, average duration, queued/running job counts), any infrastructure alerts
2933
- (only shown when present), and a tree of each orchestrator with its scalers and
2934
- agents. Each agent line shows its labels, platform/architecture, active/maximum
2935
- concurrency, and heartbeat age.
2936
-
2937
- Alert lines are colored by severity — yellow for `warning`, red for `critical`.
2938
- A severity this build does not recognize is colored red, so an alert from a
2939
- newer Platform is never shown as less urgent than it might be.
2940
-
2941
- ```bash
2942
- kici diagnostics [options]
2943
- ```
2944
-
2945
- **Examples:**
2946
-
2947
- ```bash
2948
- # Show the full infrastructure tree
2949
- kici diagnostics
2950
-
2951
- # Extended per-agent detail
2952
- kici diagnostics --verbose
2953
-
2954
- # Only one orchestrator's scalers and agents
2955
- kici diagnostics --orchestrator conn-abc123
2956
-
2957
- # Machine-readable output
2958
- kici diagnostics --json
2959
- ```
2960
-
2961
- ### kici doctor
2962
-
2963
- Walk your KiCI setup end to end and print the exact next command for each
2964
- problem found. Where `kici diagnostics` shows the org's infrastructure, `kici
2965
- doctor` checks **your own setup**: it runs six checks in onboarding order —
2966
- login (stored, unexpired credentials), active organization, a live token probe
2967
- against the platform, a connected orchestrator for the org, a present, fresh,
2968
- and committed lock file, and whether every workflow's `runsOn` labels are
2969
- satisfiable by a connected agent or scaler. Each check reports pass/warn/fail
2970
- with the fix command (e.g. `kici login`, `kici org use <name>`,
2971
- `kici compile`), so the first failing row tells you exactly what to run next.
2972
-
2973
- ```bash
2974
- kici doctor [options]
2975
- ```
2976
-
2977
- **Examples:**
2978
-
2979
- ```bash
2980
- # Diagnose the full setup
2981
- kici doctor
2982
-
2983
- # Machine-readable result for scripting
2984
- kici doctor --json
2985
- ```
2986
-
2987
- The command exits `0` when every check passes, `1` when any check warns, and
2988
- `2` when any check fails, so it also works as a CI preflight.
2989
-
2990
- ## Reference
2991
-
2992
- <!-- BEGIN GENERATED: kici-notifications-and-diagnostics (do not edit; run the doc generator) -->
2993
-
2994
- ### `kici diagnostics`
2995
-
2996
- Show orchestrators, scalers, and agents (mirrors the dashboard Infrastructure page)
2997
-
2998
- Synopsis: `kici diagnostics [options]`
2999
-
3000
- **Options**
3001
-
3002
- | Option | Default | Description |
3003
- | --------------------- | ------- | ----------------------------------- |
3004
- | `--json` | `false` | Output raw JSON |
3005
- | `--verbose` | `false` | Show extended per-agent fields |
3006
- | `--orchestrator <id>` | | Scope the tree to one connection id |
3007
-
3008
- ### `kici doctor`
3009
-
3010
- Diagnose your KiCI setup and print the exact next command for each problem
3011
-
3012
- Synopsis: `kici doctor [options]`
3013
-
3014
- **Options**
3015
-
3016
- | Option | Default | Description |
3017
- | ------------------- | ------- | ---------------------------------- |
3018
- | `--json` | `false` | Output raw JSON instead of a table |
3019
- | `--kici-dir <path>` | `.kici` | Path to the .kici directory |
3020
-
3021
- ### `kici notifications`
3022
-
3023
- Manage the org's notification channels, subscriptions, and Slack roster
3024
-
3025
- Synopsis: `kici notifications`
3026
-
3027
- ### `kici notifications channels`
3028
-
3029
- Manage notification channels (Slack / email)
3030
-
3031
- Synopsis: `kici notifications channels`
3032
-
3033
- ### `kici notifications channels add`
3034
-
3035
- Add a notification channel
3036
-
3037
- Synopsis: `kici notifications channels add [options]`
3038
-
3039
- **Options**
3040
-
3041
- | Option | Default | Description |
3042
- | ---------------------- | ------- | ---------------------------------------------- |
3043
- | `--type <slack | email>` | | Channel transport type |
3044
- | `--name <name>` | | Channel display name |
3045
- | `--connection <id>` | | Slack connection id (slack channels) |
3046
- | `--slack-channel <id>` | | Slack channel id (slack channels) |
3047
- | `--from-name <name>` | | Sender name (email channels) |
3048
- | `--reply-to <email>` | | Reply-to address (email channels) |
3049
- | `--org <id>` | | Target organization (overrides the active org) |
3050
-
3051
- ### `kici notifications channels list`
3052
-
3053
- List notification channels
3054
-
3055
- Synopsis: `kici notifications channels list [options]`
3056
-
3057
- **Options**
3058
-
3059
- | Option | Default | Description |
3060
- | ------------ | ------- | ---------------------------------------------- |
3061
- | `--org <id>` | | Target organization (overrides the active org) |
3062
- | `--json` | | Output as JSON |
3063
-
3064
- ### `kici notifications channels remove`
3065
-
3066
- Remove a notification channel
3067
-
3068
- Synopsis: `kici notifications channels remove <id> [options]`
3069
-
3070
- **Arguments**
3071
-
3072
- | Argument | Required | Variadic | Description |
3073
- | -------- | -------- | -------- | ----------- |
3074
- | `id` | yes | no | Channel id |
3075
-
3076
- **Options**
3077
-
3078
- | Option | Default | Description |
3079
- | ------------ | ------- | ---------------------------------------------- |
3080
- | `--org <id>` | | Target organization (overrides the active org) |
3081
-
3082
- ### `kici notifications roster`
3083
-
3084
- Manage the Layer 1 Slack-identity roster (actor tagging)
3085
-
3086
- Synopsis: `kici notifications roster`
3087
-
3088
- ### `kici notifications roster add`
3089
-
3090
- Add a Slack-identity roster entry
3091
-
3092
- Synopsis: `kici notifications roster add [options]`
3093
-
3094
- **Options**
3095
-
3096
- | Option | Default | Description |
3097
- | -------------------------------- | --------- | ---------------------------------------------- |
3098
- | `--connection <id>` | | Slack connection id |
3099
- | `--subject-kind <kici_user | git_login | email>` | | What the subject keys on |
3100
- | `--subject <value>` | | The KiCI user sub, git login, or email |
3101
- | `--value <slackIdEmailOrHandle>` | | Slack member id, email, or @handle |
3102
- | `--input-form <id | username | email>` | `id` | How --value should be resolved |
3103
- | `--org <id>` | | Target organization (overrides the active org) |
3104
-
3105
- ### `kici notifications roster list`
3106
-
3107
- List Slack-identity roster entries
3108
-
3109
- Synopsis: `kici notifications roster list [options]`
3110
-
3111
- **Options**
3112
-
3113
- | Option | Default | Description |
3114
- | ------------ | ------- | ---------------------------------------------- |
3115
- | `--org <id>` | | Target organization (overrides the active org) |
3116
- | `--json` | | Output as JSON |
3117
-
3118
- ### `kici notifications roster remove`
3119
-
3120
- Remove a Slack-identity roster entry
3121
-
3122
- Synopsis: `kici notifications roster remove <id> [options]`
3123
-
3124
- **Arguments**
3125
-
3126
- | Argument | Required | Variadic | Description |
3127
- | -------- | -------- | -------- | --------------- |
3128
- | `id` | yes | no | Roster entry id |
3129
-
3130
- **Options**
3131
-
3132
- | Option | Default | Description |
3133
- | ------------ | ------- | ---------------------------------------------- |
3134
- | `--org <id>` | | Target organization (overrides the active org) |
3135
-
3136
- ### `kici notifications subscriptions`
3137
-
3138
- Manage notification subscriptions
3139
-
3140
- Synopsis: `kici notifications subscriptions`
3141
-
3142
- ### `kici notifications subscriptions add`
3143
-
3144
- Add a notification subscription
3145
-
3146
- Synopsis: `kici notifications subscriptions add [options]`
3147
-
3148
- **Options**
3149
-
3150
- | Option | Default | Description |
3151
- | ---------------------------- | ------- | --------------------------------------------------- |
3152
- | `--channel <id>` | | Target channel id |
3153
- | `--on-status <csv>` | | Statuses to notify on (e.g. failed,success) |
3154
- | `--level <run | job>` | `run` | Subscription granularity |
3155
- | `--scope <org | team | user | actor>` | `org` | Subscription scope |
3156
- | `--scope-id <id>` | | Scope id (required for team/user scope) |
3157
- | `--repo-glob <glob>` | | Match runs whose repo matches this glob |
3158
- | `--workflow-glob <glob>` | | Match runs whose workflow matches this glob |
3159
- | `--job-glob <glob>` | | Match jobs matching this glob (job level) |
3160
- | `--mentions <csv>` | | Literal Slack member/group ids or emails to mention |
3161
- | `--recipient-override <csv>` | | Override the email recipient set |
3162
- | `--on-failure-class <csv>` | | Only match these failure classes |
3163
- | `--accumulate-for <ms>` | | Digest accumulation window in milliseconds |
3164
- | `--org <id>` | | Target organization (overrides the active org) |
3165
-
3166
- ### `kici notifications subscriptions list`
3167
-
3168
- List notification subscriptions
3169
-
3170
- Synopsis: `kici notifications subscriptions list [options]`
3171
-
3172
- **Options**
3173
-
3174
- | Option | Default | Description |
3175
- | ------------ | ------- | ---------------------------------------------- |
3176
- | `--org <id>` | | Target organization (overrides the active org) |
3177
- | `--json` | | Output as JSON |
3178
-
3179
- ### `kici notifications subscriptions remove`
3180
-
3181
- Remove a notification subscription
3182
-
3183
- Synopsis: `kici notifications subscriptions remove <id> [options]`
3184
-
3185
- **Arguments**
3186
-
3187
- | Argument | Required | Variadic | Description |
3188
- | -------- | -------- | -------- | --------------- |
3189
- | `id` | yes | no | Subscription id |
3190
-
3191
- **Options**
3192
-
3193
- | Option | Default | Description |
3194
- | ------------ | ------- | ---------------------------------------------- |
3195
- | `--org <id>` | | Target organization (overrides the active org) |
3196
-
3197
- ### `kici verify-attestation`
3198
-
3199
- Verify a KiCI provenance attestation bundle offline
3200
-
3201
- Synopsis: `kici verify-attestation [artifact] [options]`
3202
-
3203
- **Arguments**
3204
-
3205
- | Argument | Required | Variadic | Description |
3206
- | ---------- | -------- | -------- | ------------------------------------------------------------------------ |
3207
- | `artifact` | no | no | Artifact path to digest-check against the attestation subject (optional) |
3208
-
3209
- **Options**
3210
-
3211
- | Option | Default | Description |
3212
- | ---------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------ |
3213
- | `--bundle <path>` | | Path or URL to the attestation bundle JSON |
3214
- | `--trust-root <url-or-file>` | | Trusted issuer URL, or a self-contained { issuer, jwks } file (default: your configured orchestrator, else the hosted KiCI platform) |
3215
- | `--audience <aud>` | | Expected token audience |
3216
- | `--json` | `false` | Output structured JSON result |
3217
-
3218
- <!-- END GENERATED: kici-notifications-and-diagnostics -->
3219
-
3220
- ---
3221
-
3222
- ## kici: runs & approvals
3223
-
3224
- Source: https://docs.kici.dev/user/cli/runs-and-approvals/
3225
-
3226
- ## Guide
3227
-
3228
- ### kici run
3229
-
3230
- Execute workflows locally or remotely. A bare `kici run [event]` performs a real routed run with this machine as the ephemeral agent; the `remote` subcommand runs fixtures through an orchestrator.
3231
-
3232
- #### kici run <event> --local
3233
-
3234
- Run a workflow on this machine as a real routed dispatch. `kici run <event> --local` compiles your workflows, matches triggers against the specified event, expands matrices, and executes the matched jobs — this machine joins as an ephemeral agent through the warm local dev plane. No orchestrator deployment is required.
3235
-
3236
- `kici run local` (the old direct-execution subcommand) is retired: every run is now a real routed dispatch. Invoking `kici run local <event>` prints a hint pointing at `kici run <event> --local` and exits without running.
3237
-
3238
- ```bash
3239
- kici run [event] --local [options]
3240
- ```
3241
-
3242
- **Concurrency enforcement:**
3243
-
3244
- A local run is a real routed dispatch, so a workflow's `concurrency` block is enforced by the local dev plane's own orchestrator — the same machinery a deployed orchestrator uses:
3245
-
3246
- - The `group` callback is evaluated agent-side against the simulated event (the same `{ branch, event }` context the agent sees), and the resulting key is reported back to the plane's orchestrator before steps execute.
3247
- - `cancelInProgress: true` supersedes the older run in the group; `false` queues the newer run behind it.
3248
-
3249
- Coordination is scoped to that plane, whose state lives under `~/.kici/local/` — so enforcement is per-machine and per-user, and running the same workflow on two different machines does not serialize across them. That requires a deployed orchestrator.
3250
-
3251
- **Execution isolation:**
3252
-
3253
- By default, `kici run <event> --local` executes steps inside an **isolated tmp checkout** rather than against your real working directory. Any file a step writes, builds, or deletes — and any `git` mutation a step performs — lands in that throwaway copy, so casual local runs never touch your tree.
3254
-
3255
- What gets materialized into the isolated checkout has full parity with what `kici run remote` reconstructs: your current working tree minus gitignored files, with `.kiciignore` applied to local changes, over a real `.git` directory. Concretely, the checkout is built from a clone pinned to your current `HEAD`, with your local overlay (modified, staged, and untracked-but-not-ignored files) copied on top and locally-deleted files removed. Workflows that read git metadata work because the `.git` directory is present and pinned to your `HEAD`.
3256
-
3257
- The checkout is a fresh temp directory named `kici-local-run-<random>` under the system temp directory (for example, `/tmp/kici-local-run-ab12cd`).
3258
-
3259
- Cleanup policy:
3260
-
3261
- - The isolated checkout is removed when the run finishes, whether it succeeded or failed.
3262
- - A hard process death (SIGKILL, OOM kill) skips that cleanup. Leftovers older than a day are swept by the agent's own startup garbage collection, which every `kici run <event> --local` invocation triggers.
3263
-
3264
- Set the `KICI_TMPDIR` environment variable to place the isolated checkout (and every other KiCI-created temp directory) under a base directory other than the system temp directory.
3265
-
3266
- Secrets are always sourced from your real `.kici/` directory, not from the isolated checkout. Gitignored secret files (such as `.kici/.env.local` and `.kici/secrets.yaml`) are never copied into the checkout, so a step that reads a secret still gets it from the original location.
3267
-
3268
- Pass `--in-place` to run against the real working directory instead — useful when you explicitly want in-tree execution. `--in-place` requires no git repository; the default isolated mode does, and fails with an actionable error pointing at `--in-place` when the directory is not a git repository.
3269
-
3270
- **Examples:**
3271
-
3272
- ```bash
3273
- # Run workflows matching a push event on this machine
3274
- kici run push --local
3275
-
3276
- # Run a pull-request-open workflow locally
3277
- kici run pr:open --local
3278
-
3279
- # Reuse the working tree instead of an isolated clone
3280
- kici run push --local --in-place
3281
-
3282
- # Force the throwaway/offline plane
3283
- kici run push --local --offline
3284
-
3285
- # Environment variable overrides
3286
- kici run push --local --env NODE_ENV=test --env CI=true
3287
-
3288
- # Quiet mode (summary only, no streaming)
3289
- kici run push --local --quiet
3290
- ```
3291
-
3292
- **Exit codes:**
3293
-
3294
- | Code | Meaning |
3295
- | ---- | ----------------------- |
3296
- | 0 | All workflows succeeded |
3297
- | 1 | One or more jobs failed |
3298
-
3299
- #### kici run remote
3300
-
3301
- Execute fixtures remotely through the full CI pipeline. Fixtures are defined in `.kici/tests/*.ts` using the `fixture()` factory function. Without arguments, lists available fixtures.
3302
-
3303
- Remote runs route through the Platform. Authenticate with a personal access token (`kici login`), then target an organization with `kici org use <org>` or the `--org` flag. The Platform relays the run to the org's orchestrator, while your working-tree overlay uploads directly to object storage — see [How the run is routed](https://docs.kici.dev/user/cli/runs-and-approvals/#how-the-run-is-routed) and [The two planes](https://docs.kici.dev/user/cli/runs-and-approvals/#the-two-planes) below.
3304
-
3305
- Like `kici run <event> --local`, `kici run remote` recompiles your workflows (`.kici/workflows` → `kici.lock.json`) before dispatching, so the orchestrator matches and dispatches against your current workflow definitions — a brand-new or edited workflow takes effect without a separate `kici compile`. A compile or validation error aborts the run before anything is uploaded.
3306
-
3307
- The orchestrator must have **cache storage configured** (`KICI_STORAGE_TYPE` = `s3` or `filesystem`) with a dev-reachable upload endpoint so the CLI's direct upload succeeds; see the [testing guide](https://docs.kici.dev/user/testing-guide/) and [Storage layout](https://docs.kici.dev/operator/orchestrator/storage-layout/) for setup.
3308
-
3309
- ```bash
3310
- kici run remote [fixture] [options]
3311
- ```
3312
-
3313
- `--approve-all` works in `--json` / `--quiet` mode: the run still auto-approves each gate it holds on, and the auto-approve diagnostics are written to stderr so stdout stays a pure JSON (or summary-only) payload. Without `--approve-all`, a `--json` / `--quiet` run that hits a gate stays held and prints a one-line "run held; approve via the dashboard or `kici approve <run-id>`" notice to stderr per hold.
3314
-
3315
- **Examples:**
3316
-
3317
- ```bash
3318
- # List available fixtures
3319
- kici run remote
3320
-
3321
- # Run a single fixture against the active org
3322
- kici run remote push-main
3323
-
3324
- # Target a specific org for this run
3325
- kici run remote push-main --org xyz789ghi012
3326
-
3327
- # Target a specific orchestrator cluster within the org
3328
- kici run remote push-main --orchestrator us-east
3329
-
3330
- # Run all push-related fixtures
3331
- kici run remote 'push-*'
3332
-
3333
- # Run everything
3334
- kici run remote --all
3335
-
3336
- # Run a specific workflow directly (bypass trigger matching)
3337
- kici run remote --workflow ci
3338
-
3339
- # Quiet mode -- just pass/fail
3340
- kici run remote push-main --quiet
3341
-
3342
- # JSON output for scripting
3343
- kici run remote push-main --json
3344
-
3345
- # Fire and forget
3346
- kici run remote push-main --no-wait
3347
-
3348
- # View recent test run history
3349
- kici run remote --history
3350
-
3351
- # Interactively pick which fixtures to run (multi-select)
3352
- kici run remote --pick
3353
-
3354
- # Narrow runsOnAll jobs to a subset of the host roster
3355
- kici run remote deploy --target role:web
3356
-
3357
- # AND-combine repeated --target values (hosts must match every selector)
3358
- kici run remote deploy --target role:web --target dc:eu
3359
-
3360
- # Skip a runsOnAll job instead of failing it when the target matches no host
3361
- kici run remote deploy --target role:gpu --target-allow-empty
3362
- ```
3363
-
3364
- **Interactive fixture selection (`--pick` / `-p`):**
3365
-
3366
- Pass `--pick` (or `-p`) to open an interactive checkbox menu of the available
3367
- fixtures. Toggle one or more with space, confirm with enter, and the selected
3368
- fixtures run through the normal remote pipeline (honoring `--parallel`,
3369
- `--no-wait`, and the other run flags). Notes:
3370
-
3371
- - `--pick` is mutually exclusive with a fixture argument, `--all`, and
3372
- `--workflow`. Passing any together exits with code 2.
3373
- - When `stdin` is not a TTY, `--pick` prints the available fixtures and exits
3374
- without running anything — pass a fixture name (or `--all`) in scripts.
3375
-
3376
- #### Host narrowing with `--target`
3377
-
3378
- `--target <selector>` is a runtime narrowing for `runsOnAll` jobs, analogous to
3379
- Ansible's `--limit`. A `runsOnAll` job normally fans out to **every** roster host
3380
- matching its predicate, one pinned execution per host. `--target` intersects that
3381
- matched roster with a label selector, so the effective host set is
3382
- `runsOnAll ∩ target`:
3383
-
3384
- - **Narrow-only.** `--target` can only _remove_ hosts from the matched set, never
3385
- add them. The widening dimension (OR across host groups) lives in the workflow's
3386
- `runsOnAll`; `--target` only subtracts.
3387
- - **Run-global, `runsOnAll`-only.** A single `--target` applies to every
3388
- `runsOnAll` job in the run. Jobs pinned to a single host with `runsOn` are
3389
- untouched.
3390
- - **Repeatable and AND-combined.** Each `--target` value is its own selector; a
3391
- host must satisfy **all** of them to survive the narrowing. Use a single value
3392
- for an OR-style match within one selector and repeated values for AND.
3393
- - **Selector syntax** matches `runsOn`: an exact label (`role:web`), a glob
3394
- (`role:*`), or a regex (`/^box-0[1-3]$/`).
3395
-
3396
- When `--target` narrows a `runsOnAll` job to zero hosts, the default is to **fail**
3397
- the run (fail-loud — a typo in the selector shouldn't silently skip work). Pass
3398
- `--target-allow-empty` to **skip** the zeroed job instead; the job records a
3399
- `skipped` status, and any downstream job that needs it with `when: 'on-skip'` (or
3400
- `when: 'always'`) still runs. See [Job dependencies](https://docs.kici.dev/user/sdk/core/#job-dependencies-needs)
3401
- for the `when` gating model.
3402
-
3403
- **Exit codes:**
3404
-
3405
- | Code | Meaning |
3406
- | ---- | ---------------------------- |
3407
- | 0 | All matched workflows passed |
3408
- | 1 | One or more workflows failed |
3409
-
3410
- #### How the run is routed
3411
-
3412
- A remote run is dispatched to your **active organization** — the one set with `kici org use <org>`, or overridden per-run with `--org <id>`. The org is resolved in this order:
3413
-
3414
- 1. The `--org <id>` flag, if provided.
3415
- 2. Otherwise the active org saved in your global config by `kici org use <org>`.
3416
- 3. If neither is set, the command errors and asks you to select an org with `kici org use` or pass `--org`.
3417
-
3418
- The orchestrator anchors the org without any manual webhook source: it auto-provisions a system-managed **remote source** (routing key `remote:<orgId>`) that maps to its bound organization, so even a zero-source org is immediately routable for remote runs. You never set a routing key for a remote run — selecting the org is enough.
3419
-
3420
- When an org has more than one connected orchestrator cluster, the CLI picks the target cluster in this order:
3421
-
3422
- 1. The `--orchestrator <name>` flag, if provided.
3423
- 2. Otherwise the per-org default cluster, set with `kici orchestrators use <name>`.
3424
- 3. If the org has exactly **one** connected orchestrator, it is auto-selected.
3425
- 4. Otherwise the run errors with the list of connected clusters, and you pass `--orchestrator <name>` to choose one. Run `kici orchestrators list` to see the available cluster names.
3426
-
3427
- #### The two planes
3428
-
3429
- `kici run remote` uses two independent paths:
3430
-
3431
- - **Control plane** — run initiation, trigger, status, log retrieval, and cancellation flow from your machine through the Platform, which relays them over a WebSocket connection to the org's orchestrator. Logs are delivered by the CLI polling the Platform for log chunks (tracked by a monotonic line cursor) and run status until the run reaches a terminal state; there is no direct streaming socket to the orchestrator.
3432
- - **Data plane** — your working-tree overlay tarball uploads **directly** from your machine to the orchestrator's object store via a presigned PUT URL. The overlay never passes through the Platform. This is why the orchestrator's object-store upload endpoint must be reachable from your machine; see [Storage layout](https://docs.kici.dev/operator/orchestrator/storage-layout/).
3433
-
3434
- An orchestrator with no Platform connection cannot serve remote runs — the Platform is the service that offers them. For executing workflow steps on your own machine without an orchestrator (no scaler, agents, or environments), use [`kici run <event> --local`](https://docs.kici.dev/user/cli/runs-and-approvals/#kici-run-event---local).
3435
-
3436
- #### Fresh repos (no GitHub remote)
1363
+ `state` is one of `stopped`, `ready`, `unready`, `foreign-kici`,
1364
+ `foreign-unknown`. The key set is fixed: the plane's admin token is never part
1365
+ of it, so the output is safe to log. Every key is always present, but only
1366
+ `state`, `running` and `mode` always carry a value — the rest are `null`
1367
+ whenever the plane cannot supply them (for `stopped` that is all of them, and
1368
+ `stampVersion` is populated only for `ready`), so read them defensively
1369
+ (`jq -r '.pid // empty'`).
3437
1370
 
3438
- `kici run remote` works even if the repo has never been pushed to GitHub. When no remote is detected:
1371
+ A local run also fails fast when no agent claims it: if no scaler label set matches the job's `runsOn`, or the agent cannot start, the run gives up within a short acceptance window (2 minutes by default, overridable with `KICI_LOCAL_ACCEPTANCE_TIMEOUT_MS`) and names the plane log instead of waiting out the full no-progress timeout.
3439
1372
 
3440
- - The entire repo content is uploaded (not just a diff overlay)
3441
- - The lock file is sent inline (no GitHub API fetch)
3442
- - Steps that use git commands will fail (no `.git` directory in the remote workspace)
3443
- - Build cache (`__build__` jobs) is skipped for local repos
3444
- - Environments must have `allowLocalExecution: true` to be accessible from local runs (default is `false`)
1373
+ **Verifying an offline-signed bundle:** export the plane's trust root, then pass it to the verifier:
3445
1374
 
3446
- Destination routing is unchanged for fresh repos: the run still goes to your active org through the Platform.
1375
+ ```bash
1376
+ kici local trust-root ./local-trust-root.json
1377
+ kici verify-attestation ./dist/app.tgz \
1378
+ --bundle ./app.tgz.kici.json \
1379
+ --trust-root ./local-trust-root.json
1380
+ ```
3447
1381
 
3448
- For a detailed guide on writing fixtures, configuring secrets, and understanding the upload flow, see [Testing guide](https://docs.kici.dev/user/testing-guide/).
1382
+ For the plane's on-disk layout, port selection, PostgreSQL backends, and reset behavior, see [Local dev plane](https://docs.kici.dev/operator/orchestrator/local-dev-plane/).
3449
1383
 
3450
- #### kici orchestrators
1384
+ ### kici fixture
3451
1385
 
3452
- List the orchestrator clusters connected to an organization, and set the per-org default cluster used by `kici run remote`. Requires `kici login` and an active org (or pass `--org`).
1386
+ Generate a fixture template for an event type. Useful for creating custom test payloads.
3453
1387
 
3454
1388
  ```bash
3455
- kici orchestrators list [--org <id>]
3456
- kici orchestrators use <clusterName> [--org <id>]
1389
+ kici fixture <event> [options]
3457
1390
  ```
3458
1391
 
3459
- **`kici orchestrators list`** prints the org's connected orchestrator clusters, so you know what to pass to `--orchestrator` (or to `kici orchestrators use`).
3460
-
3461
- **`kici orchestrators use <clusterName>`** sets the default orchestrator cluster for the org, stored per-org in your global config. Subsequent `kici run remote` invocations target that cluster unless overridden with `--orchestrator`.
1392
+ **Valid events:** `pr:open`, `pr:sync`, `pr:close`, `pr:reopen`, `push`, `tag`, `comment`, `review`, `review_comment`, `release`, `dispatch`, `create`, `delete`, `status`, `workflow_run`, `fork`, `star`, `watch`, `kici_event`, `workflow_complete`, `workflows_failed_batch`, `job_complete`, `generic_webhook`, `schedule`, `lifecycle` (many support `:action` suffixes, e.g. `comment:edited`, `release:published`, `lifecycle:workflow_complete`). `webhook:<source>` is a shorthand alias for `generic_webhook:<source>`.
3462
1393
 
3463
1394
  **Examples:**
3464
1395
 
3465
1396
  ```bash
3466
- # List the active org's connected clusters
3467
- kici orchestrators list
3468
-
3469
- # List a specific org's clusters
3470
- kici orchestrators list --org xyz789ghi012
1397
+ # Print fixture to stdout
1398
+ kici fixture pr:open
3471
1399
 
3472
- # Set the default cluster for the active org
3473
- kici orchestrators use us-east
1400
+ # Write fixture to file
1401
+ kici fixture pr:open --output fixtures/pr-open.json
3474
1402
 
3475
- # Set the default cluster for a specific org
3476
- kici orchestrators use us-east --org xyz789ghi012
1403
+ # Generate push fixture
1404
+ kici fixture push --output fixtures/push.json
3477
1405
  ```
3478
1406
 
3479
- ### kici runs
3480
-
3481
- Inspect and manage execution runs from the terminal — the equivalent of the
3482
- dashboard Runs page. All `kici runs` subcommands read/write the same org-scoped
3483
- data as the dashboard, so they require `kici login` and an active org
3484
- (`kici org use <name>`).
1407
+ Use generated fixtures as reference when writing test fixture files in `.kici/tests/`:
3485
1408
 
3486
- #### kici runs list
1409
+ ```bash
1410
+ kici fixture pr:open --output fixtures/pr-open-reference.json
1411
+ # Use the generated JSON as reference when writing .kici/tests/pr-open.ts
1412
+ ```
3487
1413
 
3488
- List runs with optional filters. Output is a table (run id, workflow, status,
3489
- branch, trigger, started, duration); pagination is reported at the bottom.
1414
+ ### kici types
3490
1415
 
3491
- When no runs match, `kici runs list` checks whether any webhooks arrived
3492
- recently. If deliveries came in but nothing produced a run, it prints a
3493
- one-line summary ("3 webhooks received in the last hour, 0 matched") and
3494
- suggests `kici preview push` to test your triggers locally — the fast way to
3495
- find a misconfigured trigger. When nothing arrived it prints "No runs found."
3496
- as before.
1416
+ Generate TypeScript declaration files from orchestrator environment metadata. The generated `.d.ts` file augments the SDK's `KnownSecretKeys` and `ContextSecrets` interfaces, providing compile-time autocomplete and type checking for secret key names.
3497
1417
 
3498
1418
  ```bash
3499
- kici runs list [options]
1419
+ kici types [options]
3500
1420
  ```
3501
1421
 
3502
- ```bash
3503
- kici runs list
3504
- kici runs list --status running
3505
- kici runs list --workflow ci --branch main
3506
- kici runs list --json | jq '.runs[].runId'
3507
- ```
1422
+ **Prerequisites:** Authenticate via `kici login` to fetch the real key set. Without it, `kici types` writes an empty stub (see "Offline behavior" below).
3508
1423
 
3509
- #### kici runs show
1424
+ **Output:** `.kici/types/secrets.d.ts`
3510
1425
 
3511
- Show a run's summary header plus its jobs-and-steps tree (name, status,
3512
- duration, exit code). If the run id is not on the Platform but exists in your
3513
- local run history (from `kici run <event> --local`), the local record is shown instead.
1426
+ **Examples:**
3514
1427
 
3515
1428
  ```bash
3516
- kici runs show <run-id> [options]
3517
- ```
1429
+ # Generate types from orchestrator
1430
+ kici types
3518
1431
 
3519
- ```bash
3520
- kici runs show abc123
3521
- kici runs show abc123 --json
1432
+ # Use custom .kici directory
1433
+ kici types --kici-dir packages/app/.kici
3522
1434
  ```
3523
1435
 
3524
- #### kici runs logs
3525
-
3526
- Print each job/step's log lines in order, with headers.
1436
+ **How it works:**
3527
1437
 
3528
- ```bash
3529
- kici runs logs <run-id> [options]
3530
- ```
1438
+ 1. Fetches all environment metadata (environment names and secret key names) from the orchestrator
1439
+ 2. Generates a `.d.ts` file that augments `@kici-dev/sdk`'s `KnownSecretKeys` and `ContextSecrets` interfaces
1440
+ 3. Writes the file to `.kici/types/secrets.d.ts`
3531
1441
 
3532
- ```bash
3533
- kici runs logs abc123
3534
- kici runs logs abc123 --job build
3535
- kici runs logs abc123 --follow
3536
- ```
1442
+ After generating types, `ctx.secrets.get('MY_KEY')` and `ctx.secrets.expose('DB_HOST')` gain autocomplete and type checking in your IDE.
3537
1443
 
3538
- #### kici runs rerun
1444
+ **Git workflow:** `.kici/types/secrets.d.ts` is a local development aid, not source — its content is a snapshot of one org's secret keys fetched from the Platform. `kici init` gitignores `.kici/types/`, so the file stays out of version control. Each team member runs `kici types` (or an authenticated `kici compile`) to generate their own copy. Do not commit it: a stale committed copy would type-check against secret keys that no longer exist.
3539
1445
 
3540
- Re-trigger a completed run. Prints the new run id. The server enforces a short
3541
- cooldown between reruns of the same run.
1446
+ **Offline behavior:** When the Platform cannot be reached — not logged in, no active org, or offline — `kici types` never fails. If a `secrets.d.ts` already exists, `kici types` keeps it untouched, so a transient outage does not wipe your real key set. If the file is absent (a fresh clone or unauthenticated CI), `kici types` writes a valid empty stub. Type checking then degrades to "no known keys" (any key name is accepted) rather than breaking with "module has no exported member". Run `kici types` again once authenticated to refresh it.
3542
1447
 
3543
- ```bash
3544
- kici runs rerun <run-id> [options]
3545
- ```
1448
+ **Auto-regeneration:** `kici compile` automatically runs `kici types` after successful compilation when authenticated. See the [kici compile](https://docs.kici.dev/user/cli/authoring-and-local/#kici-compile) section for details.
3546
1449
 
3547
- ```bash
3548
- kici runs rerun abc123
3549
- ```
1450
+ **Escape hatch:** For dynamic keys not in the generated types, use a cast: `(ctx.secrets as any).DYNAMIC_KEY`.
3550
1451
 
3551
- #### kici runs cancel
1452
+ ### kici workflows list
3552
1453
 
3553
- Cancel a single run, or all in-progress runs on a branch.
1454
+ List permanently registered workflows on the orchestrator.
3554
1455
 
3555
1456
  ```bash
3556
- kici runs cancel [run-id] [options]
1457
+ kici workflows list [options]
3557
1458
  ```
3558
1459
 
1460
+ **Examples:**
1461
+
3559
1462
  ```bash
3560
- kici runs cancel abc123
3561
- kici runs cancel abc123 --force
3562
- kici runs cancel --branch feature/wip
3563
- ```
1463
+ # List all registered workflows
1464
+ kici workflows list
3564
1465
 
3565
- #### kici runs artifacts list
1466
+ # JSON output for scripting
1467
+ kici workflows list --json
3566
1468
 
3567
- List the [artifacts](https://docs.kici.dev/user/sdk/artifacts/) a run uploaded name, producing job,
3568
- size, content hash, and creation time. An artifact whose stored object can no
3569
- longer be reached is flagged `unavailable`.
1469
+ # Show workflows not updated in 30 days
1470
+ kici workflows list --stale 30d
3570
1471
 
3571
- ```bash
3572
- kici runs artifacts list <run-id> [options]
3573
- ```
1472
+ # Filter by trigger type
1473
+ kici workflows list --trigger-type push
3574
1474
 
3575
- ```bash
3576
- kici runs artifacts list abc123
3577
- kici runs artifacts list abc123 --json
1475
+ # Filter by repository
1476
+ kici workflows list --repo my-org/my-repo
3578
1477
  ```
3579
1478
 
3580
- #### kici runs artifacts download
1479
+ ### kici hook install
3581
1480
 
3582
- Download a run's artifacts. Name one to fetch just that artifact; omit the name
3583
- to download every artifact of the run. Each artifact extracts into its own
3584
- `<name>/` directory by default.
1481
+ Install a pre-commit hook that runs `kici compile` before each commit.
3585
1482
 
3586
1483
  ```bash
3587
- kici runs artifacts download <run-id> [name] [options]
1484
+ kici hook install [options]
3588
1485
  ```
3589
1486
 
3590
- - `--archive` — save the raw `.tar.gz` as `<name>.tar.gz` instead of extracting.
3591
- - `-o, --output <dir>` — write into `<dir>` instead of the current directory.
1487
+ **Examples:**
3592
1488
 
3593
1489
  ```bash
3594
- kici runs artifacts download abc123 bundle
3595
- kici runs artifacts download abc123 bundle -o ./out
3596
- kici runs artifacts download abc123 --archive
3597
- kici runs artifacts download abc123
3598
- ```
3599
-
3600
- The download streams directly from object storage over a short-lived signed URL
3601
- — the artifact bytes never pass through the KiCI Platform — and the content hash
3602
- is verified end to end, so a corrupted or truncated transfer fails loudly rather
3603
- than leaving a bad file on disk.
3604
-
3605
- Artifacts expire after the orchestrator's configured retention. When you name a
3606
- single artifact whose stored object is already gone, the command fails. When you
3607
- download the whole run, such an artifact is reported as a warning and skipped so
3608
- the remaining artifacts still land — the command fails only if every artifact of
3609
- the run was unreachable. Any other failure (a rejected signed URL, a content-hash
3610
- mismatch) stops the command immediately rather than continuing with the rest.
3611
-
3612
- Artifact names are case-sensitive, so a single run can hold both `bundle` and
3613
- `Bundle`. On a filesystem that ignores case in path lookups — macOS and Windows
3614
- default to this, Linux does not — both would land on the same path, so
3615
- downloading the whole run refuses before writing anything and names the pair.
3616
- Fetch them one at a time into separate directories instead:
1490
+ # Auto-detect hook tool (husky, lint-staged, etc.)
1491
+ kici hook install
3617
1492
 
3618
- ```bash
3619
- kici runs artifacts download abc123 bundle -o ./bundle-lower
3620
- kici runs artifacts download abc123 Bundle -o ./bundle-upper
1493
+ # Force raw git hook
1494
+ kici hook install --git
3621
1495
  ```
3622
1496
 
3623
- Naming a single artifact is never affected, and on a case-sensitive filesystem
3624
- downloading the whole run still writes both.
1497
+ The command auto-detects existing hook tools in your project:
3625
1498
 
3626
- Artifacts are packed relative to two roots: paths inside your repository and
3627
- paths under the home directory. Repository-relative files land directly under
3628
- `<name>/`; home-relative files land under `<name>/~home/`, so the two can never
3629
- overwrite each other and nothing is ever written outside the output directory.
1499
+ - **Husky**: Adds to `.husky/pre-commit`
1500
+ - **lint-staged**: Adds to lint-staged configuration
1501
+ - **Raw git**: Writes `.git/hooks/pre-commit`
3630
1502
 
3631
- When `--json` is set on any of these commands, `kici` emits only the JSON
3632
- document on stdout — the `kici v<version>` banner is suppressed — so the output
3633
- is safe to pipe into `jq` or `JSON.parse`. The same holds for the other
3634
- `--json` commands (`kici run remote --json`, `kici workflows list --json`) and
3635
- for `--quiet`.
1503
+ If multiple tools are detected, you are prompted to choose.
3636
1504
 
3637
- ### kici reject
1505
+ ### kici docs
3638
1506
 
3639
- Reject a held [approval gate](https://docs.kici.dev/user/approvals/). A rejection fails the held element and the run. A reason is required.
1507
+ Open the KiCI documentation site in the default browser. With the `llm` subcommand, print the LLM-friendly documentation bundle that ships with `@kici-dev/compiler` pipe it into a coding agent's context buffer to brief the agent on authoring conventions without an internet round-trip.
3640
1508
 
3641
1509
  ```bash
3642
- kici reject <run-id> --reason <text> [options]
1510
+ kici docs # open https://kici.dev/docs/
1511
+ kici docs --no-open # print the URL instead of opening a browser
1512
+ kici docs llm # print the llms.txt index (a router over the task bundles)
1513
+ kici docs llm sdk # print the SDK task bundle
1514
+ kici docs llm full # print llms-full.txt (every page in one file)
1515
+ kici docs llm sdk --out sdk-context.md # write a bundle to a file
3643
1516
  ```
3644
1517
 
3645
1518
  **Examples:**
3646
1519
 
3647
1520
  ```bash
3648
- # Reject a held job with a reason
3649
- kici reject abc123 --job deploy-production --reason "Wrong release branch"
3650
- ```
3651
-
3652
- ### kici approve
1521
+ # Open the docs site in your browser
1522
+ kici docs
3653
1523
 
3654
- Approve a held [approval gate](https://docs.kici.dev/user/approvals/) so the run resumes. Identify the held element by run ID, optionally narrowed to a job and step.
1524
+ # Pipe just the SDK bundle into a coding agent (small, task-scoped context)
1525
+ kici docs llm sdk | claude -- "Read this and help me author a deploy workflow"
3655
1526
 
3656
- ```bash
3657
- kici approve <run-id> [options]
1527
+ # Save the router index for offline reference
1528
+ kici docs llm --out kici-llms-index.txt
3658
1529
  ```
3659
1530
 
3660
- **Examples:**
3661
-
3662
- ```bash
3663
- # Approve a workflow-level hold
3664
- kici approve abc123
1531
+ Bundles are regenerated from `docs/` every time `@kici-dev/compiler` is built, so they always match your installed CLI version. The index lists each task bundle — `getting-started`, `sdk`, `sdk-runtime`, `cli`, `cli-remote`, `patterns`, `features`, `features-execution`, `providers`, `architecture` — with its size and a one-line purpose; pass the bundle id as the topic. Every cross-reference link inside a bundle is an absolute `docs.kici.dev` URL. The same files are published online following the [llms.txt convention](https://llmstxt.org/).
3665
1532
 
3666
- # Approve a held job
3667
- kici approve abc123 --job deploy-production
1533
+ ## Reference
3668
1534
 
3669
- # Approve a held step (steps are addressed by index)
3670
- kici approve abc123 --job migrate-and-deploy --step 1
3671
- ```
1535
+ <!-- BEGIN GENERATED: kici-authoring-and-local (do not edit; run the doc generator) -->
3672
1536
 
3673
- You must be eligible for at least one unsatisfied clause (a member of a named team, or a named user) and hold the permission that matches the hold's type — `ci_trust:write` for a **security** hold, `contexts:admin` for a **wait-timer** hold, `contexts:write` for every other hold. The server enforces this, so the same rule applies to the dashboard and to an AI agent's tools. The command reports whether the element was released, how many clauses remain, or that it was rejected.
1537
+ ### `kici compile`
3674
1538
 
3675
- ## Reference
1539
+ Compile workflows from .kici/workflows/ to kici.lock.json
3676
1540
 
3677
- <!-- BEGIN GENERATED: kici-runs-and-approvals (do not edit; run the doc generator) -->
1541
+ Synopsis: `kici compile [options]`
3678
1542
 
3679
- ### `kici approve`
1543
+ **Options**
3680
1544
 
3681
- Approve a held approval gate for a run
1545
+ | Option | Default | Description |
1546
+ | ------------------- | ------- | ---------------------------------------------------------------------------------- |
1547
+ | `--check` | `false` | Validate workflows and type-check sources (tsc --noEmit) without writing lock file |
1548
+ | `--kici-dir <path>` | `.kici` | Path to .kici directory |
1549
+ | `--verbose` | `false` | Detailed output |
1550
+ | `--watch` | `false` | Watch for changes and recompile |
3682
1551
 
3683
- Synopsis: `kici approve <run-id> [options]`
1552
+ ### `kici docs`
3684
1553
 
3685
- **Arguments**
1554
+ Open the KiCI documentation site in the default browser
3686
1555
 
3687
- | Argument | Required | Variadic | Description |
3688
- | -------- | -------- | -------- | ------------------------------------- |
3689
- | `run-id` | yes | no | Run ID whose approval gate to approve |
1556
+ Synopsis: `kici docs [options]`
3690
1557
 
3691
1558
  **Options**
3692
1559
 
3693
- | Option | Default | Description |
3694
- | ---------------- | ------- | ------------------------------------------- |
3695
- | `--job <name>` | | Approve the hold for a specific job |
3696
- | `--step <index>` | | Approve a step-scoped hold (requires --job) |
1560
+ | Option | Default | Description |
1561
+ | ----------- | ------- | ----------------------------------------------- |
1562
+ | `--no-open` | | Print the docs URL instead of opening a browser |
3697
1563
 
3698
- ### `kici reject`
1564
+ ### `kici docs llm`
3699
1565
 
3700
- Reject a held approval gate for a run
1566
+ Print KiCI LLM docs bundles. No topic prints the llms.txt index; <topic> prints a task bundle (e.g. sdk, cli, cli-remote, patterns, features, providers, architecture, getting-started); "full" prints the complete bundle.
3701
1567
 
3702
- Synopsis: `kici reject <run-id> [options]`
1568
+ Synopsis: `kici docs llm [topic] [options]`
3703
1569
 
3704
1570
  **Arguments**
3705
1571
 
3706
- | Argument | Required | Variadic | Description |
3707
- | -------- | -------- | -------- | ------------------------------------ |
3708
- | `run-id` | yes | no | Run ID whose approval gate to reject |
1572
+ | Argument | Required | Variadic | Description |
1573
+ | -------- | -------- | -------- | ----------- |
1574
+ | `topic` | no | no | |
3709
1575
 
3710
1576
  **Options**
3711
1577
 
3712
- | Option | Default | Description |
3713
- | ----------------- | ------- | ------------------------------------------ |
3714
- | `--job <name>` | | Reject the hold for a specific job |
3715
- | `--step <index>` | | Reject a step-scoped hold (requires --job) |
3716
- | `--reason <text>` | | Reason for the rejection |
1578
+ | Option | Default | Description |
1579
+ | -------------- | ------- | -------------------------------------------- |
1580
+ | `--out <path>` | | Write the bundle to a file instead of stdout |
3717
1581
 
3718
- ### `kici run`
1582
+ ### `kici fixture`
3719
1583
 
3720
- Execute workflows locally or remotely
1584
+ Generate fixture template for event type
3721
1585
 
3722
- Synopsis: `kici run [event] [options]`
1586
+ Synopsis: `kici fixture <event> [options]`
3723
1587
 
3724
1588
  **Arguments**
3725
1589
 
3726
- | Argument | Required | Variadic | Description |
3727
- | -------- | -------- | -------- | ------------------------------------------------------ |
3728
- | `event` | no | no | Event type for a routed local run (e.g. push, pr:open) |
1590
+ | Argument | Required | Variadic | Description |
1591
+ | -------- | -------- | -------- | ------------------------------------------------------------------------------------------ |
1592
+ | `event` | yes | no | Event to generate fixture for (e.g., pr:open, push, schedule, lifecycle:workflow_complete) |
3729
1593
 
3730
1594
  **Options**
3731
1595
 
3732
- | Option | Default | Description |
3733
- | ------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------ |
3734
- | `--local` | `false` | Route the run with this machine as the ephemeral agent |
3735
- | `--offline` | `false` | Force the throwaway/independent plane (offline) |
3736
- | `--connected` | `false` | Force the connected/hybrid plane (requires attachment) |
3737
- | `--in-place` | `false` | Reuse the working tree directly instead of an isolated clone |
3738
- | `--trusted` | `false` | Route to the trusted fleet agent profile: steps see the ambient host env (minus the agent identity). Alias: --no-sandbox |
3739
- | `--no-sandbox` | | Alias for --trusted (the bwrap sandbox is already off by default) |
3740
- | `--env <KEY=VALUE>` | | Per-run secret (repeatable) |
3741
- | `--payload <path>` | | Dispatch payload JSON { action?, client_payload? } for a routed dispatch run |
3742
- | `--kici-dir <path>` | `.kici` | Path to .kici directory |
3743
- | `--quiet` | `false` | Suppress the banner + streaming output |
3744
- | `--debug` | `false` | Verbose internals |
1596
+ | Option | Default | Description |
1597
+ | ----------------- | ------- | ------------------------------- |
1598
+ | `--output <path>` | | Write to file instead of stdout |
1599
+
1600
+ ### `kici hook`
3745
1601
 
3746
- ### `kici run remote`
1602
+ Manage pre-commit hooks
3747
1603
 
3748
- Execute fixtures remotely via orchestrator
1604
+ Synopsis: `kici hook`
3749
1605
 
3750
- Synopsis: `kici run remote [fixture] [options]`
1606
+ ### `kici hook install`
3751
1607
 
3752
- **Arguments**
1608
+ Install kici compile pre-commit hook
3753
1609
 
3754
- | Argument | Required | Variadic | Description |
3755
- | --------- | -------- | -------- | ----------------------------------------------------- |
3756
- | `fixture` | no | no | Fixture name or glob pattern (omit to list available) |
1610
+ Synopsis: `kici hook install [options]`
3757
1611
 
3758
1612
  **Options**
3759
1613
 
3760
- | Option | Default | Description |
3761
- | --------------------------- | ------- | ------------------------------------------------------------------------------------------- |
3762
- | `--workflow <name>` | | Run a specific workflow directly (bypass triggers) |
3763
- | `--all` | `false` | Run all available fixtures |
3764
- | `-p, --pick` | `false` | Interactively pick fixtures to run |
3765
- | `--parallel` | `false` | Run matching fixtures concurrently |
3766
- | `--no-wait` | | Fire and forget (print runIds, don't stream) |
3767
- | `--quiet` | `false` | Suppress output except final result |
3768
- | `--json` | `false` | Output structured JSON result |
3769
- | `--junit <path>` | | Output JUnit XML result |
3770
- | `--history` | `false` | Show recent run history |
3771
- | `--routing-key <key>` | | Override routing key for this run |
3772
- | `--org <id>` | | Target organization (overrides the active org) |
3773
- | `--orchestrator <name>` | | Target orchestrator cluster (overrides the per-org default) |
3774
- | `--debug` | `false` | Verbose internals |
3775
- | `--kici-dir <path>` | `.kici` | Path to .kici directory |
3776
- | `--context <ctx.key=value>` | | Inject a namespaced context secret, uploaded encrypted to the orchestrator (repeatable) |
3777
- | `--env <KEY=VALUE>` | | Provide a per-run secret (repeatable); uploaded encrypted to the orchestrator |
3778
- | `--check` | `false` | Run in check mode: report drift, change nothing |
3779
- | `--fail-on-drift` | `false` | In check mode, exit non-zero if any step reports drift |
3780
- | `--target <selector>` | | Narrow runsOnAll jobs to hosts matching this label selector (repeatable, AND-combined) |
3781
- | `--target-allow-empty` | `false` | A --target that narrows a runsOnAll job to zero hosts skips it instead of failing |
3782
- | `--input <KEY=VALUE>` | | Typed workflow-dispatch input (repeatable) |
3783
- | `--yes, --approve-all` | `false` | Auto-approve every approval gate this run holds on (run-scoped; eligibility still enforced) |
1614
+ | Option | Default | Description |
1615
+ | ------- | ------- | ---------------------------------------- |
1616
+ | `--git` | `false` | Use raw git hook (.git/hooks/pre-commit) |
3784
1617
 
3785
- ### `kici runs`
1618
+ ### `kici local`
3786
1619
 
3787
- Inspect and manage execution runs
1620
+ Manage the local dev orchestrator plane
3788
1621
 
3789
- Synopsis: `kici runs`
1622
+ Synopsis: `kici local`
3790
1623
 
3791
- ### `kici runs artifacts`
1624
+ ### `kici local attach`
3792
1625
 
3793
- List and download a run's artifacts
1626
+ Attach the local dev plane to the Platform (hybrid)
3794
1627
 
3795
- Synopsis: `kici runs artifacts`
1628
+ Synopsis: `kici local attach`
3796
1629
 
3797
- ### `kici runs artifacts download`
1630
+ ### `kici local detach`
3798
1631
 
3799
- Download one artifact, or all of them extracts by default
1632
+ Detach the local dev plane from the Platform (offline)
3800
1633
 
3801
- Synopsis: `kici runs artifacts download <run-id> [name] [options]`
1634
+ Synopsis: `kici local detach`
3802
1635
 
3803
- **Arguments**
1636
+ ### `kici local down`
3804
1637
 
3805
- | Argument | Required | Variadic | Description |
3806
- | -------- | -------- | -------- | ---------------------------------------------------------- |
3807
- | `run-id` | yes | no | Run ID whose artifacts to download |
3808
- | `name` | no | no | Artifact name (omit to download every artifact of the run) |
1638
+ Stop the local dev plane
3809
1639
 
3810
- **Options**
1640
+ Synopsis: `kici local down`
3811
1641
 
3812
- | Option | Default | Description |
3813
- | -------------------- | ------- | --------------------------------------------- |
3814
- | `--archive` | `false` | Save the raw .tar.gz instead of extracting |
3815
- | `-o, --output <dir>` | | Output directory (default: current directory) |
1642
+ ### `kici local logs`
3816
1643
 
3817
- ### `kici runs artifacts list`
1644
+ Print the local dev plane orchestrator log path
3818
1645
 
3819
- List the artifacts a run uploaded
1646
+ Synopsis: `kici local logs`
3820
1647
 
3821
- Synopsis: `kici runs artifacts list <run-id> [options]`
1648
+ ### `kici local status`
3822
1649
 
3823
- **Arguments**
1650
+ Show local dev plane status and control commands
3824
1651
 
3825
- | Argument | Required | Variadic | Description |
3826
- | -------- | -------- | -------- | ------------------------------ |
3827
- | `run-id` | yes | no | Run ID whose artifacts to list |
1652
+ Synopsis: `kici local status [options]`
3828
1653
 
3829
1654
  **Options**
3830
1655
 
3831
- | Option | Default | Description |
3832
- | -------- | ------- | --------------- |
3833
- | `--json` | `false` | Output raw JSON |
1656
+ | Option | Default | Description |
1657
+ | -------- | ------- | ---------------------------------------------------- |
1658
+ | `--json` | `false` | Emit machine-readable JSON (exits 0 for every state) |
3834
1659
 
3835
- ### `kici runs cancel`
1660
+ ### `kici local trust-root`
3836
1661
 
3837
- Cancel a run, or all in-progress runs on a branch
1662
+ Export the offline dev-signed identity trust root ({ issuer, jwks }) to a file
3838
1663
 
3839
- Synopsis: `kici runs cancel [run-id] [options]`
1664
+ Synopsis: `kici local trust-root <file>`
3840
1665
 
3841
1666
  **Arguments**
3842
1667
 
3843
- | Argument | Required | Variadic | Description |
3844
- | -------- | -------- | -------- | ---------------- |
3845
- | `run-id` | no | no | Run ID to cancel |
3846
-
3847
- **Options**
3848
-
3849
- | Option | Default | Description |
3850
- | ----------------- | ------- | ------------------------------------------- |
3851
- | `--force` | `false` | Force cancel (kill immediately, skip hooks) |
3852
- | `--branch <name>` | | Cancel all in-progress runs on this branch |
1668
+ | Argument | Required | Variadic | Description |
1669
+ | -------- | -------- | -------- | ---------------------------------------------------- |
1670
+ | `file` | yes | no | Output path for the { issuer, jwks } trust-root JSON |
3853
1671
 
3854
- ### `kici runs list`
1672
+ ### `kici local up`
3855
1673
 
3856
- List execution runs (mirrors the dashboard Runs page)
1674
+ Start (or reuse) the local dev plane
3857
1675
 
3858
- Synopsis: `kici runs list [options]`
1676
+ Synopsis: `kici local up [options]`
3859
1677
 
3860
1678
  **Options**
3861
1679
 
3862
- | Option | Default | Description |
3863
- | ----------------------- | ------- | --------------------------------------------------------- |
3864
- | `--status <s>` | | Filter by status |
3865
- | `--workflow <w>` | | Filter by workflow name |
3866
- | `--branch <b>` | | Filter by branch/ref |
3867
- | `--repo <r>` | | Filter by repository |
3868
- | `--trigger <t>` | | Filter by trigger type |
3869
- | `--source <routingKey>` | | Filter by source routing key |
3870
- | `--since <ts>` | | Only runs since (ISO-8601 or epoch ms) |
3871
- | `--cursor <cursor>` | | Keyset cursor for the next page (from a prior nextCursor) |
3872
- | `--json` | `false` | Output raw JSON |
1680
+ | Option | Default | Description |
1681
+ | ------------- | ------- | ---------------------------------------------------------------------------- |
1682
+ | `--offline` | `false` | Force the independent (offline) plane (does not clear the attachment record) |
1683
+ | `--connected` | `false` | Force the connected/hybrid plane (requires an attached, reachable Platform) |
3873
1684
 
3874
- ### `kici runs logs`
1685
+ ### `kici preview`
3875
1686
 
3876
- Print step logs for a run
1687
+ Preview which workflows match a trigger event (no execution)
3877
1688
 
3878
- Synopsis: `kici runs logs <run-id> [options]`
1689
+ Synopsis: `kici preview [event] [options]`
3879
1690
 
3880
1691
  **Arguments**
3881
1692
 
3882
- | Argument | Required | Variadic | Description |
3883
- | -------- | -------- | -------- | ----------- |
3884
- | `run-id` | yes | no | Run ID |
1693
+ | Argument | Required | Variadic | Description |
1694
+ | -------- | -------- | -------- | ----------------------------------------------------- |
1695
+ | `event` | no | no | Event type to preview (e.g., push, pr:open, schedule) |
3885
1696
 
3886
1697
  **Options**
3887
1698
 
3888
- | Option | Default | Description |
3889
- | -------------- | ------- | ------------------------ |
3890
- | `--job <name>` | | Only logs for this job |
3891
- | `-f, --follow` | `false` | Tail logs for a live run |
3892
- | `--json` | `false` | Output raw JSON |
3893
-
3894
- ### `kici runs rerun`
3895
-
3896
- Re-trigger a run
1699
+ | Option | Default | Description |
1700
+ | --------------------------- | ------- | ------------------------------------------------------------ |
1701
+ | `--branch <name>` | | Override target branch for trigger matching (default: main) |
1702
+ | `--sha <hash>` | | Override commit SHA |
1703
+ | `--workflow <name>` | | Filter to specific workflow in display |
1704
+ | `--job <name>` | | Filter to specific job in display |
1705
+ | `--debug` | `false` | Verbose internals |
1706
+ | `--kici-dir <path>` | `.kici` | Path to .kici directory |
1707
+ | `--files <path>` | | Simulate changed file path for trigger matching (repeatable) |
1708
+ | `--secret <key=value>` | | Inject flat secret (repeatable) |
1709
+ | `--context <ctx.key=value>` | | Inject context secret (repeatable) |
3897
1710
 
3898
- Synopsis: `kici runs rerun <run-id> [options]`
1711
+ ### `kici types`
3899
1712
 
3900
- **Arguments**
1713
+ Generate TypeScript declarations for secret contexts
3901
1714
 
3902
- | Argument | Required | Variadic | Description |
3903
- | -------- | -------- | -------- | --------------- |
3904
- | `run-id` | yes | no | Run ID to rerun |
1715
+ Synopsis: `kici types [options]`
3905
1716
 
3906
1717
  **Options**
3907
1718
 
3908
- | Option | Default | Description |
3909
- | -------- | ------- | --------------- |
3910
- | `--json` | `false` | Output raw JSON |
1719
+ | Option | Default | Description |
1720
+ | ------------------- | ------- | ----------------------- |
1721
+ | `--kici-dir <path>` | `.kici` | Path to .kici directory |
1722
+
1723
+ ### `kici workflows`
3911
1724
 
3912
- ### `kici runs show`
1725
+ Manage workflow registrations
3913
1726
 
3914
- Show a run summary with its jobs and steps
1727
+ Synopsis: `kici workflows`
3915
1728
 
3916
- Synopsis: `kici runs show <run-id> [options]`
1729
+ ### `kici workflows list`
3917
1730
 
3918
- **Arguments**
1731
+ List permanently registered workflows
3919
1732
 
3920
- | Argument | Required | Variadic | Description |
3921
- | -------- | -------- | -------- | ----------------- |
3922
- | `run-id` | yes | no | Run ID to inspect |
1733
+ Synopsis: `kici workflows list [options]`
3923
1734
 
3924
1735
  **Options**
3925
1736
 
3926
- | Option | Default | Description |
3927
- | -------- | ------- | --------------- |
3928
- | `--json` | `false` | Output raw JSON |
1737
+ | Option | Default | Description |
1738
+ | ----------------------- | ------- | ------------------------------------------ |
1739
+ | `--json` | `false` | Output as JSON |
1740
+ | `--stale <duration>` | | Filter stale registrations (e.g., 30d, 7d) |
1741
+ | `--trigger-type <type>` | | Filter by trigger type |
1742
+ | `--repo <repo>` | | Filter by repository |
3929
1743
 
3930
- <!-- END GENERATED: kici-runs-and-approvals -->
1744
+ <!-- END GENERATED: kici-authoring-and-local -->
3931
1745
 
3932
1746
  ---