@odla-ai/cli 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -30
- package/REQUIREMENTS.md +18 -3
- package/dist/bin.cjs +780 -276
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-UWT7C6VT.js → chunk-7WZIZCGA.js} +780 -273
- package/dist/chunk-7WZIZCGA.js.map +1 -0
- package/dist/index.cjs +786 -276
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +205 -21
- package/dist/index.d.ts +205 -21
- package/dist/index.js +7 -1
- package/llms.txt +311 -53
- package/package.json +14 -6
- package/skills/odla/SKILL.md +39 -12
- package/skills/odla/references/build.md +52 -17
- package/skills/odla/references/sdks.md +33 -3
- package/skills/odla-migrate/SKILL.md +38 -13
- package/skills/odla-migrate/references/phase-0-preflight.md +0 -2
- package/skills/odla-migrate/references/phase-1-static.md +2 -4
- package/skills/odla-migrate/references/phase-2-db.md +25 -17
- package/skills/odla-migrate/references/phase-3-auth.md +106 -20
- package/skills/odla-migrate/references/phase-3b-user-sync.md +57 -0
- package/skills/odla-migrate/references/phase-4-ai.md +6 -5
- package/skills/odla-migrate/references/phase-5-cutover.md +43 -16
- package/skills/odla-migrate/references/secrets-map.md +21 -11
- package/skills/odla-migrate/references/troubleshooting.md +27 -13
- package/skills/odla-o11y-debug/SKILL.md +93 -0
- package/dist/chunk-UWT7C6VT.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,9 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse CLI arguments and dispatch to the matching command — the entry point
|
|
3
|
+
* `bin.ts` invokes. `argv` defaults to `process.argv.slice(2)`; the first
|
|
4
|
+
* positional selects the command and the rest are parsed into flags (supporting
|
|
5
|
+
* `--flag value`, `--flag=value`, boolean `--flag`, `--no-flag`, and repeated
|
|
6
|
+
* flags collected into arrays).
|
|
7
|
+
*
|
|
8
|
+
* Recognized commands: `version`/`-v`/`--version` and `help`/`-h`/`--help` print
|
|
9
|
+
* and return; `init` scaffolds a project (requires `--app-id` and `--name`);
|
|
10
|
+
* `doctor` validates config offline; `capabilities` prints the responsibility
|
|
11
|
+
* boundary; `provision` runs the full provision (including optional secret
|
|
12
|
+
* rotation, local vars, and deployed secret push); `smoke` checks a live env;
|
|
13
|
+
* `setup` and `skill install` install the bundled offline runbooks for Claude
|
|
14
|
+
* Code, Codex, Cursor, Copilot, Gemini, and `AGENTS.md`-aware agents; and
|
|
15
|
+
* `secrets push` pipes the env's configured db/o11y secrets into the Worker via
|
|
16
|
+
* Wrangler (requires `--env`). Throws on an unknown command/subcommand, unsupported option, extra
|
|
17
|
+
* positional argument, missing required value, or a dispatched command error.
|
|
18
|
+
*
|
|
19
|
+
* @param argv Argument vector without the node/script prefix (default
|
|
20
|
+
* `process.argv.slice(2)`).
|
|
21
|
+
*/
|
|
1
22
|
declare function runCli(argv?: string[]): Promise<void>;
|
|
2
23
|
|
|
24
|
+
/** Stable, machine-readable division of work between the CLI, coding agent,
|
|
25
|
+
* human operator, and Studio. Printed by `odla-ai capabilities --json`. */
|
|
26
|
+
declare const CAPABILITIES: {
|
|
27
|
+
readonly cli: readonly ["register the app and enable configured services per environment", "issue, persist, and explicitly rotate configured service credentials", "write local Worker values and push deployed Worker secrets through Wrangler stdin", "push db schema/rules and configure platform AI, auth, and deployment links", "validate config offline and smoke-test a provisioned db environment"];
|
|
28
|
+
readonly agent: readonly ["install and import the selected odla SDKs", "wrap the Worker with withObservability and choose useful telemetry", "make application-specific schema, rules, auth, UI, and migration decisions"];
|
|
29
|
+
readonly human: readonly ["approve the odla device code and one-off third-party logins", "consent to production changes with --yes", "request destructive credential rotation explicitly", "review application semantics, security findings, releases, and merges"];
|
|
30
|
+
readonly studio: readonly ["view telemetry and environment state", "perform manual credential recovery when the CLI's local shown-once copy is unavailable"];
|
|
31
|
+
};
|
|
32
|
+
type Output = Pick<typeof console, "log">;
|
|
33
|
+
/** Print the stable responsibility boundary for humans or agent tooling. */
|
|
34
|
+
declare function printCapabilities(json?: boolean, out?: Output): void;
|
|
35
|
+
|
|
3
36
|
interface DoctorOptions {
|
|
4
37
|
configPath: string;
|
|
5
38
|
stdout?: Pick<typeof console, "log" | "error">;
|
|
6
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Validate and summarize an odla project config entirely offline — no network
|
|
42
|
+
* calls and no file writes. Loads `configPath`, builds the provision plan, and
|
|
43
|
+
* resolves the schema and rules (synthesizing deny-all rules from the schema
|
|
44
|
+
* when `db.rules` is omitted and `db.defaultRules` isn't `false`), then prints a
|
|
45
|
+
* summary line for the app, envs, services, schema entity count, rules namespace
|
|
46
|
+
* count, and AI provider.
|
|
47
|
+
*
|
|
48
|
+
* It then collects warnings for the mistakes provision can't fix silently: a
|
|
49
|
+
* schema with no entities, a rules namespace with no matching entity, the `ai`
|
|
50
|
+
* service enabled without an `ai.provider`, `auth.clerk` entries that reference
|
|
51
|
+
* an unset env var (`$FOO`), an `ai.keyEnv` that isn't set (provider key upload
|
|
52
|
+
* will be skipped), and — when `o11y` is enabled — any env whose local
|
|
53
|
+
* credentials lack an ingest token. It also folds in the shared rule linter,
|
|
54
|
+
* git-tracked secret-shaped files, and wrangler config warnings. Prints `ok`
|
|
55
|
+
* when clean, otherwise the warning list. Purely advisory: never throws on
|
|
56
|
+
* warnings and never mutates anything.
|
|
57
|
+
*
|
|
58
|
+
* @param options.configPath Path to the `odla.config.mjs` to inspect.
|
|
59
|
+
* @param options.stdout Optional console-like sink (defaults to `console`).
|
|
60
|
+
*/
|
|
7
61
|
declare function doctor(options: DoctorOptions): Promise<void>;
|
|
8
62
|
|
|
9
63
|
interface InitOptions {
|
|
@@ -17,8 +71,44 @@ interface InitOptions {
|
|
|
17
71
|
force?: boolean;
|
|
18
72
|
stdout?: Pick<typeof console, "log" | "error">;
|
|
19
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Scaffold a new odla project into `rootDir` (default: cwd). Writes an
|
|
76
|
+
* `odla.config.mjs` (default name, overridable via `configPath`) plus starter
|
|
77
|
+
* `src/odla/schema.mjs` (a single `notes` entity) and `src/odla/rules.mjs`
|
|
78
|
+
* (deny-all), and creates the `src/odla` and `.odla` directories. Also runs
|
|
79
|
+
* `ensureGitignore` so the local token/credentials paths are ignored.
|
|
80
|
+
*
|
|
81
|
+
* Fully local and synchronous — no network calls. The config file is only
|
|
82
|
+
* written when it doesn't already exist unless `force` is set (otherwise it
|
|
83
|
+
* throws); the schema/rules files are written only when missing (never
|
|
84
|
+
* overwritten, even with `force`). `appId` must match `^[a-z0-9][a-z0-9-]*$` or
|
|
85
|
+
* it throws. Defaults: `envs` → `["dev"]`, `services` → `["db","ai"]`,
|
|
86
|
+
* `aiProvider` → `"anthropic"` (which also picks the `keyEnv`, e.g.
|
|
87
|
+
* `ANTHROPIC_API_KEY`/`OPENAI_API_KEY`/`GOOGLE_API_KEY`).
|
|
88
|
+
*
|
|
89
|
+
* @param options.appId Slug for the app (lowercase alphanumerics and hyphens).
|
|
90
|
+
* @param options.name Human-readable app name embedded in the config.
|
|
91
|
+
* @param options.rootDir Project root (defaults to `process.cwd()`).
|
|
92
|
+
* @param options.configPath Config filename relative to root (default `odla.config.mjs`).
|
|
93
|
+
* @param options.envs Environment names (default `["dev"]`; production is an explicit opt-in).
|
|
94
|
+
* @param options.services Enabled services (default `["db","ai"]`).
|
|
95
|
+
* @param options.aiProvider AI provider slug (default `"anthropic"`).
|
|
96
|
+
* @param options.force Overwrite an existing config file instead of throwing.
|
|
97
|
+
* @param options.stdout Optional console-like sink (defaults to `console`).
|
|
98
|
+
*/
|
|
20
99
|
declare function initProject(options: InitOptions): void;
|
|
21
100
|
|
|
101
|
+
interface RunResult {
|
|
102
|
+
code: number;
|
|
103
|
+
stdout: string;
|
|
104
|
+
stderr: string;
|
|
105
|
+
}
|
|
106
|
+
/** Subprocess seam: injectable in tests, `defaultRunner` in production. */
|
|
107
|
+
type CommandRunner = (cmd: string, args: string[], opts?: {
|
|
108
|
+
input?: string;
|
|
109
|
+
cwd?: string;
|
|
110
|
+
}) => Promise<RunResult>;
|
|
111
|
+
|
|
22
112
|
type OdlaEnvName = string;
|
|
23
113
|
type AppRules = Record<string, {
|
|
24
114
|
view?: string;
|
|
@@ -31,6 +121,7 @@ interface ClerkAuthConfig {
|
|
|
31
121
|
audience?: string;
|
|
32
122
|
mode?: "client" | "full";
|
|
33
123
|
}
|
|
124
|
+
/** Authored `odla.config.mjs` contract consumed by doctor and provision. */
|
|
34
125
|
interface OdlaProjectConfig {
|
|
35
126
|
platformUrl?: string;
|
|
36
127
|
dbEndpoint?: string;
|
|
@@ -77,6 +168,7 @@ interface OdlaProjectConfig {
|
|
|
77
168
|
gitignore?: boolean;
|
|
78
169
|
};
|
|
79
170
|
}
|
|
171
|
+
/** Normalized project config with resolved paths, endpoints, envs, and services. */
|
|
80
172
|
interface LoadedProjectConfig extends OdlaProjectConfig {
|
|
81
173
|
configPath: string;
|
|
82
174
|
rootDir: string;
|
|
@@ -91,6 +183,7 @@ interface LoadedProjectConfig extends OdlaProjectConfig {
|
|
|
91
183
|
gitignore: boolean;
|
|
92
184
|
};
|
|
93
185
|
}
|
|
186
|
+
/** Private mode-0600 local state written by provision and never committed. */
|
|
94
187
|
interface LocalCredentials {
|
|
95
188
|
appId: string;
|
|
96
189
|
platformUrl: string;
|
|
@@ -102,10 +195,15 @@ interface LocalCredentials {
|
|
|
102
195
|
o11yToken?: string;
|
|
103
196
|
}>;
|
|
104
197
|
}
|
|
198
|
+
/** Controls one dev-first provisioning run; production mutation requires `yes`. */
|
|
105
199
|
interface ProvisionOptions {
|
|
106
200
|
configPath: string;
|
|
107
201
|
dryRun?: boolean;
|
|
108
202
|
rotateKeys?: boolean;
|
|
203
|
+
/** Rotate only the o11y ingest token; leaves db keys unchanged. */
|
|
204
|
+
rotateO11yToken?: boolean;
|
|
205
|
+
/** Push configured Worker secrets to every configured env after provisioning. */
|
|
206
|
+
pushSecrets?: boolean;
|
|
109
207
|
writeCredentials?: boolean;
|
|
110
208
|
writeDevVars?: string | boolean;
|
|
111
209
|
token?: string;
|
|
@@ -115,10 +213,14 @@ interface ProvisionOptions {
|
|
|
115
213
|
interactive?: boolean;
|
|
116
214
|
/** Test/embedding override for opening the approval URL. Defaults to the OS browser opener. */
|
|
117
215
|
openApprovalUrl?: (url: string) => Promise<void>;
|
|
216
|
+
/** Explicit consent for a non-dry-run plan containing `prod` or `production`. */
|
|
118
217
|
yes?: boolean;
|
|
119
218
|
fetch?: typeof fetch;
|
|
219
|
+
/** Test/embedding override for Wrangler subprocesses used by `pushSecrets`. */
|
|
220
|
+
secretRunner?: CommandRunner;
|
|
120
221
|
stdout?: Pick<typeof console, "log" | "error">;
|
|
121
222
|
}
|
|
223
|
+
/** Human-reviewable, secret-free plan printed by `provision({ dryRun: true })`. */
|
|
122
224
|
interface ProvisionPlan {
|
|
123
225
|
appId: string;
|
|
124
226
|
appName: string;
|
|
@@ -130,6 +232,7 @@ interface ProvisionPlan {
|
|
|
130
232
|
hasRules: boolean;
|
|
131
233
|
aiProvider?: string;
|
|
132
234
|
}
|
|
235
|
+
/** Inputs for a read-only live environment smoke check. */
|
|
133
236
|
interface SmokeOptions {
|
|
134
237
|
configPath: string;
|
|
135
238
|
env?: string;
|
|
@@ -137,21 +240,50 @@ interface SmokeOptions {
|
|
|
137
240
|
stdout?: Pick<typeof console, "log" | "error">;
|
|
138
241
|
}
|
|
139
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Provision an app end-to-end from its config — the primary deploy path, and
|
|
245
|
+
* (apart from key rotation) idempotent, so re-running is safe. Obtains a
|
|
246
|
+
* developer token, creates the registry app when absent, enables each service
|
|
247
|
+
* per env (AI also gets `setAi` with the configured provider/model), configures
|
|
248
|
+
* Clerk auth and links, then per env mints or reuses credentials only for the
|
|
249
|
+
* configured services, pushes the schema with the db key and the
|
|
250
|
+
* rules with the developer token, and stores the provider key in the tenant
|
|
251
|
+
* vault when `ai.keyEnv` is set and present. Finally writes the credentials file
|
|
252
|
+
* (mode 0600, gitignored) and, when requested, `.dev.vars`.
|
|
253
|
+
*
|
|
254
|
+
* The developer token comes from (in order) `options.token`, `$ODLA_DEV_TOKEN`,
|
|
255
|
+
* the cached `.odla` token, or a fresh device handshake — which prints a user
|
|
256
|
+
* code + approval URL and, in interactive terminals, auto-opens the browser
|
|
257
|
+
* (`open: true`/`false` forces/suppresses it). Network error bodies pass through
|
|
258
|
+
* `redactSecrets` before display.
|
|
259
|
+
*
|
|
260
|
+
* @param options.dryRun Print the resolved plan and return before any network call/write.
|
|
261
|
+
* @param options.rotateKeys Rotate db keys and o11y tokens.
|
|
262
|
+
* @param options.rotateO11yToken Rotate only the o11y token.
|
|
263
|
+
* @param options.pushSecrets Preflight Wrangler, then push each env's configured
|
|
264
|
+
* Worker secrets immediately after credential provisioning.
|
|
265
|
+
* @param options.writeDevVars `true`/a path writes `.dev.vars`; `writeCredentials: false` skips the creds file.
|
|
266
|
+
* @param options.yes Required for a non-dry-run plan containing `prod` or
|
|
267
|
+
* `production`; callers must show and review `dryRun` output first.
|
|
268
|
+
* @throws When a production plan is executed without `yes`, configuration is
|
|
269
|
+
* invalid, authorization fails, or a provisioning operation fails.
|
|
270
|
+
*/
|
|
140
271
|
declare function provision(options: ProvisionOptions): Promise<void>;
|
|
141
272
|
|
|
273
|
+
/**
|
|
274
|
+
* Return `value` with every secret-shaped substring replaced by a `[redacted]`
|
|
275
|
+
* placeholder that keeps the identifying prefix (e.g. `sk_live_[redacted]`).
|
|
276
|
+
* Matches odla db keys (`odla_sk_`/`odla_dev_`), Clerk secret keys
|
|
277
|
+
* (`sk_live_`/`sk_test_`), OpenAI keys (`sk-`), webhook signing secrets
|
|
278
|
+
* (`whsec_`), o11y tokens (`o11y_`), GitHub tokens (`ghp_`/`gho_`/`github_pat_`),
|
|
279
|
+
* and AWS access-key ids (`AKIA…`). Clerk publishable keys (`pk_test_`/
|
|
280
|
+
* `pk_live_`) are public by design and intentionally left untouched. Used to
|
|
281
|
+
* sanitize anything the CLI echoes (notably network error bodies) before it
|
|
282
|
+
* reaches stdout/stderr. Non-matching input is returned unchanged.
|
|
283
|
+
*/
|
|
142
284
|
declare function redactSecrets(value: string): string;
|
|
143
285
|
|
|
144
|
-
|
|
145
|
-
code: number;
|
|
146
|
-
stdout: string;
|
|
147
|
-
stderr: string;
|
|
148
|
-
}
|
|
149
|
-
/** Subprocess seam: injectable in tests, `defaultRunner` in production. */
|
|
150
|
-
type CommandRunner = (cmd: string, args: string[], opts?: {
|
|
151
|
-
input?: string;
|
|
152
|
-
cwd?: string;
|
|
153
|
-
}) => Promise<RunResult>;
|
|
154
|
-
|
|
286
|
+
/** Moves locally stored configured service credentials to one Wrangler environment over stdin. */
|
|
155
287
|
interface SecretsPushOptions {
|
|
156
288
|
configPath: string;
|
|
157
289
|
env: string;
|
|
@@ -162,37 +294,89 @@ interface SecretsPushOptions {
|
|
|
162
294
|
stdout?: Pick<typeof console, "log" | "error">;
|
|
163
295
|
}
|
|
164
296
|
/**
|
|
165
|
-
* Moves the env's
|
|
166
|
-
*
|
|
167
|
-
*
|
|
297
|
+
* Moves the env's configured db and/or o11y credentials from the private local
|
|
298
|
+
* credentials file into the Worker, piping values over stdin so they never
|
|
299
|
+
* appear on argv, in output, or in the conversation transcript.
|
|
168
300
|
*/
|
|
169
301
|
declare function secretsPush(options: SecretsPushOptions): Promise<void>;
|
|
170
302
|
|
|
303
|
+
/** Agent harnesses with a first-class local adapter. */
|
|
304
|
+
declare const AGENT_HARNESSES: readonly ["claude", "codex", "cursor", "copilot", "gemini", "agents"];
|
|
305
|
+
/** A supported coding-agent harness. `agents` is the portable `AGENTS.md` adapter. */
|
|
306
|
+
type AgentHarness = (typeof AGENT_HARNESSES)[number];
|
|
307
|
+
/** A harness name accepted by setup; `all` expands to every project-local adapter. */
|
|
308
|
+
type AgentHarnessSelector = AgentHarness | "all";
|
|
309
|
+
/** Controls project-local or global installation of the bundled agent runbooks. */
|
|
171
310
|
interface SkillInstallOptions {
|
|
172
|
-
/** Project directory receiving
|
|
311
|
+
/** Project directory receiving the shared runbooks and harness adapters. Defaults to cwd. */
|
|
173
312
|
dir?: string;
|
|
174
|
-
/** Install
|
|
313
|
+
/** Install user-wide Claude and/or Codex skills instead of project adapters. */
|
|
175
314
|
global?: boolean;
|
|
176
|
-
/**
|
|
315
|
+
/** Harnesses to install. The programmatic compatibility default is `claude`; the CLI passes `all`. */
|
|
316
|
+
harnesses?: AgentHarnessSelector[];
|
|
317
|
+
/** Overwrite locally modified odla-managed files or managed instruction sections. */
|
|
177
318
|
force?: boolean;
|
|
178
319
|
/** Test/embedding override for the home directory. */
|
|
179
320
|
homeDir?: string;
|
|
321
|
+
/** Test/embedding override for `$CODEX_HOME`. */
|
|
322
|
+
codexHomeDir?: string;
|
|
180
323
|
/** Test/embedding override for the bundled skills directory. */
|
|
181
324
|
sourceDir?: string;
|
|
182
325
|
stdout?: Pick<typeof console, "log" | "error">;
|
|
183
326
|
}
|
|
327
|
+
/** One harness adapter and the directories or files through which it discovers odla. */
|
|
328
|
+
interface HarnessInstallResult {
|
|
329
|
+
harness: AgentHarness;
|
|
330
|
+
targets: string[];
|
|
331
|
+
}
|
|
332
|
+
/** Files written or left unchanged by an idempotent agent-runbook installation. */
|
|
184
333
|
interface SkillInstallResult {
|
|
334
|
+
/** Primary native skill directory, retained for compatibility with earlier callers. */
|
|
185
335
|
targetDir: string;
|
|
336
|
+
/** Files changed directly under `targetDir`, relative to that directory. */
|
|
186
337
|
written: string[];
|
|
338
|
+
/** Files already current directly under `targetDir`, relative to that directory. */
|
|
187
339
|
unchanged: string[];
|
|
340
|
+
/** Absolute paths of every changed shared-runbook or adapter file. */
|
|
341
|
+
writtenPaths: string[];
|
|
342
|
+
/** Absolute paths of every already-current shared-runbook or adapter file. */
|
|
343
|
+
unchangedPaths: string[];
|
|
344
|
+
harnesses: HarnessInstallResult[];
|
|
188
345
|
}
|
|
189
346
|
/**
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
347
|
+
* Installs one shared offline runbook tree plus thin native adapters for the
|
|
348
|
+
* selected coding-agent harnesses. Project installs use `.agents/skills/` as
|
|
349
|
+
* the canonical bundle; Claude Code, Cursor, Copilot, Gemini, and generic
|
|
350
|
+
* `AGENTS.md` adapters point to it. Global installs support the native Claude
|
|
351
|
+
* and Codex skill roots only.
|
|
352
|
+
*
|
|
353
|
+
* Installation is idempotent and planned before any write: an odla-managed
|
|
354
|
+
* file changed by the user aborts the whole operation unless `force` is set.
|
|
355
|
+
* Existing `AGENTS.md`, `GEMINI.md`, and Copilot instructions are preserved;
|
|
356
|
+
* only the bounded odla-managed section is appended or replaced.
|
|
193
357
|
*/
|
|
194
358
|
declare function installSkill(options?: SkillInstallOptions): SkillInstallResult;
|
|
195
359
|
|
|
360
|
+
/**
|
|
361
|
+
* Verify a live, already-provisioned environment end-to-end. Resolves the target
|
|
362
|
+
* env (`options.env`, else `dev`, else the first declared env) and requires it to
|
|
363
|
+
* be declared in the config. Reads the local credentials file and checks that it
|
|
364
|
+
* belongs to this app and holds a `tenantId` + `dbKey` for the env — otherwise it
|
|
365
|
+
* throws pointing the user at `odla-ai provision --write-dev-vars`.
|
|
366
|
+
*
|
|
367
|
+
* It then makes real network calls: fetches the registry public-config (and, when
|
|
368
|
+
* `ai.provider` is configured, asserts the live provider matches), fetches the
|
|
369
|
+
* live db schema with the db key and asserts every entity from the local schema
|
|
370
|
+
* is present, and runs a `count` aggregate against the first entity to confirm
|
|
371
|
+
* the db answers queries. Progress lines are printed and it ends with `ok`.
|
|
372
|
+
* Read-only — it writes nothing and throws on the first mismatch or failed
|
|
373
|
+
* request.
|
|
374
|
+
*
|
|
375
|
+
* @param options.configPath Path to the `odla.config.mjs`.
|
|
376
|
+
* @param options.env Env to check (default `dev`, else the first declared env).
|
|
377
|
+
* @param options.fetch Injectable `fetch` (for tests/embedding).
|
|
378
|
+
* @param options.stdout Optional console-like sink (defaults to `console`).
|
|
379
|
+
*/
|
|
196
380
|
declare function smoke(options: SmokeOptions): Promise<void>;
|
|
197
381
|
|
|
198
|
-
export { type LoadedProjectConfig, type LocalCredentials, type OdlaProjectConfig, type ProvisionOptions, type ProvisionPlan, type SecretsPushOptions, type SkillInstallOptions, type SkillInstallResult, type SmokeOptions, doctor, initProject, installSkill, provision, redactSecrets, runCli, secretsPush, smoke };
|
|
382
|
+
export { AGENT_HARNESSES, type AgentHarness, type AgentHarnessSelector, CAPABILITIES, type HarnessInstallResult, type LoadedProjectConfig, type LocalCredentials, type OdlaProjectConfig, type ProvisionOptions, type ProvisionPlan, type SecretsPushOptions, type SkillInstallOptions, type SkillInstallResult, type SmokeOptions, doctor, initProject, installSkill, printCapabilities, provision, redactSecrets, runCli, secretsPush, smoke };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse CLI arguments and dispatch to the matching command — the entry point
|
|
3
|
+
* `bin.ts` invokes. `argv` defaults to `process.argv.slice(2)`; the first
|
|
4
|
+
* positional selects the command and the rest are parsed into flags (supporting
|
|
5
|
+
* `--flag value`, `--flag=value`, boolean `--flag`, `--no-flag`, and repeated
|
|
6
|
+
* flags collected into arrays).
|
|
7
|
+
*
|
|
8
|
+
* Recognized commands: `version`/`-v`/`--version` and `help`/`-h`/`--help` print
|
|
9
|
+
* and return; `init` scaffolds a project (requires `--app-id` and `--name`);
|
|
10
|
+
* `doctor` validates config offline; `capabilities` prints the responsibility
|
|
11
|
+
* boundary; `provision` runs the full provision (including optional secret
|
|
12
|
+
* rotation, local vars, and deployed secret push); `smoke` checks a live env;
|
|
13
|
+
* `setup` and `skill install` install the bundled offline runbooks for Claude
|
|
14
|
+
* Code, Codex, Cursor, Copilot, Gemini, and `AGENTS.md`-aware agents; and
|
|
15
|
+
* `secrets push` pipes the env's configured db/o11y secrets into the Worker via
|
|
16
|
+
* Wrangler (requires `--env`). Throws on an unknown command/subcommand, unsupported option, extra
|
|
17
|
+
* positional argument, missing required value, or a dispatched command error.
|
|
18
|
+
*
|
|
19
|
+
* @param argv Argument vector without the node/script prefix (default
|
|
20
|
+
* `process.argv.slice(2)`).
|
|
21
|
+
*/
|
|
1
22
|
declare function runCli(argv?: string[]): Promise<void>;
|
|
2
23
|
|
|
24
|
+
/** Stable, machine-readable division of work between the CLI, coding agent,
|
|
25
|
+
* human operator, and Studio. Printed by `odla-ai capabilities --json`. */
|
|
26
|
+
declare const CAPABILITIES: {
|
|
27
|
+
readonly cli: readonly ["register the app and enable configured services per environment", "issue, persist, and explicitly rotate configured service credentials", "write local Worker values and push deployed Worker secrets through Wrangler stdin", "push db schema/rules and configure platform AI, auth, and deployment links", "validate config offline and smoke-test a provisioned db environment"];
|
|
28
|
+
readonly agent: readonly ["install and import the selected odla SDKs", "wrap the Worker with withObservability and choose useful telemetry", "make application-specific schema, rules, auth, UI, and migration decisions"];
|
|
29
|
+
readonly human: readonly ["approve the odla device code and one-off third-party logins", "consent to production changes with --yes", "request destructive credential rotation explicitly", "review application semantics, security findings, releases, and merges"];
|
|
30
|
+
readonly studio: readonly ["view telemetry and environment state", "perform manual credential recovery when the CLI's local shown-once copy is unavailable"];
|
|
31
|
+
};
|
|
32
|
+
type Output = Pick<typeof console, "log">;
|
|
33
|
+
/** Print the stable responsibility boundary for humans or agent tooling. */
|
|
34
|
+
declare function printCapabilities(json?: boolean, out?: Output): void;
|
|
35
|
+
|
|
3
36
|
interface DoctorOptions {
|
|
4
37
|
configPath: string;
|
|
5
38
|
stdout?: Pick<typeof console, "log" | "error">;
|
|
6
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Validate and summarize an odla project config entirely offline — no network
|
|
42
|
+
* calls and no file writes. Loads `configPath`, builds the provision plan, and
|
|
43
|
+
* resolves the schema and rules (synthesizing deny-all rules from the schema
|
|
44
|
+
* when `db.rules` is omitted and `db.defaultRules` isn't `false`), then prints a
|
|
45
|
+
* summary line for the app, envs, services, schema entity count, rules namespace
|
|
46
|
+
* count, and AI provider.
|
|
47
|
+
*
|
|
48
|
+
* It then collects warnings for the mistakes provision can't fix silently: a
|
|
49
|
+
* schema with no entities, a rules namespace with no matching entity, the `ai`
|
|
50
|
+
* service enabled without an `ai.provider`, `auth.clerk` entries that reference
|
|
51
|
+
* an unset env var (`$FOO`), an `ai.keyEnv` that isn't set (provider key upload
|
|
52
|
+
* will be skipped), and — when `o11y` is enabled — any env whose local
|
|
53
|
+
* credentials lack an ingest token. It also folds in the shared rule linter,
|
|
54
|
+
* git-tracked secret-shaped files, and wrangler config warnings. Prints `ok`
|
|
55
|
+
* when clean, otherwise the warning list. Purely advisory: never throws on
|
|
56
|
+
* warnings and never mutates anything.
|
|
57
|
+
*
|
|
58
|
+
* @param options.configPath Path to the `odla.config.mjs` to inspect.
|
|
59
|
+
* @param options.stdout Optional console-like sink (defaults to `console`).
|
|
60
|
+
*/
|
|
7
61
|
declare function doctor(options: DoctorOptions): Promise<void>;
|
|
8
62
|
|
|
9
63
|
interface InitOptions {
|
|
@@ -17,8 +71,44 @@ interface InitOptions {
|
|
|
17
71
|
force?: boolean;
|
|
18
72
|
stdout?: Pick<typeof console, "log" | "error">;
|
|
19
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Scaffold a new odla project into `rootDir` (default: cwd). Writes an
|
|
76
|
+
* `odla.config.mjs` (default name, overridable via `configPath`) plus starter
|
|
77
|
+
* `src/odla/schema.mjs` (a single `notes` entity) and `src/odla/rules.mjs`
|
|
78
|
+
* (deny-all), and creates the `src/odla` and `.odla` directories. Also runs
|
|
79
|
+
* `ensureGitignore` so the local token/credentials paths are ignored.
|
|
80
|
+
*
|
|
81
|
+
* Fully local and synchronous — no network calls. The config file is only
|
|
82
|
+
* written when it doesn't already exist unless `force` is set (otherwise it
|
|
83
|
+
* throws); the schema/rules files are written only when missing (never
|
|
84
|
+
* overwritten, even with `force`). `appId` must match `^[a-z0-9][a-z0-9-]*$` or
|
|
85
|
+
* it throws. Defaults: `envs` → `["dev"]`, `services` → `["db","ai"]`,
|
|
86
|
+
* `aiProvider` → `"anthropic"` (which also picks the `keyEnv`, e.g.
|
|
87
|
+
* `ANTHROPIC_API_KEY`/`OPENAI_API_KEY`/`GOOGLE_API_KEY`).
|
|
88
|
+
*
|
|
89
|
+
* @param options.appId Slug for the app (lowercase alphanumerics and hyphens).
|
|
90
|
+
* @param options.name Human-readable app name embedded in the config.
|
|
91
|
+
* @param options.rootDir Project root (defaults to `process.cwd()`).
|
|
92
|
+
* @param options.configPath Config filename relative to root (default `odla.config.mjs`).
|
|
93
|
+
* @param options.envs Environment names (default `["dev"]`; production is an explicit opt-in).
|
|
94
|
+
* @param options.services Enabled services (default `["db","ai"]`).
|
|
95
|
+
* @param options.aiProvider AI provider slug (default `"anthropic"`).
|
|
96
|
+
* @param options.force Overwrite an existing config file instead of throwing.
|
|
97
|
+
* @param options.stdout Optional console-like sink (defaults to `console`).
|
|
98
|
+
*/
|
|
20
99
|
declare function initProject(options: InitOptions): void;
|
|
21
100
|
|
|
101
|
+
interface RunResult {
|
|
102
|
+
code: number;
|
|
103
|
+
stdout: string;
|
|
104
|
+
stderr: string;
|
|
105
|
+
}
|
|
106
|
+
/** Subprocess seam: injectable in tests, `defaultRunner` in production. */
|
|
107
|
+
type CommandRunner = (cmd: string, args: string[], opts?: {
|
|
108
|
+
input?: string;
|
|
109
|
+
cwd?: string;
|
|
110
|
+
}) => Promise<RunResult>;
|
|
111
|
+
|
|
22
112
|
type OdlaEnvName = string;
|
|
23
113
|
type AppRules = Record<string, {
|
|
24
114
|
view?: string;
|
|
@@ -31,6 +121,7 @@ interface ClerkAuthConfig {
|
|
|
31
121
|
audience?: string;
|
|
32
122
|
mode?: "client" | "full";
|
|
33
123
|
}
|
|
124
|
+
/** Authored `odla.config.mjs` contract consumed by doctor and provision. */
|
|
34
125
|
interface OdlaProjectConfig {
|
|
35
126
|
platformUrl?: string;
|
|
36
127
|
dbEndpoint?: string;
|
|
@@ -77,6 +168,7 @@ interface OdlaProjectConfig {
|
|
|
77
168
|
gitignore?: boolean;
|
|
78
169
|
};
|
|
79
170
|
}
|
|
171
|
+
/** Normalized project config with resolved paths, endpoints, envs, and services. */
|
|
80
172
|
interface LoadedProjectConfig extends OdlaProjectConfig {
|
|
81
173
|
configPath: string;
|
|
82
174
|
rootDir: string;
|
|
@@ -91,6 +183,7 @@ interface LoadedProjectConfig extends OdlaProjectConfig {
|
|
|
91
183
|
gitignore: boolean;
|
|
92
184
|
};
|
|
93
185
|
}
|
|
186
|
+
/** Private mode-0600 local state written by provision and never committed. */
|
|
94
187
|
interface LocalCredentials {
|
|
95
188
|
appId: string;
|
|
96
189
|
platformUrl: string;
|
|
@@ -102,10 +195,15 @@ interface LocalCredentials {
|
|
|
102
195
|
o11yToken?: string;
|
|
103
196
|
}>;
|
|
104
197
|
}
|
|
198
|
+
/** Controls one dev-first provisioning run; production mutation requires `yes`. */
|
|
105
199
|
interface ProvisionOptions {
|
|
106
200
|
configPath: string;
|
|
107
201
|
dryRun?: boolean;
|
|
108
202
|
rotateKeys?: boolean;
|
|
203
|
+
/** Rotate only the o11y ingest token; leaves db keys unchanged. */
|
|
204
|
+
rotateO11yToken?: boolean;
|
|
205
|
+
/** Push configured Worker secrets to every configured env after provisioning. */
|
|
206
|
+
pushSecrets?: boolean;
|
|
109
207
|
writeCredentials?: boolean;
|
|
110
208
|
writeDevVars?: string | boolean;
|
|
111
209
|
token?: string;
|
|
@@ -115,10 +213,14 @@ interface ProvisionOptions {
|
|
|
115
213
|
interactive?: boolean;
|
|
116
214
|
/** Test/embedding override for opening the approval URL. Defaults to the OS browser opener. */
|
|
117
215
|
openApprovalUrl?: (url: string) => Promise<void>;
|
|
216
|
+
/** Explicit consent for a non-dry-run plan containing `prod` or `production`. */
|
|
118
217
|
yes?: boolean;
|
|
119
218
|
fetch?: typeof fetch;
|
|
219
|
+
/** Test/embedding override for Wrangler subprocesses used by `pushSecrets`. */
|
|
220
|
+
secretRunner?: CommandRunner;
|
|
120
221
|
stdout?: Pick<typeof console, "log" | "error">;
|
|
121
222
|
}
|
|
223
|
+
/** Human-reviewable, secret-free plan printed by `provision({ dryRun: true })`. */
|
|
122
224
|
interface ProvisionPlan {
|
|
123
225
|
appId: string;
|
|
124
226
|
appName: string;
|
|
@@ -130,6 +232,7 @@ interface ProvisionPlan {
|
|
|
130
232
|
hasRules: boolean;
|
|
131
233
|
aiProvider?: string;
|
|
132
234
|
}
|
|
235
|
+
/** Inputs for a read-only live environment smoke check. */
|
|
133
236
|
interface SmokeOptions {
|
|
134
237
|
configPath: string;
|
|
135
238
|
env?: string;
|
|
@@ -137,21 +240,50 @@ interface SmokeOptions {
|
|
|
137
240
|
stdout?: Pick<typeof console, "log" | "error">;
|
|
138
241
|
}
|
|
139
242
|
|
|
243
|
+
/**
|
|
244
|
+
* Provision an app end-to-end from its config — the primary deploy path, and
|
|
245
|
+
* (apart from key rotation) idempotent, so re-running is safe. Obtains a
|
|
246
|
+
* developer token, creates the registry app when absent, enables each service
|
|
247
|
+
* per env (AI also gets `setAi` with the configured provider/model), configures
|
|
248
|
+
* Clerk auth and links, then per env mints or reuses credentials only for the
|
|
249
|
+
* configured services, pushes the schema with the db key and the
|
|
250
|
+
* rules with the developer token, and stores the provider key in the tenant
|
|
251
|
+
* vault when `ai.keyEnv` is set and present. Finally writes the credentials file
|
|
252
|
+
* (mode 0600, gitignored) and, when requested, `.dev.vars`.
|
|
253
|
+
*
|
|
254
|
+
* The developer token comes from (in order) `options.token`, `$ODLA_DEV_TOKEN`,
|
|
255
|
+
* the cached `.odla` token, or a fresh device handshake — which prints a user
|
|
256
|
+
* code + approval URL and, in interactive terminals, auto-opens the browser
|
|
257
|
+
* (`open: true`/`false` forces/suppresses it). Network error bodies pass through
|
|
258
|
+
* `redactSecrets` before display.
|
|
259
|
+
*
|
|
260
|
+
* @param options.dryRun Print the resolved plan and return before any network call/write.
|
|
261
|
+
* @param options.rotateKeys Rotate db keys and o11y tokens.
|
|
262
|
+
* @param options.rotateO11yToken Rotate only the o11y token.
|
|
263
|
+
* @param options.pushSecrets Preflight Wrangler, then push each env's configured
|
|
264
|
+
* Worker secrets immediately after credential provisioning.
|
|
265
|
+
* @param options.writeDevVars `true`/a path writes `.dev.vars`; `writeCredentials: false` skips the creds file.
|
|
266
|
+
* @param options.yes Required for a non-dry-run plan containing `prod` or
|
|
267
|
+
* `production`; callers must show and review `dryRun` output first.
|
|
268
|
+
* @throws When a production plan is executed without `yes`, configuration is
|
|
269
|
+
* invalid, authorization fails, or a provisioning operation fails.
|
|
270
|
+
*/
|
|
140
271
|
declare function provision(options: ProvisionOptions): Promise<void>;
|
|
141
272
|
|
|
273
|
+
/**
|
|
274
|
+
* Return `value` with every secret-shaped substring replaced by a `[redacted]`
|
|
275
|
+
* placeholder that keeps the identifying prefix (e.g. `sk_live_[redacted]`).
|
|
276
|
+
* Matches odla db keys (`odla_sk_`/`odla_dev_`), Clerk secret keys
|
|
277
|
+
* (`sk_live_`/`sk_test_`), OpenAI keys (`sk-`), webhook signing secrets
|
|
278
|
+
* (`whsec_`), o11y tokens (`o11y_`), GitHub tokens (`ghp_`/`gho_`/`github_pat_`),
|
|
279
|
+
* and AWS access-key ids (`AKIA…`). Clerk publishable keys (`pk_test_`/
|
|
280
|
+
* `pk_live_`) are public by design and intentionally left untouched. Used to
|
|
281
|
+
* sanitize anything the CLI echoes (notably network error bodies) before it
|
|
282
|
+
* reaches stdout/stderr. Non-matching input is returned unchanged.
|
|
283
|
+
*/
|
|
142
284
|
declare function redactSecrets(value: string): string;
|
|
143
285
|
|
|
144
|
-
|
|
145
|
-
code: number;
|
|
146
|
-
stdout: string;
|
|
147
|
-
stderr: string;
|
|
148
|
-
}
|
|
149
|
-
/** Subprocess seam: injectable in tests, `defaultRunner` in production. */
|
|
150
|
-
type CommandRunner = (cmd: string, args: string[], opts?: {
|
|
151
|
-
input?: string;
|
|
152
|
-
cwd?: string;
|
|
153
|
-
}) => Promise<RunResult>;
|
|
154
|
-
|
|
286
|
+
/** Moves locally stored configured service credentials to one Wrangler environment over stdin. */
|
|
155
287
|
interface SecretsPushOptions {
|
|
156
288
|
configPath: string;
|
|
157
289
|
env: string;
|
|
@@ -162,37 +294,89 @@ interface SecretsPushOptions {
|
|
|
162
294
|
stdout?: Pick<typeof console, "log" | "error">;
|
|
163
295
|
}
|
|
164
296
|
/**
|
|
165
|
-
* Moves the env's
|
|
166
|
-
*
|
|
167
|
-
*
|
|
297
|
+
* Moves the env's configured db and/or o11y credentials from the private local
|
|
298
|
+
* credentials file into the Worker, piping values over stdin so they never
|
|
299
|
+
* appear on argv, in output, or in the conversation transcript.
|
|
168
300
|
*/
|
|
169
301
|
declare function secretsPush(options: SecretsPushOptions): Promise<void>;
|
|
170
302
|
|
|
303
|
+
/** Agent harnesses with a first-class local adapter. */
|
|
304
|
+
declare const AGENT_HARNESSES: readonly ["claude", "codex", "cursor", "copilot", "gemini", "agents"];
|
|
305
|
+
/** A supported coding-agent harness. `agents` is the portable `AGENTS.md` adapter. */
|
|
306
|
+
type AgentHarness = (typeof AGENT_HARNESSES)[number];
|
|
307
|
+
/** A harness name accepted by setup; `all` expands to every project-local adapter. */
|
|
308
|
+
type AgentHarnessSelector = AgentHarness | "all";
|
|
309
|
+
/** Controls project-local or global installation of the bundled agent runbooks. */
|
|
171
310
|
interface SkillInstallOptions {
|
|
172
|
-
/** Project directory receiving
|
|
311
|
+
/** Project directory receiving the shared runbooks and harness adapters. Defaults to cwd. */
|
|
173
312
|
dir?: string;
|
|
174
|
-
/** Install
|
|
313
|
+
/** Install user-wide Claude and/or Codex skills instead of project adapters. */
|
|
175
314
|
global?: boolean;
|
|
176
|
-
/**
|
|
315
|
+
/** Harnesses to install. The programmatic compatibility default is `claude`; the CLI passes `all`. */
|
|
316
|
+
harnesses?: AgentHarnessSelector[];
|
|
317
|
+
/** Overwrite locally modified odla-managed files or managed instruction sections. */
|
|
177
318
|
force?: boolean;
|
|
178
319
|
/** Test/embedding override for the home directory. */
|
|
179
320
|
homeDir?: string;
|
|
321
|
+
/** Test/embedding override for `$CODEX_HOME`. */
|
|
322
|
+
codexHomeDir?: string;
|
|
180
323
|
/** Test/embedding override for the bundled skills directory. */
|
|
181
324
|
sourceDir?: string;
|
|
182
325
|
stdout?: Pick<typeof console, "log" | "error">;
|
|
183
326
|
}
|
|
327
|
+
/** One harness adapter and the directories or files through which it discovers odla. */
|
|
328
|
+
interface HarnessInstallResult {
|
|
329
|
+
harness: AgentHarness;
|
|
330
|
+
targets: string[];
|
|
331
|
+
}
|
|
332
|
+
/** Files written or left unchanged by an idempotent agent-runbook installation. */
|
|
184
333
|
interface SkillInstallResult {
|
|
334
|
+
/** Primary native skill directory, retained for compatibility with earlier callers. */
|
|
185
335
|
targetDir: string;
|
|
336
|
+
/** Files changed directly under `targetDir`, relative to that directory. */
|
|
186
337
|
written: string[];
|
|
338
|
+
/** Files already current directly under `targetDir`, relative to that directory. */
|
|
187
339
|
unchanged: string[];
|
|
340
|
+
/** Absolute paths of every changed shared-runbook or adapter file. */
|
|
341
|
+
writtenPaths: string[];
|
|
342
|
+
/** Absolute paths of every already-current shared-runbook or adapter file. */
|
|
343
|
+
unchangedPaths: string[];
|
|
344
|
+
harnesses: HarnessInstallResult[];
|
|
188
345
|
}
|
|
189
346
|
/**
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
347
|
+
* Installs one shared offline runbook tree plus thin native adapters for the
|
|
348
|
+
* selected coding-agent harnesses. Project installs use `.agents/skills/` as
|
|
349
|
+
* the canonical bundle; Claude Code, Cursor, Copilot, Gemini, and generic
|
|
350
|
+
* `AGENTS.md` adapters point to it. Global installs support the native Claude
|
|
351
|
+
* and Codex skill roots only.
|
|
352
|
+
*
|
|
353
|
+
* Installation is idempotent and planned before any write: an odla-managed
|
|
354
|
+
* file changed by the user aborts the whole operation unless `force` is set.
|
|
355
|
+
* Existing `AGENTS.md`, `GEMINI.md`, and Copilot instructions are preserved;
|
|
356
|
+
* only the bounded odla-managed section is appended or replaced.
|
|
193
357
|
*/
|
|
194
358
|
declare function installSkill(options?: SkillInstallOptions): SkillInstallResult;
|
|
195
359
|
|
|
360
|
+
/**
|
|
361
|
+
* Verify a live, already-provisioned environment end-to-end. Resolves the target
|
|
362
|
+
* env (`options.env`, else `dev`, else the first declared env) and requires it to
|
|
363
|
+
* be declared in the config. Reads the local credentials file and checks that it
|
|
364
|
+
* belongs to this app and holds a `tenantId` + `dbKey` for the env — otherwise it
|
|
365
|
+
* throws pointing the user at `odla-ai provision --write-dev-vars`.
|
|
366
|
+
*
|
|
367
|
+
* It then makes real network calls: fetches the registry public-config (and, when
|
|
368
|
+
* `ai.provider` is configured, asserts the live provider matches), fetches the
|
|
369
|
+
* live db schema with the db key and asserts every entity from the local schema
|
|
370
|
+
* is present, and runs a `count` aggregate against the first entity to confirm
|
|
371
|
+
* the db answers queries. Progress lines are printed and it ends with `ok`.
|
|
372
|
+
* Read-only — it writes nothing and throws on the first mismatch or failed
|
|
373
|
+
* request.
|
|
374
|
+
*
|
|
375
|
+
* @param options.configPath Path to the `odla.config.mjs`.
|
|
376
|
+
* @param options.env Env to check (default `dev`, else the first declared env).
|
|
377
|
+
* @param options.fetch Injectable `fetch` (for tests/embedding).
|
|
378
|
+
* @param options.stdout Optional console-like sink (defaults to `console`).
|
|
379
|
+
*/
|
|
196
380
|
declare function smoke(options: SmokeOptions): Promise<void>;
|
|
197
381
|
|
|
198
|
-
export { type LoadedProjectConfig, type LocalCredentials, type OdlaProjectConfig, type ProvisionOptions, type ProvisionPlan, type SecretsPushOptions, type SkillInstallOptions, type SkillInstallResult, type SmokeOptions, doctor, initProject, installSkill, provision, redactSecrets, runCli, secretsPush, smoke };
|
|
382
|
+
export { AGENT_HARNESSES, type AgentHarness, type AgentHarnessSelector, CAPABILITIES, type HarnessInstallResult, type LoadedProjectConfig, type LocalCredentials, type OdlaProjectConfig, type ProvisionOptions, type ProvisionPlan, type SecretsPushOptions, type SkillInstallOptions, type SkillInstallResult, type SmokeOptions, doctor, initProject, installSkill, printCapabilities, provision, redactSecrets, runCli, secretsPush, smoke };
|