npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@teak-dev/grove-cli

v1.5.1

Published

CLI for uploading Artillery + Playwright load test reports to a Grove instance

Readme

grove-cli

CLI for uploading Artillery load test reports to a Grove instance.

Requirements

Node.js 18+. The published package has no runtime npm dependencies (only Node built-ins).

Development

From scripts/grove-cli: npm install, npm run build (emits dist/), npm test. The grove-cli bin points at dist/cli.js.

Installation

npm install -g @teak-dev/grove-cli

Authentication

All uploads require a Grove API key. Generate one at /admin/api-keys in the Grove UI (admin role required). Keys are prefixed grv_ and are shown only once on creation.

Configuration

Interactive setup (local use)

grove-cli setup

Prompts for your Grove URL and API key, then writes them to ~/.grove/config.json. Subsequent invocations pick this up automatically.

Environment variables (CI/CD)

Set these as pipeline secrets — never commit them:

| Variable | Description | | ------------------ | ----------------------------------------------------------------------------------------------------------------------- | | GROVE_URL | Base URL of your Grove instance | | GROVE_API_KEY | Grove API key with grv_ prefix | | RUN_NAME | Run display name or batch prefix (used when --name is omitted) | | ADDITIONAL_TAGS | Comma-separated plain-string tags for Grove (max 20, max 50 chars each); same variable used in Buddy perf pipelines | | GROVE_NOTES | Notes on the run when --notes is omitted | | GROVE_RUN_CONFIG | JSON object merged into run_config (values coerced to strings) | | BUDDY_API_TOKEN | Buddy personal access token (for auto run naming) |

Environment variables take precedence over the config file. CLI flags take precedence over both (--name / --tags / --notes override RUN_NAME / ADDITIONAL_TAGS / GROVE_NOTES).

Buddy CI/CD

Run name: precedence is --name--meta nameRUN_NAME → Buddy API name (below) → filename stem.

When BUDDY_API_TOKEN is set and neither --name, --meta name, nor RUN_NAME is set, the CLI constructs the run name from the latest execution of the target pipeline:

Merge pull request #211 from org/feature/my-feature (main@540d161)

Example pipeline step (single file):

grove-cli --file ./artillery-results/report.json --suite-id "$SUITE_UUID"

playwright-tests Buddy perf pipelines use the env-driven subcommand (report discovery + suite map built in):

export GROVE_SSM_PREFIX_BASE=/protecht-platform
npx grove-cli upload-ci \
  --ssm-params feature_flags,cache_enabled \
  --ssm-region us-west-2

Requires GROVE_UPLOAD=true, GROVE_URL, GROVE_API_KEY, and SCENARIO_NAME (or SCENARIO_PATH for dev). Suite UUID comes from GROVE_SUITE_ID or performance-scenarios/grove-suite-map.json.

With GROVE_SSM_PREFIX_BASE=/protecht-platform, TARGET selects the SSM folder: https://api.performance…/protecht-platform/performance, https://api-2.performance…/protecht-platform/performance-2.

With Buddy perf metadata (also picked up automatically when set in the environment):

export RUN_NAME="Nightly perf suite"
export ADDITIONAL_TAGS="perf,nightly,suite-next"
grove-cli --dir "$REPORT_DIR/$RUN_ID" --suite-id "$SUITE_UUID"

Set these as pipeline variables pointing at the Artillery test pipeline (for API-based naming):

| Variable | Description | | -------------------------- | ------------------------------------------- | | BUDDY_TARGET_PROJECT | Project name of the Artillery test pipeline | | BUDDY_TARGET_PIPELINE_ID | Pipeline ID of the Artillery test pipeline |

BUDDY_WORKSPACE_DOMAIN is a Buddy built-in and requires no configuration. Branch and SHA are read from the API response, so no additional built-ins are needed even when running from a different project.

When uploading from CI, Buddy-built variables such as RUN_ID, SCENARIO_NAME, SCENARIO_LABEL, and BUDDY_* are merged into run_config as string fields (alongside config from --meta and GROVE_RUN_CONFIG).

Usage

grove-cli --file ./results/report.json --name "Load test - main@abc1234"

--name defaults to Buddy context (if available) then filename stem:

grove-cli --file ./results/load-homepage.json
# run name → "load-homepage"

Options

| Flag | Description | | --------------- | -------------------------------------------------------------------- | | -f, --file | Path to Artillery JSON report (required) | | -n, --name | Run name (defaults to Buddy context or filename stem) | | --suite-id | UUID of the performance test suite to associate this run with | | --tags | Comma-separated tags, e.g. smoke,main | | --notes | Free-text notes attached to the run | | --ran-at | ISO 8601 datetime override (default: firstMetricAt from report) | | --meta | Path to a JSON metadata file (see Metadata files) | | --url | Grove base URL (overrides env and config) | | --key | API key (overrides env and config) | | --dry-run | Parse and validate the report without uploading | | --json | Output the created run record as JSON on success | | -v, --version | Print version and exit | | -h, --help | Show help and exit |

Metadata files

A metadata file is a JSON file that sets suite, tags, config, and notes for a run:

{
  "suite_id": "uuid-of-suite",
  "tags": ["smoke", "main"],
  "notes": "Post-deploy smoke run",
  "config": {
    "target": "https://app.example.com",
    "vus": 50
  }
}

Pass via --meta ./path/to/meta.json. CLI flags take precedence over values in the file.

How metrics are extracted

The CLI parses the Artillery { aggregate, intermediate[] } structure and extracts:

  • total_requestsaggregate.counters['http.requests']
  • success_rate(requests - vusers.failed) / requests × 100
  • peak_request_rate — max http.request_rate across aggregate and all intermediate periods
  • response_time — mean, p50, p95, p99, min, max from http.response_time summaries/histograms
  • session_length — mean, p95, p99 from vusers.session_length (omitted if not present)

The ran_at timestamp defaults to aggregate.firstMetricAt from the report. Pass --ran-at to override.