@odla-ai/cli 0.34.0 → 0.34.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 (32) hide show
  1. package/README.md +130 -119
  2. package/REQUIREMENTS.md +6 -0
  3. package/dist/bin.cjs +50 -37
  4. package/dist/bin.cjs.map +1 -1
  5. package/dist/bin.js +1 -1
  6. package/dist/{chunk-LGNNX6AP.js → chunk-RUEM7ZTA.js} +51 -38
  7. package/dist/chunk-RUEM7ZTA.js.map +1 -0
  8. package/dist/{cli-IN6WGMSY.js → cli-NKNQLWOM.js} +2 -2
  9. package/dist/index.cjs +50 -37
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.js +1 -1
  12. package/package.json +1 -1
  13. package/skills/odla/SKILL.md +55 -35
  14. package/skills/odla/references/agent-identity.md +5 -5
  15. package/skills/odla/references/build.md +16 -15
  16. package/skills/odla/references/co-owners.md +1 -1
  17. package/skills/odla/references/pm-work-intake.md +12 -12
  18. package/skills/odla/references/pm.md +17 -17
  19. package/skills/odla/references/sdks.md +2 -2
  20. package/skills/odla-migrate/SKILL.md +23 -5
  21. package/skills/odla-migrate/references/phase-2-chapter.md +1 -1
  22. package/skills/odla-migrate/references/phase-2-db.md +11 -10
  23. package/skills/odla-migrate/references/phase-3-auth.md +2 -2
  24. package/skills/odla-migrate/references/phase-3b-user-sync.md +2 -2
  25. package/skills/odla-migrate/references/phase-4-ai.md +3 -3
  26. package/skills/odla-migrate/references/phase-5-cutover.md +5 -5
  27. package/skills/odla-migrate/references/project-state.md +4 -4
  28. package/skills/odla-migrate/references/secrets-map.md +6 -6
  29. package/skills/odla-migrate/references/troubleshooting.md +23 -23
  30. package/skills/odla-o11y-debug/SKILL.md +3 -3
  31. package/dist/chunk-LGNNX6AP.js.map +0 -1
  32. /package/dist/{cli-IN6WGMSY.js.map → cli-NKNQLWOM.js.map} +0 -0
package/README.md CHANGED
@@ -30,10 +30,10 @@ day.
30
30
  Ask before you search the web or work from memory:
31
31
 
32
32
  ```bash
33
- npx @odla-ai/cli runbook ask "how do I roll back a bad publish?" # written, cited answer
34
- npx @odla-ai/cli runbook search "restore a tenant" # the passages behind it
35
- npx @odla-ai/cli runbook get release # the whole procedure
36
- npx @odla-ai/cli runbook list # what exists
33
+ npx --yes @odla-ai/cli@latest runbook ask "how do I roll back a bad publish?" # written, cited answer
34
+ npx --yes @odla-ai/cli@latest runbook search "restore a tenant" # the passages behind it
35
+ npx --yes @odla-ai/cli@latest runbook get release # the whole procedure
36
+ npx --yes @odla-ai/cli@latest runbook list # what exists
37
37
  ```
38
38
 
39
39
  Reading works for any signed-in developer and needs no `odla.config.mjs` — the
@@ -45,9 +45,9 @@ Before an agent reads PM, Discussions, o11y, runbooks, or identity from a fresh
45
45
  workspace, it can explain the selected context without authenticating:
46
46
 
47
47
  ```bash
48
- npx @odla-ai/cli context show --platform https://odla.ai --app <appId> --env prod --json
49
- npx @odla-ai/cli context save production --platform https://odla.ai --app <appId> --env prod
50
- npx @odla-ai/cli context show --context production --json
48
+ npx --yes @odla-ai/cli@latest context show --platform https://odla.ai --app <appId> --env prod --json
49
+ npx --yes @odla-ai/cli@latest context save production --platform https://odla.ai --app <appId> --env prod
50
+ npx --yes @odla-ai/cli@latest context show --context production --json
51
51
  ```
52
52
 
53
53
  For each value, an explicit flag wins over the matching
@@ -81,13 +81,13 @@ project. The installed `references/agent-identity.md` runbook gives the full
81
81
  cross-worktree recovery procedure.
82
82
 
83
83
  ```bash
84
- ODLA_DEV_TOKEN=... npx @odla-ai/cli pm handoff --app <appId>
85
- ODLA_DEV_TOKEN=... npx @odla-ai/cli discuss list --app <appId> --json
86
- ODLA_DEV_TOKEN=... npx @odla-ai/cli o11y status --app <appId> --env prod --json
87
- ODLA_DEV_TOKEN=... npx @odla-ai/cli whoami --json
88
- npx @odla-ai/cli platform status --context production --json
89
- npx @odla-ai/cli pm handoff --context production --json
90
- npx @odla-ai/cli runbook new deploy --context production --title Deploy --file deploy.md
84
+ ODLA_DEV_TOKEN=... npx --yes @odla-ai/cli@latest pm handoff --app <appId>
85
+ ODLA_DEV_TOKEN=... npx --yes @odla-ai/cli@latest discuss list --app <appId> --json
86
+ ODLA_DEV_TOKEN=... npx --yes @odla-ai/cli@latest o11y status --app <appId> --env prod --json
87
+ ODLA_DEV_TOKEN=... npx --yes @odla-ai/cli@latest whoami --json
88
+ npx --yes @odla-ai/cli@latest platform status --context production --json
89
+ npx --yes @odla-ai/cli@latest pm handoff --context production --json
90
+ npx --yes @odla-ai/cli@latest runbook new deploy --context production --title Deploy --file deploy.md
91
91
  ```
92
92
 
93
93
  Runbooks tell an agent how to operate; PM tells every agent what this project is
@@ -96,15 +96,15 @@ app is registered, start each session with the read-only aligned-work intake,
96
96
  then read open bugs and recent decisions:
97
97
 
98
98
  ```bash
99
- npx odla-ai pm project list --app <productId>
100
- npx odla-ai pm project add --app <productId> --name "My project"
101
- npx odla-ai pm project use <projectId>
102
- npx odla-ai pm next --app <appId> --project <projectId>
103
- npx odla-ai pm handoff --app <appId>
104
- npx odla-ai pm watch --app <appId> --entity task --jsonl
105
- npx odla-ai pm bug list --app <appId> --status open
106
- npx odla-ai pm goal list --app <appId> --status open
107
- npx odla-ai pm decision list --app <appId> --limit 20
99
+ npx --yes @odla-ai/cli@latest pm project list --app <productId>
100
+ npx --yes @odla-ai/cli@latest pm project add --app <productId> --name "My project"
101
+ npx --yes @odla-ai/cli@latest pm project use <projectId>
102
+ npx --yes @odla-ai/cli@latest pm next --app <appId> --project <projectId>
103
+ npx --yes @odla-ai/cli@latest pm handoff --app <appId>
104
+ npx --yes @odla-ai/cli@latest pm watch --app <appId> --entity task --jsonl
105
+ npx --yes @odla-ai/cli@latest pm bug list --app <appId> --status open
106
+ npx --yes @odla-ai/cli@latest pm goal list --app <appId> --status open
107
+ npx --yes @odla-ai/cli@latest pm decision list --app <appId> --limit 20
108
108
  ```
109
109
 
110
110
  `pm handoff` is the authoritative unresolved-state view: unmet goals, every
@@ -129,8 +129,8 @@ Refine a Backlog task with `--goal` (or an accepted
129
129
  and claim the reviewed revision:
130
130
 
131
131
  ```bash
132
- npx odla-ai pm task ready <id> --expected-revision <n>
133
- npx odla-ai pm task claim <id> --expected-revision <n>
132
+ npx --yes @odla-ai/cli@latest pm task ready <id> --expected-revision <n>
133
+ npx --yes @odla-ai/cli@latest pm task claim <id> --expected-revision <n>
134
134
  ```
135
135
 
136
136
  Ready is stored as `todo` for API compatibility. Claims are atomic and assign
@@ -160,7 +160,7 @@ When diagnosing a deployed app, agents can request one parseable observability
160
160
  snapshot instead of scraping Studio or composing collector routes themselves:
161
161
 
162
162
  ```bash
163
- npx odla-ai o11y status --app <appId> --env prod --minutes 60 --json
163
+ npx --yes @odla-ai/cli@latest o11y status --app <appId> --env prod --minutes 60 --json
164
164
  ```
165
165
 
166
166
  Schema v9 keeps application RED, an `applicationVersions` breakdown of
@@ -242,19 +242,19 @@ slos: [{
242
242
  rollout is `ops/monitoring/odla-db.config.mjs`:
243
243
 
244
244
  ```bash
245
- npx odla-ai monitor plan --config ops/monitoring/odla-db.config.mjs --env prod --json
245
+ npx --yes @odla-ai/cli@latest monitor plan --config ops/monitoring/odla-db.config.mjs --env prod --json
246
246
  ```
247
247
 
248
248
  Preview and apply the normalized policy, then inspect or exercise it through
249
249
  stable JSON:
250
250
 
251
251
  ```bash
252
- npx odla-ai monitor plan --env prod --json
253
- npx odla-ai monitor apply --env prod --yes --json
254
- npx odla-ai monitor status --app <appId> --env prod --json
255
- npx odla-ai monitor run home --app <appId> --env prod --json
256
- npx odla-ai monitor incidents --app <appId> --env prod --runs --json
257
- npx odla-ai monitor report --app <appId> --env prod --period weekly --json
252
+ npx --yes @odla-ai/cli@latest monitor plan --env prod --json
253
+ npx --yes @odla-ai/cli@latest monitor apply --env prod --yes --json
254
+ npx --yes @odla-ai/cli@latest monitor status --app <appId> --env prod --json
255
+ npx --yes @odla-ai/cli@latest monitor run home --app <appId> --env prod --json
256
+ npx --yes @odla-ai/cli@latest monitor incidents --app <appId> --env prod --runs --json
257
+ npx --yes @odla-ai/cli@latest monitor report --app <appId> --env prod --period weekly --json
258
258
  ```
259
259
 
260
260
  Only scheduled `good` and `bad` outcomes enter the application SLO denominator.
@@ -285,10 +285,10 @@ For repository-managed settings, compare checked-in intent with the live
285
285
  owner-visible Registry projection before provisioning:
286
286
 
287
287
  ```bash
288
- npx odla-ai config diff --json
289
- npx odla-ai config plan --json > .odla/config-plan.json
290
- npx odla-ai config apply --plan .odla/config-plan.json --json
291
- npx odla-ai operations wait <operation-id> --json
288
+ npx --yes @odla-ai/cli@latest config diff --json
289
+ npx --yes @odla-ai/cli@latest config plan --json > .odla/config-plan.json
290
+ npx --yes @odla-ai/cli@latest config apply --plan .odla/config-plan.json --json
291
+ npx --yes @odla-ai/cli@latest operations wait <operation-id> --json
292
292
  ```
293
293
 
294
294
  `diff` and `plan` are read-only and request only a short-lived,
@@ -339,8 +339,8 @@ JSDoc, and neither from memory.
339
339
  **After you change something, ask which runbooks you invalidated:**
340
340
 
341
341
  ```bash
342
- npx @odla-ai/cli runbook impact # vs origin/main, uncommitted work included
343
- npx @odla-ai/cli runbook impact --base HEAD~1
342
+ npx --yes @odla-ai/cli@latest runbook impact # vs origin/main, uncommitted work included
343
+ npx --yes @odla-ai/cli@latest runbook impact --base HEAD~1
344
344
  ```
345
345
 
346
346
  It diffs the working tree, works out which surfaces moved — a package, its
@@ -351,7 +351,7 @@ before you call the change finished. Fixing what it finds is one command and
351
351
  takes effect immediately:
352
352
 
353
353
  ```bash
354
- npx @odla-ai/cli runbook edit db --note "retract replaced the null write"
354
+ npx --yes @odla-ai/cli@latest runbook edit db --note "retract replaced the null write"
355
355
  ```
356
356
 
357
357
  Platform runbook edits need admin or the `platform:runbook:write` capability,
@@ -364,7 +364,7 @@ but never grants authority.
364
364
  **Is the corpus itself still true?**
365
365
 
366
366
  ```bash
367
- npx odla-ai runbook lint
367
+ npx --yes @odla-ai/cli@latest runbook lint
368
368
  ```
369
369
 
370
370
  Because a runbook is edited without a release, its text can name a command that
@@ -381,16 +381,20 @@ the procedure and nothing else.
381
381
  ## Install
382
382
 
383
383
  No install needed — the package ships a single `odla-ai` binary, so npx can run
384
- it directly:
384
+ it directly. Agents and one-off setup should resolve the current published CLI
385
+ explicitly:
385
386
 
386
387
  ```bash
387
- npx @odla-ai/cli init --app-id my-app --name "My App"
388
+ npx --yes @odla-ai/cli@latest init --app-id my-app --name "My App"
388
389
  ```
389
390
 
390
391
  For a project you keep working in, install it as a dev dependency so the
391
- shorter `npx odla-ai` form works. ODLA is under active development: use a normal
392
- dependency declaration, commit the lockfile, and let `npm ci` reproduce the
393
- resolved graph:
392
+ lockfile records the CLI/runtime graph used by that application. Use
393
+ `npx --no-install odla-ai` only when deliberately testing that pinned graph;
394
+ agent orchestration examples use `@latest` so a stale workspace or cache does
395
+ not silently select an older CLI. ODLA is under active development: use a
396
+ normal dependency declaration, commit the lockfile, and let `npm ci` reproduce
397
+ the resolved graph:
394
398
 
395
399
  ```bash
396
400
  npm view @odla-ai/cli version
@@ -419,61 +423,62 @@ npm ls @odla-ai/cli
419
423
  ## Commands
420
424
 
421
425
  ```bash
422
- npx odla-ai runbook ask "how do I roll back a bad publish?"
423
- npx odla-ai runbook search "restore a tenant" --limit 5
424
- npx odla-ai runbook get release
425
- npx odla-ai runbook list
426
- npx odla-ai runbook impact --base origin/main
427
- npx odla-ai runbook lint
428
- npx odla-ai runbook edit db --note "what changed"
429
- npx odla-ai runbook comment release --body "step 4 no longer applies"
430
- npx odla-ai context show --app my-app --env prod --json
431
- npx odla-ai whoami
432
- npx odla-ai setup
433
- npx odla-ai init --app-id my-app --name "My App"
434
- npx odla-ai doctor
435
- npx odla-ai ai models --env dev # exact models this app may select; no admin grant
436
- npx odla-ai config diff --json
437
- npx odla-ai config plan --json > .odla/config-plan.json
438
- npx odla-ai config apply --plan .odla/config-plan.json --json
439
- npx odla-ai operations get <operation-id> --json
440
- npx odla-ai operations wait <operation-id> --timeout 60 --json
441
- npx odla-ai calendar status --env dev
442
- npx odla-ai calendar calendars --env dev
443
- npx odla-ai calendar connect --env dev
444
- npx odla-ai calendar disconnect --env dev --yes
445
- npx odla-ai capabilities --json
446
- npx odla-ai code connect --platform https://odla.ai --app-id my-app --env dev --email owner@example.com
447
- npx odla-ai code connect --env prod --once # bounded enrollment + heartbeat proof
426
+ npx --yes @odla-ai/cli@latest auth login --app my-app --email owner@example.com --no-open --wait 600
427
+ npx --yes @odla-ai/cli@latest runbook ask "how do I roll back a bad publish?"
428
+ npx --yes @odla-ai/cli@latest runbook search "restore a tenant" --limit 5
429
+ npx --yes @odla-ai/cli@latest runbook get release
430
+ npx --yes @odla-ai/cli@latest runbook list
431
+ npx --yes @odla-ai/cli@latest runbook impact --base origin/main
432
+ npx --yes @odla-ai/cli@latest runbook lint
433
+ npx --yes @odla-ai/cli@latest runbook edit db --note "what changed"
434
+ npx --yes @odla-ai/cli@latest runbook comment release --body "step 4 no longer applies"
435
+ npx --yes @odla-ai/cli@latest context show --app my-app --env prod --json
436
+ npx --yes @odla-ai/cli@latest whoami
437
+ npx --yes @odla-ai/cli@latest setup
438
+ npx --yes @odla-ai/cli@latest init --app-id my-app --name "My App"
439
+ npx --yes @odla-ai/cli@latest doctor
440
+ npx --yes @odla-ai/cli@latest ai models --env dev # exact models this app may select; no admin grant
441
+ npx --yes @odla-ai/cli@latest config diff --json
442
+ npx --yes @odla-ai/cli@latest config plan --json > .odla/config-plan.json
443
+ npx --yes @odla-ai/cli@latest config apply --plan .odla/config-plan.json --json
444
+ npx --yes @odla-ai/cli@latest operations get <operation-id> --json
445
+ npx --yes @odla-ai/cli@latest operations wait <operation-id> --timeout 60 --json
446
+ npx --yes @odla-ai/cli@latest calendar status --env dev
447
+ npx --yes @odla-ai/cli@latest calendar calendars --env dev
448
+ npx --yes @odla-ai/cli@latest calendar connect --env dev --no-open
449
+ npx --yes @odla-ai/cli@latest calendar disconnect --env dev --yes
450
+ npx --yes @odla-ai/cli@latest capabilities --json
451
+ npx --yes @odla-ai/cli@latest code connect --platform https://odla.ai --app-id my-app --env dev --email owner@example.com --no-open
452
+ npx --yes @odla-ai/cli@latest code connect --env prod --once --no-open # bounded enrollment + heartbeat proof
448
453
  # install SDKs, write the Worker, and create wrangler.jsonc before secret push
449
- npx odla-ai provision --dry-run
450
- npx odla-ai provision --email owner@example.com --write-dev-vars --push-secrets
454
+ npx --yes @odla-ai/cli@latest provision --dry-run
455
+ npx --yes @odla-ai/cli@latest provision --email owner@example.com --write-dev-vars --push-secrets --no-open --wait 600
451
456
  # recovery when the selected agent credential has no live app.manage grant
452
- npx odla-ai provision --request-grant --email owner@example.com --write-dev-vars --push-secrets
453
- npx odla-ai smoke --env dev
454
- npx odla-ai agent jobs --env dev --state dead_letter --json
455
- npx odla-ai agent retry <job-id> --env dev --json
456
- npx odla-ai discuss watch <topic-id> --jsonl
457
- npx odla-ai discuss watch <topic-id> --cursor <saved-cursor> --jsonl
458
- npx odla-ai secrets push --env dev
459
- npx odla-ai secrets set clerk_webhook_secret --env dev --stdin
460
- npx odla-ai secrets set-clerk-key --env dev --from-env CLERK_SECRET_KEY
461
- npx odla-ai security run . --env dev --ack-redacted-source
462
- npx odla-ai security github connect --env dev # infers owner/name from git origin
463
- npx odla-ai security plan --env dev
464
- npx odla-ai security sources --env dev
465
- npx odla-ai security run --source <source-id> --ref main --env dev --plan-digest <digest-from-security-plan> --ack-redacted-source
466
- npx odla-ai security status <job-id>
467
- npx odla-ai security report <job-id>
468
- npx odla-ai admin ai show --context production --email owner@example.com
469
- npx odla-ai admin ai models --context production
470
- npx odla-ai admin ai set security --context production --discovery-provider anthropic --discovery-model claude-opus-4-8 --validation-provider openai --validation-model gpt-5.5 --enabled
471
- npx odla-ai admin ai credentials --context production
472
- npx odla-ai admin ai credential set anthropic --context production --from-env ANTHROPIC_API_KEY
473
- npx odla-ai admin ai usage --context production --app-id my-app --env prod --limit 50
474
- npx odla-ai admin ai audit --context production --limit 25
475
- npx odla-ai skill install
476
- npx odla-ai version
457
+ npx --yes @odla-ai/cli@latest provision --request-grant --email owner@example.com --write-dev-vars --push-secrets --no-open --wait 600
458
+ npx --yes @odla-ai/cli@latest smoke --env dev
459
+ npx --yes @odla-ai/cli@latest agent jobs --env dev --state dead_letter --json
460
+ npx --yes @odla-ai/cli@latest agent retry <job-id> --env dev --json
461
+ npx --yes @odla-ai/cli@latest discuss watch <topic-id> --jsonl
462
+ npx --yes @odla-ai/cli@latest discuss watch <topic-id> --cursor <saved-cursor> --jsonl
463
+ npx --yes @odla-ai/cli@latest secrets push --env dev
464
+ npx --yes @odla-ai/cli@latest secrets set clerk_webhook_secret --env dev --stdin
465
+ npx --yes @odla-ai/cli@latest secrets set-clerk-key --env dev --from-env CLERK_SECRET_KEY
466
+ npx --yes @odla-ai/cli@latest security run . --env dev --ack-redacted-source
467
+ npx --yes @odla-ai/cli@latest security github connect --env dev --no-open # infers owner/name from git origin
468
+ npx --yes @odla-ai/cli@latest security plan --env dev
469
+ npx --yes @odla-ai/cli@latest security sources --env dev
470
+ npx --yes @odla-ai/cli@latest security run --source <source-id> --ref main --env dev --plan-digest <digest-from-security-plan> --ack-redacted-source
471
+ npx --yes @odla-ai/cli@latest security status <job-id>
472
+ npx --yes @odla-ai/cli@latest security report <job-id>
473
+ npx --yes @odla-ai/cli@latest admin ai show --context production --email owner@example.com --no-open
474
+ npx --yes @odla-ai/cli@latest admin ai models --context production
475
+ npx --yes @odla-ai/cli@latest admin ai set security --context production --discovery-provider anthropic --discovery-model claude-opus-4-8 --validation-provider openai --validation-model gpt-5.5 --enabled
476
+ npx --yes @odla-ai/cli@latest admin ai credentials --context production
477
+ npx --yes @odla-ai/cli@latest admin ai credential set anthropic --context production --from-env ANTHROPIC_API_KEY
478
+ npx --yes @odla-ai/cli@latest admin ai usage --context production --app-id my-app --env prod --limit 50
479
+ npx --yes @odla-ai/cli@latest admin ai audit --context production --limit 25
480
+ npx --yes @odla-ai/cli@latest skill install
481
+ npx --yes @odla-ai/cli@latest version
477
482
  ```
478
483
 
479
484
  Before a non-dry provisioning run, the executable verifies two independent
@@ -553,8 +558,8 @@ New configs contain only the `dev` environment. After the development flow is
553
558
  healthy, initialize the existing app's live instance without editing the config:
554
559
 
555
560
  ```sh
556
- npx @odla-ai/cli provision --live --dry-run
557
- npx @odla-ai/cli provision --live --yes --push-secrets
561
+ npx --yes @odla-ai/cli@latest provision --live --dry-run
562
+ npx --yes @odla-ai/cli@latest provision --live --yes --push-secrets
558
563
  ```
559
564
 
560
565
  `--live` targets only `prod`, enables every configured service, provisions its
@@ -595,16 +600,22 @@ credential set.
595
600
  the exact project id does not exist yet, approval reserves that id for this
596
601
  credential instead of failing: the credential may create only that app once,
597
602
  and Registry binds its reviewed grant to the new app incarnation.
598
- Every real CLI handshake prints exactly one canonical `/studio?code=…` URL
599
- and attempts to open it including from CI, SSH, display-less, scripted,
600
- and agent-driven shells. Only `--no-open` suppresses the attempt. Browser
601
- launch is best-effort: an agent with browser control must open that exact URL
602
- immediately; otherwise it gives the URL to the human verbatim. The device
603
- code stays only in the running process. Outside an interactive terminal the
604
- approval wait is capped (90 seconds by default; `--wait <seconds>`
605
- overrides), and a still-pending handshake exits with code 75. Rerunning
606
- always requests and opens a new code; it never resumes an older request from
607
- `.odla/`.
603
+ Every real CLI handshake prints exactly one canonical `/studio?code=…` URL.
604
+ Interactive humans may use the CLI's best-effort browser launch. Agents use
605
+ the current published CLI with `--no-open --wait 600`, immediately surface
606
+ that exact URL and code as a clickable human approval action, and preserve
607
+ the same foreground process:
608
+
609
+ ```bash
610
+ npx --yes @odla-ai/cli@latest auth login --app <appId> --email <odla-account> --no-open --wait 600
611
+ ```
612
+
613
+ The CLI owns protocol polling. An agent must not call OS `open`, use browser
614
+ control, curl a handshake endpoint, build a shell wait loop, detach the
615
+ process, or start a substitute handshake. The device code stays only in the
616
+ running process. If that process exits 75, the old code cannot be collected;
617
+ a later invocation requests a new code and never resumes an older request
618
+ from `.odla/`.
608
619
  2. Creates the platform app if needed. For a new id, this consumes the exact-id
609
620
  reservation approved in step 1; it is not ambient project-creation authority.
610
621
  3. Enables configured services in every configured environment. Calendar
@@ -649,8 +660,8 @@ working sibling runtime.
649
660
  Inventory and retire one successful deployment without disturbing any sibling:
650
661
 
651
662
  ```sh
652
- npx @odla-ai/cli credentials list --env dev
653
- npx @odla-ai/cli credentials revoke <receipt-id>
663
+ npx --yes @odla-ai/cli@latest credentials list --env dev
664
+ npx --yes @odla-ai/cli@latest credentials revoke <receipt-id>
654
665
  ```
655
666
 
656
667
  The inventory contains only receipt, target, state, and timestamp metadata.
@@ -661,7 +672,7 @@ Verify a deployment that intentionally keeps db/o11y credentials only on the
661
672
  Worker:
662
673
 
663
674
  ```sh
664
- npx @odla-ai/cli smoke --env dev --runtime
675
+ npx --yes @odla-ai/cli@latest smoke --env dev --runtime
665
676
  ```
666
677
 
667
678
  Runtime smoke never reads `.odla/credentials.local.json`. It checks Registry
@@ -823,10 +834,10 @@ or SSH `origin`; pass `--repo owner/name` when it cannot. It opens GitHub's
823
834
  installation/authorization page and polls that exact odla attempt:
824
835
 
825
836
  ```bash
826
- npx odla-ai security github connect --env dev
827
- npx odla-ai security plan --env dev
828
- npx odla-ai security sources --env dev
829
- npx odla-ai security run --source <source-id> --ref main --env dev --plan-digest <digest-from-security-plan> --ack-redacted-source
837
+ npx --yes @odla-ai/cli@latest security github connect --env dev --no-open
838
+ npx --yes @odla-ai/cli@latest security plan --env dev
839
+ npx --yes @odla-ai/cli@latest security sources --env dev
840
+ npx --yes @odla-ai/cli@latest security run --source <source-id> --ref main --env dev --plan-digest <digest-from-security-plan> --ack-redacted-source
830
841
  ```
831
842
 
832
843
  `security plan` is the owner-readable disclosure preflight. It shows the exact
@@ -949,7 +960,7 @@ LLM-usage records. The human owns the device approval, production consent, and
949
960
  explicit destructive rotation. Studio is where people view telemetry and
950
961
  perform manual recovery, configure System AI, and inspect app/run-attributed
951
962
  platform usage; its o11y token control is not the normal setup path.
952
- Run `npx odla-ai capabilities` for the human-readable contract or add `--json`
963
+ Run `npx --yes @odla-ai/cli@latest capabilities` for the human-readable contract or add `--json`
953
964
  when an agent or tool needs to branch on it without scraping prose.
954
965
 
955
966
  `setup` (and `skill install`) installs one complete offline runbook bundle at
package/REQUIREMENTS.md CHANGED
@@ -60,6 +60,12 @@ Agnacl, but none should mention or special-case Agnacl.
60
60
  - Every real CLI handshake must attempt to open that canonical approval URL,
61
61
  including in CI, SSH, display-less, and agent-driven shells. `--no-open` is
62
62
  the only production suppression; failures must visibly repeat the manual action.
63
+ - Installed agent instructions must require `--no-open --wait 600`, an explicit
64
+ clickable human approval checkpoint, and preservation of the same foreground
65
+ CLI process. They must prohibit OS `open`, browser-control opening, direct
66
+ handshake polling, shell wait loops, detached execution, and replacement
67
+ handshakes while that process is alive. Exit 75 must be described as loss of
68
+ the in-memory device code; a later invocation creates a fresh code.
63
69
  - Cached developer tokens must be mode `0600`, gitignored, and reused until
64
70
  expiry.
65
71
  - Minted developer tokens must have a metadata-only inventory (owner, label,
package/dist/bin.cjs CHANGED
@@ -207,9 +207,10 @@ function approvalLines(prompt) {
207
207
  lines.push(` No browser was opened (${prompt.browserSkipped}).`);
208
208
  }
209
209
  lines.push("");
210
- lines.push(" AGENTS: use browser control to open the URL above now; do not wait silently.");
211
- lines.push(" If browser control is unavailable, give the exact URL to the human verbatim.");
212
- lines.push(" You cannot approve it yourself, retry it away, or start a substitute handshake.");
210
+ lines.push(" AGENTS: immediately give the human this URL as a clickable approval action and repeat the code.");
211
+ lines.push(" Keep this CLI process running and wait on this same process; the CLI owns protocol polling.");
212
+ lines.push(" Do not use OS open, browser control, curl, a shell wait loop, detached execution, or a substitute handshake.");
213
+ lines.push(" You cannot approve it yourself. If this process exits, a later invocation creates a new code.");
213
214
  lines.push("");
214
215
  return lines;
215
216
  }
@@ -5483,18 +5484,29 @@ For work that creates an odla app or adds odla services, read and follow
5483
5484
  \`.agents/skills/odla-o11y-debug/SKILL.md\`.
5484
5485
 
5485
5486
  Track the work in odla's PM as you go. Before project-mutating work, run
5486
- \`npx @odla-ai/cli pm next --app <appId>\`, confirm alignment to an open goal,
5487
+ \`npx --yes @odla-ai/cli@latest pm next --app <appId>\`, confirm alignment to an open goal,
5487
5488
  and atomically claim a refined Ready task. Record decisions when you make them
5488
5489
  and file bugs when you notice them. The conventions and the full command set are
5489
5490
  in \`.agents/skills/odla/references/pm.md\`.
5490
5491
 
5491
- Use the human's signed-in odla account email for device authorization; never
5492
- infer it from git config, commit metadata, or GitHub. If authorization is not
5493
- already active, run
5494
- \`npx @odla-ai/cli auth login --app <appId> --email <odla-account>\` and open
5495
- the exact Studio URL it prints. Never file an odla project or product defect in
5496
- GitHub Issues: run \`npx @odla-ai/cli bug report --app <appId> ...\` so the bug
5497
- lands in odla PM with the rest of the project's goals, tasks, and decisions.
5492
+ Use the human's known signed-in odla account email for device authorization;
5493
+ never infer it from git config, commit metadata, or GitHub. If authorization is
5494
+ not already active, run this exact command as one foreground process:
5495
+
5496
+ \`npx --yes @odla-ai/cli@latest auth login --app <appId> --email <odla-account> --no-open --wait 600\`
5497
+
5498
+ When it prints the approval URL and code, immediately give the human a clickable
5499
+ link, name the code they must verify, and tell them to click **Approve**. Keep
5500
+ that CLI process running and wait on the same tool process for its result. The
5501
+ CLI owns protocol polling: never call the OS \`open\` command, use browser
5502
+ control, curl a handshake endpoint, build a shell wait/poll loop, detach the
5503
+ process, or start another handshake while it is alive. The device code exists
5504
+ only in that process. If it exits 75 before approval, the old code cannot be
5505
+ collected; start one fresh foreground command and surface its new URL.
5506
+
5507
+ Never file an odla project or product defect in GitHub Issues: run
5508
+ \`npx --yes @odla-ai/cli@latest bug report --app <appId> ...\` so the bug lands
5509
+ in odla PM with the rest of the project's goals, tasks, and decisions.
5498
5510
 
5499
5511
  The setup runbooks and their references are installed in this repository, pinned
5500
5512
  to this CLI version. Use them as your setup context.
@@ -5506,9 +5518,9 @@ When this repository has an \`appId\`, pass it: app-scoped discovery includes
5506
5518
  that project's instructions plus the shared platform procedures.
5507
5519
 
5508
5520
  \`\`\`
5509
- npx odla-ai runbook ask "<what you are about to do>" --app <appId>
5510
- npx odla-ai runbook list
5511
- npx odla-ai runbook get <slug>
5521
+ npx --yes @odla-ai/cli@latest runbook ask "<what you are about to do>" --app <appId>
5522
+ npx --yes @odla-ai/cli@latest runbook list
5523
+ npx --yes @odla-ai/cli@latest runbook get <slug>
5512
5524
  \`\`\`
5513
5525
 
5514
5526
  Never scrape odla.ai HTML for any of this. The CLI reads the same content
@@ -10817,8 +10829,8 @@ Usage:
10817
10829
  odla-ai runbook revert <slug> --version <n> [--app <id>]
10818
10830
  odla-ai runbook rm <slug> [--app <id>]
10819
10831
  odla-ai capabilities [--json]
10820
- odla-ai code connect [--env dev|prod] [--email <odla-account>] [--engine auto|container|podman|docker] [--slots <1-64>] [--once]
10821
- odla-ai admin ai show [--context <name>] [--platform https://odla.ai] [--email <odla-account>] [--json]
10832
+ odla-ai code connect [--env dev|prod] [--email <odla-account>] [--no-open] [--engine auto|container|podman|docker] [--slots <1-64>] [--once]
10833
+ odla-ai admin ai show [--context <name>] [--platform https://odla.ai] [--email <odla-account>] [--no-open] [--json]
10822
10834
  odla-ai admin ai models [--context <name>] [--provider <id>] [--json]
10823
10835
  odla-ai admin ai set <purpose> [--context <name>] [--provider <id>] [--model <id>] [--enabled|--no-enabled]
10824
10836
  [--max-input-bytes <n>] [--max-output-tokens <n>] [--max-calls-per-run <n>] [--json]
@@ -10837,7 +10849,7 @@ Usage:
10837
10849
  odla-ai security report <job-id> [--json]
10838
10850
  odla-ai security run [target] --ack-redacted-source [--env dev] [--profile odla] [--fail-on high]
10839
10851
  odla-ai security run [target] --self --ack-redacted-source
10840
- odla-ai provision [--live] [--config odla.config.mjs] [--email <odla-account>] [--request-grant] [--wait <seconds>] [--dry-run] [--push-secrets] [--rotate-o11y-token] [--write-dev-vars[=path]] [--yes]
10852
+ odla-ai provision [--live] [--config odla.config.mjs] [--email <odla-account>] [--request-grant] [--no-open] [--wait <seconds>] [--dry-run] [--push-secrets] [--rotate-o11y-token] [--write-dev-vars[=path]] [--yes]
10841
10853
  odla-ai credentials list [--config odla.config.mjs] [--env dev] [--all] [--json]
10842
10854
  odla-ai credentials revoke <receipt-id> [--config odla.config.mjs] [--json]
10843
10855
  odla-ai smoke [--config odla.config.mjs] [--env dev] [--runtime] [--email <odla-account>] [--no-open]
@@ -10854,7 +10866,7 @@ function printHelp(output = console) {
10854
10866
  output.log(`odla-ai
10855
10867
  ${USAGE_SECTION}
10856
10868
  Commands:
10857
- auth Start a fresh, exact-project agent authorization in the browser.
10869
+ auth Start a fresh, exact-project agent authorization for human review.
10858
10870
  The email is the signed-in odla account, never git or GitHub
10859
10871
  identity. The approval screen confirms the agent name first.
10860
10872
  agent Inspect durable agent wakeups and explicitly requeue a
@@ -10984,23 +10996,25 @@ Safety:
10984
10996
  the metadata file. Flags and specific ODLA_* scope variables beat a selected
10985
10997
  context, which beats project config. There is no ambient current context.
10986
10998
  "context show" reports only provenance and cache state and never authenticates.
10987
- Every real CLI handshake prints one canonical /studio?code= approval URL and
10988
- attempts to open it \u2014 including in CI, SSH, display-less, and agent-driven
10989
- shells. Only --no-open suppresses the attempt. Browser launch is best-effort:
10990
- agents with browser control must open that exact URL immediately; otherwise
10991
- they must give it to the human verbatim. A device code remains only in the
10992
- running process. Outside an interactive terminal the wait is capped (90s by
10993
- default, --wait <seconds> to change); a still-pending handshake then exits
10994
- with code 75. Rerunning always requests and opens a new code; older clients'
10995
- persisted pending state is discarded.
10999
+ Every real CLI handshake prints one canonical /studio?code= approval URL.
11000
+ Interactive humans may let the CLI attempt its best-effort browser launch.
11001
+ Agent-driven commands must pass --no-open --wait 600, immediately surface the
11002
+ exact URL and code as a clickable human approval action, and keep that CLI
11003
+ process alive. Wait only on that same process: the CLI owns protocol polling.
11004
+ Do not call OS open, use browser control, curl handshake endpoints, build a
11005
+ shell wait loop, detach the command, or start a substitute handshake. The
11006
+ device code remains only in the running process. If the process exits 75, its
11007
+ old code cannot be collected; a later invocation requests a new code. Older
11008
+ clients' persisted pending state is discarded.
10996
11009
  A fresh device handshake requires --email <odla-account> or ODLA_USER_EMAIL.
10997
11010
  The email is a non-secret identity hint: never provide a password or session
10998
11011
  token. It is the email shown by the signed-in odla account \u2014 never infer it
10999
11012
  from git config, a commit author, or GitHub. The matching account must already exist, be signed in, explicitly
11000
11013
  review the exact code, and finish any current request before claiming another.
11001
- Use "auth login --app <id> --email <odla-account>" when an outside agent needs
11002
- a deliberate fresh request; it ignores cached credentials and opens the same
11003
- focused authorization sequence used by every first-time command.
11014
+ Use "auth login --app <id> --email <odla-account> --no-open --wait 600" when
11015
+ an outside agent needs a deliberate fresh request; it ignores cached
11016
+ credentials and uses the same focused authorization sequence as every
11017
+ first-time command.
11004
11018
  If provision reports that the current agent principal has no live app.manage
11005
11019
  grant, run it once with --request-grant. That flag ignores ODLA_DEV_TOKEN and
11006
11020
  the local cache, prints and opens a fresh exact-project owner-review URL, then
@@ -14660,7 +14674,7 @@ var init_runbook_impact = __esm({
14660
14674
 
14661
14675
  // src/runbook-lint.ts
14662
14676
  function invocationsIn(body) {
14663
- const re = /(`|npx[^\S\n]+)?(?:@odla-ai\/cli(?:@[\w.-]+)?|odla-ai)((?:[^\S\n]+[a-z][\w-]*)+)/g;
14677
+ const re = /(`|npx[^\S\n]+(?:--yes[^\S\n]+)?)?(?:@odla-ai\/cli(?:@[\w.-]+)?|odla-ai)((?:[^\S\n]+[a-z][\w-]*)+)/g;
14664
14678
  const found = [];
14665
14679
  for (const match of body.matchAll(re)) {
14666
14680
  if (!match[1]) continue;
@@ -14894,6 +14908,7 @@ async function buildContext3(parsed, deps, action2) {
14894
14908
  };
14895
14909
  }
14896
14910
  const needsCapability = WRITES2.has(action2) && !dryRun && appId === PLATFORM_SCOPE && !stringOpt(parsed.options.token);
14911
+ const open = parsed.options.open === false ? false : parsed.options.open === true ? true : void 0;
14897
14912
  const token = needsCapability ? await getScopedPlatformToken({
14898
14913
  platform: cfg.platformUrl,
14899
14914
  scope: "platform:runbook:write",
@@ -14901,6 +14916,7 @@ async function buildContext3(parsed, deps, action2) {
14901
14916
  label: `odla CLI (runbook ${action2})`,
14902
14917
  fetch: doFetch,
14903
14918
  stdout: out,
14919
+ open,
14904
14920
  openApprovalUrl: deps.openUrl,
14905
14921
  // A project, named context, or the global operator context owns the
14906
14922
  // exact-scope cache; it never follows an arbitrary shell directory.
@@ -14912,11 +14928,7 @@ async function buildContext3(parsed, deps, action2) {
14912
14928
  configPath: cfg.configPath,
14913
14929
  token: stringOpt(parsed.options.token),
14914
14930
  email: stringOpt(parsed.options.email),
14915
- // Let the normal browser policy decide (it already suppresses tests,
14916
- // CI and SSH). Hardcoding `false` meant a first-time handshake printed
14917
- // a link and opened nothing — the one moment a browser is the whole
14918
- // point.
14919
- open: void 0
14931
+ open
14920
14932
  },
14921
14933
  doFetch,
14922
14934
  out
@@ -15064,7 +15076,8 @@ var init_runbook_command = __esm({
15064
15076
  "base",
15065
15077
  "requires",
15066
15078
  "platform",
15067
- "context"
15079
+ "context",
15080
+ "open"
15068
15081
  ];
15069
15082
  WRITES2 = /* @__PURE__ */ new Set(["new", "edit", "publish", "archive", "visibility", "revert", "rm", "import"]);
15070
15083
  }