← RevenueCatCONTENT HISTORY

Update to RevenueCat

Snapshot Sep 30, 2026 · 23:10 UTC · version 2.3.0

Collection source: not recorded for this historical snapshot.

WHAT CHANGED · RULE-BASED ANALYSIS

First saved snapshot

No earlier snapshot is available to establish a change.

Compare saved observations

Download comparison JSON
Full technical diff · 0 changed fields
Full snapshot data
{
  "description": "Use this skill whenever the user asks for a forecast, projection, extrapolation, or run-rate (MRR, ARR, revenue, or subscribers N months out; revenue to the end of the month or year), or asks what ad spend or acquisition is needed to hit a growth target. Load it before pulling charts for the projection.",
  "included_files": [],
  "name": "revenuecat-forecasting",
  "skill_md_contents": "---\nname: revenuecat-forecasting\ndescription:\n  Use this skill whenever the user asks for a forecast, projection, extrapolation, or run-rate\n  (MRR, ARR, revenue, or subscribers N months out; revenue to the end of the month or year), or\n  asks what ad spend or acquisition is needed to hit a growth target. Load it before pulling charts\n  for the projection.\n---\n\n# Forecasting\n\nUse `revenuecat-charts` for chart mechanics and metric interpretation. This skill covers turning\nthem into a projection. Prefer MCP `get-chart-options-schema` / `get-chart-data` over\n`rc charts show` — the CLI surface does not expose expiration-month segmentation and selectors\nthis playbook needs.\n\nPick the section that matches the ask:\n\n- **Month-by-month MRR/ARR** (including solve-for-spend, and **\"in one month\" / \"in N months\"**)\n  → churn line + Steps below — short horizons are N steps of that line, not a net-movement trend\n- **Revenue to end of month/year** → Rest-of-period run-rates (do not run the MRR Steps)\n- **Low/base/high or \"N months out\"** → Scenario forecasts (use the churn line when projecting\n  MRR/subs)\n- **Underspecified** (\"forecast\", \"predict the future\", no metric/horizon) → default to a\n  **12-month MRR** projection and run the MRR Steps; say that default out loud. On annual-heavy\n  books the Status snapshot will not fill every forecast month — use the expiration months it\n  has, leave empty annual months at zero due (do not invent fill-in), keep rolling short-duration\n  due and inflows, and say that the annual schedule only covers the live book's next cycle.\n\n## The churn line\n\nFor month-by-month MRR or ARR — including solving for the spend or new subscriptions needed to hit\na target, including when the user already gave you churned MRR, spend, or efficiency numbers, and\nincluding short asks like \"what will MRR be in one month\" or \"in two months\" — churned MRR in a\nmonth is:\n\n    churned MRR[m] = MRR up for renewal in m × (1 − renewal rate)\n\n### Short horizons (1–2 months, or any small N)\n\n\"In one month\" / \"in two months\" / \"by next month\" is still the churn line — **N forward steps**,\nnot a rest-of-period run-rate and not an average of recent net MRR movement.\n\n1. Read Status `expiration_month` **Total MRR** for every calendar month that overlaps the window\n   (e.g. remaining current month + next month for ~30 days out; two full months for \"in two\n   months\").\n2. Each step: `churn[m] = due[m] × (1 − rate)` per duration; roll P1M/P3M due past the snapshot;\n   leave empty annual months at zero due.\n3. Add inflows from recent new/resub/expansion only.\n4. Step the stock: `MRR[m+1] = MRR[m] − churn[m] + inflow[m]` — once for N=1, twice for N=2, …\n5. One script. Net movement / frozen churned MRR may appear as a diagnostic gap only — never as a\n   second method that sets the headline number, and never `annual_base / 12`.\n\nCorrect — one month ahead (same idea for N=2 with two months in the loop):\n\n    # due from Status expiration_month (measure=mrr), not base/12\n    due_annual_next = 28316.52          # e.g. Oct Total MRR for P1Y\n    due_monthly = monthly_base          # standing P1M book\n    churn = due_annual_next * (1 - r_annual) + due_monthly * (1 - r_monthly) + ...\n    mrr_next = mrr_now - churn + inflow_run_rate\n\nGet the **renewal rate from Subscription Retention or Cohort Explorer** (chart literals only) —\nnot from `observed_churned ÷ base`, not from Set-to-Renew %. The rate applies to the **due slice**\nfor that duration (for monthlies due ≈ stock; for quarterlies and longer terms, never take\n`churned ÷ full base` and then apply it to the due slice — that understates churn).\n\n**Get \"MRR up for renewal\" from Subscription Status** for the current cycle of the live book:\n\n    get-chart-data(\n      project_id=\"<id>\",\n      chart_name=\"subscription_status\",\n      realtime=true,\n      resolution=\"<id from options schema>\",\n      start_date=\"<YYYY-MM-DD>\",\n      end_date=\"<YYYY-MM-DD>\",\n      segment=\"expiration_month\",\n      selectors=\"{\\\"measure\\\": \\\"mrr\\\"}\",  # JSON string, not an object; not active_subscriptions\n      limit_num_segments=24,               # so later months are not folded into Other\n      # optional: filters=\"[{\\\"name\\\": \\\"product_duration\\\", \\\"values\\\": [\\\"P1Y\\\"]}]\"\n    )\n\nUse the same `get-chart-data` pattern for Retention / Cohort Explorer / MRR / MRR Movement — but\n**do not** copy Status-only fields (`segment=expiration_month`, `limit_num_segments`,\n`selectors.measure`) onto those charts; take segment/filters/selectors from each chart's options\nschema (`get-chart-options-schema` with `\"realtime\": true`).\n\nEach segment is a calendar month when currently active subscriptions' periods end. Use **Total\nMRR** only as `due[m]`. Set to Renew / Cancel / Billing Issue are near-term intent labels — not\nforecast renewal rates. Status is a snapshot of the live book only — still model new / resub /\nexpansion from MRR Movement (or the user's spend plan) as inflows. If you cannot pull due at all,\nask for the renewal schedule rather than using `annual_base / 12`.\n\n### Due and rate by duration\n\n| Duration              | Due (Status available)                                                                                                  | Due (Status unavailable)                                                   | Rate                                                                          |\n| --------------------- | ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |\n| **P1Y**               | Total MRR by `expiration_month` (first + repeat of the live book). Empty far months stay empty — do not invent fill-in. | Prior-year P1Y new + resub in M (misses repeat anniversaries — state that) | Retention Y1 / Cohort (`subscription_type = new` when using Retention)        |\n| **P1M**               | Near-term expiration buckets, then roll ≈ standing monthly base each later month                                        | Standing monthly base                                                      | Retention / Cohort (or movement `churned / due` where due ≈ base)             |\n| **P3M / other fixed** | Near-term buckets, then roll ≈ base / term-months                                                                       | base / term-months                                                         | Retention / Cohort (or movement `churned / due`, never `churned / full base`) |\n\nWrong — annual due as a flat fraction of the stock:\n\n    annual_due = annual_base / 12          # or due_frac = {\"annual\": 1/12}\n\nWrong — back-solving a residual so modeled churn matches observed:\n\n    repeat_annual = observed_annual_churn - annual_due[m] * (1 - rate)\n    churn_annual = annual_due[m] * (1 - rate) + repeat_annual      # then projected\n\nWrong — fixed-term rate on the full stock:\n\n    rate = 1 - churned_P3M / p3m_base      # then churn = (p3m_base/3) * (1 - rate)  → understates\n\nWrong — second model after a gap (blended / net movement / \"calibrated\" churn):\n\n    # after due*(1-rate) disagrees with last month's churned MRR:\n    project(net_fn)  or  mrr *= (1 - blended_churn) + inflow   # never\n\nCorrect:\n\n    # due: subscription_status, measure=mrr, segment=expiration_month, filter product_duration=P1Y\n    annual_due = {\"2026-11\": 17.32, \"2027-02\": 6.66, ...}   # Total MRR per expiration month\n    # rate: Subscription Retention Y1 or Cohort Explorer — not Set-to-Renew %\n    churn_annual[m]  = annual_due[m] * (1 - renewal_rate_annual)\n\n    # monthly: expiration-month for the next cycle, then due ≈ standing monthly_base thereafter\n    churn_monthly[m] = monthly_due[m] * (1 - renewal_rate_monthly)\n    # quarterly: due ≈ p3m_base/3; rate from Retention (or churned_P3M / due, not / p3m_base)\n\n## Steps (month-by-month MRR/ARR only)\n\nDo not use these steps for rest-of-period revenue run-rates — use that section instead.\n\n1. Pull MRR segmented by `product_duration` for the current stocks.\n2. Pull **Subscription Status** as in the `get-chart-data` example above (selectors\n   `{\"measure\": \"mrr\"}`, `segment=expiration_month`, high `limit_num_segments`), filtered by\n   `product_duration` for each duration you model. Read **Total MRR** per expiration month into\n   the script as `due` only. Roll P1M/P3M due past the snapshot per the table; leave empty annual\n   months empty.\n3. Pull rates from **Subscription Retention or Cohort Explorer** — not Set-to-Renew % from status.\n   Every rate literal in code must appear in a prior tool output.\n4. Pull MRR Movement for **new / resub / expansion run-rates only** (inflows). Do not feed\n   churned MRR, net movement, or a blended churn rate into the projection. Churn in the script\n   must be `due[m] × (1 − rate)` — never `project(net_fn)` / a fit on net MRR movement /\n   `mrr * (1 - blended_churn)`.\n5. Compute in **exactly one** script shaped like the Correct block. If month-1 modeled churn ≠\n   observed, print the gap as a diagnostic only — do not run a second, calibrated, blended, or\n   net-movement projection, and do not add a residual. The renewal-due result is the central\n   answer.\n6. Present that central case, the range and what drives it, and the gap diagnostic if any. Call a\n   number a floor or ceiling only if every stated assumption biases it that way.\n\n## Rest-of-period run-rates\n\nFor \"revenue until the end of the month/year\" and similar — not the MRR Steps above:\n\n- Today is incomplete. Exclude it from the daily average, or say that you excluded it.\n- Give a range or state the observed day-to-day volatility. A bare point estimate is not a\n  forecast.\n- Triangulate two methods — elapsed-day pace, and the prior period's shape applied to the current\n  one — and say which you weighted and why.\n- Prefer splitting out MRR already locked via Subscription Status expiration months in the\n  remainder of the period, rather than assuming renewals are spread evenly.\n- Put the headline numbers in the chat answer; do not defer them to a chart or artifact.\n\n## Scenario forecasts\n\nFor low / base / high cases or \"N months out\":\n\n- Each case names the driver that differs (acquisition rate, renewal rate, a pricing change\n  working through the base), not a multiplier on the same number.\n- Commit to a central case; a range alone does not answer the question.\n- Every renewal or retention rate in the simulation comes from a chart pull for this account.\n  Published benchmarks are context, not inputs.\n- \"N months out\" ends N months from today. If the model is anchored on the last complete month,\n  say so and name the end month.\n- When the metric is MRR or subscribers, use the churn line above for the retention side.\n\n## Prediction Explorer\n\nPrediction Explorer models cohort LTV, not churn. Use it for payback or LTV cross-checks when the\nquestion asks for them; it does not replace the churn line above.\n"
}

SHA-256 of public snapshot: 0a7be737a16df8b8d7f355caa33258bda0f4f3d023168162649daa228225f3ed