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

review-rover

v0.1.3

Published

CLI for Review Rover — automate Google review management

Downloads

404

Readme

review-rover CLI

A command-line interface for Review Rover — automate Google review management from your terminal, scripts, or AI agents.

Works with any AI that can run shell commands (Claude, Cursor, GPT, Copilot, etc.).


Table of contents


Prerequisites

  • Node.js 18+nodejs.org
  • A Review Rover accountadmin.reviewrover.co
  • A Google Business Profile connected to your account (Settings → Integrations — requires a browser the first time)
  • An API token generated at Settings → API Tokens

Installation

Option A — npx (no install needed)

npx review-rover <command>

Option B — global install

npm install -g review-rover
review-rover <command>

Authentication

Run the auth command once to save your API token:

review-rover auth
# Paste your API token: ••••••••••••••••
# Authenticated successfully. Token saved to ~/.review-rover/config.json

The token is saved to ~/.review-rover/config.json (mode 0600, readable only by you).

To generate a token: log in to admin.reviewrover.co → Settings → API Tokens → New Token.


Configuration

Config is stored in ~/.review-rover/config.json:

{
  "token": "rr_live_xxxxxxxxxxxxxxxxxxxx",
  "accountId": "acct_AbCdEfGhIj",
  "apiBase": "https://api.reviewrover.co/api/v1"
}

| Field | Description | |---|---| | token | API token (set by review-rover auth) | | accountId | Default account (set by review-rover accounts use <id>) | | apiBase | Override API base URL (optional, for self-hosted or staging) |


Commands

All read commands accept a --json flag for machine-readable output:

review-rover reviews list --unreplied --json

review-rover auth

Save your API token to the local config file.

review-rover auth

Prompts for a token, verifies it against the API, and writes it to ~/.review-rover/config.json.


review-rover accounts

accounts list

List all accounts accessible with your token.

review-rover accounts list [--json]

accounts use <id>

Set a default account for subsequent commands.

review-rover accounts use acct_AbCdEfGhIj

Once set, you won't need to pass --account to other commands.


review-rover contacts

contacts list

review-rover contacts list [--email <email>] [--limit <n>] [--json]

| Option | Description | Default | |---|---|---| | --email | Filter by exact email address | — | | --limit | Number of results (max 100) | 10 | | --json | Output as JSON | — |

# Find a specific contact
review-rover contacts list --email="[email protected]" --json

contacts upsert

Create a contact, or return the existing one if the email is already registered.

review-rover contacts upsert \
  --email="[email protected]" \
  --name="Jane Smith" \
  --phone="555-0100" \
  [--company="Acme Corp"] \
  [--json]

| Option | Required | Description | |---|---|---| | --email | Yes | Contact's email address | | --name | No | Full name (split on first space → first/last) | | --phone | No | Phone number for SMS campaigns | | --company | No | Company name |


review-rover campaigns

campaigns list

review-rover campaigns list [--json]

Lists all campaigns with their IDs, names, and active status. Use the id field when enrolling a contact.


review-rover enroll

Enroll a contact into a campaign, triggering the review-request message sequence.

review-rover enroll \
  --contact=cont_KYdl3lftgZXGRbxqoj \
  --campaign=camp_AbCdEfGhIjKlMn \
  [--json]

| Option | Required | Description | |---|---|---| | --contact | Yes | Contact ID (cont_xxx) | | --campaign | Yes | Campaign ID (camp_xxx) |

The enrollment is automatically marked completed once the contact submits a Google review.


review-rover reviews

reviews list

review-rover reviews list [--unreplied] [--json]

| Option | Description | |---|---| | --unreplied | Only show reviews without a reply (uses the /metrics/unreplied_reviews endpoint) | | --json | Output as JSON |

# Check the reply queue
review-rover reviews list --unreplied --json

--unreplied output includes a count, a reviews array (id, rating, author, snippet, received_at), and a per-location locations breakdown.

reviews draft

Generate an AI draft reply without posting it.

review-rover reviews draft \
  --id=rev_Aa1Bb2Cc3Dd4Ee \
  [--tone=professional]

| Option | Description | Default | |---|---|---| | --id | Review ID (rev_xxx) | — | | --tone | Tone hint passed to the AI (professional, friendly, brief) | professional |

Prints the suggested reply text to stdout. Nothing is saved or posted.

reviews reply

Post a reply to a review.

review-rover reviews reply \
  --id=rev_Aa1Bb2Cc3Dd4Ee \
  --message="Thank you for the kind words!" \
  [--json]

| Option | Required | Description | |---|---|---| | --id | Yes | Review ID (rev_xxx) | | --message | Yes | Reply text |


review-rover webhooks

Register HTTPS endpoints to receive real-time events instead of polling.

Supported events:

  • review.created — a new review arrived
  • enrollment.completed — a contact submitted a review, completing their enrollment

All webhook POST bodies are signed with X-ReviewRover-Signature: sha256=<hmac>. See Verifying signatures.

webhooks list

review-rover webhooks list [--json]

webhooks create

review-rover webhooks create \
  --url="https://myagent.example.com/hooks/review-rover" \
  --events=review.created \
  [--json]

| Option | Required | Description | |---|---|---| | --url | Yes | HTTPS endpoint URL | | --events | Yes | Comma-separated event types |

# Subscribe to multiple events
review-rover webhooks create \
  --url="https://myagent.example.com/hook" \
  --events="review.created,enrollment.completed"

webhooks delete

review-rover webhooks delete --id=<webhook-subscription-id>

Verifying webhook signatures

Each webhook delivery includes a X-ReviewRover-Signature: sha256=<hmac> header. Verify it in your endpoint:

// Node.js / Express
const crypto = require('crypto')

app.post('/hooks/review-rover', (req, res) => {
  const sig = req.headers['x-reviewrover-signature']
  const expected = 'sha256=' + crypto
    .createHmac('sha256', process.env.WEBHOOK_SECRET)
    .update(req.rawBody)   // raw Buffer, not parsed JSON
    .digest('hex')

  if (sig !== expected) return res.status(401).send('Invalid signature')

  const { type, payload } = req.body
  // type: 'review.created' | 'enrollment.completed'
  console.log('Event:', type, payload)
  res.sendStatus(200)
})
# Python / Flask
import hmac, hashlib, os
from flask import request, abort

@app.route('/hooks/review-rover', methods=['POST'])
def webhook():
    sig = request.headers.get('X-ReviewRover-Signature', '')
    expected = 'sha256=' + hmac.new(
        os.environ['WEBHOOK_SECRET'].encode(),
        request.data,
        hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(sig, expected):
        abort(401)

    event = request.json
    print('Event:', event['type'], event['payload'])
    return '', 200

The webhook secret is returned when you create the subscription via the API (POST /api/v1/webhook_subscriptions). Store it securely (environment variable, secrets manager). It is not surfaced again after creation.


Agent usage

A typical AI agent workflow after initial human setup:

# 1. Save the token the human handed over
review-rover auth

# 2. Find or create a contact
review-rover contacts upsert \
  --email="[email protected]" \
  --name="Customer Name" \
  --phone="555-0100"

# 3. Pick a campaign
review-rover campaigns list --json

# 4. Enroll the contact
review-rover enroll \
  --contact=cont_xxx \
  --campaign=camp_xxx

# 5. Check the reply queue
review-rover reviews list --unreplied --json

# 6. Draft a reply
review-rover reviews draft --id=rev_xxx --tone=professional

# 7. Post the reply
review-rover reviews reply \
  --id=rev_xxx \
  --message="Thanks for the great review!"

# 8. Register a webhook so future reviews push rather than poll
review-rover webhooks create \
  --url="https://myagent.example.com/hook" \
  --events=review.created

For a full narrative guide including raw HTTP equivalents, see docs.reviewrover.co/agent-workflow.


Development

# Clone
git clone https://github.com/Review-Growth/cli.git
cd cli

# Install dependencies
npm install

# Run in dev mode (no build step)
npm run dev -- auth
npm run dev -- reviews list --unreplied --json

# Build to dist/
npm run build

# Link for local testing
npm link
review-rover --version

Project structure

cli/
├── src/
│   ├── index.ts              # Entry point, command registration
│   ├── client.ts             # Typed fetch wrapper around /api/v1/*
│   ├── config.ts             # ~/.review-rover/config.json read/write
│   ├── output.ts             # printJson / printTable helpers
│   └── commands/
│       ├── auth.ts
│       ├── accounts.ts
│       ├── contacts.ts
│       ├── campaigns.ts
│       ├── enroll.ts
│       ├── reviews.ts
│       └── webhooks.ts
├── package.json
└── tsconfig.json

Environment variables

You can override the API base URL without editing the config file:

REVIEW_ROVER_API_BASE=http://localhost:3000/api/v1 npm run dev -- reviews list

This requires adding env-variable support to config.ts if needed during development.

Publishing to npm

npm run build
npm publish --access public

Requires npm publish rights to the review-rover package.