ops-revenue · diff

git:20260614.d66a5d5 to git:20260722.95f6861

61 added, 20 removed. Audit A to A.

---
name: ops-revenue
description: Revenue and costs tracker. AWS spend via aws ce, credits tracker, project revenue stages. Shows burn rate, runway estimate, credits expiring.
argument-hint: '[costs|revenue|credits|runway|all]'
allowed-tools:
- Bash
- Read
- Grep
- Glob
- Skill
- AskUserQuestion
- WebFetch
- Write
effort: low
maxTurns: 20
disallowedTools:
- Edit
- NotebookEdit
---
# OPS ► REVENUE & COSTS
## Runtime Context
Before executing, load available context:
1. **Preferences**: Read `${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.json`
- `timezone` — display all timestamps correctly
2. **Daemon health**: Read `${CLAUDE_PLUGIN_DATA_DIR}/daemon-health.json`
- If `action_needed` is not null → surface it before the cost report
3. **Secrets**: AWS Cost Explorer requires credentials.
### Secret Resolution
- AWS: check `$AWS_PROFILE` / `$AWS_ACCESS_KEY_ID` → `doppler secrets get AWS_ACCESS_KEY_ID --plain` → vault query cmd from prefs
- If no credentials available, report "AWS costs unavailable — credentials not configured" and show only the revenue pipeline from registry
## CLI/API Reference
- ### aws CLI (Cost Explorer)
+ ### AWS burn doctrine (CRITICAL — 2026-07-22)
- | Command | Usage | Output |
- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | ------------- |
- | `aws ce get-cost-and-usage --time-period Start=<YYYY-MM-DD>,End=<YYYY-MM-DD> --granularity MONTHLY --metrics "UnblendedCost" --group-by "Type=DIMENSION,Key=SERVICE" --output json` | Cost by service | Cost JSON |
- | `aws ce get-cost-and-usage --time-period Start=<YYYY-MM-DD>,End=<YYYY-MM-DD> --granularity MONTHLY --metrics "UnblendedCost" --output json` | Total cost | Cost JSON |
- | `aws ce get-cost-forecast --time-period Start=<YYYY-MM-DD>,End=<YYYY-MM-DD> --metric "UNBLENDED_COST" --granularity MONTHLY --output json` | End-of-month forecast | Forecast JSON |
- | `aws ce list-savings-plans-purchase-recommendation --output json` | Savings plan recommendations | JSON |
+ **Never report plain `UnblendedCost` / `NetUnblendedCost` totals as "spend".**
+ Startup credits, SPP discounts, and Savings Plan negation make those nets ≈ $0
+ while real Usage burn is hundreds/day. **Always** use `RECORD_TYPE=Usage` for
+ burn, pace, spikes, runway, and Bedrock. Show credits only as a mask line.
+ Canonical helper (prefer this over raw `aws ce`):
+
+ ```!
+ ${CLAUDE_PLUGIN_ROOT}/scripts/aws-usage-cost.sh snapshot 2>/dev/null || echo '{}'
+ ```
+
+ ```!
+ ${CLAUDE_PLUGIN_ROOT}/scripts/aws-usage-cost.sh all 2>/dev/null || true
+ ```
+
+ | Command | Usage | Output |
+ | ------- | ----- | ------ |
+ | `scripts/aws-usage-cost.sh snapshot` | MTD/prev Usage burn + 7d daily + top services + credit mask | JSON |
+ | `scripts/aws-usage-cost.sh daily 7` | Last N days Usage totals | JSON array |
+ | `scripts/aws-usage-cost.sh by-service mtd` | MTD Usage by service | JSON array |
+ | `scripts/aws-usage-cost.sh record-types` | Credit / Usage / SP breakdown (mask only) | JSON array |
+ | `aws ce get-cost-and-usage … --filter '{"Dimensions":{"Key":"RECORD_TYPE","Values":["Usage"]}}'` | Raw Usage-only CE (fallback if helper missing) | Cost JSON |
+ | `aws ce list-savings-plans-purchase-recommendation` | Savings plan recommendations | JSON |
+
---
## Phase 1 — Gather financial data in parallel
### FinOps dashboard — canonical revenue + burn
If `FINOPS_DASHBOARD_URL` and `FINOPS_OPS_API_TOKEN` are configured, the
dashboard is the single source of truth for per-project MRR, 30d revenue,
and current burn. Per-DBA breakdown comes from the Stripe revenue
snapshots ingested via `/api/ops/revenue`. Falls open to `{}` if unset —
the per-source AWS / RevenueCat queries below run as fallback.
+ **If the dashboard `current_month_spend` is ≈ $0 while Usage burn from
+ `aws-usage-cost.sh` is material, trust the helper** (dashboard may still be
+ credit-masked or ingest-empty). Always dual-check with the Usage helper.
+
```!
${CLAUDE_PLUGIN_ROOT}/scripts/finops-bridge.sh snapshot 2>/dev/null || echo "{}"
```
```!
${CLAUDE_PLUGIN_ROOT}/scripts/finops-bridge.sh revenue project 2>/dev/null || echo "{}"
```
When the dashboard returns data, render the per-project MRR section from
`groups[]` rather than from RevenueCat-only data.
- ### AWS costs (current month)
+ ### AWS costs — Usage burn (authoritative)
+ ```!
+ ${CLAUDE_PLUGIN_ROOT}/scripts/aws-usage-cost.sh snapshot 2>/dev/null || echo '{}'
+ ```
+
+ Fallback if helper missing:
+
```bash
+ USAGE_FILTER='{"Dimensions":{"Key":"RECORD_TYPE","Values":["Usage"]}}'
aws ce get-cost-and-usage \
--time-period "Start=$(date +%Y-%m-01),End=$(date +%Y-%m-%d)" \
--granularity MONTHLY \
--metrics "UnblendedCost" \
+ --filter "$USAGE_FILTER" \
--group-by "Type=DIMENSION,Key=SERVICE" \
--output json 2>/dev/null
```
- ### AWS costs (last 3 months trend)
+ ### AWS costs (last 3 months Usage trend)
```bash
+ USAGE_FILTER='{"Dimensions":{"Key":"RECORD_TYPE","Values":["Usage"]}}'
aws ce get-cost-and-usage \
--time-period "Start=$(date -v-3m +%Y-%m-01 2>/dev/null || date -d '3 months ago' +%Y-%m-01),End=$(date +%Y-%m-%d)" \
--granularity MONTHLY \
--metrics "UnblendedCost" \
+ --filter "$USAGE_FILTER" \
--output json 2>/dev/null
```
- ### AWS credits remaining
+ ### AWS credits / discount mask (not spend)
+ ```!
+ ${CLAUDE_PLUGIN_ROOT}/scripts/aws-usage-cost.sh record-types 2>/dev/null || echo '[]'
+ ```
+
```bash
aws ce list-savings-plans-purchase-recommendation --output json 2>/dev/null || echo '{}'
aws ce get-credits --output json 2>/dev/null || echo "credits API unavailable"
```
### AWS cost forecast (end of month)
+ Note: CE forecasts are often net-of-credits. Prefer `eom_pace` from
+ `aws-usage-cost.sh snapshot` (7d Usage avg × days in month) as the burn forecast.
+
```bash
aws ce get-cost-forecast \
--time-period "Start=$(date +%Y-%m-%d),End=$(date +%Y-%m-28)" \
--metric "UNBLENDED_COST" \
--granularity MONTHLY \
--output json 2>/dev/null
```
-
### Project registry (revenue stage)
```bash
cat "${CLAUDE_PLUGIN_ROOT}/scripts/registry.json" 2>/dev/null | jq '[.projects[] | {alias, name, stage: (.revenue_stage // .revenue.stage // "pre-revenue"), mrr: (.mrr // 0), source: (.source // "git"), type: (.type // "repo")}]'
```
### External project revenue (Shopify, custom SaaS)
```!
${CLAUDE_PLUGIN_ROOT}/bin/ops-external 2>/dev/null || echo '[]'
```
For Shopify projects showing `status: "healthy"`, pull GMV via Shopify Admin API:
```bash
# For each Shopify project in registry with valid credentials:
STORE_URL="[from project.shopify.store_url]"
TOKEN="[from env var named in project.shopify.credential_key]"
curl -s -H "X-Shopify-Access-Token: $TOKEN" \
"https://$STORE_URL/admin/api/2024-10/orders.json?status=any&created_at_min=$(date -v-30d +%Y-%m-%dT00:00:00Z 2>/dev/null)&limit=250" 2>/dev/null
```
Include Shopify GMV in the revenue pipeline table with source=shopify.
---
## Phase 2 — Render dashboard
```
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
OPS ► REVENUE & COSTS — [month]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
- AWS SPEND
- This month to date: $[X]
- Forecast (EOM): $[X]
- Last month: $[X]
+ AWS USAGE BURN (RECORD_TYPE=Usage — not credit-masked net)
+ This month usage: $[X] ← from aws-usage-cost.sh mtd_usage
+ Forecast (EOM pace): $[X] ← eom_pace (7d Usage avg × days)
+ Last month usage: $[X]
MoM change: [+/-X%]
+ 7d avg/day: $[X]
- Top services:
- [service] $[X] ([%] of total)
+ Top services (Usage):
+ [service] $[X] ([%] of usage)
[service] $[X]
...
- CREDITS
- AWS credits remaining: $[X]
+ CREDITS / MASK (do not report as low spend)
+ Credits applied MTD: $[X] (record_types Credit)
+ Discounts MTD: $[X]
+ Net after mask: ~$0 is EXPECTED when credits cover burn
+ Credits remaining: $[X] (if API available)
Expires: [date]
- Burn rate at current: [N months remaining]
+ Months cover at pace: [N]
REVENUE PIPELINE
PROJECT SOURCE STAGE MRR/GMV STATUS
──────────────────────────────────────────────────────────────
[project] git [stage] $[X] [status]
[project] shopify [stage] $[X] GMV [status]
[project] custom [stage] $[X] [status]
...
──────────────────────────────────────────────────────────────
TOTAL MRR $[X]
TOTAL SHOPIFY GMV (30d) $[X]
RUNWAY ESTIMATE
Monthly burn (AWS): $[X]
Total MRR: $[X]
Net burn: $[X/month]
Credits cover: [N months]
Cash runway: [depends on external data]
──────────────────────────────────────────────────────
```
Use **batched AskUserQuestion calls** (max 4 options each):
AskUserQuestion call 1:
```
[Drill into AWS costs by service]
[Show cost anomalies (spike detection)]
[Export cost report]
[More...]
```
AskUserQuestion call 2 (only if "More..."):
```
[Update project revenue stage]
[Set budget alert]
```
---
## Route by `$ARGUMENTS`
| Argument | Action |
| -------- | ---------------------------- |
| costs | Show only AWS cost breakdown |
| credits | Show only credits and expiry |
| revenue | Show only revenue pipeline |
| runway | Calculate and show runway |
| (empty) | Show full dashboard |
Use AskUserQuestion after the dashboard for next action.
---
## Native tool usage
### WebFetch — billing API fallback
When `aws ce` commands fail or return incomplete data, use `WebFetch` to query the AWS Cost Explorer API directly. Also useful for fetching Stripe/billing provider data if configured.
### Write — export reports
When user selects "Export cost report" (option c), use `Write` to save the report as a dated file:
```
Write(file_path: "/tmp/ops-revenue-[date].md", content: "[formatted report]")
```