@oxy-hq/cli 0.7.0 → 0.8.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 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,6 +152,7 @@ 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>
@@ -285,6 +286,46 @@ An entry may now also carry `token_id` and `expires_at`; both are optional, and
285
286
  a file written before they existed loads unchanged. `OXY_CREDENTIALS_PATH`
286
287
  overrides the path. Caches are separate, under `oxyc` (`~/.cache/oxyc`).
287
288
 
289
+ ### A signed-in browser for an agent
290
+
291
+ Sign-in is passwordless — Google or GitHub OAuth, or a magic link — and an
292
+ automation agent can finish neither. **`login-link`** prints a one-time URL
293
+ that signs a browser in with the credential `oxyc` is running on, so the whole
294
+ sign-in is one navigation:
295
+
296
+ ```bash
297
+ browser_navigate("$(oxyc login-link --env dev --next /ide)") # Playwright MCP
298
+ ```
299
+
300
+ ```ts
301
+ // a Playwright script
302
+ const link = execFileSync("oxyc", ["login-link", "--env", "dev", "--next", "/ide"], { encoding: "utf8" });
303
+ await page.goto(link.trim());
304
+ ```
305
+
306
+ Stdout is the URL and nothing else; what the link is goes to stderr.
307
+
308
+ - **The link works once and expires in minutes** (five, at the time of
309
+ writing — the server's `expires_at`). The bearer is never in it: `oxyc`
310
+ trades the token for a single-use ticket (`POST /api/auth/browser-ticket`),
311
+ and the ticket and `--next` ride the URL's fragment, which is not sent to a
312
+ server and so reaches no access log.
313
+ - **The session is bounded by the token.** It reaches what the token reaches
314
+ and nothing more, lasts at most the `session_seconds` the server answers
315
+ (stderr states it in hours), ends sooner if the token is revoked or expires,
316
+ and cannot manage tokens.
317
+ - **It needs a personal access token** (`oxy_pat_…`) — what `oxyc login`
318
+ stores. Any other credential is exit `4` with the next step: a session token
319
+ from an older login, a service account, CI or publish token, a legacy API
320
+ key. A sandbox agent token is exit `2`, before any request. A deployment that
321
+ predates sign-in links is exit `5`.
322
+ - **`--next <path>`** is where the browser lands: a path on the deployment
323
+ starting with a single `/`. A URL, `//host` or a backslash is exit `2`, and
324
+ no ticket is spent on it.
325
+ - **`--json`** prints `{ "url", "expires_at", "session_seconds" }` instead.
326
+ **`--open`** also opens the link in your default browser — which uses it, so
327
+ the printed URL will not work a second time.
328
+
288
329
  ### CI without a stored secret
289
330
 
290
331
  In a GitHub Actions job granted `id-token: write`, with no `OXY_TOKEN` set,