metergraph-cli 0.1.0 → 0.2.0-preview.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.
package/README.md CHANGED
@@ -1,8 +1,9 @@
1
1
  # metergraph-cli
2
2
 
3
- The Metergraph command line tool. This is a **development preview** (version 0.1.0).
3
+ The Metergraph command line tool. Version `0.2.0-preview.1` is published on the
4
+ `next` npm tag. The `latest` tag remains on `0.1.0`.
4
5
 
5
- Install the preview channel with npm or run it directly:
6
+ Install the released preview channel with npm or run it directly:
6
7
 
7
8
  ```sh
8
9
  npx --yes metergraph-cli@next --help
@@ -10,18 +11,45 @@ npx --yes metergraph-cli@next doctor --json
10
11
  npm install -g metergraph-cli@next
11
12
  ```
12
13
 
13
- The installed command is `metergraph`. Pin `metergraph-cli@0.1.0` when you need
14
- this exact preview. Authentication and hosted setup are not included yet.
15
-
16
- This preview does two things:
14
+ The installed command is `metergraph`. Pin `metergraph-cli@0.2.0-preview.1`
15
+ when you need this exact preview rather than whichever version `next` names later.
16
+
17
+ **Availability:**
18
+
19
+ - `metergraph-cli@0.1.0` contains only `doctor` and `skill install` /
20
+ `skill update`. It has no sign in commands.
21
+ - `metergraph-cli@0.2.0-preview.0` adds `login`, `logout`, `setup`, `verify`,
22
+ `status`, `context`, `capabilities`, `usage`, `routes` and `traces`.
23
+ - `metergraph-cli@0.2.0-preview.1` makes `setup` write the SDK service root as
24
+ `METERGRAPH_INGEST_URL` and repairs the full ingest endpoint that
25
+ `0.2.0-preview.0` wrote, after checking the saved key. It also keeps validated,
26
+ workspace-bound trace links in Metadata reads.
27
+ - Sign in needs a Metergraph service that offers Metadata-only CLI grants and grant
28
+ revocation. A service without them is reported as unsupported, and the CLI never
29
+ falls back to broader access.
30
+ - The read commands need a project signed in with `login`. `setup` also needs the
31
+ deployment's ingest bootstrap API and browser approval by a workspace member.
32
+ `verify` checks one exact trace identity in an explicit invocation window using
33
+ Metadata access. It never sends application data.
34
+
35
+ The preview includes:
17
36
 
18
37
  - `doctor` checks whether a Metergraph service is reachable, healthy and supported.
19
38
  - `skill install` and `skill update` copy the Metergraph agent skill bundled with the
20
39
  CLI into one coding agent's project skill directory.
21
-
22
- It does not sign in or connect a workspace, and it does not query workspace
23
- telemetry or send application data. Sign in, workspace binding and hosted setup commands are planned as separate
24
- follow-up releases and are not part of this package yet.
40
+ - `login` and `logout` sign a project in to one workspace through your
41
+ browser with a delegated, Metadata-only grant, and sign it out again.
42
+ - The read commands use that grant to read bounded workspace Metadata:
43
+ connection status, workspace context, capabilities, daily usage, routes and one page
44
+ of trace metadata.
45
+ - `setup` guides browser sign in and workspace choice, asks for
46
+ ingest-only approval, writes a private project env file, confirms delivery, and
47
+ installs the selected client skill.
48
+ - `verify` polls for one exact processed trace in a bounded window.
49
+ It does not infer application provenance from a Metadata match.
50
+
51
+ It does not read retained content, replay traces, call model providers or send
52
+ application data. Setup does not prove that the application sent a trace.
25
53
 
26
54
  ## Requirements
27
55
 
@@ -41,10 +69,38 @@ metergraph doctor [--url ORIGIN] [--timeout-ms N] [--json]
41
69
  metergraph help skill [--json]
42
70
  metergraph skill install --client CLIENT --runtime RUNTIME [--project DIR] [--json]
43
71
  metergraph skill update --client CLIENT --runtime RUNTIME [--project DIR] [--json]
72
+ metergraph help login [--json]
73
+ metergraph login --runtime local [--url ORIGIN] [--workspace UUID] [--project DIR] [--config-dir DIR] [--timeout-ms N] [--signup] [--no-browser] [--reconnect] [--json]
74
+ metergraph logout [--project DIR] [--config-dir DIR] [--json]
75
+ metergraph setup --runtime local (--client codex|claude|cursor | --skip-skill) [--deployment managed|customer-local|byoc|oss] [--url ORIGIN] [--workspace UUID] [--confirm-prerequisites] [--agent-token-file FILE] [--project DIR] [--config-dir DIR] [--env-file .env] [--timeout-ms N] [--signup] [--reconnect] [--no-browser] [--repair] [--json]
76
+ metergraph status [--project DIR] [--config-dir DIR] [--timeout-ms N] [--json]
77
+ metergraph context [--project DIR] [--config-dir DIR] [--timeout-ms N] [--json]
78
+ metergraph capabilities [--project DIR] [--config-dir DIR] [--timeout-ms N] [--json]
79
+ metergraph usage [--days N] [--limit N] [--project DIR] [--config-dir DIR] [--timeout-ms N] [--json]
80
+ metergraph routes [--limit N] [--project DIR] [--config-dir DIR] [--timeout-ms N] [--json]
81
+ metergraph traces [--days N] [--limit N] [--route NAME] [--status success|error] [--cursor CURSOR] [--project DIR] [--config-dir DIR] [--timeout-ms N] [--json]
82
+ metergraph verify (--trace-id ID | --request-id ID) --since TIME --until TIME [--source application|synthetic|demo|import|unspecified] [--days N] [--timeout-ms N] [--poll-ms N] [--max-attempts N] [--open] [--no-browser] [--project DIR] [--config-dir DIR] [--json]
44
83
  ```
45
84
 
46
85
  `--help`, `--version` and the `skill` commands work offline and make no network
47
- requests.
86
+ requests. `login`, `logout`, `setup`, `verify` and the read commands are not in the published `0.1.0`
87
+ package.
88
+
89
+ ### Exact trace verification
90
+
91
+ After an application invocation, pass its exact trace ID or request ID and the
92
+ invocation start and end timestamps to `verify`. The optional `--source` label is a
93
+ caller assertion. A matching Metadata row proves a processed trace is visible in the
94
+ bound workspace, but does not independently prove that it came from your application.
95
+ The result therefore keeps `application_traffic_verified: false` until a separate
96
+ application instrumentation check supplies that evidence. A missing, ambiguous, stale
97
+ or wrong-workspace result fails closed. The command neither creates an ingest key nor
98
+ sends a test event.
99
+
100
+ `--open` launches only a server-provided link carrying the exact trace and the
101
+ verified workspace ID. The dashboard must check that ID against its signed-in
102
+ workspace before displaying traces. Older links without a workspace remain a
103
+ manual handoff; a conflicting workspace or unsafe link is refused.
48
104
 
49
105
  ### doctor
50
106
 
@@ -148,9 +204,320 @@ does not match. It never downloads the skill or runs a remote script. A new skil
148
204
  revision ships only in a new CLI release; `skill update` then upgrades projects that
149
205
  hold an unchanged earlier revision.
150
206
 
207
+ ### login and logout
208
+
209
+ `login` binds a project directory to one Metergraph workspace. Your browser does the
210
+ sign in, sign up, invitation and workspace consent on the service's own pages and
211
+ keeps its own session. The CLI receives only a delegated OAuth grant limited to the
212
+ Metadata scope, `agent:metadata`, checks it with the service and saves it privately.
213
+
214
+ ```sh
215
+ metergraph login --runtime local --url https://metergraph.example.com
216
+ metergraph logout
217
+ ```
218
+
219
+ | Option | Default | Notes |
220
+ | --- | --- | --- |
221
+ | `--runtime RUNTIME` | required | `local`: the browser runs on this machine. `cloud` and `cloud-no-shell` get a handoff to the [connection guide](https://www.metergraph.dev/docs/guides/agent-access/) with exit code 6. |
222
+ | `--url ORIGIN` | `https://app.metergraph.dev` | Bare origin only, see [Safe origins](#safe-origins). |
223
+ | `--workspace UUID` | none | The workspace you expect. Sign in fails unless the browser grants exactly this one. Without it, the workspace you choose in the browser is used after the service confirms it. |
224
+ | `--project DIR` | current directory | Existing project directory to bind. |
225
+ | `--config-dir DIR` | see below | Private per-user directory for the saved grant. |
226
+ | `--timeout-ms N` | `300000` | How long to wait for the browser, 1000 to 900000. |
227
+ | `--signup` | off | Start at the hosted sign up page, which returns to the same authorization request. Managed service only; other profiles exit 6. |
228
+ | `--no-browser` | off | Print the authorization URL on stderr for you to open on this machine, then wait. Not with `--json`. |
229
+ | `--reconnect` | off | Allow replacing a binding to a different origin or workspace. |
230
+ | `--json` | off | Print exactly one JSON line on stdout and nothing on stderr. |
231
+
232
+ What `login` does, in order:
233
+
234
+ 1. Refuses cloud runtimes, SSH sessions, cloud development environments and CI (by the
235
+ presence of variables such as `SSH_CONNECTION`, `CODESPACES` or `CI`; values are
236
+ never read into output) before any request, listener or file write.
237
+ 2. Reads the project binding. A project bound to another origin or workspace is refused
238
+ with exit code 8 unless you pass `--reconnect`. A project that is already signed in
239
+ and still verified is left as it is, with no browser and no new client.
240
+ 3. Runs the same checks as `doctor`, then reads the service's OAuth metadata from the
241
+ same origin. Every endpoint must be a fixed path on that origin, and the service must
242
+ offer `agent:metadata`, PKCE with `S256`, public clients and revocation.
243
+ 4. Registers a public client named `Metergraph CLI` for one loopback redirect,
244
+ `http://127.0.0.1:PORT/callback` on an ephemeral port, creates a random state and
245
+ PKCE verifier, and arms the callback listener and its timeout before the browser
246
+ opens.
247
+ 5. Opens the authorization URL with the operating system's launcher (no shell). The
248
+ listener accepts one `GET` with the exact host, path and state. Other requests get a
249
+ fixed page and do not end the wait.
250
+ 6. Exchanges the code and accepts only a Bearer grant for exactly `agent:metadata` whose
251
+ claims name this issuer, resource, client and one workspace. The claims are a sanity
252
+ check; the CLI does not verify token signatures.
253
+ 7. Asks the service, with the new token, for `/v1/agent/workspace` and
254
+ `/v1/agent/capabilities`. The workspace ID, its provenance and the token must agree,
255
+ the deployment profile must match step 3, the access scopes must be exactly
256
+ `agent:metadata`, and content, evidence and replay capabilities must be unavailable.
257
+ Nothing else is read.
258
+ 8. Saves the grant in the config directory and writes `.metergraph/project.json`.
259
+
260
+ Once the token response has been validated and holds a usable refresh token, a grant
261
+ the CLI decides not to keep (a workspace other than the one expected or bound, failed
262
+ verification, cancellation) is sent to the revocation endpoint before the command
263
+ exits. If the grant cannot be saved or the binding cannot be written, the saved grant
264
+ is removed, revocation is requested the same way, and the command exits 9. This is best
265
+ effort: the service may not answer or may not confirm, and the CLI does not retry. A
266
+ token response that fails validation is dropped without a revocation request, because
267
+ the CLI cannot safely use anything in it; a server-side grant may remain active until it
268
+ expires or is revoked from the service.
269
+
270
+ The config directory is `--config-dir`, else `METERGRAPH_CONFIG_DIR` (an absolute
271
+ path), else `~/.config/metergraph` on Linux and macOS or `AppData\Roaming\Metergraph` in
272
+ your Windows profile. It holds `credentials/SLOT.json`:
273
+
274
+ - On Linux and macOS the directories must be `0700` and the file `0600`, all owned by
275
+ you. Existing paths with other permissions, other owners or symbolic links are
276
+ refused and never changed.
277
+ - On Windows the grant is encrypted with DPAPI for the current user before it is
278
+ written. File permissions alone are not relied on there.
279
+
280
+ `.metergraph/project.json` holds the origin, workspace ID, deployment profile and the
281
+ name of the credential slot. It holds no token, user name or absolute path, so it is
282
+ safe to commit. Other files in `.metergraph`, such as the skill receipt, are kept.
283
+
284
+ Access tokens near expiry are refreshed once, under a lock, and the new refresh token
285
+ is saved before it is used. If a refresh request may have reached the service but its
286
+ result was not saved (a timeout after sending, a dropped connection, a server error or
287
+ an unusable answer), the old refresh token is never sent again: the next use asks you
288
+ to run `login` again. A revoked grant or lost workspace access fails closed with exit
289
+ code 12.
290
+
291
+ `logout` asks the service to revoke the project's grant through its revocation
292
+ endpoint, then removes the saved grant and `.metergraph/project.json`. Other credential
293
+ slots and project files are kept. A `200` from the service means it accepted the
294
+ revocation request. If it does not answer `200`, local sign out still happens and the
295
+ command exits 13 with `revocation: "unconfirmed"`. A project that is not signed in
296
+ exits 0 without any request.
297
+
298
+ ### setup
299
+
300
+ Run setup once from a project directory, choosing the coding client that will use
301
+ the skill:
302
+
303
+ ```sh
304
+ metergraph setup --runtime local --client codex --project /path/to/project
305
+ ```
306
+
307
+ For a customer-local bundle, point setup at its installed origin and exact
308
+ workspace:
309
+
310
+ ```sh
311
+ metergraph setup --runtime local --deployment customer-local --url http://localhost:8080 --workspace 11111111-1111-4111-8111-111111111111 --confirm-prerequisites --client codex
312
+ ```
313
+
314
+ `--confirm-prerequisites` records the operator's attestation that the released
315
+ signed bundle, registry invitation, local admin, and separate Metadata access
316
+ prerequisites are ready. It is not proof of bundle publication or registry
317
+ access. Setup checks the live deployment profile before login. BYOC uses
318
+ `--deployment byoc` and an explicit HTTPS private origin; its provisioning,
319
+ network, and identity prerequisites remain the operator's work. An optional
320
+ `--agent-token-file` can verify a separate Metadata credential for either
321
+ route. OSS uses separate `MG_TOKENS` ingestion and `MG_AGENT_TOKENS` read
322
+ credentials; `--deployment oss` verifies its Metadata route with a private
323
+ agent token file and hands ingest configuration to the operator. It does not
324
+ try hosted login or ingest bootstrap against OSS. Remote runtimes are handed
325
+ off to a local machine, with no implicit tunnel or credential forwarding.
326
+
327
+ If the project has no usable Metadata sign in, `setup` opens the deployment's
328
+ browser sign in and workspace choice. `--signup` starts at hosted sign up;
329
+ `--workspace UUID` requires that exact workspace. An existing binding to a
330
+ different origin or workspace requires explicit `--reconnect`. The selected
331
+ deployment must advertise `metergraph.cli-setup/v1` on its own origin. Setup
332
+ refuses reconnecting an existing ingest family to another workspace; its
333
+ original workspace must be restored before that family can be reused. Setup
334
+ checks the env file and Git state, then opens the deployment's consent page. An
335
+ owner or member of the verified workspace approves an ingest-only key. The CLI
336
+ redeems the single-use receipt, writes `METERGRAPH_APP_TOKEN` and
337
+ `METERGRAPH_INGEST_URL` into `.env`, checks the new key with the service, and
338
+ acknowledges delivery. It then installs the bundled skill for `codex`, `claude`
339
+ or `cursor`. Use `--skip-skill` only if you intentionally want to install it
340
+ later. Neither sign in nor setup requests Debug or Replay access. The browser
341
+ page shows the workspace and the consequence of approval. A signed-in browser
342
+ on another workspace must switch in Metergraph and rerun; the CLI does not
343
+ switch it automatically.
344
+
345
+ `METERGRAPH_INGEST_URL` is the deployment's service root. The Python SDK
346
+ appends `/v1/ingest` itself. A setup rerun with a verified
347
+ key repairs the endpoint value written by the first preview without minting a
348
+ new key.
349
+
350
+ The env file must be a project-relative `.env`, `.env.<name>` or `<name>.env`
351
+ (`--env-file` selects another). The writer refuses tracked files, links,
352
+ ambiguous dotenv syntax and unsafe paths. It adds a project `.gitignore` rule
353
+ when needed and makes the env file private; Windows uses a user-only ACL.
354
+ The env token is never printed, read from argv or stdin, or copied to the
355
+ project's setup state file. An already working key is checked and reused without
356
+ another browser approval.
357
+
358
+ `.metergraph/setup.json` holds a family UUID, its current key ID and fixed state,
359
+ but no credential. It is written before approval. If the redemption response is
360
+ lost, a rerun asks for a new browser approval for that same family. The server
361
+ resolves the request to creation if no key was issued or replacement of that
362
+ family's pending key if one exists; the old receipt is not retried. If an
363
+ acknowledged key no longer verifies or its env file was lost, use `--repair`
364
+ to explicitly approve replacement of that exact key.
365
+ An unsafe or changed state file is refused. If the earlier approval never
366
+ reached redemption, rerun the command; the `create` intent is still safe.
367
+
368
+ The JSON result includes a secret-free `receipt` with the origin, workspace ID,
369
+ deployment profile, selected client, and completed and pending steps. A skill
370
+ conflict leaves the delivered key in place and reports `credential_ready_skill_pending`;
371
+ resolve the skill file conflict and rerun setup without another approval.
372
+ Success means the key was delivered and the project is ready to instrument.
373
+ It does **not** mean application traffic has arrived. Run your application and
374
+ verify one exact trace afterward. The hosted service advertises the setup
375
+ contract, but each non-hosted deployment must be checked at its own origin.
376
+ Local protocol tests do not prove browser approval or real application traffic.
377
+
378
+ ### Read commands
379
+
380
+ The read commands use the grant `login` saved for this project. They never open a
381
+ browser, never sign in on their own and never request another scope. Each one:
382
+
383
+ - reads `.metergraph/project.json` and the saved grant, and refreshes the grant at most
384
+ once, under the same lock and rules as `login` (an interrupted refresh is never
385
+ retried with a possibly used token);
386
+ - asks the service for `/v1/agent/workspace` and `/v1/agent/capabilities` and checks,
387
+ as `login` does, that the workspace, deployment profile and `agent:metadata` scope
388
+ still match the binding and that content, evidence and replay are unavailable;
389
+ - sends only `GET` requests to fixed paths on the bound origin, follows no redirects and
390
+ reads at most 1 MiB of a response;
391
+ - runs every request, including a refresh and any wait for another command that is
392
+ refreshing the same grant, within one total `--timeout-ms` deadline (1000 to 60000,
393
+ default 15000), which is never reset per request or page. A deadline exits 4
394
+ (`timeout`) and Ctrl+C exits 17, also while waiting for that lock; a lock held by
395
+ another process is never removed or taken over;
396
+ - prints only fields it validated. Unknown response fields are ignored and never named.
397
+ A metadata row that holds a field such as `prompt`, `messages`, `tool_calls` or
398
+ `access_token` is refused as a whole (exit 11). Names that contain control or
399
+ formatting characters are shown as `null`. Service warning and error text is not
400
+ printed. If any printed value, such as a workspace name, route name, cursor or
401
+ provenance source, contains a token the CLI holds for this project, nothing is
402
+ printed and the command exits 11 with `credential_in_metadata_response`.
403
+
404
+ Read commands do not change workspace configuration or telemetry, send no ingest data
405
+ and call no model provider. They are not side-effect free on the service: a command may
406
+ refresh its own saved grant, and the service may update its audit records and last used
407
+ times for the grant.
408
+
409
+ | Command | Request | What it prints |
410
+ | --- | --- | --- |
411
+ | `status` | `GET /healthz` and `GET /v1/deployment` (no credentials, checked as `doctor` does), then the two checks above | `configured`, `reachable`, `healthy`, `authenticated`, the bound (`intended`) and verified (`actual`) workspace, the bound deployment profile and `deployment_profile_verified`, scopes and capability flags. A `/v1/deployment` profile that differs from the binding exits 11 with `profile_mismatch` before the grant is used. `application_traffic_verified` is always `false`: a signed in project, existing data or a configured SDK does not prove that your application sends traffic. |
412
+ | `context` | the two checks above | Workspace ID, slug, name and creation time, Metadata retention days, whether the workspace captures content (never included here) and the access scope. |
413
+ | `capabilities` | the two checks above | Each known agent capability with `available`, `privacy_class`, `required_scope` and flags, and the service's bounds. Privacy class descriptions are not printed. |
414
+ | `usage` | `GET /v1/agent/usage?days=N&limit=N` | Daily rows per route: calls, errors, cost, tokens and latency (latency may be `null`), the window, evidence completeness, warning codes and totals of the returned rows. |
415
+ | `routes` | `GET /v1/agent/routes` | Route name, calls, replay eligible calls, evaluation contract version and hash, and whether a description or contract exists. |
416
+ | `traces` | `GET /v1/agent/traces?days=N&limit=N[&route=&status=&cursor=]` | One page of trace metadata: IDs, name, status, times, span count, tokens, cost (may be `null`), routes, providers and models, plus `next_cursor`. |
417
+
418
+ Bounds and honesty rules:
419
+
420
+ - `--days` is 1 to 90 (default 7) and `--limit` 1 to 200 (default 50, or 20 for
421
+ `traces`). Values outside these ranges exit 2. A value above the service's own
422
+ advertised `max_days` or `max_rows` exits 6 with `exceeds_service_bounds`; it is never
423
+ reduced silently.
424
+ - `usage` and `traces` report `truncated` and `complete`. Totals are sums of the
425
+ returned rows only; when `complete` is `false` they are not workspace totals. An
426
+ empty window is a successful result with `empty: true`.
427
+ - `GET /v1/agent/routes` takes no limit or window. The CLI validates every returned row,
428
+ keeps the first `--limit`, and reports `server_rows`, `truncated` and
429
+ `truncation: "local"`. Route descriptions, constraints and evaluation contract bodies
430
+ are never printed; `omitted_fields` lists them.
431
+ - `traces` fetches exactly one page. When more exist it returns `next_cursor`; pass it
432
+ back with `--cursor` to read the next page. The cursor is opaque and at most 512
433
+ printable characters. A page whose `limit` differs from the request, or rows that do
434
+ not match `--status` or `--route`, exit 11. Free-text filter values are not printed
435
+ back.
436
+ - The `traces` listing prints no trace links; each row has `link: null` and the
437
+ page reports `link_status: "server_link_unavailable"`. Exact-trace
438
+ `verify --open` uses a server link only when it includes the verified
439
+ workspace binding.
440
+ - `--environment`, `--workload`, `--since`, `--until`, `--sql`, `--query`, `--content`,
441
+ `--include-content`, `--debug` and `--replay` are recognized and refused with exit 6
442
+ before any request. The agent access contract has no environment selector or
443
+ absolute time range, and these commands never read content or replay. `--workload`
444
+ is refused by this CLI version because the returned trace rows do not show which
445
+ workload they belong to, so a filtered page could not be verified.
446
+ - A capability the service does not offer to this grant exits 14 without a read. A
447
+ refused read exits 15 (`insufficient_scope` or `forbidden`), rate limiting exits 16
448
+ with `retry_after_seconds` when the service sends a whole number of seconds, and a
449
+ token refused during the read exits 12. Nothing is retried. Ctrl+C exits 17.
450
+
451
+ A successful `usage`, shortened:
452
+
453
+ ```json
454
+ {
455
+ "schema_version": 1,
456
+ "command": "usage",
457
+ "ok": true,
458
+ "outcome": "ok",
459
+ "exit_code": 0,
460
+ "data": {
461
+ "origin": "https://metergraph.example.com",
462
+ "workspace": { "id": "0b5c7c1e-1a2b-4c3d-8e4f-5a6b7c8d9e01" },
463
+ "deployment_profile": "managed",
464
+ "authenticated": true,
465
+ "scopes": ["agent:metadata"],
466
+ "result": {
467
+ "provenance": {
468
+ "deployment_profile": "managed",
469
+ "workspace_id": "0b5c7c1e-1a2b-4c3d-8e4f-5a6b7c8d9e01",
470
+ "generated_at": "2026-01-08T12:00:00Z",
471
+ "source": "example-source"
472
+ },
473
+ "window": { "days": 7, "since": "2026-01-01T12:00:00Z", "until": "2026-01-08T12:00:00Z" },
474
+ "evidence": { "sources": ["telemetry"], "rows": 1, "complete": true },
475
+ "warnings": [],
476
+ "content_included": false,
477
+ "truncated": false,
478
+ "complete": true,
479
+ "empty": false,
480
+ "rows": 1,
481
+ "items": [
482
+ {
483
+ "date": "2026-01-02",
484
+ "route": "checkout-summary",
485
+ "calls": 40,
486
+ "error_calls": 2,
487
+ "cost_usd": 0.0125,
488
+ "input_tokens": 12000,
489
+ "output_tokens": 3400,
490
+ "avg_latency_ms": 820,
491
+ "p95_latency_ms": null
492
+ }
493
+ ],
494
+ "totals": {
495
+ "scope": "returned_rows",
496
+ "complete": true,
497
+ "calls": 40,
498
+ "error_calls": 2,
499
+ "cost_usd": 0.0125,
500
+ "input_tokens": 12000,
501
+ "output_tokens": 3400
502
+ }
503
+ },
504
+ "retry_after_seconds": null,
505
+ "notices": [],
506
+ "next_action": null
507
+ },
508
+ "error": null
509
+ }
510
+ ```
511
+
512
+ On failure `result` is `null`, `authenticated` says whether the grant was verified
513
+ before the failure, and `notices` lists fixed tokens such as `rows_truncated`,
514
+ `evidence_incomplete`, `routes_truncated_locally`, `unsafe_text_omitted` or
515
+ `trace_links_unavailable`.
516
+
151
517
  ## Exit codes
152
518
 
153
- Exit codes are stable. Changing one is a breaking change.
519
+ Exit codes are stable. Changing one is a breaking change. Codes 10 to 17 were
520
+ added in `0.2.0-preview.0` and are unavailable in `0.1.0`.
154
521
 
155
522
  | Code | Outcome | Meaning |
156
523
  | --- | --- | --- |
@@ -160,10 +527,18 @@ Exit codes are stable. Changing one is a breaking change.
160
527
  | 3 | `authentication_required` | Service is reachable, healthy and supported, and requires authentication. No workspace is connected. |
161
528
  | 4 | `connection_failed` | The origin could not be reached, the connection failed, or the probe timed out. |
162
529
  | 5 | `unhealthy` | The service answered but reported that it is not healthy, or answered with a server error. |
163
- | 6 | `unsupported` | The service answered with a response, deployment profile or status this CLI does not support, or the skill client or runtime cannot use project skill files. Nothing was written. |
530
+ | 6 | `unsupported` | The service answered with a response, deployment profile or status this CLI does not support, or the skill client or runtime cannot use project skill files, or sign in cannot run in this environment. Nothing was written. |
164
531
  | 7 | `redirect_rejected` | The service answered with a redirect. Redirects are never followed. |
165
- | 8 | `conflict` | The skill target is not owned by this CLI, was modified, is unsafe, is locked or needs an explicit update. Nothing was changed. |
166
- | 9 | `filesystem_error` | Project files could not be read or written. Partial changes were rolled back unless the message says otherwise. |
532
+ | 8 | `conflict` | The skill target is not owned by this CLI, was modified, is unsafe, is locked or needs an explicit update, or the project is bound to a different origin or workspace. Nothing was changed. |
533
+ | 9 | `filesystem_error` | Project or credential files could not be read or written. Partial changes were rolled back unless the message says otherwise. |
534
+ | 10 | `authorization_failed` | Browser authorization did not finish: it was denied, cancelled, timed out or returned an invalid callback. Nothing was saved. |
535
+ | 11 | `verification_failed` | The service issued a grant that does not match the requested origin, workspace, client, resource or Metadata scope. Nothing was saved. |
536
+ | 12 | `login_required` | No usable sign in for this project: none was saved, it expired, was revoked, lost access or could not be refreshed safely. Run login again. |
537
+ | 13 | `revocation_unconfirmed` | Local credentials were removed, but the service did not confirm that the grant was revoked. |
538
+ | 14 | `capability_unavailable` | The service does not make this read available to the project's Metadata grant. No data was read. |
539
+ | 15 | `permission_denied` | The service refused this read for the signed in grant, for example for a missing scope or permission. |
540
+ | 16 | `rate_limited` | The service asked the CLI to slow down. Nothing was retried. Try again later. |
541
+ | 17 | `cancelled` | A read command was interrupted before it finished. Read commands never change workspace configuration or telemetry. |
167
542
 
168
543
  ## JSON output
169
544
 
@@ -226,8 +601,8 @@ A successful `skill install`:
226
601
  "status": "installed",
227
602
  "source": {
228
603
  "name": "metergraph",
229
- "revision": "sha256-90f7d8d78a5b",
230
- "sha256": "90f7d8d78a5b0b7a57436f194222f0c73310b0b04201c297c8fbf0b00ad6bb3f"
604
+ "revision": "sha256-57b920677adf",
605
+ "sha256": "57b920677adf62759c7221629327192a2d16b7e6034f7948ffd96cee402d4891"
231
606
  },
232
607
  "discovery": "pending",
233
608
  "authenticated": false,
@@ -247,7 +622,57 @@ A successful `skill install`:
247
622
  `receipt_invalid`, `locked`, `invalid_project`, `client_not_supported`,
248
623
  `write_failed` or `bundled_skill_invalid`.
249
624
 
625
+ A successful `login`:
626
+
627
+ ```json
628
+ {
629
+ "schema_version": 1,
630
+ "command": "login",
631
+ "ok": true,
632
+ "outcome": "ok",
633
+ "exit_code": 0,
634
+ "data": {
635
+ "origin": "https://metergraph.example.com",
636
+ "runtime": "local",
637
+ "deployment_profile": "managed",
638
+ "workspace": { "id": "0b5c7c1e-1a2b-4c3d-8e4f-5a6b7c8d9e01" },
639
+ "scopes": ["agent:metadata"],
640
+ "authenticated": true,
641
+ "configured": true,
642
+ "status": "signed_in",
643
+ "binding": ".metergraph/project.json",
644
+ "credential_protection": "owner_only_file",
645
+ "previous_grant_revocation": null,
646
+ "next_action": {
647
+ "kind": "connected",
648
+ "message": "This project is signed in with Metadata access. Run \"metergraph logout\" to sign out."
649
+ }
650
+ },
651
+ "error": null
652
+ }
653
+ ```
654
+
655
+ - `status` is `signed_in`, `reused` (already signed in and verified, nothing changed)
656
+ or `reconnected` (a new grant replaced the previous one; `previous_grant_revocation`
657
+ is then `accepted`, `unconfirmed` or `not_attempted`).
658
+ - `credential_protection` is `owner_only_file` or `dpapi`.
659
+ - On failure `authenticated` and `configured` are `false`, `scopes` is empty, and
660
+ `next_action` is `null` or a handoff such as `connection_guide`, `reconnect`,
661
+ `run_in_terminal` or `no_browser`.
662
+ - The schema version `1` is the version of this CLI's own JSON output. It is unrelated
663
+ to the service's agent access contract version, `metergraph.agent-access/v1`.
664
+ - `login` and `logout` never print tokens, the authorization code, the PKCE verifier,
665
+ user names, email addresses, workspace names, absolute paths or server text. The
666
+ read commands never print tokens, email addresses, absolute paths or server error
667
+ text either; `context` prints the workspace slug and name, and the read commands
668
+ print validated route, trace, provider and model names, as described above.
669
+
670
+ `logout` prints `local_credentials` (`removed` or `none`), `binding` (`removed`,
671
+ `kept` or `none`) and `revocation` (`accepted`, `unconfirmed` or `not_attempted`).
672
+
250
673
  Without `--json`, results are printed as text on stdout and usage errors go to stderr.
674
+ `login` prints progress lines, and with `--no-browser` the authorization URL, on
675
+ stderr.
251
676
 
252
677
  ## Safe origins
253
678
 
@@ -259,7 +684,7 @@ Without `--json`, results are printed as text on stdout and usage errors go to s
259
684
  Usernames, passwords, paths, queries and fragments are rejected before any request is
260
685
  made. Invalid values and unknown arguments are not printed back, because a mistyped
261
686
  argument can contain a credential. An accepted origin is printed in the output and sent
262
- to the network, so do not put secrets in a hostname. See [SECURITY.md](SECURITY.md).
687
+ to the network, so do not put secrets in a hostname. See [Security](#security).
263
688
 
264
689
  ## Deployment profiles
265
690
 
@@ -287,6 +712,36 @@ CLI never assumes such a server is hosted.
287
712
  - It does not claim a client has loaded the skill. `discovery` stays `pending`.
288
713
  - It never prints file contents, absolute paths or raw error text.
289
714
 
715
+ ## What login does not do
716
+
717
+ - It never asks for Debug (`agent:read`) or Replay (`agent:replay`) access, and never
718
+ falls back to them when the service does not offer `agent:metadata`.
719
+ - It never copies browser cookies or the browser's sign in.
720
+ - It does not create an application ingest key, and no manual API key is required. The
721
+ service records the grant as an OAuth connection on its own side; that connection
722
+ can only use `agent:metadata`, is separate from any API or ingest key you manage, and
723
+ is what `logout` asks the service to revoke.
724
+ - It reads no telemetry, retained content or traces, and makes no model provider calls.
725
+ - It sends the grant only to the origin it came from, follows no redirects and reads
726
+ bounded responses within fixed time limits.
727
+ - It accepts no credential on the command line, in the environment or on stdin.
728
+
729
+ ## What the read commands do not do
730
+
731
+ - They never sign in, open a browser, create a grant or change the project binding.
732
+ The only file they may write is the saved grant, when a refresh rotates it.
733
+ - They never request `agent:read` or `agent:replay`, never read retained content,
734
+ evidence or replays, and never call a model provider.
735
+ - They make only `GET` requests to the read endpoints (a grant refresh, when needed, is
736
+ the only `POST`). They send no ingest data and change no evaluations, provider
737
+ settings, workspace configuration or telemetry. The service may still record the
738
+ access, for example audit entries and the grant's last used time.
739
+ - They never print a token the CLI holds, even inside an otherwise valid name.
740
+ - They never follow a cursor or page on their own, and never widen a request: an
741
+ unsupported option, an out of range value or a capability the grant lacks fails
742
+ instead.
743
+ - They accept no credential on the command line, in the environment or on stdin.
744
+
290
745
  ## Development
291
746
 
292
747
  ```sh
@@ -295,13 +750,20 @@ npm run test:package # npm pack into a temporary directory, clean install,
295
750
  node bin/metergraph.js --help
296
751
  node bin/metergraph.js doctor --url http://127.0.0.1:8080 --json
297
752
  node bin/metergraph.js skill install --client claude --runtime local --project /path/to/project --json
753
+ node bin/metergraph.js login --runtime local --url http://127.0.0.1:8080 --project /path/to/project
298
754
  ```
299
755
 
756
+ The sign in and read command tests run against a synthetic loopback service and a
757
+ test-only browser stand-in loaded with `--import`. They prove the protocol, file
758
+ handling and output rules, not the real service, a real browser, real workspace
759
+ consent or real workspace data. The Windows DPAPI round trip
760
+ runs only on the Windows CI runner.
761
+
300
762
  To try a packed artifact without publishing:
301
763
 
302
764
  ```sh
303
765
  npm pack --pack-destination "$(mktemp -d)"
304
- npx --yes --package=/path/to/metergraph-cli-0.1.0.tgz -- metergraph --version
766
+ npx --yes --package=/path/to/metergraph-cli-0.2.0-preview.1.tgz -- metergraph --version
305
767
  ```
306
768
 
307
769
  Do not commit tarballs or other generated files.
@@ -310,8 +772,9 @@ Do not commit tarballs or other generated files.
310
772
 
311
773
  The source of truth is the public repository
312
774
  [github.com/metergraph/cli](https://github.com/metergraph/cli), licensed Apache-2.0.
313
- The first preview uses the `next` npm tag. Subsequent releases must pass the
314
- checks below before publication.
775
+ `0.2.0-preview.1` is published on the `next` npm tag; `latest` remains on
776
+ `0.1.0`. The hosted service supports sign in, Metadata reads and ingest bootstrap.
777
+ Subsequent releases must pass the checks below before publication.
315
778
 
316
779
  Releases are manual. The `Release CLI` workflow (`.github/workflows/release.yml`) runs
317
780
  only when a maintainer starts it from `main`. It does not run on tags, pushes or a
@@ -343,12 +806,12 @@ commit:
343
806
  - If `main` moves after you copy the SHA, the run fails. Start a new run with the new
344
807
  head. To release an older state, land it on `main` first.
345
808
 
346
- ### First package bootstrap
809
+ ### First package bootstrap (completed for 0.1.0)
347
810
 
348
811
  npm trusted publishing is configured on a package that already exists, so the very
349
- first version cannot come from this workflow. Creating the package is a one time,
350
- human step that a Metergraph maintainer must approve and perform. Nothing in this
351
- repository automates it, and no npm token or secret is stored here.
812
+ first version could not come from this workflow. The steps below describe the
813
+ completed bootstrap of `0.1.0`; they are not part of subsequent releases. No npm
814
+ token or secret is stored here.
352
815
 
353
816
  1. Confirm the intended npm maintainer accounts and that `metergraph-cli` is
354
817
  available. The first approved publish establishes package ownership.
@@ -377,15 +840,13 @@ Trusted publishing requires npm 11.5.1 or newer. The publish job checks this bef
377
840
  publishes. After the trusted publisher works, consider restricting the package to
378
841
  trusted publishing so that long lived tokens cannot publish it.
379
842
 
380
- ### Remaining maintainer setup
843
+ ### Release configuration
381
844
 
382
- The source repository and license are settled. Before any automated release, a
383
- maintainer still has to:
845
+ Before an automated publish, confirm the following settings are still in place:
384
846
 
385
- - complete the [first package bootstrap](#first-package-bootstrap);
386
- - configure the [trusted publisher](#trusted-publishing);
387
- - create the `npm-release` environment with required reviewers;
388
- - set the repository variable `METERGRAPH_CLI_PUBLISH_ENABLED` to `true`.
847
+ - the [trusted publisher](#trusted-publishing) matches this repository and workflow;
848
+ - the `npm-release` environment has required reviewers;
849
+ - the repository variable `METERGRAPH_CLI_PUBLISH_ENABLED` is `true`.
389
850
 
390
851
  Until all of these are done, leave `publish` false.
391
852
 
@@ -404,7 +865,13 @@ Releases from the workflow should show a provenance attestation that names
404
865
 
405
866
  ## Security
406
867
 
407
- See [SECURITY.md](SECURITY.md).
868
+ Report security issues privately through
869
+ [GitHub private vulnerability reporting](https://github.com/metergraph/cli/security/advisories/new)
870
+ for `metergraph/cli`. Do not open a public issue, and do not include real credentials,
871
+ tokens or customer data in a report. The security policy and the CLI's security
872
+ properties are in `SECURITY.md` in the
873
+ [source repository](https://github.com/metergraph/cli); it is not shipped in the npm
874
+ package.
408
875
 
409
876
  ## License
410
877