OPS ► REVENUE & COSTS skill

OPS on-demand: This skill should be used when the user asks to "burn rate", "runway", or…

by Lifecycle-Innovations-Limited·MIT license·★ 543 Stars on the repo·GitHub ↗

Use now

Inside this skill

SKILL.md · the author's own words
# OPS ► REVENUE & COSTS

Load `ops-rules` before acting. Public repo (no personal data). Outbound: one draft → one approval → one send. If `AskUserQuestion` / `Work…

## 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

Word-for-word excerpt, not a result. Read the full SKILL.md ↓

Files of OPS ► REVENUE & COSTS

Lifecycle-Innovations-Limited/main1 file shown
SKILL.md
Show the full text270 lines

OPS ► REVENUE & COSTS

Load ops-rules before acting. Public repo (no personal data). Outbound: one draft → one approval → one send. If AskUserQuestion / Workflow are missing, follow Rule 10 in ops-rules (Hermes: numbered options / two-turn Telegram card; delegate_task).

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 burn doctrine (CRITICAL — 2026-07-22)

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 — Usage burn (authoritative)
${CLAUDE_PLUGIN_ROOT}/scripts/aws-usage-cost.sh snapshot 2>/dev/null || echo '{}'

Fallback if helper missing:

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 Usage trend)
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 / discount mask (not spend)
${CLAUDE_PLUGIN_ROOT}/scripts/aws-usage-cost.sh record-types 2>/dev/null || echo '[]'
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.

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)
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:

# 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 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 (Usage):
 [service]  $[X]  ([%] of usage)
 [service]  $[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]
 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]")
1---
2name: ops-revenue
3description: "OPS on-demand: This skill should be used when the user asks to \"burn rate\", \"runway\", or…"
4argument-hint: '[costs|revenue|credits|runway|all]'
5allowed-tools:
6 - Bash
7 - Read
8 - Grep
9 - Glob
10 - Skill
11 - AskUserQuestion
12 - WebFetch
13 - Write
14effort: low
15maxTurns: 20
16disallowedTools:
17 - Edit
18 - NotebookEdit
19---
20 
21# OPS ► REVENUE & COSTS
22 
23Load `ops-rules` before acting. Public repo (no personal data). Outbound: one draft → one approval → one send. If `AskUserQuestion` / `Workflow` are missing, follow Rule 10 in `ops-rules` (Hermes: numbered options / two-turn Telegram card; `delegate_task`).
24 
25## Runtime Context
26 
27Before executing, load available context:
28 
291. **Preferences**: Read `${CLAUDE_PLUGIN_DATA_DIR:-$HOME/.claude/plugins/data/ops-ops-marketplace}/preferences.json`
30 - `timezone` — display all timestamps correctly
31 
322. **Daemon health**: Read `${CLAUDE_PLUGIN_DATA_DIR}/daemon-health.json`
33 - If `action_needed` is not null → surface it before the cost report
34 
353. **Secrets**: AWS Cost Explorer requires credentials.
36 ### Secret Resolution
37 - AWS: check `$AWS_PROFILE` / `$AWS_ACCESS_KEY_ID` → `doppler secrets get AWS_ACCESS_KEY_ID --plain` → vault query cmd from prefs
38 - If no credentials available, report "AWS costs unavailable — credentials not configured" and show only the revenue pipeline from registry
39 
40## CLI/API Reference
41 
42### AWS burn doctrine (CRITICAL — 2026-07-22)
43 
44**Never report plain `UnblendedCost` / `NetUnblendedCost` totals as "spend".**
45Startup credits, SPP discounts, and Savings Plan negation make those nets ≈ $0
46while real Usage burn is hundreds/day. **Always** use `RECORD_TYPE=Usage` for
47burn, pace, spikes, runway, and Bedrock. Show credits only as a mask line.
48 
49Canonical helper (prefer this over raw `aws ce`):
50 
51```!
52${CLAUDE_PLUGIN_ROOT}/scripts/aws-usage-cost.sh snapshot 2>/dev/null || echo '{}'
53```
54 
55```!
56${CLAUDE_PLUGIN_ROOT}/scripts/aws-usage-cost.sh all 2>/dev/null || true
57```
58 
59| Command | Usage | Output |
60| ------- | ----- | ------ |
61| `scripts/aws-usage-cost.sh snapshot` | MTD/prev Usage burn + 7d daily + top services + credit mask | JSON |
62| `scripts/aws-usage-cost.sh daily 7` | Last N days Usage totals | JSON array |
63| `scripts/aws-usage-cost.sh by-service mtd` | MTD Usage by service | JSON array |
64| `scripts/aws-usage-cost.sh record-types` | Credit / Usage / SP breakdown (mask only) | JSON array |
65| `aws ce get-cost-and-usage … --filter '{"Dimensions":{"Key":"RECORD_TYPE","Values":["Usage"]}}'` | Raw Usage-only CE (fallback if helper missing) | Cost JSON |
66| `aws ce list-savings-plans-purchase-recommendation` | Savings plan recommendations | JSON |
67 
68---
69 
70## Phase 1 — Gather financial data in parallel
71 
72### FinOps dashboard — canonical revenue + burn
73 
74If `FINOPS_DASHBOARD_URL` and `FINOPS_OPS_API_TOKEN` are configured, the
75dashboard is the single source of truth for per-project MRR, 30d revenue,
76and current burn. Per-DBA breakdown comes from the Stripe revenue
77snapshots ingested via `/api/ops/revenue`. Falls open to `{}` if unset —
78the per-source AWS / RevenueCat queries below run as fallback.
79 
80**If the dashboard `current_month_spend` is ≈ $0 while Usage burn from
81`aws-usage-cost.sh` is material, trust the helper** (dashboard may still be
82credit-masked or ingest-empty). Always dual-check with the Usage helper.
83 
84```!
85${CLAUDE_PLUGIN_ROOT}/scripts/finops-bridge.sh snapshot 2>/dev/null || echo "{}"
86```
87 
88```!
89${CLAUDE_PLUGIN_ROOT}/scripts/finops-bridge.sh revenue project 2>/dev/null || echo "{}"
90```
91 
92When the dashboard returns data, render the per-project MRR section from
93`groups[]` rather than from RevenueCat-only data.
94 
95### AWS costs — Usage burn (authoritative)
96 
97```!
98${CLAUDE_PLUGIN_ROOT}/scripts/aws-usage-cost.sh snapshot 2>/dev/null || echo '{}'
99```
100 
101Fallback if helper missing:
102 
103```bash
104USAGE_FILTER='{"Dimensions":{"Key":"RECORD_TYPE","Values":["Usage"]}}'
105aws ce get-cost-and-usage \
106 --time-period "Start=$(date +%Y-%m-01),End=$(date +%Y-%m-%d)" \
107 --granularity MONTHLY \
108 --metrics "UnblendedCost" \
109 --filter "$USAGE_FILTER" \
110 --group-by "Type=DIMENSION,Key=SERVICE" \
111 --output json 2>/dev/null
112```
113 
114### AWS costs (last 3 months Usage trend)
115 
116```bash
117USAGE_FILTER='{"Dimensions":{"Key":"RECORD_TYPE","Values":["Usage"]}}'
118aws ce get-cost-and-usage \
119 --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)" \
120 --granularity MONTHLY \
121 --metrics "UnblendedCost" \
122 --filter "$USAGE_FILTER" \
123 --output json 2>/dev/null
124```
125 
126### AWS credits / discount mask (not spend)
127 
128```!
129${CLAUDE_PLUGIN_ROOT}/scripts/aws-usage-cost.sh record-types 2>/dev/null || echo '[]'
130```
131 
132```bash
133aws ce list-savings-plans-purchase-recommendation --output json 2>/dev/null || echo '{}'
134aws ce get-credits --output json 2>/dev/null || echo "credits API unavailable"
135```
136 
137### AWS cost forecast (end of month)
138 
139Note: CE forecasts are often net-of-credits. Prefer `eom_pace` from
140`aws-usage-cost.sh snapshot` (7d Usage avg × days in month) as the burn forecast.
141 
142```bash
143aws ce get-cost-forecast \
144 --time-period "Start=$(date +%Y-%m-%d),End=$(date +%Y-%m-28)" \
145 --metric "UNBLENDED_COST" \
146 --granularity MONTHLY \
147 --output json 2>/dev/null
148```
149### Project registry (revenue stage)
150 
151```bash
152cat "${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")}]'
153```
154 
155### External project revenue (Shopify, custom SaaS)
156 
157```!
158${CLAUDE_PLUGIN_ROOT}/bin/ops-external 2>/dev/null || echo '[]'
159```
160 
161For Shopify projects showing `status: "healthy"`, pull GMV via Shopify Admin API:
162 
163```bash
164# For each Shopify project in registry with valid credentials:
165STORE_URL="[from project.shopify.store_url]"
166TOKEN="[from env var named in project.shopify.credential_key]"
167curl -s -H "X-Shopify-Access-Token: $TOKEN" \
168 "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
169```
170 
171Include Shopify GMV in the revenue pipeline table with source=shopify.
172 
173---
174 
175## Phase 2 — Render dashboard
176 
177```
178━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
179 OPS ► REVENUE & COSTS — [month]
180━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
181 
182AWS USAGE BURN (RECORD_TYPE=Usage — not credit-masked net)
183 This month usage: $[X] ← from aws-usage-cost.sh mtd_usage
184 Forecast (EOM pace): $[X] ← eom_pace (7d Usage avg × days)
185 Last month usage: $[X]
186 MoM change: [+/-X%]
187 7d avg/day: $[X]
188 
189 Top services (Usage):
190 [service] $[X] ([%] of usage)
191 [service] $[X]
192 ...
193 
194CREDITS / MASK (do not report as low spend)
195 Credits applied MTD: $[X] (record_types Credit)
196 Discounts MTD: $[X]
197 Net after mask: ~$0 is EXPECTED when credits cover burn
198 Credits remaining: $[X] (if API available)
199 Expires: [date]
200 Months cover at pace: [N]
201 
202REVENUE PIPELINE
203 PROJECT SOURCE STAGE MRR/GMV STATUS
204 ──────────────────────────────────────────────────────────────
205 [project] git [stage] $[X] [status]
206 [project] shopify [stage] $[X] GMV [status]
207 [project] custom [stage] $[X] [status]
208 ...
209 ──────────────────────────────────────────────────────────────
210 TOTAL MRR $[X]
211 TOTAL SHOPIFY GMV (30d) $[X]
212 
213RUNWAY ESTIMATE
214 Monthly burn (AWS): $[X]
215 Total MRR: $[X]
216 Net burn: $[X/month]
217 Credits cover: [N months]
218 Cash runway: [depends on external data]
219 
220──────────────────────────────────────────────────────
221```
222 
223Use **batched AskUserQuestion calls** (max 4 options each):
224 
225AskUserQuestion call 1:
226 
227```
228 [Drill into AWS costs by service]
229 [Show cost anomalies (spike detection)]
230 [Export cost report]
231 [More...]
232```
233 
234AskUserQuestion call 2 (only if "More..."):
235 
236```
237 [Update project revenue stage]
238 [Set budget alert]
239```
240 
241---
242 
243## Route by `$ARGUMENTS`
244 
245| Argument | Action |
246| -------- | ---------------------------- |
247| costs | Show only AWS cost breakdown |
248| credits | Show only credits and expiry |
249| revenue | Show only revenue pipeline |
250| runway | Calculate and show runway |
251| (empty) | Show full dashboard |
252 
253Use AskUserQuestion after the dashboard for next action.
254 
255---
256 
257## Native tool usage
258 
259### WebFetch — billing API fallback
260 
261When `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.
262 
263### Write — export reports
264 
265When user selects "Export cost report" (option c), use `Write` to save the report as a dated file:
266 
267```
268Write(file_path: "/tmp/ops-revenue-[date].md", content: "[formatted report]")
269```
270 

Discussion