metergraph-cli 0.2.0-preview.2 → 0.2.0-preview.4

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,536 +1,136 @@
1
1
  # metergraph-cli
2
2
 
3
- The Metergraph command line tool. Version `0.2.0-preview.2` is published on the
4
- `next` npm tag. The `latest` tag remains on `0.1.0`.
5
-
6
- Install the released preview channel with npm or run it directly:
3
+ [![npm](https://img.shields.io/npm/v/metergraph-cli/next?label=npm%40next)](https://www.npmjs.com/package/metergraph-cli)
4
+ [![CI](https://github.com/metergraph/cli/actions/workflows/ci.yml/badge.svg)](https://github.com/metergraph/cli/actions/workflows/ci.yml)
5
+ [![License](https://img.shields.io/badge/license-Apache--2.0-blue)](https://github.com/metergraph/cli/blob/main/LICENSE)
6
+
7
+ Connect a project to [Metergraph](https://www.metergraph.dev/) from the terminal or from
8
+ your coding agent. Metergraph learns from your application's LLM traces, benchmarks
9
+ models against your real usage and routes each task to the model that clears your
10
+ quality bar. This CLI signs a project in, writes its ingest key, installs the Metergraph
11
+ skill for Codex, Claude Code or Cursor, proves that a trace arrived, and reads cost,
12
+ token and route metadata back. Every command has stable `--json` output and exit codes,
13
+ so agents can run it as well as people.
7
14
 
8
15
  ```sh
9
16
  npx --yes metergraph-cli@next --help
10
- npx --yes metergraph-cli@next doctor --json
11
- npm install -g metergraph-cli@next
12
17
  ```
13
18
 
14
- The installed command is `metergraph`. Pin `metergraph-cli@0.2.0-preview.2`
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
- - `metergraph-cli@0.2.0-preview.2` makes `verify` exit 11 `verification_failed`
28
- when its deadline expires after the service reported the trace as pending, lets
29
- `login` and `setup` reruns that need no approval succeed with `--json
30
- --no-browser`, and reports why `verify --open` did not launch a browser.
31
- - Sign in needs a Metergraph service that offers Metadata-only CLI grants and grant
32
- revocation. A service without them is reported as unsupported, and the CLI never
33
- falls back to broader access.
34
- - The read commands need a project signed in with `login`. `setup` also needs the
35
- deployment's ingest bootstrap API and browser approval by a workspace member.
36
- `verify` checks one exact trace identity in an explicit invocation window using
37
- Metadata access. It never sends application data.
38
-
39
- The preview includes:
40
-
41
- - `doctor` checks whether a Metergraph service is reachable, healthy and supported.
42
- - `skill install` and `skill update` copy the Metergraph agent skill bundled with the
43
- CLI into one coding agent's project skill directory.
44
- - `login` and `logout` sign a project in to one workspace through your
45
- browser with a delegated, Metadata-only grant, and sign it out again.
46
- - The read commands use that grant to read bounded workspace Metadata:
47
- connection status, workspace context, capabilities, daily usage, routes and one page
48
- of trace metadata.
49
- - `setup` guides browser sign in and workspace choice, asks for
50
- ingest-only approval, writes a private project env file, confirms delivery, and
51
- installs the selected client skill.
52
- - `verify` polls for one exact processed trace in a bounded window.
53
- It does not infer application provenance from a Metadata match.
54
-
55
- It does not read retained content, replay traces, call model providers or send
56
- application data. Setup does not prove that the application sent a trace.
19
+ This is a preview, published on the `next` npm tag. `latest` is still `0.1.0`, which has
20
+ only `doctor` and `skill`. See the [changelog](https://github.com/metergraph/cli/blob/main/CHANGELOG.md).
57
21
 
58
- ## Requirements
22
+ ## Quickstart
59
23
 
60
- | | Supported |
61
- | --- | --- |
62
- | Node.js | 22 and 24 |
63
- | Operating systems | Linux, macOS and Windows (each in the CI matrix) |
64
- | Runtime dependencies | None |
65
-
66
- ## Commands
24
+ **1. Set up the project.** Run this in your project directory. It opens your browser to
25
+ sign in and choose a workspace, asks a workspace member to approve an ingest-only key,
26
+ writes `METERGRAPH_APP_TOKEN` and `METERGRAPH_INGEST_URL` to a private `.env`, and
27
+ installs the skill for your coding agent.
67
28
 
68
29
  ```sh
69
- metergraph --help [--json]
70
- metergraph help doctor [--json]
71
- metergraph --version [--json]
72
- metergraph doctor [--url ORIGIN] [--timeout-ms N] [--json]
73
- metergraph help skill [--json]
74
- metergraph skill install --client CLIENT --runtime RUNTIME [--project DIR] [--json]
75
- metergraph skill update --client CLIENT --runtime RUNTIME [--project DIR] [--json]
76
- metergraph help login [--json]
77
- metergraph login --runtime local [--url ORIGIN] [--workspace UUID] [--project DIR] [--config-dir DIR] [--timeout-ms N] [--signup] [--no-browser] [--reconnect] [--json]
78
- metergraph logout [--project DIR] [--config-dir DIR] [--json]
79
- 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]
80
- metergraph status [--project DIR] [--config-dir DIR] [--timeout-ms N] [--json]
81
- metergraph context [--project DIR] [--config-dir DIR] [--timeout-ms N] [--json]
82
- metergraph capabilities [--project DIR] [--config-dir DIR] [--timeout-ms N] [--json]
83
- metergraph usage [--days N] [--limit N] [--project DIR] [--config-dir DIR] [--timeout-ms N] [--json]
84
- metergraph routes [--limit N] [--project DIR] [--config-dir DIR] [--timeout-ms N] [--json]
85
- metergraph traces [--days N] [--limit N] [--route NAME] [--status success|error] [--cursor CURSOR] [--project DIR] [--config-dir DIR] [--timeout-ms N] [--json]
86
- 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]
30
+ npx --yes metergraph-cli@next setup --runtime local --client claude
87
31
  ```
88
32
 
89
- `--help`, `--version` and the `skill` commands work offline and make no network
90
- requests. `login`, `logout`, `setup`, `verify` and the read commands are not in the published `0.1.0`
91
- package.
92
-
93
- ### Exact trace verification
33
+ Use `--client codex` or `--client cursor` for the other agents.
94
34
 
95
- After an application invocation, pass its exact trace ID or request ID and the
96
- invocation start and end timestamps to `verify`. The optional `--source` label is a
97
- caller assertion. A matching Metadata row proves a processed trace is visible in the
98
- bound workspace, but does not independently prove that it came from your application.
99
- The result therefore keeps `application_traffic_verified: false` until a separate
100
- application instrumentation check supplies that evidence. A missing, ambiguous, stale
101
- or wrong-workspace result fails closed. The command neither creates an ingest key nor
102
- sends a test event.
103
-
104
- `--open` launches only a server-provided link carrying the exact trace and the
105
- verified workspace ID. The dashboard must check that ID against its signed-in
106
- workspace before displaying traces. Older links without a workspace remain a
107
- manual handoff; a conflicting workspace or unsafe link is refused. The result's
108
- `browser` field is `launcher_started`, `launcher_unavailable`, `not_requested`
109
- (no `--open`), or `suppressed_by_json` / `suppressed_by_no_browser` when `--open`
110
- was given but that flag returned the link instead of launching it.
111
-
112
- If `--timeout-ms` expires after the service has answered at least once with a
113
- pending result, `verify` exits 11 `verification_failed` with reason
114
- `verification_timeout`: the origin is reachable and the trace is not visible yet.
115
- Exit 4 `connection_failed` with that reason means no valid answer arrived before
116
- the deadline.
117
-
118
- ### doctor
119
-
120
- `doctor` sends three unauthenticated, read-only `GET` requests to one origin, in order,
121
- and stops at the first problem:
122
-
123
- 1. `/healthz` must answer `200` with the JSON body `{"ok": true}`.
124
- 2. `/v1/deployment` must answer `200` with a JSON `deployment_profile` this CLI supports.
125
- 3. `/v1/agent/capabilities` must answer `401` with a `WWW-Authenticate: Bearer` challenge.
126
-
127
- Options:
128
-
129
- | Option | Default | Notes |
130
- | --- | --- | --- |
131
- | `--url ORIGIN` | `https://app.metergraph.dev` | Bare origin only, see [Safe origins](#safe-origins). |
132
- | `--timeout-ms N` | `5000` | Whole number from 100 to 30000. Covers the whole probe, not each request. |
133
- | `--json` | off | Print exactly one JSON line on stdout and nothing on stderr. |
35
+ **2. Run your application once**, instrumented with a Metergraph SDK (see the
36
+ [first trace guide](https://www.metergraph.dev/docs/start/first-trace/)). Note the trace
37
+ ID or request ID and when the call started and ended.
134
38
 
135
- A healthy, supported service exits with code **3, `authentication_required`**. That is
136
- the best result this preview can report: the service is reachable, but this CLI holds
137
- no credentials, so `authenticated` is always `false` and `workspace` is always `null`.
138
- A reachable service is not a working workspace connection. To connect an application,
139
- follow the [connection guide](https://www.metergraph.dev/docs/guides/agent-access/).
140
-
141
- `doctor` never opens a browser, never prompts and never reads stdin, so it is safe in
142
- scripts and CI.
143
-
144
- ### skill install and skill update
145
-
146
- `skill install` copies the Metergraph skill bundled with this CLI into one client's
147
- native project skill directory. Both `--client` and `--runtime` are required, so the
148
- command never guesses where the skill will be used.
149
-
150
- | `--client` | Client | Skill file written | Client documentation |
151
- | --- | --- | --- | --- |
152
- | `codex` | Codex | `.agents/skills/metergraph/SKILL.md` | [Build skills](https://learn.chatgpt.com/docs/build-skills) |
153
- | `claude` | Claude Code | `.claude/skills/metergraph/SKILL.md` | [Skills](https://code.claude.com/docs/en/skills) |
154
- | `cursor` | Cursor | `.cursor/skills/metergraph/SKILL.md` | [Skills](https://cursor.com/docs/skills) |
155
-
156
- Each client has its own directory, so installing for several clients never makes one
157
- overwrite another.
158
-
159
- | Option | Default | Notes |
160
- | --- | --- | --- |
161
- | `--client CLIENT` | required | `codex`, `claude` or `cursor`. |
162
- | `--runtime RUNTIME` | required | `local` when the client runs on this machine, `cloud` when it runs in a cloud environment with a shell and a checkout of the project. Recorded, not detected. |
163
- | `--project DIR` | current directory | Must be an existing directory. Symbolic links in this path are resolved once; nothing below it is followed. |
164
- | `--json` | off | Print exactly one JSON line on stdout and nothing on stderr. |
165
-
166
- What it writes, and nothing else:
167
-
168
- 1. The skill file in the table above, plus any of its missing parent directories.
169
- 2. `.metergraph/skill-installations.json`, a small ownership receipt. For each client it
170
- records the relative skill path, the skill name, the source revision and SHA-256,
171
- and the runtimes requested. It contains no credentials, user names or absolute
172
- paths, so it is safe to commit.
173
-
174
- Ownership rules:
175
-
176
- - `install` never replaces a skill it did not install, even one with identical bytes.
177
- - Running `install` again on an unchanged skill it installed changes nothing.
178
- - A skill it installed that was edited since is never overwritten, by `install` or by
179
- `update`. Restore or remove the file first.
180
- - `update` is the only way to replace an older revision this CLI installed. There is no
181
- force option.
182
- - A skill file this CLI installed that has gone missing is written again.
183
- - Symbolic links and other non-regular entries on the skill or receipt path are
184
- refused.
185
- - Files are written to an exclusive temporary file and renamed into place, under a lock
186
- file, `.metergraph/skill-installations.lock`. The receipt is written only after the
187
- skill file, and a failed receipt write puts the skill file back as it was. If the
188
- process is killed between the two writes, the skill is left without a receipt entry,
189
- so later runs refuse to touch it, and the lock stays until you delete it.
190
- - It never changes client settings, MCP configuration, `AGENTS.md`, `CLAUDE.md` or any
191
- other file, and keeps the permissions of a file it replaces.
192
-
193
- `--runtime cloud` writes the same project file. A cloud client sees it only through
194
- its own checkout of the project, so commit the file if you installed it elsewhere.
195
- Writing a skill file in a cloud checkout does not connect MCP, sign in or copy anything
196
- from your own machine. Local skills do not sync to desktop or cloud apps on their own.
197
-
198
- Clients and runtimes that cannot load project skill files get a pointer to the
199
- [connection guide](https://www.metergraph.dev/docs/guides/agent-access/) with exit code
200
- 6, and nothing is written: `--client claude-desktop`, `--client chatgpt` and
201
- `--runtime cloud-no-shell` (a cloud runtime without a shell or project checkout).
202
-
203
- A successful run exits `0` with `discovery: "pending"` and `authenticated: false`.
204
- Writing the file does not prove that a client has loaded it. Start or reload the client
205
- in the project and check that it lists the `metergraph` skill. The skill itself is
206
- instructions for the agent; it holds no credentials and does not connect a workspace.
207
-
208
- #### Bundled skill source
209
-
210
- `assets/skill/SKILL.md` is a byte-for-byte copy of the public skill at
211
- <https://www.metergraph.dev/SKILL.md>. The source has no version number of its own, so
212
- `assets/skill/manifest.json` records its source URL, size and SHA-256, and a revision
213
- derived from that hash (`sha256-` followed by the first 12 hex digits). The package
214
- version is not the skill version. At runtime the CLI checks the bundled file against a
215
- hash pinned in its code and in the manifest, and refuses to write anything if either
216
- does not match. It never downloads the skill or runs a remote script. A new skill
217
- revision ships only in a new CLI release; `skill update` then upgrades projects that
218
- hold an unchanged earlier revision.
219
-
220
- ### login and logout
221
-
222
- `login` binds a project directory to one Metergraph workspace. Your browser does the
223
- sign in, sign up, invitation and workspace consent on the service's own pages and
224
- keeps its own session. The CLI receives only a delegated OAuth grant limited to the
225
- Metadata scope, `agent:metadata`, checks it with the service and saves it privately.
39
+ **3. Prove the trace arrived.** Setup only proves the key works; `verify` checks that this
40
+ exact trace is visible in your workspace.
226
41
 
227
42
  ```sh
228
- metergraph login --runtime local --url https://metergraph.example.com
229
- metergraph logout
43
+ npx --yes metergraph-cli@next verify --trace-id TRACE_ID \
44
+ --since 2026-01-08T12:00:00Z --until 2026-01-08T12:00:05Z
230
45
  ```
231
46
 
232
- | Option | Default | Notes |
233
- | --- | --- | --- |
234
- | `--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. |
235
- | `--url ORIGIN` | `https://app.metergraph.dev` | Bare origin only, see [Safe origins](#safe-origins). |
236
- | `--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. |
237
- | `--project DIR` | current directory | Existing project directory to bind. |
238
- | `--config-dir DIR` | see below | Private per-user directory for the saved grant. |
239
- | `--timeout-ms N` | `300000` | How long to wait for the browser, 1000 to 900000. |
240
- | `--signup` | off | Start at the hosted sign up page, which returns to the same authorization request. Managed service only; other profiles exit 6. |
241
- | `--no-browser` | off | Print the authorization URL on stderr for you to open on this machine, then wait. With `--json`, a rerun that needs no approval succeeds; one that needs approval exits 6 `no_browser_requires_terminal`. |
242
- | `--reconnect` | off | Allow replacing a binding to a different origin or workspace. |
243
- | `--json` | off | Print exactly one JSON line on stdout and nothing on stderr. |
244
-
245
- What `login` does, in order:
246
-
247
- 1. Refuses cloud runtimes, SSH sessions, cloud development environments and CI (by the
248
- presence of variables such as `SSH_CONNECTION`, `CODESPACES` or `CI`; values are
249
- never read into output) before any request, listener or file write.
250
- 2. Reads the project binding. A project bound to another origin or workspace is refused
251
- with exit code 8 unless you pass `--reconnect`. A project that is already signed in
252
- and still verified is left as it is, with no browser and no new client.
253
- 3. Runs the same checks as `doctor`, then reads the service's OAuth metadata from the
254
- same origin. Every endpoint must be a fixed path on that origin, and the service must
255
- offer `agent:metadata`, PKCE with `S256`, public clients and revocation.
256
- 4. Registers a public client named `Metergraph CLI` for one loopback redirect,
257
- `http://127.0.0.1:PORT/callback` on an ephemeral port, creates a random state and
258
- PKCE verifier, and arms the callback listener and its timeout before the browser
259
- opens.
260
- 5. Opens the authorization URL with the operating system's launcher (no shell). The
261
- listener accepts one `GET` with the exact host, path and state. Other requests get a
262
- fixed page and do not end the wait.
263
- 6. Exchanges the code and accepts only a Bearer grant for exactly `agent:metadata` whose
264
- claims name this issuer, resource, client and one workspace. The claims are a sanity
265
- check; the CLI does not verify token signatures.
266
- 7. Asks the service, with the new token, for `/v1/agent/workspace` and
267
- `/v1/agent/capabilities`. The workspace ID, its provenance and the token must agree,
268
- the deployment profile must match step 3, the access scopes must be exactly
269
- `agent:metadata`, and content, evidence and replay capabilities must be unavailable.
270
- Nothing else is read.
271
- 8. Saves the grant in the config directory and writes `.metergraph/project.json`.
272
-
273
- Once the token response has been validated and holds a usable refresh token, a grant
274
- the CLI decides not to keep (a workspace other than the one expected or bound, failed
275
- verification, cancellation) is sent to the revocation endpoint before the command
276
- exits. If the grant cannot be saved or the binding cannot be written, the saved grant
277
- is removed, revocation is requested the same way, and the command exits 9. This is best
278
- effort: the service may not answer or may not confirm, and the CLI does not retry. A
279
- token response that fails validation is dropped without a revocation request, because
280
- the CLI cannot safely use anything in it; a server-side grant may remain active until it
281
- expires or is revoked from the service.
282
-
283
- The config directory is `--config-dir`, else `METERGRAPH_CONFIG_DIR` (an absolute
284
- path), else `~/.config/metergraph` on Linux and macOS or `AppData\Roaming\Metergraph` in
285
- your Windows profile. It holds `credentials/SLOT.json`:
286
-
287
- - On Linux and macOS the directories must be `0700` and the file `0600`, all owned by
288
- you. Existing paths with other permissions, other owners or symbolic links are
289
- refused and never changed.
290
- - On Windows the grant is encrypted with DPAPI for the current user before it is
291
- written. File permissions alone are not relied on there.
292
-
293
- `.metergraph/project.json` holds the origin, workspace ID, deployment profile and the
294
- name of the credential slot. It holds no token, user name or absolute path, so it is
295
- safe to commit. Other files in `.metergraph`, such as the skill receipt, are kept.
296
-
297
- Access tokens near expiry are refreshed once, under a lock, and the new refresh token
298
- is saved before it is used. If a refresh request may have reached the service but its
299
- result was not saved (a timeout after sending, a dropped connection, a server error or
300
- an unusable answer), the old refresh token is never sent again: the next use asks you
301
- to run `login` again. A revoked grant or lost workspace access fails closed with exit
302
- code 12.
303
-
304
- `logout` asks the service to revoke the project's grant through its revocation
305
- endpoint, then removes the saved grant and `.metergraph/project.json`. Other credential
306
- slots and project files are kept. A `200` from the service means it accepted the
307
- revocation request. If it does not answer `200`, local sign out still happens and the
308
- command exits 13 with `revocation: "unconfirmed"`. A project that is not signed in
309
- exits 0 without any request.
310
-
311
- ### setup
312
-
313
- Run setup once from a project directory, choosing the coding client that will use
314
- the skill:
47
+ Then read what Metergraph has recorded:
315
48
 
316
49
  ```sh
317
- metergraph setup --runtime local --client codex --project /path/to/project
50
+ npx --yes metergraph-cli@next usage --days 7 # calls, errors, cost and tokens per route per day
51
+ npx --yes metergraph-cli@next traces --limit 20 # one page of trace metadata
318
52
  ```
319
53
 
320
- For a customer-local bundle, point setup at its installed origin and exact
321
- workspace:
54
+ To install it globally instead, run `npm install -g metergraph-cli@next`. The command is
55
+ `metergraph`. Pin an exact version, such as `metergraph-cli@0.2.0-preview.4`, when a
56
+ script must not change with the `next` tag.
322
57
 
323
- ```sh
324
- metergraph setup --runtime local --deployment customer-local --url http://localhost:8080 --workspace 11111111-1111-4111-8111-111111111111 --confirm-prerequisites --client codex
325
- ```
58
+ ## Requirements
326
59
 
327
- `--confirm-prerequisites` records the operator's attestation that the released
328
- signed bundle, registry invitation, local admin, and separate Metadata access
329
- prerequisites are ready. It is not proof of bundle publication or registry
330
- access. Setup checks the live deployment profile before login. BYOC uses
331
- `--deployment byoc` and an explicit HTTPS private origin; its provisioning,
332
- network, and identity prerequisites remain the operator's work. An optional
333
- `--agent-token-file` can verify a separate Metadata credential for either
334
- route. OSS uses separate `MG_TOKENS` ingestion and `MG_AGENT_TOKENS` read
335
- credentials; `--deployment oss` verifies its Metadata route with a private
336
- agent token file and hands ingest configuration to the operator. It does not
337
- try hosted login or ingest bootstrap against OSS. Remote runtimes are handed
338
- off to a local machine, with no implicit tunnel or credential forwarding.
339
-
340
- If the project has no usable Metadata sign in, `setup` opens the deployment's
341
- browser sign in and workspace choice. `--signup` starts at hosted sign up;
342
- `--workspace UUID` requires that exact workspace. An existing binding to a
343
- different origin or workspace requires explicit `--reconnect`. The selected
344
- deployment must advertise `metergraph.cli-setup/v1` on its own origin. Setup
345
- refuses reconnecting an existing ingest family to another workspace; its
346
- original workspace must be restored before that family can be reused. Setup
347
- checks the env file and Git state, then opens the deployment's consent page. An
348
- owner or member of the verified workspace approves an ingest-only key. The CLI
349
- redeems the single-use receipt, writes `METERGRAPH_APP_TOKEN` and
350
- `METERGRAPH_INGEST_URL` into `.env`, checks the new key with the service, and
351
- acknowledges delivery. It then installs the bundled skill for `codex`, `claude`
352
- or `cursor`. Use `--skip-skill` only if you intentionally want to install it
353
- later. Neither sign in nor setup requests Debug or Replay access. The browser
354
- page shows the workspace and the consequence of approval. A signed-in browser
355
- on another workspace must switch in Metergraph and rerun; the CLI does not
356
- switch it automatically.
357
-
358
- `METERGRAPH_INGEST_URL` is the deployment's service root. The Python SDK
359
- appends `/v1/ingest` itself. A setup rerun with a verified
360
- key repairs the endpoint value written by the first preview without minting a
361
- new key.
362
-
363
- The env file must be a project-relative `.env`, `.env.<name>` or `<name>.env`
364
- (`--env-file` selects another). The writer refuses tracked files, links,
365
- ambiguous dotenv syntax and unsafe paths. It adds a project `.gitignore` rule
366
- when needed and makes the env file private; Windows uses a user-only ACL.
367
- The env token is never printed, read from argv or stdin, or copied to the
368
- project's setup state file. An already working key is checked and reused without
369
- another browser approval.
370
-
371
- `.metergraph/setup.json` holds a family UUID, its current key ID and fixed state,
372
- but no credential. It is written before approval. If the redemption response is
373
- lost, a rerun asks for a new browser approval for that same family. The server
374
- resolves the request to creation if no key was issued or replacement of that
375
- family's pending key if one exists; the old receipt is not retried. If an
376
- acknowledged key no longer verifies or its env file was lost, use `--repair`
377
- to explicitly approve replacement of that exact key.
378
- An unsafe or changed state file is refused. If the earlier approval never
379
- reached redemption, rerun the command; the `create` intent is still safe.
380
-
381
- The JSON result includes a secret-free `receipt` with the origin, workspace ID,
382
- deployment profile, selected client, and completed and pending steps. A skill
383
- conflict leaves the delivered key in place and reports `credential_ready_skill_pending`;
384
- resolve the skill file conflict and rerun setup without another approval.
385
- Success means the key was delivered and the project is ready to instrument.
386
- It does **not** mean application traffic has arrived. Run your application and
387
- verify one exact trace afterward. The hosted service advertises the setup
388
- contract, but each non-hosted deployment must be checked at its own origin.
389
- Local protocol tests do not prove browser approval or real application traffic.
390
-
391
- ### Read commands
392
-
393
- The read commands use the grant `login` saved for this project. They never open a
394
- browser, never sign in on their own and never request another scope. Each one:
395
-
396
- - reads `.metergraph/project.json` and the saved grant, and refreshes the grant at most
397
- once, under the same lock and rules as `login` (an interrupted refresh is never
398
- retried with a possibly used token);
399
- - asks the service for `/v1/agent/workspace` and `/v1/agent/capabilities` and checks,
400
- as `login` does, that the workspace, deployment profile and `agent:metadata` scope
401
- still match the binding and that content, evidence and replay are unavailable;
402
- - sends only `GET` requests to fixed paths on the bound origin, follows no redirects and
403
- reads at most 1 MiB of a response;
404
- - runs every request, including a refresh and any wait for another command that is
405
- refreshing the same grant, within one total `--timeout-ms` deadline (1000 to 60000,
406
- default 15000), which is never reset per request or page. A deadline exits 4
407
- (`timeout`) and Ctrl+C exits 17, also while waiting for that lock; a lock held by
408
- another process is never removed or taken over;
409
- - prints only fields it validated. Unknown response fields are ignored and never named.
410
- A metadata row that holds a field such as `prompt`, `messages`, `tool_calls` or
411
- `access_token` is refused as a whole (exit 11). Names that contain control or
412
- formatting characters are shown as `null`. Service warning and error text is not
413
- printed. If any printed value, such as a workspace name, route name, cursor or
414
- provenance source, contains a token the CLI holds for this project, nothing is
415
- printed and the command exits 11 with `credential_in_metadata_response`.
416
-
417
- Read commands do not change workspace configuration or telemetry, send no ingest data
418
- and call no model provider. They are not side-effect free on the service: a command may
419
- refresh its own saved grant, and the service may update its audit records and last used
420
- times for the grant.
421
-
422
- | Command | Request | What it prints |
423
- | --- | --- | --- |
424
- | `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. |
425
- | `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. |
426
- | `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. |
427
- | `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. |
428
- | `routes` | `GET /v1/agent/routes` | Route name, calls, replay eligible calls, evaluation contract version and hash, and whether a description or contract exists. |
429
- | `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`. |
430
-
431
- Bounds and honesty rules:
432
-
433
- - `--days` is 1 to 90 (default 7) and `--limit` 1 to 200 (default 50, or 20 for
434
- `traces`). Values outside these ranges exit 2. A value above the service's own
435
- advertised `max_days` or `max_rows` exits 6 with `exceeds_service_bounds`; it is never
436
- reduced silently.
437
- - `usage` and `traces` report `truncated` and `complete`. Totals are sums of the
438
- returned rows only; when `complete` is `false` they are not workspace totals. An
439
- empty window is a successful result with `empty: true`.
440
- - `GET /v1/agent/routes` takes no limit or window. The CLI validates every returned row,
441
- keeps the first `--limit`, and reports `server_rows`, `truncated` and
442
- `truncation: "local"`. Route descriptions, constraints and evaluation contract bodies
443
- are never printed; `omitted_fields` lists them.
444
- - `traces` fetches exactly one page. When more exist it returns `next_cursor`; pass it
445
- back with `--cursor` to read the next page. The cursor is opaque and at most 512
446
- printable characters. A page whose `limit` differs from the request, or rows that do
447
- not match `--status` or `--route`, exit 11. Free-text filter values are not printed
448
- back.
449
- - The `traces` listing prints no trace links; each row has `link: null` and the
450
- page reports `link_status: "server_link_unavailable"`. Exact-trace
451
- `verify --open` uses a server link only when it includes the verified
452
- workspace binding.
453
- - `--environment`, `--workload`, `--since`, `--until`, `--sql`, `--query`, `--content`,
454
- `--include-content`, `--debug` and `--replay` are recognized and refused with exit 6
455
- before any request. The agent access contract has no environment selector or
456
- absolute time range, and these commands never read content or replay. `--workload`
457
- is refused by this CLI version because the returned trace rows do not show which
458
- workload they belong to, so a filtered page could not be verified.
459
- - A capability the service does not offer to this grant exits 14 without a read. A
460
- refused read exits 15 (`insufficient_scope` or `forbidden`), rate limiting exits 16
461
- with `retry_after_seconds` when the service sends a whole number of seconds, and a
462
- token refused during the read exits 12. Nothing is retried. Ctrl+C exits 17.
463
-
464
- A successful `usage`, shortened:
465
-
466
- ```json
467
- {
468
- "schema_version": 1,
469
- "command": "usage",
470
- "ok": true,
471
- "outcome": "ok",
472
- "exit_code": 0,
473
- "data": {
474
- "origin": "https://metergraph.example.com",
475
- "workspace": { "id": "0b5c7c1e-1a2b-4c3d-8e4f-5a6b7c8d9e01" },
476
- "deployment_profile": "managed",
477
- "authenticated": true,
478
- "scopes": ["agent:metadata"],
479
- "result": {
480
- "provenance": {
481
- "deployment_profile": "managed",
482
- "workspace_id": "0b5c7c1e-1a2b-4c3d-8e4f-5a6b7c8d9e01",
483
- "generated_at": "2026-01-08T12:00:00Z",
484
- "source": "example-source"
485
- },
486
- "window": { "days": 7, "since": "2026-01-01T12:00:00Z", "until": "2026-01-08T12:00:00Z" },
487
- "evidence": { "sources": ["telemetry"], "rows": 1, "complete": true },
488
- "warnings": [],
489
- "content_included": false,
490
- "truncated": false,
491
- "complete": true,
492
- "empty": false,
493
- "rows": 1,
494
- "items": [
495
- {
496
- "date": "2026-01-02",
497
- "route": "checkout-summary",
498
- "calls": 40,
499
- "error_calls": 2,
500
- "cost_usd": 0.0125,
501
- "input_tokens": 12000,
502
- "output_tokens": 3400,
503
- "avg_latency_ms": 820,
504
- "p95_latency_ms": null
505
- }
506
- ],
507
- "totals": {
508
- "scope": "returned_rows",
509
- "complete": true,
510
- "calls": 40,
511
- "error_calls": 2,
512
- "cost_usd": 0.0125,
513
- "input_tokens": 12000,
514
- "output_tokens": 3400
515
- }
516
- },
517
- "retry_after_seconds": null,
518
- "notices": [],
519
- "next_action": null
520
- },
521
- "error": null
522
- }
60
+ | | Supported |
61
+ | --- | --- |
62
+ | Node.js | 22 and 24 |
63
+ | Operating systems | Linux, macOS and Windows, each tested in CI |
64
+ | Runtime dependencies | None |
65
+ | Service | Hosted Metergraph, or a self-hosted deployment (see [Deployments](#deployments)) |
66
+
67
+ Sign in needs a service that offers Metadata-only CLI grants and grant revocation; a
68
+ service without them is reported as unsupported, and the CLI never falls back to
69
+ broader access. `setup` also needs the deployment's ingest bootstrap API and approval by
70
+ a workspace member. Sign in needs a browser on the same machine. From SSH sessions,
71
+ cloud development environments and CI, `login` and `setup` hand off to a local machine
72
+ instead (exit 6).
73
+
74
+ ## Using it with a coding agent
75
+
76
+ The CLI is built to be run by Codex, Claude Code and Cursor as well as by people:
77
+
78
+ - **Skill.** `setup` installs the Metergraph skill, which tells the agent how to set up
79
+ and query Metergraph. To install or update only the skill, with no sign in and no
80
+ network access:
81
+
82
+ ```sh
83
+ npx --yes metergraph-cli@next skill install --client codex --runtime local
84
+ ```
85
+
86
+ A Python equivalent, [`metergraph-skills`](https://github.com/metergraph/cli/blob/main/python/metergraph-skills/README.md), is
87
+ ready for its first PyPI release. Both write the same files and recognise each
88
+ other's installs.
89
+ - **Machine output.** Every command takes `--json` and then prints exactly one JSON
90
+ line on stdout and nothing on stderr. All results share one envelope:
91
+ `schema_version`, `command`, `ok`, `outcome`, `exit_code`, `data` and `error`.
92
+ Failures carry a fixed `error.reason` and, where useful, a `data.next_action` that
93
+ tells the agent what to do next.
94
+ - **No hidden prompts.** No command reads stdin or asks a question. `--no-browser`
95
+ prints the sign in URL for a person to open instead of launching a browser; with
96
+ `--json`, a step that needs approval exits 6 with a `run_in_terminal` next action.
97
+ - **MCP.** Workspace tools for agents are served by the hosted MCP endpoint, not by this
98
+ CLI. See the [MCP server guide](https://www.metergraph.dev/docs/guides/mcp-server/)
99
+ and the [agent access guide](https://www.metergraph.dev/docs/guides/agent-access/).
100
+
101
+ Suggested `AGENTS.md` or `CLAUDE.md` lines for a project that uses Metergraph:
102
+
103
+ ```md
104
+ - Metergraph CLI: `npx --yes metergraph-cli@next <command> --json`. Check exit codes;
105
+ follow `data.next_action` on failure.
106
+ - After changing instrumented code, run the app once and confirm the trace with
107
+ `metergraph verify` before reporting that tracing works.
523
108
  ```
524
109
 
525
- On failure `result` is `null`, `authenticated` says whether the grant was verified
526
- before the failure, and `notices` lists fixed tokens such as `rows_truncated`,
527
- `evidence_incomplete`, `routes_truncated_locally`, `unsafe_text_omitted` or
528
- `trace_links_unavailable`.
110
+ ## Commands
111
+
112
+ | Command | What it does | Network |
113
+ | --- | --- | --- |
114
+ | `setup` | Sign in, choose a workspace, write the ingest key to `.env`, record the repository, install the skill | Yes |
115
+ | `verify` | Confirm that one exact trace, by trace ID or request ID, reached the workspace | Yes |
116
+ | `usage` | Daily calls, errors, cost, tokens and latency per route | Yes |
117
+ | `traces` | One page of trace metadata, with a cursor for the next page | Yes |
118
+ | `routes` | Routes with call counts and evaluation contract status | Yes |
119
+ | `status` | Whether the project is signed in, and to which workspace | Yes |
120
+ | `context` | Workspace details and retention | Yes |
121
+ | `capabilities` | What the workspace makes available to this project | Yes |
122
+ | `login`, `logout` | Sign a project in or out without the rest of `setup` | Yes |
123
+ | `doctor` | Check that a service is reachable, healthy and supported, without credentials | Yes |
124
+ | `skill install`, `skill update` | Install or update the Metergraph skill for one agent | No |
125
+
126
+ `metergraph help COMMAND` lists a command's options. The
127
+ [CLI reference](https://github.com/metergraph/cli/blob/main/docs/reference.md) covers every option, what each command reads and
128
+ writes, and full JSON examples.
529
129
 
530
130
  ## Exit codes
531
131
 
532
- Exit codes are stable. Changing one is a breaking change. Codes 10 to 17 were
533
- added in `0.2.0-preview.0` and are unavailable in `0.1.0`.
132
+ Exit codes are stable. Changing one is a breaking change. Codes 10 to 17 are not in
133
+ `0.1.0`.
534
134
 
535
135
  | Code | Outcome | Meaning |
536
136
  | --- | --- | --- |
@@ -538,14 +138,14 @@ added in `0.2.0-preview.0` and are unavailable in `0.1.0`.
538
138
  | 1 | `internal_error` | Unexpected failure inside the CLI. |
539
139
  | 2 | `invalid_input` | Unknown command or argument, or an invalid option value. No request was made. |
540
140
  | 3 | `authentication_required` | Service is reachable, healthy and supported, and requires authentication. No workspace is connected. |
541
- | 4 | `connection_failed` | The origin could not be reached, the connection failed, or the probe timed out. |
141
+ | 4 | `connection_failed` | The origin could not be reached, the connection failed, or the probe timed out. For `verify`, the deadline expired before any valid answer arrived. A trace that is still pending is exit 11, not 4. |
542
142
  | 5 | `unhealthy` | The service answered but reported that it is not healthy, or answered with a server error. |
543
- | 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. |
143
+ | 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, or `--json --no-browser` needs a browser approval it cannot show (`no_browser_requires_terminal`). Nothing was written. |
544
144
  | 7 | `redirect_rejected` | The service answered with a redirect. Redirects are never followed. |
545
145
  | 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. |
546
146
  | 9 | `filesystem_error` | Project or credential files could not be read or written. Partial changes were rolled back unless the message says otherwise. |
547
147
  | 10 | `authorization_failed` | Browser authorization did not finish: it was denied, cancelled, timed out or returned an invalid callback. Nothing was saved. |
548
- | 11 | `verification_failed` | The service issued a grant that does not match the requested origin, workspace, client, resource or Metadata scope. Nothing was saved. |
148
+ | 11 | `verification_failed` | The service issued a grant that does not match the requested origin, workspace, client, resource or Metadata scope. Nothing was saved. For `verify`, the exact trace was not confirmed: for example `trace_not_found_within_bounds` when the service kept answering but the trace was not visible before attempts or the deadline ran out. |
549
149
  | 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. |
550
150
  | 13 | `revocation_unconfirmed` | Local credentials were removed, but the service did not confirm that the grant was revoked. |
551
151
  | 14 | `capability_unavailable` | The service does not make this read available to the project's Metadata grant. No data was read. |
@@ -553,339 +153,47 @@ added in `0.2.0-preview.0` and are unavailable in `0.1.0`.
553
153
  | 16 | `rate_limited` | The service asked the CLI to slow down. Nothing was retried. Try again later. |
554
154
  | 17 | `cancelled` | A read command was interrupted before it finished. Read commands never change workspace configuration or telemetry. |
555
155
 
556
- ## JSON output
557
-
558
- With `--json`, every command prints one line with the same top-level keys:
559
-
560
- ```json
561
- {
562
- "schema_version": 1,
563
- "command": "doctor",
564
- "ok": false,
565
- "outcome": "authentication_required",
566
- "exit_code": 3,
567
- "data": {
568
- "origin": "https://app.metergraph.dev",
569
- "reachable": true,
570
- "healthy": true,
571
- "deployment_profile": "managed",
572
- "profile_status": "supported",
573
- "authentication_required": true,
574
- "authenticated": false,
575
- "workspace": null,
576
- "checks": [
577
- { "name": "health", "path": "/healthz", "result": "pass", "http_status": 200, "reason": null },
578
- { "name": "deployment", "path": "/v1/deployment", "result": "pass", "http_status": 200, "reason": null },
579
- { "name": "capabilities", "path": "/v1/agent/capabilities", "result": "pass", "http_status": 401, "reason": "bearer_token_required" }
580
- ],
581
- "next_action": { "kind": "connection_guide", "url": "https://www.metergraph.dev/docs/guides/agent-access/" }
582
- },
583
- "error": {
584
- "code": "authentication_required",
585
- "reason": "bearer_token_required",
586
- "message": "The service is reachable and supported, and it requires authentication. No workspace is connected."
587
- }
588
- }
589
- ```
590
-
591
- (Shown formatted here. The CLI prints it on a single line.)
592
-
593
- - `ok` is `true` only when `outcome` is `ok`. When `ok` is `false`, `error.code` equals
594
- `outcome` and `error.reason` is a fixed token such as `timeout`, `invalid_url`,
595
- `unrecognized_profile` or `response_too_large`.
596
- - `profile_status` is `supported`, `unrecognized`, `unavailable` (the server has no
597
- `/v1/deployment` endpoint) or `unknown` (not checked).
598
- - Checks that did not run have `result: "skipped"`.
599
- - `--help --json` includes the command list and the exit code table.
600
-
601
- A successful `skill install`:
602
-
603
- ```json
604
- {
605
- "schema_version": 1,
606
- "command": "skill install",
607
- "ok": true,
608
- "outcome": "ok",
609
- "exit_code": 0,
610
- "data": {
611
- "client": "claude",
612
- "runtime": "local",
613
- "path": ".claude/skills/metergraph/SKILL.md",
614
- "status": "installed",
615
- "source": {
616
- "name": "metergraph",
617
- "revision": "sha256-57b920677adf",
618
- "sha256": "57b920677adf62759c7221629327192a2d16b7e6034f7948ffd96cee402d4891"
619
- },
620
- "discovery": "pending",
621
- "authenticated": false,
622
- "next_action": {
623
- "kind": "reload_client",
624
- "message": "Start or restart Claude Code in this project, then confirm that it lists the metergraph skill."
625
- }
626
- },
627
- "error": null
628
- }
629
- ```
630
-
631
- - `status` is `installed`, `updated` or `reused` (already in place, nothing rewritten).
632
- - `path` is always relative to the project. Absolute paths are never printed.
633
- - On failure `status` and `discovery` are `null`, and `error.reason` is a fixed token
634
- such as `not_owned`, `modified`, `update_required`, `not_installed`, `unsafe_path`,
635
- `receipt_invalid`, `locked`, `invalid_project`, `client_not_supported`,
636
- `write_failed` or `bundled_skill_invalid`.
637
-
638
- A successful `login`:
639
-
640
- ```json
641
- {
642
- "schema_version": 1,
643
- "command": "login",
644
- "ok": true,
645
- "outcome": "ok",
646
- "exit_code": 0,
647
- "data": {
648
- "origin": "https://metergraph.example.com",
649
- "runtime": "local",
650
- "deployment_profile": "managed",
651
- "workspace": { "id": "0b5c7c1e-1a2b-4c3d-8e4f-5a6b7c8d9e01" },
652
- "scopes": ["agent:metadata"],
653
- "authenticated": true,
654
- "configured": true,
655
- "status": "signed_in",
656
- "binding": ".metergraph/project.json",
657
- "credential_protection": "owner_only_file",
658
- "previous_grant_revocation": null,
659
- "next_action": {
660
- "kind": "connected",
661
- "message": "This project is signed in with Metadata access. Run \"metergraph logout\" to sign out."
662
- }
663
- },
664
- "error": null
665
- }
666
- ```
667
-
668
- - `status` is `signed_in`, `reused` (already signed in and verified, nothing changed)
669
- or `reconnected` (a new grant replaced the previous one; `previous_grant_revocation`
670
- is then `accepted`, `unconfirmed` or `not_attempted`).
671
- - `credential_protection` is `owner_only_file` or `dpapi`.
672
- - On failure `authenticated` and `configured` are `false`, `scopes` is empty, and
673
- `next_action` is `null` or a handoff such as `connection_guide`, `reconnect`,
674
- `run_in_terminal` or `no_browser`.
675
- - The schema version `1` is the version of this CLI's own JSON output. It is unrelated
676
- to the service's agent access contract version, `metergraph.agent-access/v1`.
677
- - `login` and `logout` never print tokens, the authorization code, the PKCE verifier,
678
- user names, email addresses, workspace names, absolute paths or server text. The
679
- read commands never print tokens, email addresses, absolute paths or server error
680
- text either; `context` prints the workspace slug and name, and the read commands
681
- print validated route, trace, provider and model names, as described above.
682
-
683
- `logout` prints `local_credentials` (`removed` or `none`), `binding` (`removed`,
684
- `kept` or `none`) and `revocation` (`accepted`, `unconfirmed` or `not_attempted`).
685
-
686
- Without `--json`, results are printed as text on stdout and usage errors go to stderr.
687
- `login` prints progress lines, and with `--no-browser` the authorization URL, on
688
- stderr.
689
-
690
- ## Safe origins
691
-
692
- `--url` accepts only a bare origin, with an optional trailing slash:
693
-
694
- - `https://` origins on any host, for example `https://metergraph.example.com`.
695
- - `http://` only for `localhost`, `127.0.0.1` and `[::1]`, with an optional port.
696
-
697
- Usernames, passwords, paths, queries and fragments are rejected before any request is
698
- made. Invalid values and unknown arguments are not printed back, because a mistyped
699
- argument can contain a credential. An accepted origin is printed in the output and sent
700
- to the network, so do not put secrets in a hostname. See [Security](#security).
701
-
702
- ## Deployment profiles
703
-
704
- The CLI recognizes these `deployment_profile` values: `local`, `managed` and
705
- `byoc-core`. Managed staging uses the `managed` profile. Any other value is reported as `unsupported` and is not echoed. A server
706
- without `/v1/deployment`, such as a self-hosted open source server, is reported as
707
- `unsupported` with `profile_status: "unavailable"` until a dedicated adapter ships. The
708
- CLI never assumes such a server is hosted.
709
-
710
- ## What doctor does not do
711
-
712
- - It reads no credentials from environment variables, files, arguments or cookies, and
713
- sends no `Authorization` or `Cookie` header.
714
- - It follows no redirects.
715
- - It reads at most 32 KiB of any response body and stops at the `--timeout-ms` limit.
716
- - It never prints response bodies, response headers, authentication challenges,
717
- server-supplied URLs or error text from the network stack.
718
- - It makes no model provider calls, sends no usage data and reads no stored traces.
719
-
720
- ## What skill install does not do
721
-
722
- - It makes no network requests and no model provider calls. The skill comes from this
723
- package, not from a download.
724
- - It does not sign in, store credentials, configure MCP or edit client settings.
725
- - It does not claim a client has loaded the skill. `discovery` stays `pending`.
726
- - It never prints file contents, absolute paths or raw error text.
727
-
728
- ## What login does not do
729
-
730
- - It never asks for Debug (`agent:read`) or Replay (`agent:replay`) access, and never
731
- falls back to them when the service does not offer `agent:metadata`.
732
- - It never copies browser cookies or the browser's sign in.
733
- - It does not create an application ingest key, and no manual API key is required. The
734
- service records the grant as an OAuth connection on its own side; that connection
735
- can only use `agent:metadata`, is separate from any API or ingest key you manage, and
736
- is what `logout` asks the service to revoke.
737
- - It reads no telemetry, retained content or traces, and makes no model provider calls.
738
- - It sends the grant only to the origin it came from, follows no redirects and reads
739
- bounded responses within fixed time limits.
740
- - It accepts no credential on the command line, in the environment or on stdin.
741
-
742
- ## What the read commands do not do
743
-
744
- - They never sign in, open a browser, create a grant or change the project binding.
745
- The only file they may write is the saved grant, when a refresh rotates it.
746
- - They never request `agent:read` or `agent:replay`, never read retained content,
747
- evidence or replays, and never call a model provider.
748
- - They make only `GET` requests to the read endpoints (a grant refresh, when needed, is
749
- the only `POST`). They send no ingest data and change no evaluations, provider
750
- settings, workspace configuration or telemetry. The service may still record the
751
- access, for example audit entries and the grant's last used time.
752
- - They never print a token the CLI holds, even inside an otherwise valid name.
753
- - They never follow a cursor or page on their own, and never widen a request: an
754
- unsupported option, an out of range value or a capability the grant lacks fails
755
- instead.
756
- - They accept no credential on the command line, in the environment or on stdin.
757
-
758
- ## Development
759
-
760
- ```sh
761
- npm test # unit tests and CLI subprocess tests against loopback servers
762
- npm run test:package # npm pack into a temporary directory, clean install, run the installed bin
763
- node bin/metergraph.js --help
764
- node bin/metergraph.js doctor --url http://127.0.0.1:8080 --json
765
- node bin/metergraph.js skill install --client claude --runtime local --project /path/to/project --json
766
- node bin/metergraph.js login --runtime local --url http://127.0.0.1:8080 --project /path/to/project
767
- ```
768
-
769
- The sign in and read command tests run against a synthetic loopback service and a
770
- test-only browser stand-in loaded with `--import`. They prove the protocol, file
771
- handling and output rules, not the real service, a real browser, real workspace
772
- consent or real workspace data. The Windows DPAPI round trip
773
- runs only on the Windows CI runner.
774
-
775
- To try a packed artifact without publishing:
776
-
777
- ```sh
778
- npm pack --pack-destination "$(mktemp -d)"
779
- npx --yes --package=/path/to/metergraph-cli-0.2.0-preview.2.tgz -- metergraph --version
780
- ```
781
-
782
- Do not commit tarballs or other generated files.
783
-
784
- ## Releasing
785
-
786
- The source of truth is the public repository
787
- [github.com/metergraph/cli](https://github.com/metergraph/cli), licensed Apache-2.0.
788
- `0.2.0-preview.2` is published on the `next` npm tag; `latest` remains on
789
- `0.1.0`. The hosted service supports sign in, Metadata reads and ingest bootstrap.
790
- Subsequent releases must pass the checks below before publication.
791
-
792
- Releases are manual. The `Release CLI` workflow (`.github/workflows/release.yml`) runs
793
- only when a maintainer starts it from `main`. It does not run on tags, pushes or a
794
- schedule. It:
795
-
796
- 1. checks that `commit_sha` equals the commit the run started from (see
797
- [Exact revision rule](#exact-revision-rule)), that it is on `main`, and that
798
- `version` equals `package.json`;
799
- 2. asks the npm registry for that exact version and continues only on a `404`. An
800
- existing version, any other status or a network failure stops the run;
801
- 3. runs `npm test` and `npm run test:package` at that commit;
802
- 4. packs the tarball and records its SHA-256;
803
- 5. only if `publish` is true, waits for approval on the `npm-release` environment,
804
- checks out the same commit again, verifies the checksum and runs
805
- `npm publish --provenance` for that exact tarball.
806
-
807
- Leave `publish` false for a dry run that validates and packs without publishing.
808
-
809
- ### Exact revision rule
810
-
811
- npm provenance records the commit that triggered the workflow (`GITHUB_SHA`) as the
812
- source of the package. To keep that statement true, the workflow only releases that
813
- commit:
814
-
815
- - `commit_sha` must be the full 40 character SHA of the current head of `main`, and it
816
- must equal `GITHUB_SHA` for the run. Older commits on `main` are rejected even though
817
- they are ancestors of `main`.
818
- - Both the validate job and the publish job check out that commit and confirm it.
819
- - If `main` moves after you copy the SHA, the run fails. Start a new run with the new
820
- head. To release an older state, land it on `main` first.
821
-
822
- ### First package bootstrap (completed for 0.1.0)
823
-
824
- npm trusted publishing is configured on a package that already exists, so the very
825
- first version could not come from this workflow. The steps below describe the
826
- completed bootstrap of `0.1.0`; they are not part of subsequent releases. No npm
827
- token or secret is stored here.
828
-
829
- 1. Confirm the intended npm maintainer accounts and that `metergraph-cli` is
830
- available. The first approved publish establishes package ownership.
831
- 2. Run the `Release CLI` workflow with `publish` false. Download the
832
- `metergraph-cli-release` artifact and check its SHA-256 against the run summary.
833
- 3. From a maintainer machine with npm two-factor authentication, publish that exact
834
- tarball manually using `npm publish /path/to/metergraph-cli-0.1.0.tgz --access public
835
- --tag next --provenance=false --ignore-scripts`. This bootstrap version has no
836
- provenance attestation. Use a new version for the first trusted release.
837
- 4. Configure trusted publishing as described below.
838
-
839
- ### Trusted publishing
840
-
841
- After the package exists, follow the official npm guide,
842
- [Trusted publishing for npm packages](https://docs.npmjs.com/trusted-publishers/), and
843
- add a GitHub Actions trusted publisher with exactly these values:
844
-
845
- | Field | Value |
846
- | --- | --- |
847
- | Organization or user | `metergraph` |
848
- | Repository | `cli` |
849
- | Workflow filename | `release.yml` |
850
- | Environment name | `npm-release` |
851
-
852
- Trusted publishing requires npm 11.5.1 or newer. The publish job checks this before it
853
- publishes. After the trusted publisher works, consider restricting the package to
854
- trusted publishing so that long lived tokens cannot publish it.
855
-
856
- ### Release configuration
857
-
858
- Before an automated publish, confirm the following settings are still in place:
859
-
860
- - the [trusted publisher](#trusted-publishing) matches this repository and workflow;
861
- - the `npm-release` environment has required reviewers;
862
- - the repository variable `METERGRAPH_CLI_PUBLISH_ENABLED` is `true`.
863
-
864
- Until all of these are done, leave `publish` false.
865
-
866
- ### After a release
867
-
868
- After each release, confirm from a clean machine, replacing `VERSION`:
869
-
870
- ```sh
871
- npx --yes metergraph-cli@VERSION --version --json
872
- npx --yes metergraph-cli@VERSION doctor --json
873
- npm view metergraph-cli@VERSION dist.attestations
874
- ```
875
-
876
- Releases from the workflow should show a provenance attestation that names
877
- `metergraph/cli` and the released commit. The bootstrap version will not.
878
-
879
- ## Security
880
-
881
- Report security issues privately through
882
- [GitHub private vulnerability reporting](https://github.com/metergraph/cli/security/advisories/new)
883
- for `metergraph/cli`. Do not open a public issue, and do not include real credentials,
884
- tokens or customer data in a report. The security policy and the CLI's security
885
- properties are in `SECURITY.md` in the
886
- [source repository](https://github.com/metergraph/cli); it is not shipped in the npm
887
- package.
156
+ ## Security and privacy
157
+
158
+ - **No usage telemetry.** The CLI collects no analytics about how you use it. It talks
159
+ only to the Metergraph origin you point it at.
160
+ - **Least access.** Sign in grants only the Metadata scope, `agent:metadata`. The CLI
161
+ never requests Debug or Replay access, never falls back to broader access, and never
162
+ reads retained prompts, responses or other content. It calls no model provider.
163
+ - **Credentials.** The sign in grant is stored per user in `~/.config/metergraph`
164
+ (`AppData\Roaming\Metergraph` on Windows), as owner-only files on Linux and macOS and
165
+ encrypted with DPAPI on Windows. The ingest key goes only into the project's private
166
+ `.env`, which `setup` adds to `.gitignore`. No command accepts a credential on the
167
+ command line, in the environment or on stdin, or prints one.
168
+ - **Files it writes in your project:** `.env` (from `setup`), the skill file, and
169
+ secret-free state under `.metergraph/` that is safe to commit. The skill installer
170
+ never replaces a file it did not write and has no force option.
171
+ - **Network.** Only `GET` requests to fixed paths for reads, no redirects followed,
172
+ bounded response sizes and fixed timeouts. Mistyped arguments are never echoed, since
173
+ they may hold a secret. `--help`, `--version` and `skill` make no network requests.
174
+
175
+ The [CLI reference](https://github.com/metergraph/cli/blob/main/docs/reference.md) states what each command does and does not do.
176
+ Report vulnerabilities privately through
177
+ [GitHub private vulnerability reporting](https://github.com/metergraph/cli/security/advisories/new),
178
+ not in a public issue, and leave real credentials, tokens and customer data out of the
179
+ report. See [SECURITY.md](https://github.com/metergraph/cli/blob/main/SECURITY.md).
180
+
181
+ ## Deployments
182
+
183
+ `--url ORIGIN` selects the service; the default is `https://app.metergraph.dev`. It
184
+ accepts a bare `https://` origin, or `http://` on `localhost`, `127.0.0.1` or `[::1]`.
185
+ `setup --deployment` supports the hosted service (`managed`), the commercial
186
+ `customer-local` bundle, customer-owned cloud (`byoc`) and the open source server
187
+ (`oss`). See [self-hosting](https://www.metergraph.dev/docs/self-host/local/) and the
188
+ [setup reference](https://github.com/metergraph/cli/blob/main/docs/reference.md#setup).
189
+
190
+ ## Links
191
+
192
+ - [Documentation](https://www.metergraph.dev/docs/)
193
+ - [CLI reference](https://github.com/metergraph/cli/blob/main/docs/reference.md) and [changelog](https://github.com/metergraph/cli/blob/main/CHANGELOG.md)
194
+ - [Issues](https://github.com/metergraph/cli/issues)
195
+ - [Contributing](https://github.com/metergraph/cli/blob/main/CONTRIBUTING.md) and [releasing](https://github.com/metergraph/cli/blob/main/RELEASING.md)
888
196
 
889
197
  ## License
890
198
 
891
- Apache-2.0. See [LICENSE](LICENSE).
199
+ Apache-2.0. See [LICENSE](https://github.com/metergraph/cli/blob/main/LICENSE).