finance-analytics

Use this skill when the user wants to analyze financial performance, review P&L health, monitor MRR/ARR, investigate margin or cost trends, build a finance report, check cash flow or runway, or answer

SKILL.md

GitHub

Finance Analytics

Analyze financial performance using data from Coupler.io dataflows (QuickBooks, Xero, Stripe, NetSuite, Sage, billing systems). This skill guides you through retrieving accounting and revenue data, computing P&L, margin, subscription, and cash metrics, detecting anomalies, and presenting actionable insights a finance lead can act on.

Step 0: Context Check (Pre-requisite · HARD GATE)

Before any analysis, confirm the user has a live Coupler.io connection to their finance data. No live connection, no analysis — no pasted P&L screenshots, no numbers from memory or a prior conversation, no benchmarking against industry averages instead of the user's actual QuickBooks, Xero, NetSuite, Stripe, or Sage data. Unsure counts as no.

If no data source is connected, stop and hand off to the create-dataflow skill to connect one — don't re-implement the connection flow here.

Before starting any analysis, the Data Context Check skill (generate-data-set-context) runs as a gate. It calls get-schema on each target dataset to determine whether meaningful context (chart of accounts mapping, entity/subsidiary structure, currency conventions, fiscal calendar, accrual vs. cash convention) is attached.

  • If context exists → proceed to Step 1.
  • If context is missing → the user is offered the option to generate it first.

Do not duplicate this check in Step 1d.

Step 1: Discover and Select Data Sources

1a. Discover available data

Default to search-datasets with finance-flavored keywords — quickbooks, xero, netsuite, stripe, sage, gl, invoice, revenue, mrr, arr, bank, or whatever system the user named. Search keeps the response small and lands on the right dataflow when the domain is known.

Fall back to list-datasets only when the user is genuinely browsing or hasn't given any source/keyword to anchor on. Each dataflow represents a data pipeline (e.g. "QuickBooks GL", "Stripe Charges", "NetSuite Revenue", "Xero Invoices", "Bank Transactions").

1b. Select relevant datasets

Unambiguous match (1 dataflow) → use it; mention which one.

Obvious candidates (2–3) → state your selection with one-line reasoning, proceed but invite corrections.

Ambiguous (5+, or unclear) → present best candidates (up to 5–7) grouped by source/scope, with reasoning, and wait for confirmation:

I found 3 dataflows likely relevant to your MRR question:
  1. stripe_subscriptions — has plan, MRR amount, status
  2. quickbooks_gl — has revenue accounts, but at journal grain
  3. salesforce_opportunities — has booked ARR, less useful for recognized
Should I use Stripe alone, or combine Stripe and QuickBooks for cross-check?

Hard gate only when ambiguous. If you're confident and stated reasoning, proceed.

1c. Get dataflow details

Call get-dataflow for each candidate. Note schedule (data freshness), source health, and the close status of any GL data — finance refreshes are often slower than transactional sources.

1d. Understand the data structure

Call get-schema on each target dataset. If context was generated in Step 0, use the enriched schema directly.

For finance schemas, watch for these critical column families: account/account_code (chart of accounts), entity_id/subsidiary, currency, transaction_date/posting_date, amount (signed: positive = credit, varies by source), invoice_status (paid/open/voided), customer_id, plan_id, billing_period_start/end, refund flags.

1e. Sample the data

Sample each dataset to verify contents. Watch specifically for: signed-amount conventions (debit-positive vs. credit-positive), currency mixing, journal entry duplicates, voided/reversed entries that need exclusion. Flag anything off before proceeding.

Coverage Verdict (say this out loud before analysing)

Tell the user which parts of this analysis the connected data can actually support before computing anything — it decides what the rest of the run can credibly say.

Data area If present, enables If absent, means
GL/journal-level detail (vs. summary P&L rows) Cost-center drill-down by sub-account or vendor Cost-Center Investigation can only run at the category level — say so, don't fabricate a vendor-level split from summary rows
Bank/cash transaction data Cash burn and runway calculations Say bank/cash data isn't in scope. Don't extrapolate runway from P&L data without it
Multi-entity/subsidiary structure Proper consolidation across entities and currencies Don't sum across entities without knowing the structure — say consolidation can't be verified, or state the single-entity assumption used
Budget/plan data Actual-vs-budget comparisons Budget figures usually don't live in QuickBooks, Xero, NetSuite, or Stripe — say budget comparison isn't available unless the user supplies it or a budget dataflow is connected
Close status (preliminary, soft-closed, hard-closed) Confidence that period-end numbers are final Treat pre-close numbers as provisional and say so before presenting them

Any row marked absent is one more Coupler.io source or context field away — tell the user what to connect rather than working around the gap silently.

Early exit. If only summary-level or partial data is connected, run the parts the coverage table supports, state plainly which sections were skipped and why, and don't backfill the gap with assumptions or industry benchmarks.

Step 2: Compute Metrics via SQL

Always compute via SQL in get-data. Floating-point aggregations over thousands of rows in-context are unreliable.

Working with multiple datasets

Combining datasets: get-data reads one dataset at a time and cannot join across them. Query each separately and synthesize when you are comparing side by side or pulling something small. When the user wants to repeat an analysis that needs a real join (matching rows across datasets, or aggregating over the combined result), build it with create-dataset so it re-runs on every refresh; its inputs must all live in the same dataflow. For a one-off question, combine the results yourself, and if the data is too large for that, say so and suggest create-dataset.

Date alignment: Posting date vs. transaction date vs. service date can differ — confirm which the user wants. Use fiscal calendar if the company doesn't operate on calendar months.

Currency normalization: Multi-entity companies need consolidation; always state your conversion approach (period-end FX vs. average FX vs. native).

Cash vs. accrual: Critical distinction. Confirm which convention the user wants. Stripe data is mostly cash; QuickBooks/NetSuite GL can be either depending on configuration.

Recognized vs. booked: Booked = contract signed (Salesforce). Billed = invoice issued. Recognized = ASC 606 revenue recognition (subscription pro-ration). Don't conflate; ask if unclear.

Voided/reversed entries: GL data often includes voided journals — exclude them in the WHERE clause. Don't double-count refunds as new revenue.

Step 3: Draft Findings and Get User Feedback

Before generating a full analysis, present a brief summary — the 3–5 most important numbers, anomalies, and direction. Wait for user response before continuing.

Step 4: Build the Analysis

P&L Review

Standard structure: Revenue → COGS → Gross Profit → Operating Expenses → Operating Income → Other → Net Income.

  • Gross margin % = (Revenue − COGS) / Revenue. Track period-over-period; a 2-point compression is meaningful.
  • Operating margin % = Operating Income / Revenue.
  • Expense breakdown by category (Sales & Marketing, R&D, G&A) — flag categories growing faster than revenue.
  • Period-over-period and year-over-year comparisons. State the comparison basis explicitly.

Flag concentration: if one customer/product is >20% of revenue, call it out as a concentration risk.

MRR / ARR & Subscription Health

For SaaS or subscription businesses:

  • MRR = sum of monthly recurring revenue across active subscriptions. ARR = MRR × 12.
  • MRR movement bridge: Starting MRR + New + Expansion + Reactivation − Contraction − Churn = Ending MRR. Always reconcile the bridge — gaps reveal data issues or missing categories.
  • Net Revenue Retention (NRR) = (Starting MRR of cohort + Expansion − Contraction − Churn) / Starting MRR. Healthy SaaS: >100%.
  • Gross Revenue Retention (GRR) = (Starting MRR − Contraction − Churn) / Starting MRR. Excludes expansion.
  • Logo churn vs. revenue churn — present both; high logo churn with stable revenue churn signals SMB churn masked by enterprise stability.

Cash & Runway

  • Cash burn (monthly) = avg monthly net cash outflow over trailing 3 months.
  • Runway = current cash balance / monthly burn. State both calendar months and 'months at current burn'.
  • Operating cash flow vs. net income — divergences signal AR/AP timing issues.

If bank/cash data isn't in scope, say so. Don't extrapolate runway from P&L data without cash data.

Cost-Center Investigation

When the user asks 'why did costs go up' or 'where is spend growing fastest':

  1. Break down the cost category by sub-account or vendor.
  2. Compare to prior period at the sub-account level.
  3. Identify the top 3 sub-accounts driving the change.
  4. Check for one-time items (annual renewals, project spikes) vs. structural increases.
  5. Present: "Of the $X increase, $Y is from <vendor/account> renewing on annual cycle, $Z is structural increase in <category>, balance is distributed."

Anomaly Detection and Metric Investigations

Any time the analysis involves investigating a change, drop, or spike — apply this framework:

Severity classification:

  • Informational — within 1 SD of trailing 4-month average, or <5% change. Note it.
  • Warning — 1–2 SD, or 5–15% change. Investigate, present hypotheses.
  • Critical — >2 SD, >15% change, or any metric crossing a covenant/threshold. Lead with this finding.

Finance has tighter sensitivity than marketing/ecom — a 10% gross margin drop is a 'critical' event, not 'warning'.

Baseline comparison: Same period prior year (annual seasonality matters in finance), trailing 3-month average, budget if available.

Root cause investigation steps:

  1. Isolate the scope — which entity, which account, which customer/vendor.
  2. Check posting period — late-arriving journals, period-end accruals, reversal entries.
  3. Check upstream changes — pricing changes, contract renewals, vendor changes, new accounting policy.
  4. Check for data issues — duplicate journals, currency conversion errors, voided entries not excluded.
  5. Present hypotheses ranked by likelihood — "Most likely: annual security audit fee posted to G&A in this month vs. amortized last year. Less likely: structural growth in headcount cost."

Step 5: Present Results

Lead with the headline, use plain language, ensure every finding has a 'So what?' and 'Now what?', structure for scannability.

Abbreviation expansion: First use of MRR, ARR, NRR, GRR, EBITDA, COGS, GAAP, ASC 606, AR, AP, FX — expand it.

Currency: Always state on first use. If multi-currency, state your normalization approach (period-end vs. average FX, source of rates).

Materiality: Note material vs. immaterial movements. A $5 swing in a $50M revenue line is noise.

Rules & Edge Cases

  • Always state data freshness and the close status (preliminary, soft-closed, hard-closed) before presenting numbers. Pre-close numbers can shift materially.
  • State revenue convention (cash, accrual, recognized) on first use; never silently switch.
  • Voided/reversed journals must be excluded from totals. If you can't tell which entries are voided, say so.
  • Multi-entity / multi-currency: never sum across entities without consolidation. State your consolidation approach.
  • Prior-period adjustments and reclassifications: if a prior month was restated, mention it — comparing current period to a restated prior gives different results than to the original.
  • Round to materiality: don't report margins to 4 decimals when 1 decimal is enough. Don't report dollar amounts to the cent on totals over $10K.
  • Tax: distinguish pre-tax and post-tax metrics explicitly when both exist.
  • If a dataflow's last execution failed or is stale (>2 days for a daily GL refresh), warn the user — and consider that GL data is often refreshed less frequently than transactional sources, so 'stale' definitions differ.

Next Question (REQUIRED)

Exactly one, drawn from what this run found. Never a menu — a second only when the data genuinely points two ways.

  • "Gross margin compressed from 61% to 58% quarter-over-quarter — want me to drill into the cost centers driving that 3-point drop?"
  • "The MRR bridge doesn't reconcile — Starting + New + Expansion − Contraction − Churn lands $12K short of Ending MRR — want me to trace the gap to find the missing category?"
  • "Runway is at 8 months at the current burn rate — want a deeper look at operating cash flow vs. net income to check whether AR timing is inflating the burn?"