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 +147 -839
- package/assets/skill/SKILL.md +22 -2
- package/assets/skill/manifest.json +3 -3
- package/package.json +1 -1
- package/src/args.js +13 -3
- package/src/auth-login.js +10 -9
- package/src/auth-oauth.js +26 -0
- package/src/cli.js +19 -1
- package/src/output.js +5 -2
- package/src/repository-identity.js +246 -0
- package/src/setup.js +31 -8
- package/src/skill-bundle.js +1 -1
- package/src/verify.js +7 -2
package/README.md
CHANGED
|
@@ -1,536 +1,136 @@
|
|
|
1
1
|
# metergraph-cli
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/metergraph-cli)
|
|
4
|
+
[](https://github.com/metergraph/cli/actions/workflows/ci.yml)
|
|
5
|
+
[](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
|
-
|
|
15
|
-
|
|
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
|
-
##
|
|
22
|
+
## Quickstart
|
|
59
23
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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 --
|
|
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
|
-
`--
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
136
|
-
|
|
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
|
|
229
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
321
|
-
|
|
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
|
-
|
|
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
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
`
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
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
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
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
|
|
533
|
-
|
|
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
|
-
##
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
-
|
|
594
|
-
|
|
595
|
-
|
|
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).
|