@odla-ai/cli 0.34.0 → 0.35.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.
Files changed (32) hide show
  1. package/README.md +130 -119
  2. package/REQUIREMENTS.md +6 -0
  3. package/dist/bin.cjs +419 -138
  4. package/dist/bin.cjs.map +1 -1
  5. package/dist/bin.js +1 -1
  6. package/dist/{chunk-LGNNX6AP.js → chunk-EG23MPUC.js} +396 -139
  7. package/dist/chunk-EG23MPUC.js.map +1 -0
  8. package/dist/{cli-IN6WGMSY.js → cli-Z5NSTS75.js} +2 -2
  9. package/dist/index.cjs +395 -138
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.js +1 -1
  12. package/package.json +2 -2
  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-Z5NSTS75.js.map} +0 -0
package/dist/index.js CHANGED
@@ -56,7 +56,7 @@ import {
56
56
  startHostedSecurityJob,
57
57
  surfacePaths,
58
58
  validateInvocation
59
- } from "./chunk-LGNNX6AP.js";
59
+ } from "./chunk-EG23MPUC.js";
60
60
  import {
61
61
  exitCodeFor,
62
62
  redactSecrets
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@odla-ai/cli",
3
- "version": "0.34.0",
3
+ "version": "0.35.0",
4
4
  "description": "Agent-operable CLI for odla provisioning, calendar consent and connection lifecycle, System AI administration, Worker secrets, security jobs, and smoke checks.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://odla.ai/docs/packages/cli",
@@ -61,7 +61,7 @@
61
61
  "@odla-ai/ai": "0.14.0",
62
62
  "@odla-ai/apps": "0.11.0",
63
63
  "@odla-ai/brand": "0.5.0",
64
- "@odla-ai/db": "0.10.3",
64
+ "@odla-ai/db": "0.11.0",
65
65
  "@odla-ai/security": "0.3.3"
66
66
  },
67
67
  "devDependencies": {
@@ -49,7 +49,9 @@ State which path you're taking and what you'll build in one line; get a nod.
49
49
  registry matches the exact string. An address that is not a registered
50
50
  account does NOT error: it mints an indistinguishable decoy, so the CLI
51
51
  prints a normal approval URL that can never be approved by anyone. Ask the
52
- human, or reuse the address already in `.odla/handshake.local.json`.
52
+ human, or reuse the same-audience account identity already recorded with a
53
+ collected developer token. Current clients never persist pending device
54
+ codes in `.odla/handshake.local.json`.
53
55
  2. **Sandbox before live.** Every app has two databases on production odla.ai:
54
56
  a sandbox (env `dev`, tenant `<appId>--dev`) and a live one (env `prod`,
55
57
  tenant `<appId>`). "prod" names the app's live DATABASE, never a different
@@ -69,6 +71,26 @@ State which path you're taking and what you'll build in one line; get a nod.
69
71
  platform/Google consent URL returned by odla; booking runs server-side
70
72
  through the SDK with the app's existing key, never from a browser.
71
73
 
74
+ ## Agent handshake protocol
75
+
76
+ Use the current published CLI and suppress browser auto-launch. Start the exact
77
+ authorization as one foreground tool process:
78
+
79
+ ```bash
80
+ npx --yes @odla-ai/cli@latest auth login --app <appId> --email <odla-account> --no-open --wait 600
81
+ ```
82
+
83
+ When the CLI prints its one `/studio?code=` URL, immediately give the human a
84
+ clickable link, repeat the code they must verify, and say that opening the page
85
+ is not enough: they must click **Approve**. Keep the same CLI process alive and
86
+ wait on that process for completion. The CLI owns protocol polling. Never call
87
+ the OS `open` command, use browser control, curl a handshake endpoint, create a
88
+ shell polling/wait loop, detach the process, or start a substitute handshake.
89
+ The device code exists only in the running CLI. If it exits 75, the old request
90
+ cannot be collected; start one fresh foreground invocation and surface only its
91
+ new URL. Apply the same `--no-open --wait 600` flags when another command, such
92
+ as first provision, must request a different reviewed capability.
93
+
72
94
  ## Tooling sources
73
95
 
74
96
  - **odla**: this skill plus the installed `@odla-ai/*` packages are the
@@ -93,28 +115,26 @@ State which path you're taking and what you'll build in one line; get a nod.
93
115
 
94
116
  ## The flow
95
117
 
96
- You reached this skill because the human ran `npx @odla-ai/cli setup`. Then:
118
+ You reached this skill because the human ran `npx --yes @odla-ai/cli@latest setup`. Then:
97
119
 
98
- First run `npx @odla-ai/cli capabilities --json`; use that contract instead of
120
+ First run `npx --yes @odla-ai/cli@latest capabilities --json`; use that contract instead of
99
121
  guessing which platform/credential steps need manual work. Then:
100
122
 
101
- 1. **init** — `npx @odla-ai/cli init --app-id <id> --name "<Name>"` scaffolds
123
+ 1. **init** — `npx --yes @odla-ai/cli@latest init --app-id <id> --name "<Name>"` scaffolds
102
124
  `odla.config.mjs`, `src/odla/schema.mjs`, `src/odla/rules.mjs` (deny-all).
103
125
  2. **build the Worker shell** — install the SDKs, write the app, and create its
104
126
  Wrangler config (`references/sdks.md`). With o11y, add `nodejs_compat` and
105
127
  `withObservability`. The CLI will refuse secret delivery until the Wrangler
106
128
  target exists.
107
129
  3. **provision** ⏸ —
108
- `npx @odla-ai/cli provision --email <existing-odla-account>
109
- --write-dev-vars --push-secrets`. A device code prints; that same account
130
+ `npx --yes @odla-ai/cli@latest provision --email <existing-odla-account>
131
+ --write-dev-vars --push-secrets --no-open --wait 600`. A device code prints;
132
+ that same account
110
133
  signs in, reviews the exact code, and approves it at https://odla.ai/studio.
111
- Opening the link alone is inert. The CLI prints exactly one `/studio?code=`
112
- URL and attempts to open it in every real environment. **If you have browser
113
- control, open that exact URL now.** If you do not, give it to the human
114
- verbatim; never wait silently or start a substitute handshake. Outside an
115
- interactive terminal the wait is capped (90s default,
116
- `--wait <seconds>`); exit code 75 means still pending. The device code is
117
- not cached: rerunning always opens a fresh code for human review. It creates the app,
134
+ Opening the link alone is inert. Follow the agent handshake protocol above:
135
+ surface the exact link and code, keep this process alive, and let the CLI
136
+ wait. The device code is not cached; if the process exits, a rerun creates a
137
+ fresh code for human review. After approval it creates the app,
118
138
  consuming a one-time exact-id reservation when the approved app is new,
119
139
  enables services, issues or reuses configured credentials (db key + o11y
120
140
  ingest token when enabled), composes declared integration schema/rules and
@@ -125,13 +145,13 @@ guessing which platform/credential steps need manual work. Then:
125
145
  syncs.
126
146
  4. **run** — `npx wrangler dev` (auto-loads `.dev.vars`); verify locally.
127
147
  When an agent mention appears stuck, inspect the durable delivery ledger
128
- with `npx odla-ai agent jobs --env <env> --json`. Requeue only an exact
129
- dead-letter id with `npx odla-ai agent retry <job-id> --env <env> --json`;
148
+ with `npx --yes @odla-ai/cli@latest agent jobs --env <env> --json`. Requeue only an exact
149
+ dead-letter id with `npx --yes @odla-ai/cli@latest agent retry <job-id> --env <env> --json`;
130
150
  pending/running/succeeded jobs are intentionally not replayable.
131
151
  5. **security** — run the passive `@odla-ai/security` odla profile; inspect
132
152
  every lead and keep critical candidate gating enabled. If the human approves
133
153
  redacted source disclosure, follow with
134
- `npx @odla-ai/cli security run . --env dev --ack-redacted-source` for
154
+ `npx --yes @odla-ai/cli@latest security run . --env dev --ack-redacted-source` for
135
155
  app-attributed discovery + independent validation. Never request provider
136
156
  keys; the platform selects the routes and returns bounded role grants. For
137
157
  repeatable server-side review, run `security github connect --env dev`
@@ -141,8 +161,8 @@ guessing which platform/credential steps need manual work. Then:
141
161
  --ack-redacted-source`.
142
162
  The source job follows, reports, and gates by default. Never request a PAT or
143
163
  treat GitHub read approval as redacted-snippet disclosure consent.
144
- 6. **ship** ⏸ — run `npx @odla-ai/cli provision --live --dry-run`, show the
145
- human, then `npx @odla-ai/cli provision --live --yes --push-secrets` and
164
+ 6. **ship** ⏸ — run `npx --yes @odla-ai/cli@latest provision --live --dry-run`, show the
165
+ human, then `npx --yes @odla-ai/cli@latest provision --live --yes --push-secrets` and
146
166
  `npx wrangler deploy`. Add `prod` to `envs` only when future ordinary
147
167
  provision runs should target both environments.
148
168
 
@@ -154,13 +174,13 @@ on the app. It is platform-side: there is nothing PM-specific to install or
154
174
  provision. Start a session by reading it, and keep it current while you build:
155
175
 
156
176
  ```cmd
157
- npx @odla-ai/cli pm next --app <appId>
177
+ npx --yes @odla-ai/cli@latest pm next --app <appId>
158
178
  ```
159
179
 
160
180
  For a durable supervisor loop, establish and persist an exact-project PM cursor:
161
181
 
162
182
  ```cmd
163
- npx @odla-ai/cli pm watch --app <appId> --entity task --jsonl
183
+ npx --yes @odla-ai/cli@latest pm watch --app <appId> --entity task --jsonl
164
184
  ```
165
185
 
166
186
  A Ready event is a wake-up signal, not permission: reload the task and linked
@@ -198,11 +218,11 @@ procedures — releasing, backups, database and code-runtime operations — are
198
218
  in odla and change without a CLI release. Read one at the moment you follow it:
199
219
 
200
220
  ```cmd
201
- npx @odla-ai/cli runbook list
221
+ npx --yes @odla-ai/cli@latest runbook list
202
222
  ```
203
223
 
204
224
  ```cmd
205
- npx @odla-ai/cli runbook get release
225
+ npx --yes @odla-ai/cli@latest runbook get release
206
226
  ```
207
227
 
208
228
  `runbook get` prints raw markdown, so pipe it or read it directly. Do not follow a
@@ -214,11 +234,11 @@ cited answer; `search` returns the **sections** behind it, each with its source
214
234
  and the command to pull the rest:
215
235
 
216
236
  ```cmd
217
- npx @odla-ai/cli runbook ask "how do I roll back a bad publish?"
237
+ npx --yes @odla-ai/cli@latest runbook ask "how do I roll back a bad publish?"
218
238
  ```
219
239
 
220
240
  ```cmd
221
- npx @odla-ai/cli runbook search "roll back a bad publish"
241
+ npx --yes @odla-ai/cli@latest runbook search "roll back a bad publish"
222
242
  ```
223
243
 
224
244
  Cite what you quote — `release#rolling-back-a-bad-publish (v3)` — so the reader
@@ -237,7 +257,7 @@ installed version in front of you, and the runbook is not claiming to describe i
237
257
  ### After you change something, ask what you invalidated
238
258
 
239
259
  ```cmd
240
- npx @odla-ai/cli runbook impact
260
+ npx --yes @odla-ai/cli@latest runbook impact
241
261
  ```
242
262
 
243
263
  It diffs your working tree against `origin/main` (`--base <ref>` for anything
@@ -255,7 +275,7 @@ in the same piece of work.
255
275
  The other direction — are the runbooks themselves still true?
256
276
 
257
277
  ```cmd
258
- npx @odla-ai/cli runbook lint
278
+ npx --yes @odla-ai/cli@latest runbook lint
259
279
  ```
260
280
 
261
281
  Every `odla-ai …` command the runbooks name is held against this CLI's real
@@ -268,20 +288,20 @@ reader on an older CLI gets an "unknown action" error instead of an explanation.
268
288
 
269
289
  Found a wrong step? Fix an app runbook directly. For a platform runbook,
270
290
  `runbook edit` requests an admin-approved capability — a plain handshake token is
271
- never admin, and `npx @odla-ai/cli whoami` tells you what you hold.
291
+ never admin, and `npx --yes @odla-ai/cli@latest whoami` tells you what you hold.
272
292
 
273
- ⏸ That request prints the same canonical approval block. **Use browser control
274
- to open its URL immediately; if unavailable, give it to the human verbatim.**
275
- You cannot approve it yourself the grant is issued to you, not by you — and
276
- the command blocks until a signed-in admin approves it. Never wait silently or
277
- start a substitute handshake because the automatic opener produced no tab.
293
+ ⏸ That request prints the same canonical approval block. Follow the agent
294
+ handshake protocol: run with `--no-open --wait 600`, immediately surface its
295
+ clickable URL and code to the human, and preserve that foreground process. You
296
+ cannot approve it yourself — the grant is issued to you, not by you and the
297
+ command blocks until a signed-in admin approves it.
278
298
  If approval is not available, comment on the runbook instead so an admin can fix
279
299
  it later.
280
300
 
281
- `npx @odla-ai/cli doctor` is an offline config check anytime;
282
- `npx @odla-ai/cli smoke --env dev` verifies a live deployment from local
301
+ `npx --yes @odla-ai/cli@latest doctor` is an offline config check anytime;
302
+ `npx --yes @odla-ai/cli@latest smoke --env dev` verifies a live deployment from local
283
303
  service credentials. After `provision --push-secrets`, use
284
- `npx @odla-ai/cli smoke --env dev --runtime`; it verifies the Worker and
304
+ `npx --yes @odla-ai/cli@latest smoke --env dev --runtime`; it verifies the Worker and
285
305
  anonymous integration routes without retrieving its db/o11y secrets.
286
306
  When `o11y.monitoring` is configured, apply its repository-owned Kitesurf or
287
307
  existing-o11y performance indicators, cadence, SLOs, and email schedule with `monitor plan` followed by
@@ -18,8 +18,8 @@ checkout that first obtained the credential.
18
18
  ## 1. Save non-secret context outside the checkout
19
19
 
20
20
  ```cmd
21
- npx @odla-ai/cli context save delivery --platform https://odla.ai --app <appId> --env prod
22
- npx @odla-ai/cli context show --context delivery --json
21
+ npx --yes @odla-ai/cli@latest context save delivery --platform https://odla.ai --app <appId> --env prod
22
+ npx --yes @odla-ai/cli@latest context show --context delivery --json
23
23
  ```
24
24
 
25
25
  The context stores only platform/app/environment metadata. Its private token
@@ -34,7 +34,7 @@ exists, the CLI starts the normal email-bound device handshake and prints the
34
34
  exact Studio approval URL.
35
35
 
36
36
  ```cmd
37
- npx @odla-ai/cli whoami --context delivery --email <account-email> --json
37
+ npx --yes @odla-ai/cli@latest whoami --context delivery --email <account-email> --json
38
38
  ```
39
39
 
40
40
  In Studio, review the exact code, requested handle, projects, and capabilities.
@@ -47,8 +47,8 @@ project in every checkout and worktree.
47
47
  After approval and collection, verify the selected identity and context:
48
48
 
49
49
  ```cmd
50
- npx @odla-ai/cli whoami --context delivery --json
51
- npx @odla-ai/cli pm next --context delivery --json
50
+ npx --yes @odla-ai/cli@latest whoami --context delivery --json
51
+ npx --yes @odla-ai/cli@latest pm next --context delivery --json
52
52
  ```
53
53
 
54
54
  If the agent request omits the handle, Registry deliberately creates a new
@@ -5,7 +5,7 @@ Exact commands, verified against `@odla-ai/cli`. ⏸ marks a human step.
5
5
  ## 1. Scaffold
6
6
 
7
7
  ```
8
- npx @odla-ai/cli init --app-id my-app --name "My App"
8
+ npx --yes @odla-ai/cli@latest init --app-id my-app --name "My App"
9
9
  ```
10
10
 
11
11
  Writes `odla.config.mjs`, `src/odla/schema.mjs`, `src/odla/rules.mjs`, and adds
@@ -48,7 +48,7 @@ vendor docs, never memorized steps.
48
48
  ## 3. Provision ⏸ device-code approval
49
49
 
50
50
  ```
51
- npx @odla-ai/cli provision --email <existing-odla-account> --write-dev-vars --push-secrets
51
+ npx --yes @odla-ai/cli@latest provision --email <existing-odla-account> --write-dev-vars --push-secrets --no-open --wait 600
52
52
  ```
53
53
 
54
54
  The email is an account identifier, never a password or session credential.
@@ -61,7 +61,7 @@ o11y ingest token when o11y is enabled), pushes the composed app + integration
61
61
  schema/rules, creates missing guarded seeds, writes
62
62
  `.dev.vars`, and transfers configured Worker secrets through Wrangler stdin.
63
63
  Local credential files are `0600` and gitignored. Verify with
64
- `npx @odla-ai/cli doctor` — it prints the app, envs, services, integrations, and flags
64
+ `npx --yes @odla-ai/cli@latest doctor` — it prints the app, envs, services, integrations, and flags
65
65
  anything unset. `--push-secrets` preflights the Wrangler config and login before
66
66
  issuing or rotating a shown-once credential.
67
67
 
@@ -76,9 +76,10 @@ mutations remain direct-human operations.
76
76
 
77
77
  If provision reports that the selected agent credential has no live
78
78
  `app.manage` grant, retries cannot add authority. Run
79
- `npx @odla-ai/cli provision --request-grant --email <existing-odla-account>
80
- --write-dev-vars --push-secrets`. This deliberately ignores `ODLA_DEV_TOKEN`
81
- and the local token cache, prints/opens a fresh exact-project review URL, and
79
+ `npx --yes @odla-ai/cli@latest provision --request-grant --email <existing-odla-account>
80
+ --write-dev-vars --push-secrets --no-open --wait 600`. This deliberately
81
+ ignores `ODLA_DEV_TOKEN` and the local token cache, prints a fresh exact-project
82
+ review URL, and
82
83
  continues with the approved replacement credential. Remove an explicit
83
84
  `--token`; a supplied credential cannot approve authority for itself.
84
85
 
@@ -87,7 +88,7 @@ prints/opens a state-bound Google URL issued by the platform and waits while
87
88
  the human grants the booking scopes in a browser. The CLI never receives the
88
89
  Google callback code or tokens, and nothing syncs afterward — Google stays
89
90
  the single source of truth. Once connected, run
90
- `npx @odla-ai/cli calendar calendars --env dev --json`, refine the checked-in
91
+ `npx --yes @odla-ai/cli@latest calendar calendars --env dev --json`, refine the checked-in
91
92
  calendar ids if needed, re-provision, and verify `calendar status --env dev`
92
93
  reports `bookable: yes`.
93
94
 
@@ -95,7 +96,7 @@ The CLI stops at the source boundary: it verifies but does not invent your
95
96
  application semantics. Do not use Studio to mint a routine o11y token. Manual
96
97
  Studio rotation is recovery-only;
97
98
  normal replacement is
98
- `npx @odla-ai/cli provision --rotate-o11y-token --push-secrets` after explicit
99
+ `npx --yes @odla-ai/cli@latest provision --rotate-o11y-token --push-secrets` after explicit
99
100
  human approval.
100
101
 
101
102
  ## 4. Run locally
@@ -139,17 +140,17 @@ Optional hosted follow-up (human must explicitly approve redacted tracked-source
139
140
  disclosure under the configured providers' retention/residency terms):
140
141
 
141
142
  ```
142
- npx @odla-ai/cli security run . --env dev --ack-redacted-source
143
+ npx --yes @odla-ai/cli@latest security run . --env dev --ack-redacted-source
143
144
  ```
144
145
 
145
146
  For a repeatable commit-pinned job after the human approves the read-only
146
147
  GitHub App:
147
148
 
148
149
  ```
149
- npx @odla-ai/cli security github connect --env dev
150
- npx @odla-ai/cli security plan --env dev
151
- npx @odla-ai/cli security sources --env dev
152
- npx @odla-ai/cli security run --source <source-id> --ref main --env dev --plan-digest <digest-from-security-plan> --ack-redacted-source
150
+ npx --yes @odla-ai/cli@latest security github connect --env dev
151
+ npx --yes @odla-ai/cli@latest security plan --env dev
152
+ npx --yes @odla-ai/cli@latest security sources --env dev
153
+ npx --yes @odla-ai/cli@latest security run --source <source-id> --ref main --env dev --plan-digest <digest-from-security-plan> --ack-redacted-source
153
154
  ```
154
155
 
155
156
  The CLI infers the repository from a safe GitHub origin, never requests a PAT
@@ -170,7 +171,7 @@ supplied one. Surface either without looping or manufacturing a provider key.
170
171
  Initialize live after the sandbox is healthy (prod tenant = the bare `appId`), then:
171
172
 
172
173
  ```
173
- npx @odla-ai/cli provision --live --yes --push-secrets # prod mutation + configured Worker secrets
174
+ npx --yes @odla-ai/cli@latest provision --live --yes --push-secrets # prod mutation + configured Worker secrets
174
175
  npx wrangler deploy
175
176
  ```
176
177
 
@@ -180,5 +181,5 @@ should manage sandbox and live together. If calendar is enabled, predeclare
180
181
  `calendar.google.availabilityCalendars.prod`; the live Google connection still
181
182
  has its own consent checkpoint.
182
183
 
183
- Verify with `npx @odla-ai/cli smoke --env prod`. Point env vars at the service
184
+ Verify with `npx --yes @odla-ai/cli@latest smoke --env prod`. Point env vars at the service
184
185
  custom domains, never `*.workers.dev` (Workers can't fetch same-account workers.dev).
@@ -25,7 +25,7 @@ records who co-owns an app; the db honors any co-owner when they provision.
25
25
  primary owner:
26
26
 
27
27
  ```cmd
28
- npx @odla-ai/cli provision --email teammate@example.com --write-dev-vars --push-secrets
28
+ npx --yes @odla-ai/cli@latest provision --email teammate@example.com --write-dev-vars --push-secrets --no-open --wait 600
29
29
  ```
30
30
 
31
31
  provision verifies the existing app (it does not re-create it), mints the
@@ -16,9 +16,9 @@ for the current chat and should name the PM goal and task references.
16
16
  ## 1. Resolve context and read authoritative state
17
17
 
18
18
  ```cmd
19
- npx @odla-ai/cli context show --context <profile>
20
- npx @odla-ai/cli pm next --app <appId> --json
21
- npx @odla-ai/cli pm handoff --app <appId> --json
19
+ npx --yes @odla-ai/cli@latest context show --context <profile>
20
+ npx --yes @odla-ai/cli@latest pm next --app <appId> --json
21
+ npx --yes @odla-ai/cli@latest pm handoff --app <appId> --json
22
22
  ```
23
23
 
24
24
  Read any existing Doing task before selecting another. For each candidate, read
@@ -53,9 +53,9 @@ Create/refine the task with one alignment source, an actionable description,
53
53
  acceptance criteria, and execution mode:
54
54
 
55
55
  ```cmd
56
- npx @odla-ai/cli pm task add --app <appId> --title "<work>" --goal <goal-id> --description "<bounded work>" --acceptance "<observable proof>" --execution agent
57
- npx @odla-ai/cli pm task get <task-id> --json
58
- npx @odla-ai/cli pm task ready <task-id> --expected-revision <revision>
56
+ npx --yes @odla-ai/cli@latest pm task add --app <appId> --title "<work>" --goal <goal-id> --description "<bounded work>" --acceptance "<observable proof>" --execution agent
57
+ npx --yes @odla-ai/cli@latest pm task get <task-id> --json
58
+ npx --yes @odla-ai/cli@latest pm task ready <task-id> --expected-revision <revision>
59
59
  ```
60
60
 
61
61
  Use `--alignment-decision <decision-id>` instead of `--goal` only for an
@@ -72,8 +72,8 @@ silently become its executor.
72
72
  Review the latest task revision immediately before claiming:
73
73
 
74
74
  ```cmd
75
- npx @odla-ai/cli pm task get <task-id> --json
76
- npx @odla-ai/cli pm task claim <task-id> --expected-revision <revision>
75
+ npx --yes @odla-ai/cli@latest pm task get <task-id> --json
76
+ npx --yes @odla-ai/cli@latest pm task claim <task-id> --expected-revision <revision>
77
77
  ```
78
78
 
79
79
  Only one concurrent caller can win. On conflict, reload `pm next` and the task;
@@ -110,7 +110,7 @@ later. Reserve `pm ... ref <id>` for structured odla Discussion markup.
110
110
  If the claimant must stop:
111
111
 
112
112
  ```cmd
113
- npx @odla-ai/cli pm task release <task-id> --expected-revision <revision>
113
+ npx --yes @odla-ai/cli@latest pm task release <task-id> --expected-revision <revision>
114
114
  ```
115
115
 
116
116
  Comment with the branch/worktree, last verified commit, unfinished step, and
@@ -124,9 +124,9 @@ Establish a checkpoint before waiting for PM lifecycle changes, persist every
124
124
  checkpoint record, and resume with its opaque cursor:
125
125
 
126
126
  ```cmd
127
- npx @odla-ai/cli pm watch --app <appId> --entity task --jsonl
128
- npx @odla-ai/cli pm watch --app <appId> --cursor <cursor> --entity task --state ready --self <principal-id> --jsonl
129
- npx @odla-ai/cli pm watch --app <appId> --cursor <cursor> --entity task --action comment.created --self <principal-id> --jsonl
127
+ npx --yes @odla-ai/cli@latest pm watch --app <appId> --entity task --jsonl
128
+ npx --yes @odla-ai/cli@latest pm watch --app <appId> --cursor <cursor> --entity task --state ready --self <principal-id> --jsonl
129
+ npx --yes @odla-ai/cli@latest pm watch --app <appId> --cursor <cursor> --entity task --action comment.created --self <principal-id> --jsonl
130
130
  ```
131
131
 
132
132
  Delivery is at least once. Deduplicate by `eventId`; advance durable consumer
@@ -49,23 +49,23 @@ Entity is `goal | task | decision | bug`; every command takes `--json` for
49
49
  machine-readable output.
50
50
 
51
51
  ```cmd
52
- npx @odla-ai/cli pm bug add --app <appId> --title "Checkout 500s on retry" --severity high --desc "…"
52
+ npx --yes @odla-ai/cli@latest pm bug add --app <appId> --title "Checkout 500s on retry" --severity high --desc "…"
53
53
  ```
54
54
 
55
55
  ```cmd
56
- npx @odla-ai/cli pm bug list --app <appId> --status open
56
+ npx --yes @odla-ai/cli@latest pm bug list --app <appId> --status open
57
57
  ```
58
58
 
59
59
  ```cmd
60
- npx @odla-ai/cli pm next --app <appId>
60
+ npx --yes @odla-ai/cli@latest pm next --app <appId>
61
61
  ```
62
62
 
63
63
  ```cmd
64
- npx @odla-ai/cli pm task claim <id> --expected-revision <n>
64
+ npx --yes @odla-ai/cli@latest pm task claim <id> --expected-revision <n>
65
65
  ```
66
66
 
67
67
  ```cmd
68
- npx @odla-ai/cli pm decision list --q "stripe"
68
+ npx --yes @odla-ai/cli@latest pm decision list --q "stripe"
69
69
  ```
70
70
 
71
71
  - `add` needs `--app <appId>` and `--title`; it takes the entity's own fields
@@ -116,8 +116,8 @@ the request in PM but do not require them to repeat it with a Ready transition.
116
116
  write:
117
117
 
118
118
  ```cmd
119
- npx @odla-ai/cli context show --context <profile>
120
- npx @odla-ai/cli pm next --app <appId>
119
+ npx --yes @odla-ai/cli@latest context show --context <profile>
120
+ npx --yes @odla-ai/cli@latest pm next --app <appId>
121
121
  ```
122
122
 
123
123
  Then read `pm bug list --app <appId> --status open` and
@@ -167,13 +167,13 @@ Discussion markup uses stable typed references. Prefer it over pasting a title
167
167
  that can be renamed:
168
168
 
169
169
  ```cmd
170
- npx @odla-ai/cli pm task ref <task-id>
170
+ npx --yes @odla-ai/cli@latest pm task ref <task-id>
171
171
  ```
172
172
 
173
173
  Paste the returned markup into `--markup`, alongside other references:
174
174
 
175
175
  ```cmd
176
- npx @odla-ai/cli discuss post --app <appId> --subject "Ready for review" --markup "Review @[Checkout retries](pm:task/<task-id>) for @[Retry safety](pm:goal/<goal-id>)."
176
+ npx --yes @odla-ai/cli@latest discuss post --app <appId> --subject "Ready for review" --markup "Review @[Checkout retries](pm:task/<task-id>) for @[Retry safety](pm:goal/<goal-id>)."
177
177
  ```
178
178
 
179
179
  The same copied `pm:*` markup works in an item's own PM comment. It is stored as
@@ -181,8 +181,8 @@ a structured reference, rendered as a PM chip, and printed as markup again by
181
181
  the `comments` command:
182
182
 
183
183
  ```cmd
184
- npx @odla-ai/cli pm task comment <task-id> --body "Blocked by @[Retry safety](pm:goal/<goal-id>)."
185
- npx @odla-ai/cli pm task comments <task-id>
184
+ npx --yes @odla-ai/cli@latest pm task comment <task-id> --body "Blocked by @[Retry safety](pm:goal/<goal-id>)."
185
+ npx --yes @odla-ai/cli@latest pm task comments <task-id>
186
186
  ```
187
187
 
188
188
  Use `pm:task`, `pm:goal`, `pm:decision`, `pm:bug`, and `pm:runbook`. The message
@@ -237,9 +237,9 @@ For work that must run from several worktrees or another project, save a named,
237
237
  non-secret operator context and select it explicitly:
238
238
 
239
239
  ```cmd
240
- npx @odla-ai/cli context save delivery --platform https://odla.ai --app <appId>
241
- npx @odla-ai/cli context show --context delivery
242
- npx @odla-ai/cli pm next --context delivery
240
+ npx --yes @odla-ai/cli@latest context save delivery --platform https://odla.ai --app <appId>
241
+ npx --yes @odla-ai/cli@latest context show --context delivery
242
+ npx --yes @odla-ai/cli@latest pm next --context delivery
243
243
  ```
244
244
 
245
245
  The selected profile uses a user-level private credential cache instead of the
@@ -258,9 +258,9 @@ Every goal/task/decision/bug create/update/delete appends an immutable event
258
258
  snapshot in the same transaction. Consume the exact-project stream with:
259
259
 
260
260
  ```cmd
261
- npx @odla-ai/cli pm watch --app <appId> --jsonl
262
- npx @odla-ai/cli pm watch --app <appId> --cursor <cursor> --entity task --state ready --self <principal-id> --jsonl
263
- npx @odla-ai/cli pm watch --app <appId> --cursor <cursor> --entity task --action comment.created --self <principal-id> --jsonl
261
+ npx --yes @odla-ai/cli@latest pm watch --app <appId> --jsonl
262
+ npx --yes @odla-ai/cli@latest pm watch --app <appId> --cursor <cursor> --entity task --state ready --self <principal-id> --jsonl
263
+ npx --yes @odla-ai/cli@latest pm watch --app <appId> --cursor <cursor> --entity task --action comment.created --self <principal-id> --jsonl
264
264
  ```
265
265
 
266
266
  The first call establishes a checkpoint and intentionally does not replay old
@@ -121,7 +121,7 @@ recordError(err, { route, code }); // structured errors
121
121
  ```
122
122
 
123
123
  When `o11y` is in `services`, run
124
- `npx @odla-ai/cli provision --write-dev-vars --push-secrets`. The CLI enables
124
+ `npx --yes @odla-ai/cli@latest provision --write-dev-vars --push-secrets`. The CLI enables
125
125
  the service, issues or reuses its token, persists it locally, writes
126
126
  `.dev.vars`, and transfers `ODLA_O11Y_TOKEN` to the Worker over Wrangler stdin.
127
127
  With a token present, the SDK defaults `ODLA_O11Y_ENDPOINT` to
@@ -151,7 +151,7 @@ npx odla-security scan . --profile odla --out .odla/security/pre-ship --fail-on
151
151
  ```
152
152
 
153
153
  Deterministic rules emit leads. After explicit redacted-source approval, run
154
- `npx @odla-ai/cli security run . --env dev --ack-redacted-source` for hosted,
154
+ `npx --yes @odla-ai/cli@latest security run . --env dev --ack-redacted-source` for hosted,
155
155
  app-attributed discovery and independent validation. It obtains owner auth and
156
156
  never asks for provider keys. The lower-level library flow remains available
157
157
  for custom orchestrators; active reproduction still requires an explicitly
@@ -65,6 +65,24 @@ installed skill at `../odla/SKILL.md` instead.
65
65
  Read `references/project-state.md` before recording or resuming work. Never
66
66
  put credentials or secret values in PM.
67
67
 
68
+ ## Agent handshake protocol
69
+
70
+ Run the current published CLI with browser auto-launch suppressed and keep the
71
+ authorization command as one foreground tool process:
72
+
73
+ ```bash
74
+ npx --yes @odla-ai/cli@latest auth login --app <appId> --email <odla-account> --no-open --wait 600
75
+ ```
76
+
77
+ Immediately surface the printed `/studio?code=` URL as a clickable human action,
78
+ repeat the code to verify, and tell the human to click **Approve**. Wait on the
79
+ same process; the CLI owns protocol polling. Never call the OS `open` command,
80
+ use browser control, curl a handshake endpoint, create a shell polling/wait
81
+ loop, detach the process, or start a substitute handshake. The device code
82
+ exists only in the running CLI. If it exits 75, its old URL cannot be collected;
83
+ start one fresh foreground invocation and surface only the new URL. Use the same
84
+ `--no-open --wait 600` flags when provision itself needs a reviewed capability.
85
+
68
86
  ## Phase state machine
69
87
 
70
88
  Phases run strictly in order; each has a verification gate:
@@ -75,7 +93,7 @@ Phases run strictly in order; each has a verification gate:
75
93
  PM is the durable state: goals define the migration gates, board tasks show the
76
94
  active phase, decisions preserve product and architecture choices, bugs capture
77
95
  defects, and comments carry evidence. In a fresh session, query PM first as
78
- specified in `references/project-state.md`; `npx @odla-ai/cli doctor` then
96
+ specified in `references/project-state.md`; `npx --yes @odla-ai/cli@latest doctor` then
79
97
  confirms the checked-in config state.
80
98
 
81
99
  ## Auth model (one line)
@@ -100,14 +118,14 @@ so this is a natural first step.
100
118
 
101
119
  ## Verification tools
102
120
 
103
- - `npx @odla-ai/cli capabilities --json` — authoritative automation boundary;
121
+ - `npx --yes @odla-ai/cli@latest capabilities --json` — authoritative automation boundary;
104
122
  run once when orienting so source edits and human checkpoints are not confused
105
123
  with CLI-owned platform/credential work.
106
- - `npx @odla-ai/cli doctor` — offline config/schema/rules validation; run
124
+ - `npx --yes @odla-ai/cli@latest doctor` — offline config/schema/rules validation; run
107
125
  after any config edit.
108
- - `npx @odla-ai/cli provision --dry-run` — the plan, zero network/file I/O;
126
+ - `npx --yes @odla-ai/cli@latest provision --dry-run` — the plan, zero network/file I/O;
109
127
  show it to the human before the first real provision.
110
- - `npx @odla-ai/cli smoke --env dev` — live, read-only: public-config, live
128
+ - `npx --yes @odla-ai/cli@latest smoke --env dev` — live, read-only: public-config, live
111
129
  schema diff, a count aggregate. Run after every provision.
112
130
  - `wrangler dev` + curl — exercise routes locally before deploying.
113
131
  - Contract probes — compare old and new method/auth/request/response schemas,
@@ -50,7 +50,7 @@ hand-author only the namespaces it does not.
50
50
  `/admin/#people/person/record-id/profile`; keep legacy query/path links only
51
51
  as inbound compatibility URLs.
52
52
  6. **Override rather than inherit wherever local behavior was a decision.**
53
- 7. `npx @odla-ai/cli doctor` → `provision --dry-run` (show the human) → provision.
53
+ 7. `npx --yes @odla-ai/cli@latest doctor` → `provision --dry-run` (show the human) → provision.
54
54
 
55
55
  ### Existing admin workspace gate
56
56