@plune-ai/cli 0.32.2 → 0.34.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +80 -1
- package/dist/cli.cjs +1503 -173
- package/dist/index.cjs +34 -16
- package/dist/index.d.cts +9 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +34 -16
- package/dist/mcp-tools.cjs +932 -0
- package/dist/mcp-tools.d.cts +894 -0
- package/dist/mcp-tools.d.ts +894 -0
- package/dist/mcp-tools.js +895 -0
- package/package.json +8 -2
package/README.md
CHANGED
|
@@ -121,8 +121,9 @@ the last resort, used only when `PLUNE_TOKEN` is set nowhere else. Nothing write
|
|
|
121
121
|
| `plune init` | Scaffold `plune.yaml`, a sample dataset, and `.env.example`. Flags: `--yes` (non-interactive), `--force`. |
|
|
122
122
|
| `plune login` | Save a [Plune platform](https://plune.ai/platform) API token so `sync` and `ingest` can reach it. The token is **checked against the API before it is saved**, so a wrong one fails here rather than two commands later. Get one at `https://beta.plune.ai` → Account → API tokens. Flags: `--token <token>` (omit to paste it or pipe it via stdin), `--skip-verify` (save without checking, for offline setup). In CI, skip this step: every platform command reads `PLUNE_TOKEN` from the environment first, and the saved login only when it is not set. |
|
|
123
123
|
| `plune logout` | Remove the saved token. |
|
|
124
|
+
| `plune mcp serve` | Serve the Plune tools to an AI agent (Claude Code, Codex, any MCP client) over **MCP stdio**. See [Plune tools for AI agents](#plune-tools-for-ai-agents-plune-mcp). Flags: `--project <id>` (default `PLUNE_PROJECT`), `--read-only` (offer only the read tools). |
|
|
124
125
|
| `plune sync` | Upload the latest local run to the platform. Flags: `--file <path>` to send a specific run JSON, `--fail-on-failures` to read the run's summary back once after the upload and exit with [the gate](#a-release-gate---fail-on-failures)'s code. Each upload carries an `Idempotency-Key` (SHA-256 of the body), so sending the same run again returns the same run rather than creating a second one. Against a platform with `POST /v1/jobs` the upload is also reported as a job (kind `sync`, counting the run's rows) that ends completed, or failed with the error text if the sync fails; an older platform without the route is not told, and a job report never fails the sync: when the sync goes through, one the platform did not take is said in one line on stderr. |
|
|
125
|
-
| `plune run import <file \| folder>` | Turn a **JUnit XML** or **Playwright JSON** report, a **folder of JUnit XML files** (Maven Surefire's `target/surefire-reports`, Gradle's `build/test-results/test`), or an **Allure `allure-results` folder**, into a run in Plune. Needs no provider key — nothing is generated. Flags: `--format junit\|playwright-json\|allure` (detected when omitted: a folder with a `*-result.json` is Allure, any other folder is read as the JUnit `*.xml` files in it), `--name <text>` to call the run something other than the [folder-based default](#what-the-run-is-called), `--key <externalKey>` to land several reports in one run (with `PLUNE_SHARED_RUN=1` — see below), `--create` to offer unmatched tests to the review queue, `--fail-on-missing-attachments` to exit 1 when a file a JUnit report names with `[[ATTACHMENT\|path]]`, or an Allure result names as a `source`, is not there (the results are sent either way), `--upload-concurrency <n>` for files uploaded at once ([1 to 32, default 16](#many-screenshots-upload-concurrency-and-retries)), `--fail-on-failures` to exit with [the gate](#a-release-gate---fail-on-failures)'s code on the summary the platform froze when this import finished the run. |
|
|
126
|
+
| `plune run import <file \| folder>` | Turn a **JUnit XML** or **Playwright JSON** report, a **k6 summary** or **Lighthouse JSON** report, a **folder of JUnit XML files** (Maven Surefire's `target/surefire-reports`, Gradle's `build/test-results/test`), or an **Allure `allure-results` folder**, into a run in Plune. Needs no provider key — nothing is generated. Flags: `--format junit\|playwright-json\|allure\|k6\|lighthouse` (detected when omitted: a folder with a `*-result.json` is Allure, any other folder is read as the JUnit `*.xml` files in it), `--name <text>` to call the run something other than the [folder-based default](#what-the-run-is-called), `--min-score <category>=<0-100>` (repeatable) for the score a [Lighthouse](#a-k6-summary-or-a-lighthouse-report) category needs to pass, `--key <externalKey>` to land several reports in one run (with `PLUNE_SHARED_RUN=1` — see below), `--create` to offer unmatched tests to the review queue, `--fail-on-missing-attachments` to exit 1 when a file a JUnit report names with `[[ATTACHMENT\|path]]`, or an Allure result names as a `source`, is not there (the results are sent either way), `--upload-concurrency <n>` for files uploaded at once ([1 to 32, default 16](#many-screenshots-upload-concurrency-and-retries)), `--fail-on-failures` to exit with [the gate](#a-release-gate---fail-on-failures)'s code on the summary the platform froze when this import finished the run. |
|
|
126
127
|
| `plune run start` | Open a platform run — or join the one already carrying `--key` — and print its id. Flags: `--key <externalKey>` (generated when absent), `--name <text>` to call the run something other than the [default](#what-the-run-is-called), `--json` for one machine-readable line. |
|
|
127
128
|
| `plune run finish <id>` | Close a platform run. This is what the reporter tells you to do for a run it had to leave open. Flags: `--terminate` to record it as cut short, `--reason <text>`, `--fail-on-failures` to exit with [the gate](#a-release-gate---fail-on-failures)'s code on the summary the platform froze. |
|
|
128
129
|
| `plune run exec -- <command>` | Open a run, run the command inside it, close the run — and exit with whatever the command returned. Sets `PLUNE_SHARED_RUN` for you, so anything reporting inside joins that run. Flags: `--key <externalKey>`, `--name <text>` (as on `run start`), `--fail-on-failures` to exit with [the gate](#a-release-gate---fail-on-failures)'s code instead — or with the command's own when no result reached the run. |
|
|
@@ -242,6 +243,8 @@ plune run import ./junit.xml # Jest, Vitest, pytest, PHPUnit, Surefire,
|
|
|
242
243
|
plune run import target/surefire-reports # or a folder of JUnit files: Maven, Gradle — see Java below
|
|
243
244
|
plune run import ./playwright.json # or Playwright's own JSON report
|
|
244
245
|
plune run import ./allure-results # or the folder an Allure adapter wrote — see below
|
|
246
|
+
plune run import ./summary.json # or a k6 summary, thresholds as pass or fail — see below
|
|
247
|
+
plune run import ./lighthouse.json # or a Lighthouse report, a category per result — see below
|
|
245
248
|
```
|
|
246
249
|
|
|
247
250
|
The format is read from the file, not from its name. Statuses go over as the report wrote them and
|
|
@@ -410,6 +413,56 @@ For a JUnit report, check that the output reaches the report: Gradle writes it o
|
|
|
410
413
|
and Maven Surefire moves it out of the XML when `redirectTestOutputToFile` is `true`. As in the Playwright
|
|
411
414
|
reporter, a file whose name starts with an underscore is skipped, and a file several tests name is uploaded once per test.
|
|
412
415
|
|
|
416
|
+
### A k6 summary or a Lighthouse report
|
|
417
|
+
|
|
418
|
+
Plune runs no load or page-speed tests of its own: it takes the results of the tools that do, as a run.
|
|
419
|
+
|
|
420
|
+
**k6.** Import the end-of-test summary, written with `k6 run --summary-export=summary.json script.js` or
|
|
421
|
+
from `handleSummary` (`return { 'summary.json': JSON.stringify(data) }`; both have the same `metrics`).
|
|
422
|
+
Each threshold of each metric is one result, named after the metric and the expression
|
|
423
|
+
(`http_req_duration p(95)<500`): passed when k6 says the threshold held, failed when it was crossed. The
|
|
424
|
+
metric's measured values (`avg`, `p(95)`, `rate`, …) are the result's message. A summary with no
|
|
425
|
+
thresholds is refused (exit 2) and nothing is imported: k6 judged nothing, so there is nothing to pass or fail.
|
|
426
|
+
A threshold is known by the file's name as well as the metric and the expression, so `smoke.json` and
|
|
427
|
+
`load.json` imported under one `--key` stay two results each; renaming the summary file starts a new test.
|
|
428
|
+
|
|
429
|
+
Only the file's base name counts, not its folder: `a/summary.json` and `b/summary.json` give the same keys.
|
|
430
|
+
So when the jobs of a matrix import into one run under one `--key`, each job names its summary file
|
|
431
|
+
apart, or every job's thresholds land on one result (the same key twice is a duplicate, not a second
|
|
432
|
+
result) and all but one job's verdict is lost:
|
|
433
|
+
|
|
434
|
+
```yaml
|
|
435
|
+
- run: k6 run --summary-export=summary-${{ matrix.scenario }}.json script.js
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
What a verdict does: a crossed k6 threshold, or a Lighthouse category under its bar, is a **failed** result,
|
|
439
|
+
and only that. The run takes it like any other failed test and is finished as usual — neither the run nor
|
|
440
|
+
the import is stopped or refused for it — and `plune run import` exits 0. To have the job fail, add
|
|
441
|
+
[`--fail-on-failures`](#a-release-gate---fail-on-failures): the command then exits 1 when the summary the
|
|
442
|
+
platform froze has a failed (or broken) result, 0 when every threshold held and every category reached its
|
|
443
|
+
bar. The results are sent either way. A shard that leaves a shared run open has no verdict yet; gate on the
|
|
444
|
+
step that finishes it.
|
|
445
|
+
|
|
446
|
+
**Lighthouse.** Import the JSON report, `lighthouse <url> --output=json --output-path=lighthouse.json`. Each
|
|
447
|
+
category in it (`performance`, `accessibility`, `best-practices`, `seo`, …) is one result, named after the
|
|
448
|
+
category, the page and the form factor Lighthouse ran as (`performance (https://example.com/, mobile)`), so a
|
|
449
|
+
mobile and a desktop report of one page imported under one `--key` are two sets of results, with the score as Lighthouse shows it, 0–100. It passes at or above the bar:
|
|
450
|
+
`--min-score performance=80` sets it per category (repeat the flag), and a category you do not name needs 90,
|
|
451
|
+
where Lighthouse's own "good" band starts. A category Lighthouse could not score (`null`) fails and says so;
|
|
452
|
+
a report that stopped on a runtime error (`NO_FCP`, …) fails every category with that error's message
|
|
453
|
+
(`NO_ERROR`, which older Lighthouse writes into a clean report, is no error). A `--min-score` for a category
|
|
454
|
+
the report does not have (`perf=95` for `performance`) is refused with exit 2 and the categories it does have,
|
|
455
|
+
and so is `--min-score` for any report that is not Lighthouse, a folder included; no run is opened either way.
|
|
456
|
+
|
|
457
|
+
```bash
|
|
458
|
+
plune run import summary.json
|
|
459
|
+
plune run import lighthouse.json --min-score performance=80 --min-score seo=95
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
Both are recognised by their own keys (`metrics` for k6, `lighthouseVersion` and `categories` for
|
|
463
|
+
Lighthouse), never by the file name; `--format k6` or `--format lighthouse` says it outright. A report file
|
|
464
|
+
that starts with a UTF-8 byte order mark is read as if it did not, in every format.
|
|
465
|
+
|
|
413
466
|
### Several jobs, one run
|
|
414
467
|
|
|
415
468
|
Two suites, or a sharded matrix, report into a single run when every job shares a key **and** knows
|
|
@@ -570,6 +623,32 @@ and is never printed or logged. `PLUNE_API_URL` points `sync`, `pull` and `push`
|
|
|
570
623
|
useful for a self-hosted backend. The Markdown format `pull` writes and `push` reads is documented at
|
|
571
624
|
[docs.plune.ai/platform/cases/markdown](https://docs.plune.ai/platform/cases/markdown/).
|
|
572
625
|
|
|
626
|
+
### Plune tools for AI agents: `plune mcp`
|
|
627
|
+
|
|
628
|
+
`plune mcp serve` gives an agent the same Plune your token reaches — the review queue, cases,
|
|
629
|
+
missions, questions, strategy, reports — as MCP tools over stdio. The agent sees at most 20 tools at
|
|
630
|
+
once; the rest it finds with `plune_discover_tools`. Every write tool takes `dry_run`, batches stop at
|
|
631
|
+
100 items, and the agent is held to the platform's agent rules: a proposed case lands in the review
|
|
632
|
+
queue, a bulk decision needs a confirm, and nothing is deleted through MCP.
|
|
633
|
+
|
|
634
|
+
Claude Code:
|
|
635
|
+
|
|
636
|
+
```bash
|
|
637
|
+
claude mcp add plune -- npx -y @plune-ai/cli mcp serve
|
|
638
|
+
```
|
|
639
|
+
|
|
640
|
+
Codex (`~/.codex/config.toml`):
|
|
641
|
+
|
|
642
|
+
```toml
|
|
643
|
+
[mcp_servers.plune]
|
|
644
|
+
command = "npx"
|
|
645
|
+
args = ["-y", "@plune-ai/cli", "mcp", "serve"]
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
The server reads the token the way every platform command does: `PLUNE_TOKEN` from the environment
|
|
649
|
+
(set it in the client's `env` block), else the login `plune login` saved. A read token, or
|
|
650
|
+
`--read-only`, offers only the read tools.
|
|
651
|
+
|
|
573
652
|
## Programmatic API
|
|
574
653
|
|
|
575
654
|
The same engine that powers `plune run` is exported for use from your own code. Unlike the
|