An open-source CLI for managing Pax8 cloud marketplace operations. Built for MSPs who want to manage subscriptions, billing, customers, and growth opportunities from the terminal.
Published on npm as @pax8/cli. We're using engagement signals (installs, issues, command usage) to learn which capabilities are worth investing in further. Feedback, issues, and PRs are welcome.
- Answers the API doesn't — renewals, invoice audit, upsell recommendations, Pax8 cost analytics computed locally from raw Pax8 data
- Closes the loop —
pax8 recommendations actwalks portfolio gaps and places the orders, so insight and action live in the same tool - Works for humans and agents identically — every command emits structured JSON, so a Claude Code skill, a shell pipeline, or a person at a terminal all use the same surface
- Demo mode —
PAX8_DEMO=1runs every command against an in-memory fixture, no credentials required
The Pax8 API is a CRUD layer — it returns raw subscriptions, invoices, and products. It doesn't answer the questions MSPs actually ask: Which renewals are coming up? Am I being overbilled? Which customers are missing backup?
This CLI computes what the API doesn't:
- Renewal tracking — no renewals endpoint exists; the CLI parses commitment dates, calculates the Pax8 monthly cost renewing in window (a temporal filter, not a churn-risk prediction — see Metric definitions), and sorts by urgency
- Invoice auditing — cross-references invoice line items against active subscriptions to flag overcharges and undercharges with dollar impact
- Upsell recommendations — analyzes each customer's stack, identifies gaps, estimates the additional Pax8 monthly cost if acted on, and returns ready-to-execute order commands (note: estimates are computed locally from price × quantity — the partner's cost-to-Pax8, not partner-side resale revenue)
- Pax8 cost analytics — aggregation by company/product/vendor with annual-to-monthly amortization. Reports the partner's monthly / annualized cost to Pax8, not partner-side resale revenue
Every command supports --json, so humans and AI agents use the same tool.
Pax8 publishes a hosted MCP server at mcp.pax8.com for AI assistants — see the Pax8 MCP docs. Use this CLI when you want a richer command surface (recommendations, invoice audit, Pax8 cost analytics, demo mode) or when you're scripting against a stable, versioned interface. Use the Pax8 MCP when you want zero-install access via Claude, Cursor, Copilot, or VS Code and you don't need the CLI-specific capabilities.
Run node --version in your terminal.
- If it prints v20 or newer, you're set — skip to Quick Start.
- If it prints an older version, or you see
command not found, install Node.js. Use the GUI installer by default; the package-manager one-liners below are just shortcuts if you already use one.- For any OS: download the Node.js LTS installer from nodejs.org and run it.
- Windows, if you already use winget (built into Windows 10/11):
winget install OpenJS.NodeJS.LTS. - Windows, if you already use Chocolatey:
choco install nodejs-lts. - macOS or Linux, if you already use Homebrew:
brew install node(installs current Node).
Once installed — whichever path you took — close this terminal, open a new one, and run node --version again. All of these paths leave your existing shell with a stale PATH; a fresh shell is what picks up the new node binary.
Don't have Node 20+? See Prerequisites first.
PAX8_DEMO=1 npx -y -p @pax8/cli pax8 dashboardnpx -y -p @pax8/cli pax8 auth login
npx -y -p @pax8/cli pax8 dashboardnpm install -g @pax8/cli
pax8 dashboardPermission denied? If
npm install -gfails withEACCES(permission denied), do not usesudo. Either usenpxinstead, or install Node via a version manager (nvm or fnm) so the global prefix lives in your home directory. See Troubleshooting for details.
Run with demo data by prefixing PAX8_DEMO=1:
PAX8_DEMO=1 pax8 dashboard # Pax8 monthly cost, renewals, growth opportunities
PAX8_DEMO=1 pax8 recommendations list # Cross-sell and seat gap opportunities
PAX8_DEMO=1 pax8 recommendations act # Walk through and place orders (y/s/q)
PAX8_DEMO=1 pax8 clients list # Browse customers (type # to drill in)
PAX8_DEMO=1 pax8 clients show "Acme" # Full customer summaryOr if you installed globally:
pax8 init --demo # Enable demo mode persistently
pax8 dashboard
pax8 recommendations list
pax8 recommendations actpax8 --help is the canonical inventory; every command and subcommand documents its flags via pax8 <command> --help. The sections below cover the most-used surface; the More commands section near the end lists the rest.
pax8 dashboard # Quick snapshot: Pax8 monthly cost, renewals, recs, trials
pax8 dashboard --all # Full dashboard with top customers and details
pax8 dashboard --renewals # Focus on upcoming renewals
pax8 dashboard --growth # Focus on growth opportunitiespax8 clients list # List all (type # to drill in)
pax8 clients list --status Active # Filter by status
pax8 clients show "Acme Corp" # Customer details
pax8 clients more "Acme Corp" # Full summary: subs, vendors, Pax8 monthly cost, issues
pax8 clients create --name "Acme" --city Denver --state CO --zip 80202 --phone "+1-303-555-0101" --first-name Maya --last-name Chen --email maya@acme.example.com --yesNote: The single contact you supply on
clients createis set as primary on all three types (Admin, Billing, Technical). Split roles afterward viapax8 contacts updateor additionalpax8 contacts create --typecalls.
pax8 clients *is the canonical (and only) command surface. The earlierpax8 companies *alias was removed pre-launch (#476); update any scripts that called the old verb. The data surface (companyId,companyName,--companyflag, etc.) stays aligned with the wire until Pax8's API renames the field.
pax8 subscriptions list # All subscriptions
pax8 subscriptions list --company "Acme Corp" # Filter by company
pax8 subscriptions list --status Active # Filter by status
pax8 subscriptions show <id> --history # Details + change history
pax8 subscriptions renewals # Upcoming renewals (30d default)
pax8 subscriptions renewals --within 7d # Urgent renewals
pax8 subscriptions renewals --company "Acme Corp" # Renewals for one companypax8 recommendations list # All growth opportunities
pax8 recommendations list --company "Acme Corp" # For one company
pax8 recommendations list --product "AvePoint" # Filter by product
pax8 recommendations list --priority high # High priority only
pax8 recommendations act # Walk through and order
pax8 recommendations act --company "Acme Corp" # Act on one company
pax8 recommendations act --product "backup" # Add backup everywhere
pax8 recommendations act --yes # Non-interactive: place all matchespax8 orders list # Recent orders
pax8 orders create --company "Acme" --product "M365 Business Premium" --quantity 10
pax8 orders show <id> # Check order statusThe order preview shows unit price, total, and estimated Pax8 monthly cost impact before you confirm.
pax8 cost sim --company "Acme Corp" --product "Microsoft 365 Business Premium" --quantity 50
pax8 cost sim --company "Acme Corp" --product "Microsoft 365 Business Premium" --from "Microsoft 365 Business Basic" --quantity 45
pax8 cost sim --company "Acme Corp" --product "AvePoint Cloud Backup for Microsoft 365" --quantity 30 --billing-term Monthly --jsonModel the financial impact of a SKU swap, quantity change, or new-product add before placing the order. The output shows current and proposed monthly/annual cost, the delta, and a per-seat breakdown — pure compute over existing pricing data, no writes.
pax8 invoices list # All invoices
pax8 invoices list --company "Acme Corp" --status Unpaid
pax8 invoices audit # Flag billing discrepancies
pax8 invoices audit --company "Acme Corp" # Audit one companypax8 products search "Microsoft 365" # Search catalog
pax8 products show <id> # Product details + pricingPax8-cost reporting surface — what's renewing, where your spend is concentrated, and grouped subscription rollups.
pax8 report renewals --within 90 # Subscriptions ending in the next 90 days
pax8 report concentration --by client --top 5 # Top customers by Pax8 cost
pax8 report concentration --by vendor --json # Concentration by vendor
pax8 report subscriptions --by billing-term # Active subs grouped by billing term
pax8 report subscriptions --by vendor --json # Pax8 cost rollup by vendorAll values are Pax8 cost (what Pax8 charges you), emitted as { amount, currency } envelopes. For partner-side resale revenue, combine with sell-through pricing from your PSA.
pax8 doctor # Node, auth, API endpoints, cache, telemetry
pax8 auth status # Check credentials
pax8 version # CLI versionThe full surface also includes these less-prominent command groups — see pax8 <group> --help for flags and examples:
pax8 contacts list|show|create|update|delete # Per-company contacts (Admin/Billing/Technical)
pax8 quotes list|show|create|update|send|delete # Sales quotes (v2 API)
pax8 webhooks list|create|update|delete|enable|disable # Subscription endpoints
pax8 webhooks logs|test|topics # Delivery history, fire test deliveries, list topics
pax8 usage list|show # Metered usage (Azure consumption, etc.)
pax8 config init|show|set|path # Config file management
pax8 init # First-run setup wizard
pax8 completions bash # Shell completions (bash/zsh/fish/powershell)
pax8 report-bug # File a sanitized GitHub issue from the last failure (see Reporting bugs)
pax8 telemetry enable|disable|status # Opt-in usage telemetry (see Telemetry)| Flag | Format | Use case |
|---|---|---|
| (default) | Colored table | Interactive terminal use |
--json |
JSON | Scripting, piping to jq |
--csv |
CSV | Spreadsheets, PSA imports |
--quiet |
Minimal | Cron jobs, CI pipelines |
pax8 subscriptions list --json | jq '.[] | select(.quantity > 10)'
pax8 invoices list --csv > march-billing.csv
pax8 clients list --ids-only | xargs -I{} pax8 subscriptions list --company {}Piping JSON to other tools. Banners and spinners go to stderr; redirect for clean JSON:
pax8 subscriptions list --json 2>/dev/null | jq '.[].id'
pax8 dashboard --json 2>/dev/null > today.jsonRun the CLI with no arguments to enter the interactive REPL — works with any of the three invocation paths from Quick Start:
pax8 # if linked via npm link
node packages/cli/dist/index.js # from a built checkout
pnpm dev # dev mode (tsx)You'll see the Pax8 ASCII banner with a tagline, your CLI version, and a "Common commands" cheat sheet — then a pax8> prompt:
$ pax8
────────────────────────────────────────────────
██████╗ █████╗ ██╗ ██╗ █████╗
██╔══██╗██╔══██╗╚██╗██╔╝██╔══██╗
██████╔╝███████║ ╚███╔╝ ╚█████╔╝
██╔═══╝ ██╔══██║ ██╔██╗ ██╔══██╗
██║ ██║ ██║██╔╝ ██╗╚█████╔╝
╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚════╝
C O M M A N D L I N E
Common commands:
dashboard Portfolio at a glance
subscriptions renewals What's renewing in 30 days
recommendations Upsell opportunities
invoices audit Reconcile invoices vs subscriptions
Type a command, or help / exit
pax8> dashboard
pax8> clients list
pax8> 3 # Drill into client #3
pax8> back # Re-run the last list command
pax8> n # Next page; p for previous
pax8> recommendations act # Walk through recs
pax8> exit
No pax8 prefix needed inside the REPL. Numbered shortcuts work after any list command (pick the row by position). The cheat-sheet adapts to your auth state: if you're not yet authenticated, you'll see init --demo / auth login / doctor instead of the common-commands list.
# Interactive (stores in ~/.pax8/credentials.json)
# Prompts for Client ID and Client Secret (secret input is masked).
pax8 auth login
# Non-interactive
pax8 auth login --client-id <id> --client-secret <secret>
# Environment variables
export PAX8_CLIENT_ID=your-client-id
export PAX8_CLIENT_SECRET=your-client-secretGenerate API credentials in the Pax8 Integrations Hub. For detailed setup instructions, see the Credential Setup Guide. A copy-pasteable starter is in .env.example.
Pass --browser to pax8 auth login to open the credentials page in your default browser before the prompt — you still paste the Client ID and Secret into the terminal (the flag doesn't eliminate the secret, just the click-through to find the page). Falls back to printing the URL on headless / SSH boxes.
By default, the CLI talks to https://api.pax8.com/v1. Partners testing against a sandbox or staging environment can override the base URL without code changes:
export PAX8_API_BASE=https://staging-api.pax8.com/v1/
pax8 dashboard
pax8 doctor # confirms the active API base in its outputPAX8_API_BASE is honored by both the API client and the OAuth token endpoint, so a single override switches the whole CLI (and any process embedding @pax8/core) to the alternate environment.
Run any command against sample data without API credentials by prefixing with PAX8_DEMO=1:
PAX8_DEMO=1 pax8 dashboard
PAX8_DEMO=1 pax8 recommendations actAlternatively, enable demo mode persistently in your config:
pax8 init --demo
pax8 dashboard # Now runs with sample data by defaultDisable demo mode with pax8 init --demo off.
The CLI ships with a Claude Code skill, so AI agents get the same computed intelligence as human operators — without reimplementing business logic or wrestling with raw API calls.
An agent asking "Am I being overbilled?" doesn't need to make 13+ API calls, join invoice line items against subscriptions, and compute deltas. It runs pax8 invoices audit --json and gets categorized discrepancies with dollar impact in one call.
Available tools: clients, subscriptions, renewals, invoices, invoice audits, recommendations, Pax8 cost rollups, and product search — all returning structured JSON.
The skill wraps CLI commands with behavioral rules (act first, no clarifying questions, parallel fetches when possible). See packages/claude-skill/skill.md.
You: "Which customers are missing backup, and how much would adding it cost?"
Claude: runs pax8 recommendations list --json, returns prioritized gaps
with the estimated additional Pax8 monthly cost per gap and
ready-to-execute order commands
Works with Claude Code, Cursor, Copilot, and any agent framework that can run shell commands.
For non-Claude agent runtimes, see AGENTS.md at the repo root.
All business logic lives in @pax8/core with zero CLI dependencies — the renewal tracker, invoice auditor, recommendation engine, and Pax8 cost analytics are all importable from a portal feature, a Lambda, a dashboard, or your own tool. The CLI is one consumer; the durable asset is the domain knowledge in core. See packages/core/README.md for the install, import example, and capability list.
- API caching — repeat calls return in ~80ms (1-hour TTL)
- Parallel fetching — dashboard loads clients, subscriptions, and products simultaneously
- Product name enrichment — resolves UUIDs to human-readable names automatically
Cause: Node.js is not installed on your system.
Solution: Install Node.js 20+ from nodejs.org.
Cause: Your terminal session started before Node.js was installed, so its PATH doesn't yet include npm's binary directory.
Solution: Close the terminal and open a new one, then re-run the command. Most shells only read PATH at startup, so a freshly opened terminal will pick up the new installation. To reload in place without opening a new window, run exec $SHELL.
Still not found in a new shell? Run node --version. If it prints v20.x or newer but pax8 or npx still aren't found, this is a real PATH problem rather than a stale shell — your Node install put its binaries somewhere that isn't on PATH (common with version managers that need extra shell config). If node --version also fails, the install didn't complete; reinstall from nodejs.org.
Cause: npm doesn't have permission to write to the global installation directory (usually because it's owned by root).
Solution: Do not use sudo. Instead:
- Use
npxto run without a global install:npx -y -p @pax8/cli pax8 <command> - Or install Node via a version manager:
- Or set an npm prefix in your home directory:
npm config set prefix ~/.npm && export PATH=~/.npm/bin:$PATH
Run the diagnostic command to check your setup:
pax8 doctorThis verifies Node.js version, authentication, API connectivity, cache, and telemetry. If all checks pass, try running a command like pax8 dashboard to confirm end-to-end functionality.
git clone https://github.com/pax8labs/pax8-cli.git
cd pax8-cli
pnpm install
pnpm build
pnpm test # comprehensive test suite (800+ tests across unit, CLI integration, and e2e flows; see CI for current count)
pnpm test:coveragepackages/core— API client, auth, recommendation engine, types (zero CLI dependencies)packages/cli— Commander.js commands, formatting, interactive UXpackages/claude-skill— Claude Code skill
Anonymous, opt-in usage telemetry via PostHog. Off by default — telemetry.enabled defaults to false in config and the CLI sends nothing until you explicitly opt in.
pax8 telemetry enable # Opt in
pax8 telemetry disable # Opt out
pax8 telemetry status # Check current stateThe CLI also honors two ambient environment variables (no opt-in required) and short-circuits before constructing the PostHog client:
PAX8_TELEMETRY_DISABLED=1DO_NOT_TRACK=1(the Console Do Not Track standard)
Single event: command_executed
| Property | Sent | Notes |
|---|---|---|
command |
always | The top-level command, e.g. clients |
subcommand |
when present | Dotted path, e.g. recommendations.list |
flags |
always | The flag names the user passed (no values) |
duration_ms |
always | Wall-clock duration in ms |
success |
always | Boolean |
error_code |
on error | One of the canonical ERROR_* constants — see packages/core/src/errors/codes.ts for the full catalog (codes are append-only) |
cli_version |
always | From package.json |
node_version |
always | process.version |
os |
always | process.platform |
demo_mode |
always | Whether PAX8_DEMO=1 was set |
recs_presented, recs_ordered, recs_skipped, recs_mrr_captured |
recommendations act |
Aggregate counts only |
order_success, order_total_dollars, order_mrr_impact, order_seats |
orders create |
Aggregate transaction outcome only |
The anonymous distinct_id is sha256(hostname + ":" + username) truncated to 16 hex chars — computed locally, never reversible to its inputs.
Never sent:
- API client_id, client_secret, OAuth tokens
- Customer / company / subscription / order IDs
- Customer or company names
- Command argument values (only flag names —
--company, never--company "Acme Corp") - Partner identifiers, account names, billing data
- Stack traces, file paths, environment variables
- Any PII
On the embedded PostHog key: the project key shipped in the bundle is the public, write-only PostHog project ingestion key — this is the standard pattern for OSS analytics, and PostHog's own guidance recommends embedding it. It cannot read events back, only append.
When a command fails, the CLI prints recovery hints and a one-line nudge:
✗ ERROR_AUTH_EXPIRED Authentication failed.
Recovery steps:
→ Your credentials may have expired. Run pax8 auth login to re-authenticate.
→ Help us fix this: run pax8 report-bug to file a sanitized report
pax8 report-bug files a GitHub issue against pax8labs/pax8-cli prefilled with the redacted envelope of the most recent failure. It runs through a redactor (see packages/cli/src/lib/redactor.ts) that strips:
- UUIDs (replaced with
<REDACTED:UUID>) - Email addresses (
<REDACTED:EMAIL>) $HOMEpaths on macOS / Linux / Windows /~/...form (<REDACTED:PATH>— the suffix after the username is preserved so the tail of the path is still useful for debugging)- JWTs and
Bearertokens (<REDACTED:JWT>/<REDACTED:TOKEN>) - Long opaque hex / base64-shaped strings (
>=32chars; covers Pax8 client secrets and similar) (<REDACTED:TOKEN>) - Positional argument values (the client / customer / product names you typed at the command line) — replaced with
<REDACTED:ARG>placeholders in both thecommandfield and theMessagebody. The command structure (clients show <REDACTED:ARG>) is preserved so maintainers can reproduce the bug without partner-specific data ever leaving your machine.
The reporter is opt-in per invocation, not via a config setting. Nothing leaves your machine without explicit [y/N] confirmation — the command always prints the body to stdout first, so you can see exactly what would be submitted.
Maintainer-side drift watcher: Pax8 also runs an internal scheduled GitHub Action (.github/workflows/api-watch.yml) that queries the same PostHog telemetry stream every 6 hours and opens a maintainer issue when ERROR_API_VALIDATION events spike above a threshold. This is a purely aggregate, server-side view used for maintainer triage — it reads only the anonymised event counts and CLI version strings already in PostHog. Partners' data is unchanged; no new data collection is involved.
pax8 report-bug # interactive: review the body, then [y/N]
pax8 report-bug --print # print the redacted Markdown body and exit
pax8 report-bug --json # print the redacted envelope as JSON (for piping)
pax8 report-bug -y # submit without prompting (for scripts)If you have gh installed and authenticated, the command shells out to gh issue create. Otherwise it falls back to opening a prefilled issue URL via your platform's default browser (open on macOS, xdg-open on Linux, start on Windows). No new npm dependencies — only Node's built-in child_process.
The error envelope persisted to ~/.pax8/last-error.json (mode 0600) is what pax8 report-bug reads. It contains the same fields as the --json error output (code, message, causes, recoverySteps, docsUrl), plus the command name, flag names (no values), CLI / Node / OS versions, and an ISO timestamp. The redactor runs over this envelope on every invocation — so even though the file on disk is your own data, the report you submit cannot leak the content of an argument or a path under your home directory.
For partners on restricted networks, this is the complete allowlist of hosts the CLI may contact:
| Host | When | Required? |
|---|---|---|
https://api.pax8.com |
Every API call | Always |
https://api.pax8.com/v1/token |
OAuth client-credentials token exchange | Always (during auth) |
https://us.i.posthog.com |
Telemetry capture | Only when pax8 telemetry enable has been set AND no opt-out env var is present |
https://github.com/pax8labs/pax8-cli/issues/new |
Bug-report submission | Only when you run pax8 report-bug AND confirm [y/N] (or pass -y). When gh is installed, the upload happens via gh; otherwise the URL is opened in your default browser |
No other network egress. The CLI does not contact npm, the Pax8 portal, the marketing site, or any auto-update service at runtime.
All business logic lives in @pax8/core with zero CLI dependencies — the renewal tracker, invoice auditor, recommendation engine, and Pax8 cost analytics (computeMrr, computeGrowth) are all importable. See packages/core/README.md for the full API; here is a minimal end-to-end example:
import {
Pax8Client,
TokenManager,
SubscriptionsApi,
getUpcomingRenewals,
ALL_SUBS_PAGE_SIZE,
} from "@pax8/core";
const tokenManager = new TokenManager({
clientId: process.env.PAX8_CLIENT_ID!,
clientSecret: process.env.PAX8_CLIENT_SECRET!,
});
const client = new Pax8Client({ tokenManager });
const subscriptions = new SubscriptionsApi(client);
const { content } = await subscriptions.list({ size: ALL_SUBS_PAGE_SIZE });
const report = getUpcomingRenewals(content, 30);
console.log(`${report.items.length} renewals in 30 days, $${report.totalMrrRenewing}/mo renewing`);
for (const r of report.items.slice(0, 5)) {
console.log(` ${r.daysUntilRenewal}d ${r.companyName} ${r.productName} $${r.mrrRenewing}/mo`);
}The same pattern works for auditInvoices(...), computeMrr(...), computeGrowth(...), and getRecommendations(...) — see packages/core/README.md for the full surface. computeMrr / computeGrowth are retained in @pax8/core for embeddable reuse; the CLI-side reporting surface is now pax8 report renewals|concentration|subscriptions (Pax8-cost framed, emits AmountCurrency envelopes). The previous pax8 report mrr / pax8 report growth CLI commands were removed because they framed Pax8-cost data as partner-side MRR.
These are tracked, prioritized for v0.1.x, and not blockers for v0.1.0. Each links to a GitHub issue with repro and fix shape.
Real-API surfaces (depend on Pax8 backend):
pax8 orders listagainst busy tenants can hit the 30s default timeout. Extend it by settingPAX8_TIMEOUT_MS=<ms>(default 30000, max 300000). Workaround for very large portfolios:--size 25or smaller.pax8 usage listreturns 404 against the live Pax8 sandbox tenant — likely a path-version mismatch in the client; demo mode works (#212).pax8 doctormarks the~/.pax8/configfile as ✗ (and exits 1) when credentials are configured purely via env vars orPAX8_DEMO=1(#220).
Demo-mode UX:
- Some demo fixtures are thin (
usage,quotes,webhooks) — README quick-start commands work but produce minimal output (#196). - List commands with 0 rows render an empty table rather than a helpful empty-state message (#197).
Human-render UX invariants (tooling gap):
- The per-command e2e matrix exercises every command in subprocess (non-TTY) mode, where the CLI's agent-first contract auto-routes to JSON. Some UX invariants (no UUIDs leaking into table cells, density bounds on tables, drill-in hint visibility) only apply in TTY-render mode and need a node-pty harness — tracked as a follow-up to broaden matrix coverage.
Polish:
- No update-notifier — the CLI doesn't tell you when a newer version exists (#183).
- The scheduled API-drift watcher only filters
ERROR_API_VALIDATIONevents; widening toERROR_API_TIMEOUT/ERROR_API_NOT_FOUND/ etc. is tracked separately (#213). Also note: the watcher is silent untilPOSTHOG_PROJECT_API_KEYis provisioned in repo secrets, and telemetry is opt-in by default.
The CLI surfaces partner-side Pax8 cost figures across pax8 dashboard, pax8 clients more, and pax8 subscriptions renewals. These reflect the partner's monthly / annualized cost to Pax8 (sum of price × quantity across active subs, amortized monthly) — not partner-side resale revenue or partner-billed MRR. Internal Pax8 reporting may also call this "Partner Gross MRR" in the Unified Semantic Layer; the CLI's user-facing labels frame it as cost to disambiguate.
Pax8 monthly cost: The partner's monthly cost to Pax8 from active
subscriptions. For monthly billing terms: price × quantity. For annual
billing terms: (price × quantity) ÷ 12. For 2-Year: ÷ 24. For 3-Year: ÷ 36.
Excludes one-time charges and prorated amounts. Emitted on dashboard --json,
clients more --json, and the report subscriptions / renewals / concentration
commands as a wrapped AmountCurrency object: { "amount": number, "currency": string }. The wrapped shape matches the canonical Pax8 wire
envelope (AmountCurrency from @pax8/core).
Pax8 annual cost: Pax8 monthly cost × 12. The yearly equivalent. Emitted
as annualCost with the same { amount, currency } shape.
pax8 subscriptions renewals emits mrrRenewing (and arrRenewing) on each
row and a totalMrrRenewing / totalArrRenewing aggregate. The field names
are preserved on the wire so existing partner-side risk-framing scripts keep
working; the values are the partner's Pax8 monthly / annual cost from
subscriptions whose commitment ends within the requested window. These are
temporal filters, not churn-risk predictions. Pax8's patent-filed
Revenue at Risk Predictor is a separate ML-based product that scores the
probability of churn; the CLI does not expose that signal.
The previous field names (mrrAtRisk, arrAtRisk, totalMrrAtRisk,
totalArrAtRisk) silently conflated with that ML model's name. They are
retained as deprecated aliases — emitted alongside the new keys with the same
value — for one minor version cycle so existing scripts don't break, then
removed.
pax8 recommendations list surfaces cross-product seat mismatches (e.g.
100 email seats but only 30 backup seats — flagged as seat_gap). This is
distinct from Pax8's canonical "Seat Utilization" metric, which measures
single-product assigned-vs-purchased seats. The CLI's heuristic is a coverage
signal across the customer's stack, not a utilization rate within one product.
pax8 recommendations list emits a type field with the CLI's local product
taxonomy alongside an opportunityType field with OE's canonical 5-type
taxonomy. Two things diverge from Pax8's canonical models — partners parsing
--json should know about both:
-
Product categories. The recommendations engine bins products into a local 7-category taxonomy (
productivity,email,security,endpoint_protection,identity,backup,cloud_infrastructure) that does not match Pax8's canonical STAX taxonomy (8 L1 categories: Productivity, Infrastructure, Continuity, Security, Communications, Network, Operations, Network & Communications Commissioned). The CLI over-decomposes Security into four buckets and omits Communications, Network, and Operations entirely. The simplification was deliberate for the local security-focused cross-sell heuristic. -
seat_gapheuristic. The CLI'sseat_gaptype flags cross-product seat mismatches (e.g. 100 email seats but only 30 backup seats). It is not Pax8's canonical Seat Utilization metric, which is a single-product assigned-vs-purchased rate. The closest OE-canonical surrogate isUpsell— carried on the additiveopportunityTypefield.
CLI category (type / module taxonomy) |
Closest Pax8 / OE concept | Notes |
|---|---|---|
productivity |
STAX L1 Productivity | Aligned |
email, security, endpoint_protection, identity |
STAX L1 Security (+ Productivity for email) | CLI over-decomposes STAX Security into four buckets |
backup |
STAX L1 Continuity | Aligned |
cloud_infrastructure |
STAX L1 Infrastructure | Aligned |
| (no CLI category) | STAX L1 Communications / Network / Operations | Not currently produced by the engine |
type: "seat_gap" |
OE opportunityType: "Upsell" (closest), NOT Seat Utilization |
Cross-product coverage signal, not a utilization rate |
type: "cross_sell" + active subs |
OE opportunityType: "Cross-sell" |
Both carried on the record |
type: "cross_sell" + zero-sub company |
OE opportunityType: "Net-new" |
Both carried on the record |
Both the CLI's product taxonomy and the seat_gap heuristic will sunset when
Pax8's first-party Opportunity Explorer API ships (GET /opportunities).
The local taxonomy is replaced at that point — tracked under
#375. The module docstring
at packages/core/src/services/recommendations.ts carries the same disclosure
for in-IDE readers; this README section is the canonical version for partners
who only see --json output.
- Credential Setup Guide — get API credentials and configure the CLI
- Contributing — dev setup, demo fixtures, tests, releases, DCO sign-off
- Support — troubleshooting, bug reports, security disclosure path
- Agents — entry point for Cursor, aider, OpenCode, and other AI runtimes
- Product Requirements — internal product context
- UX Guide — command patterns and agent-facing contract (contributor reference)
@pax8/corelibrary — using the business logic without the CLI- Pax8 API Reference — upstream API docs
Contributions welcome. See CONTRIBUTING.md.
Apache-2.0 — see LICENSE
Pax8 and the Pax8 logo are trademarks of Pax8, Inc.