@oxy-hq/cli 0.7.0 → 0.9.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 +131 -8
- package/dist/main.mjs +4909 -3551
- package/dist/main.mjs.map +1 -1
- package/dist/{mcp-xxWL3_dz.mjs → mcp-Bdp0rX0l.mjs} +2 -2
- package/dist/{mcp-xxWL3_dz.mjs.map → mcp-Bdp0rX0l.mjs.map} +1 -1
- package/package.json +5 -5
- package/skills/oxy-agents/SKILL.md +318 -0
- package/skills/oxy-agents/references/quick-reference.md +222 -0
- package/skills/oxy-agents/templates/agentic-template.yml +141 -0
- package/skills/oxy-airway-pipelines/SKILL.md +223 -316
- package/skills/oxy-automations/SKILL.md +61 -15
- package/skills/oxy-cli/SKILL.md +37 -4
- package/skills/oxy-custom-apps/SKILL.md +193 -291
- package/skills/oxy-custom-apps/references/minimal-starter.md +63 -0
- package/skills/oxy-custom-apps/references/performance-and-usage.md +105 -0
- package/skills/oxy-custom-apps/references/reading-data.md +106 -0
- package/skills/oxy-custom-apps/references/sandbox-agent-loop.md +267 -0
- package/skills/oxy-custom-apps/references/verifying-in-the-browser.md +65 -0
- package/skills/oxy-data-apps/SKILL.md +362 -0
- package/skills/oxy-data-apps/references/examples.md +263 -0
- package/skills/oxy-data-apps/references/quick-reference.md +171 -0
- package/skills/oxy-data-apps/templates/dashboard-with-controls.app.yml +128 -0
- package/skills/oxy-data-apps/templates/simple-dashboard.app.yml +102 -0
- package/skills/oxy-data-architecture/SKILL.md +137 -152
- package/skills/oxy-evals/SKILL.md +362 -0
- package/skills/oxy-evals/references/diagnosis.md +243 -0
- package/skills/oxy-evals/references/results-json.md +145 -0
- package/skills/oxy-evals/references/writing-expected.md +112 -0
- package/skills/oxy-semantic-modeling/SKILL.md +239 -59
- package/skills/oxy-semantic-modeling/references/warehouse-casts.md +57 -0
- package/skills/oxy-semantic-modeling/templates/topic-template.yml +38 -0
- package/skills/oxy-semantic-modeling/templates/view-template.yml +119 -0
- package/template/.github/workflows/publish.yaml +15 -13
- package/template/.nvmrc +1 -1
- package/template/.oxyc-managed +5 -5
- package/template/README.md +21 -10
- package/template/package.json +3 -2
- package/template/pnpm-workspace.yaml +28 -17
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
`oxyc` — a `gh api`-shaped client for the Oxy HTTP API, plus the tooling that
|
|
4
4
|
manages customer workspace repos.
|
|
5
5
|
|
|
6
|
-
- **API client** — `api`, `routes`, `schema`, `openapi`, `login`, `whoami`, `token`, `tokens`, `assume`, `oltp`
|
|
6
|
+
- **API client** — `api`, `routes`, `schema`, `openapi`, `login`, `whoami`, `token`, `login-link`, `tokens`, `assume`, `oltp`
|
|
7
7
|
- **Customer workspaces** — `list`, `new`, `import`, `doctor`, `update`, `adopt`, `launch`
|
|
8
8
|
- **Custom apps** — `publish`, `init-ci`, `proxy`, `apps`
|
|
9
9
|
- **Checks** — `checks run`
|
|
@@ -152,14 +152,30 @@ route's surface and fleet role.
|
|
|
152
152
|
oxyc login [--env <e>] [--login-env <e...>] [--assume <org> -r <why>]
|
|
153
153
|
oxyc whoami [--json] # who the credential is, and what it can reach
|
|
154
154
|
oxyc token # print the bearer, for a raw curl
|
|
155
|
+
oxyc login-link [--next <path>] [--json] [--open] # a one-time URL that signs a browser in
|
|
155
156
|
oxyc logout # revoke the cached token, then forget it
|
|
156
157
|
oxyc tokens list [--json] # your personal access tokens
|
|
157
158
|
oxyc tokens revoke <id>
|
|
158
159
|
oxyc tokens revoke --current # end the token in OXY_TOKEN
|
|
159
160
|
oxyc tokens create # opens Account → Personal access tokens
|
|
160
161
|
oxyc tokens create --sandbox-agent --app <org>/<app> [--app …] [--hours 8] [--name …]
|
|
162
|
+
oxyc tokens create --agent [--standing] [--hours 8] [--name …]
|
|
161
163
|
```
|
|
162
164
|
|
|
165
|
+
**An agent runs on its own token, never on the person's `oxyc login`.** Which
|
|
166
|
+
one depends on the task:
|
|
167
|
+
|
|
168
|
+
| The agent is… | It mints | Which reaches |
|
|
169
|
+
| --- | --- | --- |
|
|
170
|
+
| building a custom app in a sandbox | `tokens create --sandbox-agent --app …` (`oxy_sbx_…`) | the sandboxes of the apps it names, and nothing else |
|
|
171
|
+
| doing anything else: reading data with `oxyc api`, reproducing a bug against live data | `tokens create --agent` (`oxy_pat_…`) | everything its approver can, for hours |
|
|
172
|
+
|
|
173
|
+
Both are approved once in the browser by the person the agent works for, both
|
|
174
|
+
are printed once as `export OXY_TOKEN=…` and never stored, and both end with
|
|
175
|
+
`tokens revoke --current`. After a mint, pass `--token-env OXY_TOKEN` to every
|
|
176
|
+
command: a named variable is the only source, so a command that lost the
|
|
177
|
+
variable exits `4` instead of quietly running on the person's cached login.
|
|
178
|
+
|
|
163
179
|
**Every command resolves its credential the same way, first match wins:**
|
|
164
180
|
|
|
165
181
|
1. **`OXY_TOKEN`** (or the variable `--token-env` names). It holds any
|
|
@@ -167,7 +183,8 @@ oxyc tokens create --sandbox-agent --app <org>/<app> [--app …] [--hours 8] [--
|
|
|
167
183
|
token (`oxy_pat_…`), a service account token (`oxy_sat_…`), a CI token
|
|
168
184
|
(`oxy_ci_…`) or a sandbox agent token (`oxy_sbx_…`) — a legacy API key
|
|
169
185
|
(`oxy_…`), a publish token, or a session token. A blank value counts as
|
|
170
|
-
unset.
|
|
186
|
+
unset. An agent token is a personal access token by its prefix: only its
|
|
187
|
+
own description tells it from a login (`oxyc whoami`).
|
|
171
188
|
2. **The login cache** — what `oxyc login` stored for this deployment.
|
|
172
189
|
3. **GitHub OIDC**, in a GitHub Actions job granted `id-token: write`: the job's
|
|
173
190
|
OIDC token is exchanged, once per process, for a fifteen-minute token acting
|
|
@@ -195,7 +212,7 @@ Settings → Workspace → Legacy API keys. Use an API token for anything new.
|
|
|
195
212
|
|
|
196
213
|
**`login`** runs a browser loopback flow. Against a current deployment it
|
|
197
214
|
receives a one-time code and exchanges it (PKCE) for a **personal access
|
|
198
|
-
token** named `oxyc on <hostname>`: revocable,
|
|
215
|
+
token** named `oxyc on <hostname>`: revocable, a year, and replacing that
|
|
199
216
|
machine's previous one. No credential travels in a URL. Against a deployment
|
|
200
217
|
that predates the exchange it stores the session token the page hands back,
|
|
201
218
|
exactly as before, and says so — nothing needs upgrading first, in either
|
|
@@ -211,7 +228,10 @@ rather than reading as fine from the cache. For a token it also prints what the
|
|
|
211
228
|
token is and what it can reach — `all access`, or one line per grant with the
|
|
212
229
|
role it is capped at, and any organization whose policy blocks it. For a legacy
|
|
213
230
|
API key it prints `Legacy API key`, and that it reaches everything its owner
|
|
214
|
-
can.
|
|
231
|
+
can. For an agent token it says `agent token`, who approved it, whether it
|
|
232
|
+
carries their staff or partner access, and when it expires. When a token in
|
|
233
|
+
`OXY_TOKEN` is refused (exit `4`), the advice is never to log in — a login
|
|
234
|
+
cannot replace what is in the variable. An agent stops and reports.
|
|
215
235
|
|
|
216
236
|
**`token`** prints the bearer on stdout and nothing else. Inside a GitHub
|
|
217
237
|
Actions job with nothing stored it prints the token the job's OIDC identity
|
|
@@ -275,6 +295,35 @@ A refusal from the server carries a hint an agent can act on — never "try
|
|
|
275
295
|
`oxyc login` again". Exit `4` under this token means it expired, was revoked,
|
|
276
296
|
or its minter lost access: stop and report.
|
|
277
297
|
|
|
298
|
+
**`tokens create --agent`** mints an **agent token** for everything that is not
|
|
299
|
+
a sandbox: a personal access token (`oxy_pat_…`) that reaches what its approver
|
|
300
|
+
reaches through their organization memberships, for 8 hours by default
|
|
301
|
+
(`--hours`, 1 to 168). It cannot be extended, edited or regenerated, and it
|
|
302
|
+
cannot create, extend or revoke tokens; it can open a browser session as itself
|
|
303
|
+
(`login-link`).
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
eval "$(oxyc tokens create --agent --env dev)"
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
The same browser loopback again, with the same guarantees: stdout is the single
|
|
310
|
+
line `export OXY_TOKEN=oxy_pat_…`, printed once, everything else is on stderr,
|
|
311
|
+
it holds no credential while it runs, never writes the credentials file and
|
|
312
|
+
revokes no other token. Arguments are checked before the browser opens (exit
|
|
313
|
+
`2`); `--agent` and `--sandbox-agent` together are a usage error.
|
|
314
|
+
|
|
315
|
+
`--standing` asks for the approver's staff or partner access as well. The
|
|
316
|
+
approver decides on the page, where it starts **off**: a token that comes back
|
|
317
|
+
without it is accepted, and stderr says so in one line. Without `--standing`, a
|
|
318
|
+
token that carries either is refused.
|
|
319
|
+
|
|
320
|
+
What comes back is checked before anything is printed: it must be a whole
|
|
321
|
+
`oxy_pat_`; it must describe itself (`GET /api/auth/token`) as `personal` with
|
|
322
|
+
`source` `oxyc_agent`; it must expire no later than the hours asked for; and it
|
|
323
|
+
must carry no standing that was not asked for. A deployment that predates agent
|
|
324
|
+
tokens would otherwise hand back an ordinary ninety-day login. On any mismatch
|
|
325
|
+
the command prints nothing, revokes what was minted, and exits `8`.
|
|
326
|
+
|
|
278
327
|
Credentials live in the OS config directory under **`oxy`** — the same file the
|
|
279
328
|
Rust `oxy login` wrote before it was removed, so an existing login still works:
|
|
280
329
|
|
|
@@ -285,6 +334,46 @@ An entry may now also carry `token_id` and `expires_at`; both are optional, and
|
|
|
285
334
|
a file written before they existed loads unchanged. `OXY_CREDENTIALS_PATH`
|
|
286
335
|
overrides the path. Caches are separate, under `oxyc` (`~/.cache/oxyc`).
|
|
287
336
|
|
|
337
|
+
### A signed-in browser for an agent
|
|
338
|
+
|
|
339
|
+
Sign-in is passwordless — Google or GitHub OAuth, or a magic link — and an
|
|
340
|
+
automation agent can finish neither. **`login-link`** prints a one-time URL
|
|
341
|
+
that signs a browser in with the credential `oxyc` is running on, so the whole
|
|
342
|
+
sign-in is one navigation:
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
browser_navigate("$(oxyc login-link --env dev --next /ide)") # Playwright MCP
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
```ts
|
|
349
|
+
// a Playwright script
|
|
350
|
+
const link = execFileSync("oxyc", ["login-link", "--env", "dev", "--next", "/ide"], { encoding: "utf8" });
|
|
351
|
+
await page.goto(link.trim());
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Stdout is the URL and nothing else; what the link is goes to stderr.
|
|
355
|
+
|
|
356
|
+
- **The link works once and expires in minutes** (five, at the time of
|
|
357
|
+
writing — the server's `expires_at`). The bearer is never in it: `oxyc`
|
|
358
|
+
trades the token for a single-use ticket (`POST /api/auth/browser-ticket`),
|
|
359
|
+
and the ticket and `--next` ride the URL's fragment, which is not sent to a
|
|
360
|
+
server and so reaches no access log.
|
|
361
|
+
- **The session is bounded by the token.** It reaches what the token reaches
|
|
362
|
+
and nothing more, lasts at most the `session_seconds` the server answers
|
|
363
|
+
(stderr states it in hours), ends sooner if the token is revoked or expires,
|
|
364
|
+
and cannot manage tokens.
|
|
365
|
+
- **It needs a personal access token** (`oxy_pat_…`) — what `oxyc login`
|
|
366
|
+
stores. Any other credential is exit `4` with the next step: a session token
|
|
367
|
+
from an older login, a service account, CI or publish token, a legacy API
|
|
368
|
+
key. A sandbox agent token is exit `2`, before any request. A deployment that
|
|
369
|
+
predates sign-in links is exit `5`.
|
|
370
|
+
- **`--next <path>`** is where the browser lands: a path on the deployment
|
|
371
|
+
starting with a single `/`. A URL, `//host` or a backslash is exit `2`, and
|
|
372
|
+
no ticket is spent on it.
|
|
373
|
+
- **`--json`** prints `{ "url", "expires_at", "session_seconds" }` instead.
|
|
374
|
+
**`--open`** also opens the link in your default browser — which uses it, so
|
|
375
|
+
the printed URL will not work a second time.
|
|
376
|
+
|
|
288
377
|
### CI without a stored secret
|
|
289
378
|
|
|
290
379
|
In a GitHub Actions job granted `id-token: write`, with no `OXY_TOKEN` set,
|
|
@@ -507,7 +596,15 @@ lets it publish.
|
|
|
507
596
|
*The workflow* is `.github/workflows/oxy-publish.yml` at the repo root: a
|
|
508
597
|
`build` job (no id-token) that runs `publish --build-only`, and a `publish` job
|
|
509
598
|
bound to a GitHub `environment:` (`--environment`, default `oxy-publish`) whose
|
|
510
|
-
only work is `publish --prebuilt`.
|
|
599
|
+
only work is `publish --prebuilt`. `build` installs pnpm with
|
|
600
|
+
`pnpm/action-setup@v6` — the pnpm the repo root's package.json pins
|
|
601
|
+
(`packageManager` or `devEngines.packageManager`), with no `version:` of its
|
|
602
|
+
own, since the action refuses a second, different one; pnpm 11 when nothing
|
|
603
|
+
pins it — and both jobs run the Node in `.nvmrc`, else 26 (pnpm 11 needs
|
|
604
|
+
Node 22.13 or later). It warns when nothing pins pnpm, and when
|
|
605
|
+
`pnpm-workspace.yaml` approves build scripts only with `onlyBuiltDependencies`,
|
|
606
|
+
which pnpm 11 ignores (the build's install would fail with
|
|
607
|
+
`ERR_PNPM_IGNORED_BUILDS`; move the entries to `allowBuilds`). The publish job uses no third-party action: each
|
|
511
608
|
step runs `npx @oxy-hq/cli@<this version>` and `oxyc` exchanges the job's OIDC
|
|
512
609
|
token for itself, acting as the service account `--service-account <org>/<name>`
|
|
513
610
|
names — by default `<app's org>/deployer`. **Here, and only here, the account is
|
|
@@ -664,6 +761,26 @@ object to stdout instead:
|
|
|
664
761
|
{ "app": "acme/dashboards", "appId": "…", "checks": [{ "name": "canary", "runId": "…", "status": "done", "passed": true, "durationMs": 4123 }] }
|
|
665
762
|
```
|
|
666
763
|
|
|
764
|
+
**`--browser`** also loads the app's page in headless Chromium and proves it
|
|
765
|
+
mounted: the platform runtime's `oxy-app-ready` beacon fires, nothing on the
|
|
766
|
+
page throws, and `--expect-selector <css>` (optional) becomes visible. With
|
|
767
|
+
`--app-env` the page must also report that environment and the build it serves
|
|
768
|
+
(`oxyc env show`'s `build_uuid`) in `window.__OXY_APP__`. The credential and
|
|
769
|
+
`X-Oxy-App-Env` ride only on requests under the app's own base path
|
|
770
|
+
(`/customer-apps/<org>/<app>/`: the document, assets, beacon and `/fn` calls).
|
|
771
|
+
The rest of the deployment's API is on the same origin, and the code under test
|
|
772
|
+
is often a build someone else published, so its `/api/…` calls go without the
|
|
773
|
+
credential, as an anonymous visitor's would. The result is one more entry in `checks[]`, with `"kind": "browser"` and
|
|
774
|
+
the `/fn` calls the page made. Playwright is not a dependency: it is resolved
|
|
775
|
+
from the working directory (`playwright`, `playwright-core` or
|
|
776
|
+
`@playwright/test`), so run it where one is installed. The page loads as a
|
|
777
|
+
user, so a publish, service-account, CI or sandbox agent token is refused
|
|
778
|
+
before any request.
|
|
779
|
+
|
|
780
|
+
```bash
|
|
781
|
+
oxyc checks run acme/store --app-env dev-a1 --browser --expect-selector 'main'
|
|
782
|
+
```
|
|
783
|
+
|
|
667
784
|
**Auth** follows the same rule as `oxyc api`'s bearer surface, with one
|
|
668
785
|
difference: `checks run` talks to `/api/admin/**`, which is not the
|
|
669
786
|
`/external/api/*` surface, so a configured API key is sent explicitly as
|
|
@@ -980,9 +1097,12 @@ them, and a tool that can only fail still costs its schema every turn. A dead
|
|
|
980
1097
|
token ends the server at startup with exit `4`.
|
|
981
1098
|
|
|
982
1099
|
**`guide`** prints a page to paste into `AGENTS.md` / `CLAUDE.md`.
|
|
983
|
-
**`skills install`** symlinks the
|
|
1100
|
+
**`skills install`** symlinks the bundled Oxy platform skills into
|
|
984
1101
|
`~/.claude/skills`; it refuses to run from an `npx` cache, whose symlinks dangle
|
|
985
|
-
once npm reclaims it.
|
|
1102
|
+
once npm reclaims it. The same skills are published to
|
|
1103
|
+
[`oxy-hq/skills`](https://github.com/oxy-hq/skills) for every other agent —
|
|
1104
|
+
`npx skills add oxy-hq/skills`, or the Claude Code plugin `oxy@oxy-hq`. They are
|
|
1105
|
+
written in `skills/` here; see `internal-docs/platform-skills.md`.
|
|
986
1106
|
|
|
987
1107
|
## Exit codes
|
|
988
1108
|
|
|
@@ -998,7 +1118,10 @@ once npm reclaims it.
|
|
|
998
1118
|
9 a check ran and failed or timed out (`oxyc checks run`)
|
|
999
1119
|
```
|
|
1000
1120
|
|
|
1001
|
-
`4` almost always means the wrong `--env`.
|
|
1121
|
+
`4` almost always means the wrong `--env`. A person logs in again. An agent on
|
|
1122
|
+
its own token (`tokens create --agent` or `--sandbox-agent`) does not: there,
|
|
1123
|
+
`4` means the token expired or was revoked, and the agent stops and reports.
|
|
1124
|
+
`7` is worth retrying; `6` never is.
|
|
1002
1125
|
|
|
1003
1126
|
## Environment variables
|
|
1004
1127
|
|