What it does
One runway number hides the two things a founder is actually betting on: the deals in the pipeline and the customers who might leave. A board asks "what if the big deal slips" and the answer lives in three tools, so it gets guessed.
Once a month the agent takes cash and three months of net burn from the bank, MRR and the accounts showing churn signals from Stripe, and the open deals with their stage probability and close date from HubSpot. It projects cash month by month three ways and names the accounts and deals that move the range, so the card says "14 months, 19 if the pipeline closes, 11 if two accounts leave".
How it works
1Read cash and three months of burn
Sum
currentBalancefromGET /api/v1/accounts, orCurrentBalanceof QuickBooksBankaccounts if the books are where cash lives. PullGET /api/v1/transactions?start=<first day 3 months back>&end=<last day of last month>, dropinternalTransferandfailed,cancelledorreversedrows, and average money out minus money in over the 3 full months.2Find MRR that is at risk
From
GET /v1/subscriptions?status=all, sum MRR overactiveandpast_duesubscriptions. Mark a customer at risk when a subscription hascancel_at_period_end: true, ispast_dueorunpaid, or its latest invoice is open withattempt_countof 2 or more; keep each one's MRR and the date it would stop.3Weight the open pipeline
POST /crm/v3/objects/deals/searchwithclosedatewithin the next 90 days anddealstagenot in a closed stage (stages whosemetadata.isClosedistrueinGET /crm/v3/pipelines/deals), readingamount,closedate,dealstageandhs_deal_stage_probability. Weighted value is amount x probability, turned into monthly revenue (divided by 12 when deal amounts are annual, as set in settings) starting the month afterclosedate.- 4
4Join Stripe customers to CRM companies
Key: the domain of the Stripe customer's email, lowercased, against the HubSpot company
domainwithoutwww.; for gmail.com and other free domains, match the full email to a contact instead. A deal whose company already pays in Stripe counts only its increase over current MRR, and renewals count nothing. At-risk customers get their HubSpot owner and any open renewal deal; unmatched ones keep their Stripe name. - 5
5Project three runways
Month by month from today: base is cash over average net burn; best lowers each month's burn by the weighted new MRR from its close month on; worst raises it by the at-risk MRR from the month it stops. Runway is the number of full months before cash goes below zero. Read last month's card at
GET https://briefkin.dev/v1/cards/insight-mercury-runway-with-pipelinefor the change. Post it to the board
With
BRIEFKIN_TOKENset, the agent sends the result as one card that updates in place every run. Without it, you get the report in the chat.
Install and run it
Pick your agent, where the data comes from and how to schedule it; the commands below follow.
Install the skill
One command. It puts the SKILL.md in ~/.claude/skills and in ~/.agents/skills, which Codex, Cursor, Gemini CLI, Copilot CLI and OpenCode read too.
shell
curl -fsSL https://briefkin.dev/skills/mercury-runway-with-pipeline/install | shRun it
Ask Claude Code:
prompt
Run the mercury-runway-with-pipeline skillOr paste the prompt instead of installing:
prompt
Give me my runway three ways. Cash: total balance of my Mercury accounts. Burn: average of money out minus money in over the last 3 full months, leaving out transfers between my own accounts and failed payments. From Stripe, MRR and the at-risk customers (cancel_at_period_end, past_due or unpaid, or an open invoice with 2 or more failed attempts) with their MRR. From HubSpot, open deals closing in the next 90 days with amount and stage probability; weighted monthly value is amount times probability, divided by 12 for annual amounts, from the close month on. Match Stripe customers to HubSpot companies by email domain so existing customers are not counted as new deals. Project cash month by month: base, best (weighted pipeline closes) and worst (at-risk accounts churn). Give me the three runways in months, the inputs, the at-risk accounts with owner, and the top 5 deals. End with the one account or deal to act on first.Put it on a schedule
1st of the month at 8:00, from cron on any machine where Claude Code is signed in:
crontab
0 8 1 * * claude -p "Run the mercury-runway-with-pipeline skill"Add it with
crontab -e. A laptop asleep at that time runs it when it wakes if you use launchd or Task Scheduler instead; GitHub Actions works for the API route.Send it to your board
Connect Briefkin once with
curl -fsSL https://briefkin.dev/install | shand every run lands on your board as a stat tile. How setup works
View the SKILL.mdRaw file
SKILL.md---
name: mercury-runway-with-pipeline
description: "Monthly: months of runway on cash alone, with the deals likely to close and without the accounts likely to churn, from Mercury, Stripe and HubSpot. Use when the user asks for this, or when it runs on a schedule."
---
# Runway with pipeline and churn risk: bank, Stripe and CRM
Monthly: months of runway on cash alone, with the deals likely to close and without the accounts likely to churn, from Mercury, Stripe and HubSpot.
One runway number hides the two things a founder is actually betting on: the deals in the pipeline and the customers who might leave. A board asks "what if the big deal slips" and the answer lives in three tools, so it gets guessed.
Once a month the agent takes cash and three months of net burn from the bank, MRR and the accounts showing churn signals from Stripe, and the open deals with their stage probability and close date from HubSpot. It projects cash month by month three ways and names the accounts and deals that move the range, so the card says "14 months, 19 if the pipeline closes, 11 if two accounts leave".
## Two ways to get the data
Use the API or MCP route when you have an MCP server, a CLI or an API token for the app. Otherwise, if you can drive a browser the user is signed in to (Claude in Chrome, a Playwright or Chrome DevTools MCP server), use the browser route. Say which one you used.
## Route A: API or MCP server
### What you need
- A Mercury Read Only token or the Mercury MCP server with `read` scope (or QuickBooks read access if your bank is not Mercury), and a Stripe restricted key with Read on Subscriptions and Invoices.
- HubSpot read access to deals and companies (`crm.objects.deals.read`, `crm.objects.companies.read`), with stage probabilities set on the pipeline and the same customer email domain in Stripe and HubSpot.
If something is missing, say what and stop; do not invent numbers.
### Steps
1. **Read cash and three months of burn** (Mercury): Sum `currentBalance` from `GET /api/v1/accounts`, or `CurrentBalance` of QuickBooks `Bank` accounts if the books are where cash lives. Pull `GET /api/v1/transactions?start=<first day 3 months back>&end=<last day of last month>`, drop `internalTransfer` and `failed`, `cancelled` or `reversed` rows, and average money out minus money in over the 3 full months.
2. **Find MRR that is at risk** (Stripe): From `GET /v1/subscriptions?status=all`, sum MRR over `active` and `past_due` subscriptions. Mark a customer at risk when a subscription has `cancel_at_period_end: true`, is `past_due` or `unpaid`, or its latest invoice is open with `attempt_count` of 2 or more; keep each one's MRR and the date it would stop.
3. **Weight the open pipeline** (HubSpot): `POST /crm/v3/objects/deals/search` with `closedate` within the next 90 days and `dealstage` not in a closed stage (stages whose `metadata.isClosed` is `true` in `GET /crm/v3/pipelines/deals`), reading `amount`, `closedate`, `dealstage` and `hs_deal_stage_probability`. Weighted value is amount x probability, turned into monthly revenue (divided by 12 when deal amounts are annual, as set in settings) starting the month after `closedate`.
4. **Join Stripe customers to CRM companies**: Key: the domain of the Stripe customer's email, lowercased, against the HubSpot company `domain` without `www.`; for gmail.com and other free domains, match the full email to a contact instead. A deal whose company already pays in Stripe counts only its increase over current MRR, and renewals count nothing. At-risk customers get their HubSpot owner and any open renewal deal; unmatched ones keep their Stripe name.
5. **Project three runways**: Month by month from today: base is cash over average net burn; best lowers each month's burn by the weighted new MRR from its close month on; worst raises it by the at-risk MRR from the month it stops. Runway is the number of full months before cash goes below zero. Read last month's card at `GET https://briefkin.dev/v1/cards/insight-mercury-runway-with-pipeline` for the change.
## Route B: the browser
### What you need
- Signed in to Mercury (the person handles 2FA), Stripe with a role that can view subscriptions, and HubSpot with access to the deal pipeline.
If something is missing, say what and stop; do not invent numbers.
### Steps
Start at https://app.mercury.com/dashboard. The user is signed in already; never type passwords or codes, and ask if a sign-in page appears.
1. **Read cash and burn in Mercury**: Note the total balance across accounts on the dashboard. Open Transactions, set the range to the last 3 full months, and read money in and money out per month, leaving out transfers between your own accounts; the average of out minus in is net burn.
2. **Find at-risk accounts in Stripe**: Open `https://dashboard.stripe.com/subscriptions` and filter Status `Past due` and `Unpaid`, then look for subscriptions marked as canceling at period end. Note each customer, email domain and monthly amount, and read MRR on Billing > Overview.
3. **Weight the pipeline in HubSpot**: Open `https://app.hubspot.com/` and go to CRM > Deals, board view, filtered to open deals with Close date in the next 90 days. View settings > Show metrics adds a card with the Weighted deal amount; note each deal's amount, deal probability and close date, and skip companies already paying in Stripe unless the deal adds to their plan.
4. **Project three runways**: Base is cash divided by net burn. Best: lower burn by each deal's weighted monthly value from its close month. Worst: raise burn by the at-risk MRR from next month. Count full months before cash runs out.
Note: Mercury's dashboard charts money in and out but not by full calendar month for every range, so reading three months can mean exporting Transactions as CSV. HubSpot's weighted amount uses the stage probability of each pipeline; deal amounts entered as annual values need dividing by 12.
## The report
- **Runway on cash alone** in months, with the monthly trend.
- **Best case** if weighted pipeline closes on schedule, and **worst case** if at-risk accounts churn.
- **Inputs**: cash, average net burn for 3 months, MRR, weighted new MRR, at-risk MRR.
- **At-risk accounts** with MRR, signal and owner, and the **top deals** by weighted value.
- One line on what to do first, for example "Call Acme Logistics about the failed card: it is $9,400 of the $16,200 at risk".
## Post it to Briefkin
When `BRIEFKIN_TOKEN` is set, or `~/.config/briefkin/env` exists (the installer from https://briefkin.dev/docs writes it), also send the result to the user's Briefkin board as one card. Keep the `item_key` the same on every run so the card updates in place, use a new `event_id` per run, and put today's real numbers in place of the example ones. If the request fails, say so once and carry on.
```bash
[ -n "${BRIEFKIN_TOKEN:-}" ] || . ~/.config/briefkin/env
curl -sS -X POST "${BRIEFKIN_URL:-https://briefkin.dev}/v1/events" \
-H "authorization: Bearer $BRIEFKIN_TOKEN" \
-H "content-type: application/json" \
-d @- <<'JSON'
{
"v": 1,
"event_id": "mercury-runway-with-pipeline/<date of this run, e.g. 2026-10-16>",
"item_key": "mercury-runway-with-pipeline",
"project": "Acme",
"source": "Runway with pipeline and churn risk: bank, Stripe and CRM skill",
"kind": "metric",
"title": "Runway 14 months on cash, 19 with pipeline, 11 if 2 accounts churn",
"metric": {
"label": "Runway on cash alone",
"value": 14,
"unit": "months",
"period_label": "",
"better": "higher",
"period_start": "<start of the period, ISO 8601>",
"period_end": "<end of the period, ISO 8601>"
},
"glance": [
{
"type": "Grid",
"props": {
"columns": 3
},
"children": [
{
"type": "Stat",
"props": {
"label": "If pipeline closes",
"value": 19,
"unit": "mo",
"tone": "ok"
}
},
{
"type": "Stat",
"props": {
"label": "If at-risk churn",
"value": 11,
"unit": "mo",
"tone": "warn"
}
},
{
"type": "Stat",
"props": {
"label": "Net burn",
"value": "$60k",
"unit": "/mo",
"better": "lower"
}
}
]
}
],
"widget": [
{
"type": "KeyValue",
"props": {
"items": [
{
"key": "Cash",
"value": "$840,000 across 3 Mercury accounts"
},
{
"key": "Net burn, 3-month average",
"value": "$60,000 (Jul $58k, Aug $61k, Sep $61k)"
},
{
"key": "MRR",
"value": "$48,200"
},
{
"key": "Weighted new MRR",
"value": "$17,000 from 9 deals closing Oct to Dec"
},
{
"key": "At-risk MRR",
"value": "$16,200 from 2 accounts"
}
]
}
},
{
"type": "Table",
"props": {
"columns": [
"At-risk account",
"MRR",
"Signal",
"Owner"
],
"align": [
"left",
"right",
"left",
"left"
],
"rows": [
[
"Acme Logistics",
"$9,400",
"Card failed twice",
"Dana"
],
[
"Northwind Foods",
"$6,800",
"Cancels at period end",
"Sam"
]
]
}
}
],
"size": "md"
}
JSON
```
Widgets come from the Briefkin catalog (https://briefkin.dev/v1/catalog). Without a token, just give the user the report.
Set `period_start` and `period_end` to the window the number covers: the tile names it from them ("Last 7 days", "Today", "This month"). For a count right now (open items, a balance), send `"period_label": ""` so no period shows; for another name, send it as `period_label` (at most 24 characters).
## Run it on a schedule
Suggested: 1st of the month at 8:00 (`0 8 1 * *`). From cron, with the agent signed in on that machine:
```bash
0 8 1 * * claude -p "Run the mercury-runway-with-pipeline skill"
# Codex: codex exec, Gemini CLI: gemini -p, Copilot CLI: copilot -p, OpenCode: opencode run
```
Or use the agent's own scheduler (Claude Code routines, Codex automations, Claude or ChatGPT scheduled tasks): https://briefkin.dev/skills/mercury-runway-with-pipeline#schedule
Source: https://briefkin.dev/skills/mercury-runway-with-pipeline
What your agent needs
A Mercury Read Only token or the Mercury MCP server with
readscope (or QuickBooks read access if your bank is not Mercury), and a Stripe restricted key with Read on Subscriptions and Invoices.HubSpot read access to deals and companies (
crm.objects.deals.read,crm.objects.companies.read), with stage probabilities set on the pipeline and the same customer email domain in Stripe and HubSpot.
Connecting Mercury
- Mercury MCP, Mercury's official remote server at
https://mcp.mercury.com/mcp, signed in with OAuth. It's in Claude's connector directory. In Claude Code runclaude mcp add --transport http -s user mercury https://mcp.mercury.com/mcpand thenclaude mcp login mercury; in Codex,codex mcp add mercury --url https://mcp.mercury.com/mcp; Cursor takes the same URL (docs). Its tools load accounts, transactions, statements, recipients and cards. - API with a Read Only token. In the Mercury dashboard, open the organization menu, then Settings > Tokens, and create an API token of the Read Only type, which needs no IP whitelist. Store it in
MERCURY_API_TOKENand send it asAuthorization: Bearer.
At the MCP consent screen, grant only read: the write scopes (transactions:request, transfers:request, transactions:update and the category scopes) let an agent request payments or recategorize transactions. A Read Only API token fetches everything a report needs and can't move money.
Connecting QuickBooks
- QuickBooks connector in Claude. Intuit and Anthropic partnered in 2026 to bring QuickBooks into Claude; where your plan offers the connector, connect it with your Intuit sign-in.
- QuickBooks Online MCP server, Intuit's open-source local server (source). It runs over stdio and reads
QUICKBOOKS_CLIENT_ID,QUICKBOOKS_CLIENT_SECRET,QUICKBOOKS_REFRESH_TOKEN,QUICKBOOKS_REALM_IDandQUICKBOOKS_ENVIRONMENT. - Accounting API with OAuth 2.0. Register an app in the Intuit Developer Portal, authorize the company once with the
com.intuit.quickbooks.accountingscope, and store the same five values. Access tokens last an hour and the refresh token can change on each refresh, so the skill must save the newest one.
The accounting scope has no read-only version; with Intuit's MCP server, set QUICKBOOKS_DISABLE_WRITE, QUICKBOOKS_DISABLE_UPDATE and QUICKBOOKS_DISABLE_DELETE to true so the agent gets only read, search and report tools.
Connecting Stripe
- Stripe MCP server, Stripe's official remote server at
https://mcp.stripe.com. Add Stripe from Claude's connector directory, or runclaude mcp add --transport http stripe https://mcp.stripe.com/, and sign in with OAuth; clients without OAuth can send a restricted key as a Bearer token. - The Stripe CLI. Run
stripe loginonce, thenstripe subscriptions list --status active --limit 100orstripe invoices list --status open. The CLI defaults to test mode, so add--livefor real data. - API with a restricted key. Create a restricted key (
rk_live_...) in the Dashboard under Developers > API keys, store it inSTRIPE_API_KEY, and give it Read on the resources the report touches: Subscriptions, Invoices, Charges, Customers, PaymentIntents, Balance and Disputes.
Never hand an agent the secret key (sk_live_...); a restricted key with Read where needed and None everywhere else can't refund, cancel or charge anything.
Connecting HubSpot
- HubSpot MCP server, HubSpot's remote server at
https://mcp.hubspot.com. HubSpot also offers a Claude connector built on the same server; you sign in with your HubSpot user and it sees what that user can see (docs). - API with a private app token. Create a private app in your HubSpot account settings, give it only the scopes the report reads (
crm.objects.deals.read,crm.objects.contacts.read,crm.objects.companies.read,crm.objects.owners.read), and store its token inHUBSPOT_ACCESS_TOKEN.
The MCP server and connector can create and update records, so for unattended reports a private app with only .read scopes is the safer credential.
Questions
Why not just add the whole pipeline to the best case?
Because most of it will not close. Multiplying each deal by its stage probability gives the expected value, and starting its revenue after the close date stops a deal closing in December from extending runway in October. If your stage probabilities are HubSpot's defaults rather than your own win rates, the best case is optimistic; set them from last year's closed deals.
What if Stripe and HubSpot use different emails for the same customer?
The join uses the email domain, so billing@acme.com in Stripe still finds the Acme company in HubSpot. It fails when a customer pays with a personal or agency email; those at-risk accounts keep their Stripe name with no owner, and a deal for them may be counted as new. Adding the company domain to the Stripe customer's metadata fixes it for good.
Do I need Briefkin to use the Runway with pipeline and churn risk: bank, Stripe and CRM skill?
No. The skill runs with your own agent and gives you the report in the chat. With a Briefkin token set, each run also posts it to your board as a stat tile, so you can glance at it instead of asking again.
Which agents can run it?
Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot CLI, OpenCode, Windsurf and Amp all read SKILL.md files. The install command puts it in ~/.claude/skills and ~/.agents/skills, where they look. ChatGPT, the Claude app and Grok take the prompt instead. Pick your agent under "Install and run it" and the commands change to match.
Can it work without an API or MCP server, from my browser?
Yes. Switch the data source to "Your browser" and the steps change to the Mercury, QuickBooks, Stripe and HubSpot pages themselves: the agent opens app.mercury.com/dashboard in a browser you are signed in to and reads the numbers off the page. Claude Code, Codex, Cursor, Claude app and ChatGPT can drive a browser out of the box; Gemini CLI, Copilot CLI and OpenCode need a Playwright or Chrome DevTools MCP server first. It is slower than the API and needs you signed in, so it suits a report you run by hand or from a scheduler on your own computer.