Which deals are really at risk, and what will actually close?

Deal Keeper is an open-source pipeline forecaster for small B2B sales teams. It learns each stage's real win rate from your own closed deals instead of the generic percentages in your CRM, gives a forecast range it has backtested against deals that were open in the past, and ranks the stale, slipping or stalled deals by the money at stake, so you know which phone call to make first.

1. Read your pipeline

2. Run Deal Keeper yourself

git clone https://github.com/Duncan-Haywood/oss-monorepo && cd oss-monorepo/ventures/deal-keeper
API_KEY=$(openssl rand -hex 16) ADMIN_KEY=$(openssl rand -hex 16) node server.mjs

curl -X POST localhost:8080/v1/deals -H "authorization: Bearer $API_KEY" \
  -d '{"id":"acme","name":"Acme","amount":12000,"stage":"proposal","closeDate":"2026-11-30"}'
curl localhost:8080/v1/pipeline -H "authorization: Bearer $API_KEY"
curl "localhost:8080/v1/forecast?target=50000" -H "authorization: Bearer $API_KEY"

Move a deal with another POST /v1/deals that changes stage; close it with "status":"won" or "lost"; log a conversation with POST /v1/deals/:id/activity. Set ALERT_WEBHOOK_URL and you get a signed webhook once when a deal first goes stale, overdue or slips. One-click deploy files for Render, Fly.io and Docker are in the folder.

Questions

Why not use Pipedrive, HubSpot, Close or Streak?

Those are full CRMs: contacts, email sync, calling, automations and a per-seat price that adds up. Deal Keeper does the narrow job those tools do worst for a small team: tell you which open deals are really at risk and what the pipeline will plausibly close, using your own closed deals instead of the generic stage percentages every CRM ships with. It is one dependency-free Node process with a JSON file for state, there is no per-seat fee, and your deals never leave your server. Keep your CRM for contacts and email; point this at its export or its webhooks.

How are win chances worked out?

For each stage, Deal Keeper counts how many of your past closed deals got that far and how many of those were won, then pulls that rate toward a generic default so three lucky deals cannot claim 100%. The rate is forced to rise (or stay level) as deals move down the funnel. A deal that has sat in its stage a long time is compared only with past deals that also stayed at least that long, which is how stalling lowers its chance. Every probability comes with the sentences behind it.

How do I know the forecast is any good?

When your history has exact stage dates and enough closed deals, Deal Keeper runs an out-of-time backtest: it trains only on deals closed before a cutoff, forecasts the deals that were open that day using the stage each was in, and compares with how they ended. It reports how many wins it predicted against how many happened, and a Brier skill score against simply guessing your overall win rate. With too little data it says so and labels the chances as defaults. The forecast range is a 10th-to-90th percentile band that treats deals as independent, so it is optimistic when your deals move together.

How much data do I need?

About 20 closed deals with at least 5 won and 5 lost for the stage chances to be called learned, and roughly 30 deals with exact stage dates for the backtest. Below that you still get the hygiene list (stale, overdue, slipped, no next step), which needs no history, and defaults for the chances. At a handful of deals a month, your own judgement beats any model; this pays off from a few dozen closed deals.

What does the hygiene list flag?

No activity for longer than your won deals ever went quiet, a close date in the past, a close date pushed back twice or more, a deal past the first stage with no next step, a deal sitting longer in its stage than three quarters of your won deals did, and deals with no amount or no close date. Deals are ranked by the value at risk, probability times amount, so the one worth a phone call today is at the top.

Is it safe to put real customer data in?

Send only deal ids you choose and short deal names, never contact details. You run the server, so you are responsible for securing the API key, backing up the state file and following the privacy rules where you and your buyers live. The browser page on this site runs entirely in your tab and uploads nothing.