@odla-ai/cli 0.8.0 → 0.10.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 +95 -8
- package/REQUIREMENTS.md +14 -0
- package/dist/bin.cjs +806 -56
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-BHAEDEL2.js → chunk-WDKBW4BE.js} +824 -64
- package/dist/chunk-WDKBW4BE.js.map +1 -0
- package/dist/index.cjs +826 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +232 -282
- package/dist/index.d.ts +232 -282
- package/dist/index.js +21 -1
- package/llms.txt +315 -291
- package/package.json +3 -3
- package/skills/odla/SKILL.md +12 -3
- package/skills/odla/references/build.md +19 -0
- package/skills/odla/references/sdks.md +29 -0
- package/skills/odla-migrate/SKILL.md +8 -2
- package/skills/odla-migrate/references/phase-2-db.md +2 -2
- package/skills/odla-migrate/references/phase-2b-calendar.md +42 -0
- package/skills/odla-migrate/references/phase-3b-user-sync.md +15 -8
- package/skills/odla-migrate/references/secrets-map.md +16 -2
- package/dist/chunk-BHAEDEL2.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@odla-ai/cli",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Agent-operable CLI for odla provisioning, System AI administration,
|
|
3
|
+
"version": "0.10.0",
|
|
4
|
+
"description": "Agent-operable CLI for odla provisioning, calendar consent and sync lifecycle, System AI administration, Worker secrets, security jobs, and smoke checks.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://odla.ai/docs/packages/cli",
|
|
7
7
|
"repository": {
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"@odla-ai/ai": "^0.3.3",
|
|
63
|
-
"@odla-ai/apps": "^0.
|
|
63
|
+
"@odla-ai/apps": "^0.8.0",
|
|
64
64
|
"@odla-ai/db": "^0.6.2",
|
|
65
65
|
"@odla-ai/security": "^0.2.2"
|
|
66
66
|
},
|
package/skills/odla/SKILL.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
name: odla
|
|
3
3
|
description: >
|
|
4
4
|
Build a new app on odla — a realtime database (odla-db) plus AI, Clerk auth,
|
|
5
|
-
and observability on Cloudflare, provisioned by @odla-ai/cli. Use when the user
|
|
5
|
+
read-only Google Calendar mirrors, and observability on Cloudflare, provisioned by @odla-ai/cli. Use when the user
|
|
6
6
|
wants to create/scaffold an odla app, add odla-db/ai/auth/o11y to a repo, or
|
|
7
7
|
"get started with odla". For moving an existing static or GitHub Pages site to
|
|
8
8
|
odla, use the odla-migrate skill instead.
|
|
@@ -15,7 +15,7 @@ runbookOrder:
|
|
|
15
15
|
|
|
16
16
|
You drive setup and building on **odla** — an agent-operable app platform on
|
|
17
17
|
Cloudflare: a realtime graph database (**odla-db**), multi-provider **AI**,
|
|
18
|
-
**Clerk** auth, and OpenTelemetry **observability**, all provisioned by the
|
|
18
|
+
**Clerk** auth, read-only **Google Calendar** mirrors, and OpenTelemetry **observability**, all provisioned by the
|
|
19
19
|
`@odla-ai/cli`. The human approves a couple of browser-only checkpoints; you do
|
|
20
20
|
everything else.
|
|
21
21
|
|
|
@@ -48,6 +48,9 @@ State which path you're taking and what you'll build in one line; get a nod.
|
|
|
48
48
|
4. Never `git add -A` without reading `git status` first. Never run
|
|
49
49
|
`provision --rotate-keys` or `provision --rotate-o11y-token` unless the human
|
|
50
50
|
explicitly asks.
|
|
51
|
+
5. Google OAuth is a distinct human checkpoint. Never request, paste, print, or
|
|
52
|
+
store a Google authorization code/refresh token. Open only the state-bound
|
|
53
|
+
platform/Google consent URL returned by odla; calendar actions remain unavailable in the read-only slice.
|
|
51
54
|
|
|
52
55
|
## The flow
|
|
53
56
|
|
|
@@ -67,7 +70,9 @@ guessing which platform/credential steps need manual work. Then:
|
|
|
67
70
|
prints; the human approves it at https://odla.ai/studio. It creates the app,
|
|
68
71
|
enables services, issues or reuses configured credentials (db key + o11y
|
|
69
72
|
ingest token when enabled), pushes schema + rules, writes `.dev.vars`, and
|
|
70
|
-
transfers Worker secrets through Wrangler stdin.
|
|
73
|
+
transfers Worker secrets through Wrangler stdin. With calendar enabled it
|
|
74
|
+
then prints a second, server-issued Google URL; the human grants read-only consent
|
|
75
|
+
and the CLI follows initial sync.
|
|
71
76
|
4. **run** — `npx wrangler dev` (auto-loads `.dev.vars`); verify locally.
|
|
72
77
|
5. **security** — run the passive `@odla-ai/security` odla profile; inspect
|
|
73
78
|
every lead and keep critical candidate gating enabled. If the human approves
|
|
@@ -88,6 +93,10 @@ guessing which platform/credential steps need manual work. Then:
|
|
|
88
93
|
|
|
89
94
|
`npx @odla-ai/cli doctor` is an offline config check anytime;
|
|
90
95
|
`npx @odla-ai/cli smoke --env dev` verifies a live deployment.
|
|
96
|
+
Use `calendar status --json` for safe connection/sync state and `calendar
|
|
97
|
+
calendars --json` to discover ids after consent; update checked-in config and
|
|
98
|
+
re-provision. Resync production only with `--yes`; disconnect always requires
|
|
99
|
+
`--yes` and leaves retained rows potentially stale.
|
|
91
100
|
|
|
92
101
|
The CLI owns deterministic platform work from `odla.config.mjs`: service
|
|
93
102
|
enablement, credential issuance/storage, `.dev.vars`, and Wrangler secret
|
|
@@ -15,6 +15,13 @@ deny-all rules from the schema. To turn on auth/observability, add `"o11y"` to
|
|
|
15
15
|
`services` and an `auth.clerk` block in `odla.config.mjs` (init leaves it
|
|
16
16
|
commented).
|
|
17
17
|
|
|
18
|
+
For a Google booking mirror, include both `"db"` and `"calendar"`. Configure
|
|
19
|
+
`calendar.google.calendars` for every env (start with `"primary"`), optional
|
|
20
|
+
match filters, and `attendeePolicy: "full" | "hashed"`. This release is
|
|
21
|
+
read-only; do not add OAuth credentials or action scopes to config.
|
|
22
|
+
For static Appointment Schedule parity, add the public per-env
|
|
23
|
+
`bookingPageUrl`; it is link/embed configuration, never a credential.
|
|
24
|
+
|
|
18
25
|
## 2. Build the Worker shell
|
|
19
26
|
|
|
20
27
|
`npm i` only the SDKs you need and use the local `references/sdks.md` as the
|
|
@@ -43,6 +50,13 @@ Local credential files are `0600` and gitignored. Verify with
|
|
|
43
50
|
anything unset. `--push-secrets` preflights the Wrangler config and login before
|
|
44
51
|
issuing or rotating a shown-once credential.
|
|
45
52
|
|
|
53
|
+
Calendar adds a second ⏸ checkpoint after the odla device approval: provision
|
|
54
|
+
prints/opens a state-bound Google URL issued by the platform and waits while the human grants
|
|
55
|
+
`calendar.events.readonly` and the hosted connector performs initial sync. The
|
|
56
|
+
CLI never receives the Google callback code or tokens. Once connected, run
|
|
57
|
+
`npx @odla-ai/cli calendar calendars --env dev --json`, refine the checked-in
|
|
58
|
+
calendar ids if needed, re-provision, and verify `calendar status --json`.
|
|
59
|
+
|
|
46
60
|
The CLI stops at the source boundary: it verifies but does not invent your
|
|
47
61
|
application semantics. Do not use Studio to mint a routine o11y token. Manual
|
|
48
62
|
Studio rotation is recovery-only;
|
|
@@ -61,6 +75,11 @@ means the namespace has no rule yet — add one in `src/odla/rules.mjs`
|
|
|
61
75
|
(deliberately; e.g. `{ notes: { view: "auth.signedIn", create: "auth.signedIn" } }`),
|
|
62
76
|
re-provision to push it, and retry.
|
|
63
77
|
|
|
78
|
+
Calendar uses the same `ODLA_ENDPOINT`, `ODLA_TENANT`, and server-only
|
|
79
|
+
`ODLA_API_KEY`; it adds no Worker secret. Keep `initCalendar` in trusted Worker
|
|
80
|
+
code. Browser code uses db subscriptions under explicit rules or pure
|
|
81
|
+
`@odla-ai/calendar/client` helpers, never the admin key.
|
|
82
|
+
|
|
64
83
|
## 5. Security preflight
|
|
65
84
|
|
|
66
85
|
Install the passive harness and scan before any production secret or deploy:
|
|
@@ -31,6 +31,35 @@ Worker/admin side: `init({ appId: tenantId, adminToken: env.ODLA_API_KEY, endpoi
|
|
|
31
31
|
The publishable key is public; `provision` stores it (`setAuth`). Rules evaluate
|
|
32
32
|
the signed-in user's JWT as `auth` — e.g. `auth.signedIn`, `auth.email`.
|
|
33
33
|
|
|
34
|
+
## @odla-ai/calendar — read-only Google booking mirror
|
|
35
|
+
|
|
36
|
+
Calendar requires `services: ["db", "calendar"]` plus a `calendar.google`
|
|
37
|
+
block. Normal provision opens a second, state-bound Google checkpoint issued by the platform for the
|
|
38
|
+
human to grant `calendar.events.readonly`; Google tokens stay in the hosted
|
|
39
|
+
connector and never become app/CLI secrets.
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
// Trusted Worker only — the admin key must never enter browser code.
|
|
43
|
+
const calendar = initCalendar({
|
|
44
|
+
appId: env.ODLA_TENANT,
|
|
45
|
+
adminToken: env.ODLA_API_KEY,
|
|
46
|
+
endpoint: env.ODLA_ENDPOINT,
|
|
47
|
+
});
|
|
48
|
+
const next = await calendar.bookings.next("member@example.com");
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Browser code may query `$bookings` with `@odla-ai/db/client` only under an
|
|
52
|
+
explicit view rule, and may import pure formatting helpers from
|
|
53
|
+
`@odla-ai/calendar/client`. Do not import `initCalendar` or expose
|
|
54
|
+
`ODLA_API_KEY` in a browser. Provider actions are not part of the read-only
|
|
55
|
+
slice; a `calendar_not_connected`/501 action response is not a reason to widen
|
|
56
|
+
credentials or request a Google token.
|
|
57
|
+
|
|
58
|
+
After consent, use `odla-ai calendar calendars --env dev --json` to discover
|
|
59
|
+
selectable ids, edit the checked-in list, and optionally set a public per-env
|
|
60
|
+
`bookingPageUrl` for Appointment Schedule embed/link mode. Re-provision, then verify with
|
|
61
|
+
`calendar status --json` and `smoke`.
|
|
62
|
+
|
|
34
63
|
## @odla-ai/ai — inference (Claude / GPT / Gemini)
|
|
35
64
|
|
|
36
65
|
```ts
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
name: odla-migrate
|
|
3
3
|
description: >
|
|
4
4
|
Migrate a static site (e.g. GitHub Pages) to odla on Cloudflare in safe
|
|
5
|
-
phases, then add a database, Clerk login, and AI. Use when the user wants to
|
|
5
|
+
phases, then add a database, optional read-only calendar mirror, Clerk login, and AI. Use when the user wants to
|
|
6
6
|
move a static or GitHub Pages site to Cloudflare/odla, or to add a backend,
|
|
7
7
|
database, login/auth, or AI features to a static site via odla.
|
|
8
8
|
runbookOrder:
|
|
9
9
|
- references/phase-0-preflight.md
|
|
10
10
|
- references/phase-1-static.md
|
|
11
11
|
- references/phase-2-db.md
|
|
12
|
+
- references/phase-2b-calendar.md
|
|
12
13
|
- references/phase-3-auth.md
|
|
13
14
|
- references/phase-3b-user-sync.md
|
|
14
15
|
- references/phase-4-ai.md
|
|
@@ -45,12 +46,16 @@ installed skill at `../odla/SKILL.md` instead.
|
|
|
45
46
|
approved o11y rotation with `--push-secrets` so the Worker is updated in the
|
|
46
47
|
same run. If the final Wrangler transfer fails, use the CLI's printed
|
|
47
48
|
non-rotating `secrets push` retry; never rotate again just to retry delivery.
|
|
49
|
+
7. Existing calendar embeds are public links, not proof of a booking. Preserve
|
|
50
|
+
them via `bookingPageUrl`; never claim reconciliation until the read-only
|
|
51
|
+
mirror is connected and the app correlates `$bookings` deliberately. Google
|
|
52
|
+
OAuth tokens never enter the repo, CLI, or chat.
|
|
48
53
|
|
|
49
54
|
## Phase state machine
|
|
50
55
|
|
|
51
56
|
Phases run strictly in order; each has a verification gate:
|
|
52
57
|
|
|
53
|
-
P0 preflight -> P1 static-on-cloudflare -> P2 database -> P3 login
|
|
58
|
+
P0 preflight -> P1 static-on-cloudflare -> P2 database -> P2b calendar (optional) -> P3 login
|
|
54
59
|
-> P4 ai (optional) -> P5 prod + DNS cutover
|
|
55
60
|
|
|
56
61
|
`MIGRATION.md` at the user's repo root is the durable state: create it in
|
|
@@ -100,6 +105,7 @@ Read the current phase's file when you enter it — not before:
|
|
|
100
105
|
- references/phase-0-preflight.md
|
|
101
106
|
- references/phase-1-static.md
|
|
102
107
|
- references/phase-2-db.md
|
|
108
|
+
- references/phase-2b-calendar.md (optional: preserve an embed and add authoritative read-only reconciliation)
|
|
103
109
|
- references/phase-3-auth.md
|
|
104
110
|
- references/phase-3b-user-sync.md (optional: mirror Clerk users into $users)
|
|
105
111
|
- references/phase-4-ai.md
|
|
@@ -10,8 +10,8 @@ in the browser in interactive terminals).
|
|
|
10
10
|
|
|
11
11
|
## Steps
|
|
12
12
|
|
|
13
|
-
1. Require `npm view @odla-ai/cli@0.
|
|
14
|
-
`npm i -D --save-exact @odla-ai/cli@0.
|
|
13
|
+
1. Require `npm view @odla-ai/cli@0.10.0 version` to succeed, then run
|
|
14
|
+
`npm i -D --save-exact @odla-ai/cli@0.10.0` and `npm i @odla-ai/db`.
|
|
15
15
|
2. `npx @odla-ai/cli init --app-id <id> --name "<Name>" --env dev --services db`
|
|
16
16
|
Review `odla.config.mjs`. Keep `envs: ["dev"]` — prod is Phase 5. Set
|
|
17
17
|
`links.dev` to the URL the Phase 1 `wrangler deploy` **actually printed** —
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Phase 2b — Google Calendar (optional, read-only)
|
|
2
|
+
|
|
3
|
+
Use this phase only when the existing site has a Google Appointment Schedule
|
|
4
|
+
link/embed or locally reported meeting state. Keep the old booking experience
|
|
5
|
+
working while adding an authoritative read-only mirror.
|
|
6
|
+
|
|
7
|
+
Human obligations: review attendee-data retention and complete the second,
|
|
8
|
+
server-issued Google consent page. They never paste an OAuth code or token.
|
|
9
|
+
|
|
10
|
+
1. Inventory the old behavior. Distinguish a public appointment-page link from
|
|
11
|
+
actual event create/reschedule/cancel APIs. Do not promise more than exists.
|
|
12
|
+
2. Require `npm view @odla-ai/calendar@0.1.0 version` to succeed, then install
|
|
13
|
+
`npm i --save-exact @odla-ai/calendar@0.1.0` as a runtime dependency. An
|
|
14
|
+
exact-version `E404` blocks this phase; do not substitute a git checkout or
|
|
15
|
+
another version. Add `"calendar"` beside
|
|
16
|
+
`"db"` in services and configure:
|
|
17
|
+
- `calendar.google.calendars.dev` (start with `"primary"`);
|
|
18
|
+
- optional summary/organizer/attendee match filters;
|
|
19
|
+
- deliberate `attendeePolicy: "full" | "hashed"`;
|
|
20
|
+
- the old public Appointment Schedule URL as `bookingPageUrl.dev` when
|
|
21
|
+
preserving the embed/link. It is public configuration, not a secret.
|
|
22
|
+
3. Run `doctor`, then `provision --dry-run`. Show the human the calendars,
|
|
23
|
+
attendee policy, public booking page, and read-only scope.
|
|
24
|
+
4. Run normal dev provision. After odla device approval, pause again while the
|
|
25
|
+
human grants Google `calendar.events.readonly`; the CLI follows initial sync.
|
|
26
|
+
5. Run `calendar calendars --env dev --json`, refine the checked-in ids, and
|
|
27
|
+
re-provision. Verify `calendar status --env dev --json` and `smoke --env dev`.
|
|
28
|
+
6. Put `initCalendar` only in trusted Worker code. Browser code may keep using
|
|
29
|
+
the public `bookingPageUrl`, query `$bookings` through explicit db rules, or
|
|
30
|
+
import pure helpers from `@odla-ai/calendar/client`. Never expose
|
|
31
|
+
`ODLA_API_KEY`.
|
|
32
|
+
7. Replace self-reported meeting state only after an explicit, tested
|
|
33
|
+
application-to-booking correlation exists. A matching attendee email may be
|
|
34
|
+
sufficient for some apps; do not silently regress later workflow statuses.
|
|
35
|
+
|
|
36
|
+
This slice cannot create, reschedule, or cancel Google events. A static picker
|
|
37
|
+
continues to be Google's sealed UI; odla supplies configuration, mirror reads,
|
|
38
|
+
and reconciliation.
|
|
39
|
+
|
|
40
|
+
Gate: the old embed/link still works, status is healthy, the selected calendars
|
|
41
|
+
match config, `$bookings` smoke succeeds, no Google credential exists in local
|
|
42
|
+
files, and `MIGRATION.md` records the disclosure/correlation decision.
|
|
@@ -8,9 +8,10 @@ build the mirror yourself — the platform does it. This phase enables it.
|
|
|
8
8
|
Goal: signed-in users appear as rows in the app's `$users`, kept in sync with
|
|
9
9
|
Clerk (create/update/delete). Dev first, then prod.
|
|
10
10
|
|
|
11
|
-
Human obligation: create a Clerk webhook endpoint and
|
|
12
|
-
(`whsec_…`) into
|
|
13
|
-
|
|
11
|
+
Human obligation: create a Clerk webhook endpoint and get its signing secret
|
|
12
|
+
(`whsec_…`) into the tenant vault — piped through `secrets set` when a command
|
|
13
|
+
can print it, or pasted into Studio (both write-only). That plus the Phase-3
|
|
14
|
+
`clerk auth login` are the only human Clerk steps.
|
|
14
15
|
|
|
15
16
|
## How `$users` fills — two paths
|
|
16
17
|
|
|
@@ -37,12 +38,18 @@ Enable it here.
|
|
|
37
38
|
Clerk dashboard → Webhooks → Add Endpoint. (`whsec_` is a real secret — never
|
|
38
39
|
print/commit it; it is the only thing you paste, and it goes into the vault,
|
|
39
40
|
not chat.)
|
|
40
|
-
2. **Store the secret in the tenant vault** as `clerk_webhook_secret`, write-only
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
2. **Store the secret in the tenant vault** as `clerk_webhook_secret`, write-only.
|
|
42
|
+
If any command can print the `whsec_` (Clerk CLI, Svix API), pipe it without
|
|
43
|
+
it ever being displayed:
|
|
44
|
+
`<command that prints whsec_…> | npx @odla-ai/cli secrets set clerk_webhook_secret --env dev --stdin`.
|
|
45
|
+
Otherwise a human pastes it into Studio's secret UI (`odla.ai/studio` → the
|
|
46
|
+
app → the env → secrets) — same write-only slot. The server decrypts it only
|
|
47
|
+
to verify inbound events (svix HMAC over `id.timestamp.body`).
|
|
43
48
|
3. **(Optional) `sk_…`** — the webhook payload already carries email/name/image,
|
|
44
|
-
so the basic mirror needs only `whsec_`. Add the Clerk backend key
|
|
45
|
-
|
|
49
|
+
so the basic mirror needs only `whsec_`. Add the Clerk backend key only if
|
|
50
|
+
you later need to resolve data the webhook doesn't send (invites, member
|
|
51
|
+
lookups): `npx @odla-ai/cli secrets set-clerk-key --env dev --from-env CLERK_SECRET_KEY`
|
|
52
|
+
stores it in the reserved `$clerk_secret` slot, write-only.
|
|
46
53
|
|
|
47
54
|
## Verify
|
|
48
55
|
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
| Value | Lives in | Handling |
|
|
6
6
|
|---|---|---|
|
|
7
7
|
| Clerk publishable key (`pk_test_`/`pk_live_`) | registry, via provision → setAuth | public by design; the one value a human may paste into chat; fine inline in odla.config.mjs |
|
|
8
|
-
| Clerk webhook secret (`whsec_…`) | tenant vault (`clerk_webhook_secret`) | only for auth mode "full"; entered in Studio
|
|
9
|
-
| Clerk secret key (`sk_test_`/`sk_live_`) | not
|
|
8
|
+
| Clerk webhook secret (`whsec_…`) | tenant vault (`clerk_webhook_secret`) | only for auth mode "full"; piped with `secrets set clerk_webhook_secret --env <env> --stdin`, or entered in Studio; never wrangler, never chat |
|
|
9
|
+
| Clerk secret key (`sk_test_`/`sk_live_`) | not needed for this journey | if a later feature needs user resolution/invites, pipe it with `secrets set-clerk-key --env <env>` (reserved `$clerk_secret`, write-only); never chat |
|
|
10
10
|
| LLM provider key | tenant vault | env var in the HUMAN's shell for one provision run; never wrangler vars, never git, never chat |
|
|
11
11
|
| `odla_sk_…` (tenant db key) | wrangler secret `ODLA_API_KEY` + `.odla/credentials.local.json` (0600) + `.dev.vars` | present when db is enabled; move it only with the pipeline below |
|
|
12
12
|
| `odla_dev_…` (developer token) | `.odla/dev-token.json` (0600) | ~24h lifetime, provision-time only; never deployed |
|
|
@@ -42,6 +42,20 @@ Manual fallback (identical mechanics, if the CLI is unavailable):
|
|
|
42
42
|
(For prod, use `c.envs.prod.dbKey` and drop `--env` — the top-level
|
|
43
43
|
wrangler env is prod.)
|
|
44
44
|
|
|
45
|
+
## Moving a tenant-vault secret (never through the transcript)
|
|
46
|
+
|
|
47
|
+
`secrets set` fills the same write-only vault slot as Studio's Secrets panel,
|
|
48
|
+
reading the value only from stdin or a named env var — never argv — so a
|
|
49
|
+
producer command pipes straight into the vault:
|
|
50
|
+
|
|
51
|
+
<command that prints the value> | npx @odla-ai/cli secrets set clerk_webhook_secret --env dev --stdin
|
|
52
|
+
npx @odla-ai/cli secrets set-clerk-key --env dev --from-env CLERK_SECRET_KEY
|
|
53
|
+
|
|
54
|
+
The value cannot be read back by the CLI, Studio, or the developer token —
|
|
55
|
+
only by that tenant's app API key (reserved `$` secrets not even then). Studio
|
|
56
|
+
remains the fallback when no producer command exists (a human copies from the
|
|
57
|
+
Clerk dashboard between two browser tabs). Prod-named envs require `--yes`.
|
|
58
|
+
|
|
45
59
|
## Standing rules
|
|
46
60
|
|
|
47
61
|
- Never `cat`, `head`, `grep -v`, or otherwise display `.dev.vars`,
|