New
Apps 923Makers 922This week 923
Promote your app−30%
1views in
the last 30 days

PromptSpend

Estimate what an AI-built app will cost to run before you build it.

Built with Claude/Claude Code

by andrewavery7 · from USUnited States · added Oct 29, 2026
no ratings0 comments

PromptSpend

Know the tab before you build.
Estimate, compare and understand what an AI feature will cost — from a catalog that re-checks itself every morning, so the numbers are never a year out of date.

16 providers 1583 tests 104 KB gzip initial payload CI Sync pricing PromptSpend MCP on mcprush

→ Open PromptSpend  ·  free  ·  open source  ·  no accounts, no ads  ·  Writing: What LLM Cost Calculators Get Wrong  ·  September 2026 Price Movement Report

https://github.com/user-attachments/assets/6bfecd10-84a9-408b-b08c-ff9481648692

1 minute 37 — press play, and hit 🔊 to unmute (GitHub starts videos silent).  ·  Download the MP4


Why this exists

Every LLM cost calculator on the web has the same failure mode: it is a snapshot. Someone builds it, hard-codes a dozen model prices, and within a few months the entire premise is wrong — the models it compares have been superseded and the prices it quotes no longer exist.

PromptSpend is built the other way round. The pricing pipeline is the product; the calculator is what sits on top of it. Every morning a GitHub Action re-fetches the catalog from independent sources, merges them under an explicit trust order, runs sanity checks, and either commits the result or opens a pull request for a human. Capture patterns are family-level, so a brand-new model version is picked up automatically without anyone touching code.

What it does

  • Receipt — copy a fully visible, one-response cost-audit object into an existing AI conversation. It estimates the visible workload, retrieves current PromptSpend prices, names the two largest cost drivers and suggests cheaper models worth testing without pretending price proves equal quality.
  • Estimate — describe one interaction (paste your real prompt or move the sliders), set your scale, and see the monthly, yearly, per-user and margin numbers for up to four models side by side.
  • Compare — every tracked model on a price-versus-capability value map, plus a sortable catalog you can select from directly, with the source and verification date for every row.
  • Learn — seven short interactive lessons on tokens, why output costs more, how wide the price spread is, compounding chat history, hidden reasoning tokens, caching and batching, and how the data pipeline works.
  • Free tiers — which providers let a new account start without paying, card rules, limits and whether free use trains their models, quoted word for word from each vendor's own pages with a link and date on every fact, and re-checked each morning. One comparison page and one page per provider; see docs/FREE_TIERS.md.
  • Data & Alerts — pipeline health, full provenance for every number with a link to the vendor page it came from, what is currently flagged, and four ways to hear about a price change: an Atom feed, the repository's own pull requests, browser push, and an email digest.

Price alerts

Opt-in, and off unless a deployment is configured for them. Browser push stores nothing personal — a push subscription is an opaque URL the browser issues. Email is double opt-in with one-click unsubscribe, and stores your address, the models you follow, and the date you asked; nothing else. Either channel can watch the whole catalog or just the models you pick.

The delivery service is a Cloudflare Worker in worker/, with the push payload encryption written out against RFC 8291 and checked byte for byte against the RFC's own worked example. docs/ALERTS.md has the architecture, the cost model and the domain cutover.

Things it does that most calculators get wrong

Output is priced separately Output typically costs 3–5× input. Averaging the two, as many calculators do, understates most real workloads.
Chat history compounds Turn N re-sends turns 1…N−1 as input, so conversation cost grows with the square of the turn count.
Tokenizers differ per family The same pasted text is counted with each model's own tokenizer — exactly (js-tiktoken, run in your browser) for OpenAI-family models and with a clearly labelled calibrated ratio elsewhere.
Caching is not free Cache writes cost 1.25× input at both OpenAI and Anthropic. Counting only the cheaper reads reports a saving your invoice will not have, so writes are billed and caching is off by default.
Long context costs more Above 272K input tokens OpenAI bills the whole request at 2× input and 1.5× output. Tiers apply per request, so a conversation can cross over partway through.
Reasoning tokens are billable A multiplier for hidden thinking tokens, because the visible answer is not what you pay for.
Promotional pricing expires Introductory rates apply only inside their window, and the engine takes a date.
Assumptions are visible Every non-published number used in a calculation is listed under the results, not buried — and so is what the prices do not cover.
Impossible scenarios are named A request that will not fit the context window, or a response past the output ceiling, is flagged rather than priced as if it would work.

How the data stays current

                    ┌─────────────────────────┐
  LiteLLM catalog ──┤                         │
                    │   allowlist → merge →   │──→ public/data/pricing.json ──→ the app
  OpenRouter API ───┤   validate → diff       │
                    └───────────┬─────────────┘
  data/pricing-overrides.json ──┘            └──→ docs/pricing-changelog.md
       (hand-verified, wins)

The trust ladder, in order:

  1. Hand-verified vendor rates (data/pricing-overrides.json) — win every conflict.
  2. The LiteLLM community catalog — the automated daily feed; thousands of models, updated within days of a release.
  3. The OpenRouter API — an independent cross-check, never a source of record. Reseller pricing differs from first-party list pricing, so a disagreement of more than 20% flags the model rather than changing it.
  4. Sanity rules — schema validation, non-negative rates, implausibility checks, a review flag on any price that moved more than 50% in a single day, a floor on how many rows a source may return, and a cap on how much the catalog may shrink in one run.

A diff is committed and deployed automatically, flags included: there is no human gate on publication, on purpose, because a flag that held the whole catalog once left the site's dates two days behind. A newly raised flag publishes with everything else, marks that row disputed on the site, and opens an issue for review — a long-standing disagreement does not re-open one every morning. A run that loses a source or trips a size guard is degraded: it publishes nothing, records why in public/data/sync-status.json, and fails loudly. Either way the change lands in docs/pricing-changelog.md.

Nothing disappears on one bad morning. A model missing from the feed is kept and marked stale, not deleted; retiring one for good is a deliberate edit to data/models-allowlist.json.

Rung 1 is worked by hand, and the split is published rather than blurred. Every row says which rung it came from, and rows read against a vendor's own page carry the URL that was read and the date it was read. Most of the catalog is now vendor-sourced — but not all of it, because some vendors do not publish a pricing page that lists their own models, and the honest answer there is to leave the row labelled litellm rather than launder an aggregator's number into a first-party claim. The models this currently affects are named in docs/DEFERRED.md. A number is only worth what its worst source is, so the site shows you the source per row instead of an average you cannot inspect.

Something watches the promise

A daily job reads the live site — not the copy in this repository — and raises an issue if the published catalog is more than two days old. That distinction is the whole point. Between a price moving upstream and you seeing it, four things can fail: the sync errors, the sync cannot commit its result, the deploy fails after a green sync, or the CDN serves a stale artifact. Checking the file in git catches the first of those. Fetching what the site actually serves catches all four.

It exists because the sync once failed at its publishing step and nothing said so; the site quietly served a day-old catalog until someone happened to look. A project that claims its numbers are never a year out of date should be the first to know when they are.

Two dates, not one

The site shows prices last changed and sources last checked separately, because they answer different questions. A quiet week in the market makes the first date age while everything works perfectly; a broken scheduler looks exactly the same if you only publish one date. The second comes from a health manifest written on every run, successful or not:

https://promptspend.com/data/sync-status.json

Right now the first of those reads not yet recorded, and that is correct rather than broken. No vendor has moved a price since this catalog's history began on 2026-08-01, so there is no date to show — and the alternative, quietly displaying the last build date, would announce a price change every morning nothing happened. An empty field you can trust beats a populated one you cannot.

The second is now a state and not just a date: the chip on the results panel is green while the sources were checked within a day, blue at two days, amber past the window the freshness monitor tolerates or after a degraded run, and outlined-grey when the manifest could not be loaded at all. That last state exists on purpose. A status light that reads "fine" when its own evidence is missing is precisely the failure the monitor was built to catch.

Three things a number can do

Keeping "prices last changed" honest means the pipeline has to tell apart three events that all look like a diff:

What happened lastChanged
Price change Same source, different number. The vendor repriced. stamped
Coverage A field went from absent to present. We started recording a rate that was always offered. untouched
Correction The number moved in the same run its source URL did. We had been reading the wrong page. untouched

Only the first is news. Conflating them is not hypothetical: reading x.ai's real pricing page instead of its model list once gained a long-context tier and restated a cached-input rate, and the catalog stamped both as price changes — putting PRICES CHANGED 2026-08-06 on the busiest panel of the site with no vendor having touched a rate. Suppressing corrections can hide a genuine same-day move, and that trade is deliberate: on a catalog whose whole claim is provenance, announcing a change nobody made costs more than missing one by a day.

Use the data yourself

There is a free, keyless, CORS-open API at promptspend.dev — no account, no key, no rate limit:

curl https://promptspend.dev/v1/prices          # flat rows: the numbers only
curl https://promptspend.dev/v1/models/gpt-5    # one model, in full
curl https://promptspend.dev/v1/prices.csv      # the same rows, for a spreadsheet

Filters: ?provider=, ?status=, ?aliases=include. Every response carries X-PromptSpend-Generated-At, and OpenAPI 3.1 lives at /openapi.json. See docs/API.md.

Or drop a price badge in your own README

claude-opus-5 price

[![claude-opus-5 price](https://promptspend.dev/badge/claude-opus-5.svg)](https://promptspend.dev/)

Swap the model id for any id from /v1/models. The badge is drawn fresh on every fetch — no cache — so the date it shows is always the day that price was last confirmed.

Or inside your coding agent

claude mcp add promptspend -- npx -y @promptspend/mcp

Or with nothing to install: add https://promptspend.dev/mcp as a custom connector in Claude.ai or ChatGPT (claude mcp add --transport http promptspend https://promptspend.dev/mcp in Claude Code).

Other pricing MCP servers exist and index more models than this one. What none of them do is tell you where a number came from and when it was last confirmed — the competing server's own documentation says only that pricing "is updated regularly", with no verification date per price. That gap is the reason this exists.

It matters more to a model than to a person. Someone reading a web page sees the interface around a figure and calibrates. A model handed a bare number repeats it with whatever confidence the sentence implies. Given the source and the date it can say "as of 1 August, per OpenAI's pricing page" — and when two sources disagree it is told so, rather than being handed a number somebody picked.

Three tools, deliberately. estimate_cost is the one a price lookup cannot provide: it runs this repository's cost engine, imported rather than reimplemented, so it accounts for compounding conversation history, cache writes, long-context tiers and reasoning tokens — and cannot report a figure that disagrees with the calculator, because it is the same code. A test asserts that.

And because MCP tool definitions load into your context on every turn, the server's own overhead is measured, budgeted at 900, checked in CI and published: ~823 tokens. Nothing else in the ecosystem appears to publish its own footprint. See mcp/README.md.

Or in your editor

The same catalog, on the line of code that chooses the model.

response = client.messages.create(
    model="claude-sonnet-4-6", # $3 / $15 per M · max out $0.061
    max_tokens=4096,
)

A linter for model choice rather than a calculator in a sidebar — a calculator in an editor is only this website with worse ergonomics. What an editor can do that a web page cannot is notice things: a nearby max_tokens becomes the output ceiling in money, a cap above what the model can emit is named rather than priced as though it would work, deprecated and disputed rows reach the Problems panel, and an Explorer view lists every model the repository calls, dearest first.

Everything it says is Information severity, never a warning. None of these are mistakes and the extension has no idea what the code needs. The cheaper-model suggestion is off by default for the same reason the value map's capability axis is labelled illustrative: it is an opinion, where the rest are facts.

code --install-extension promptspend.promptspend

Or search PromptSpend in the Extensions pane. It is on Open VSX too, which is where Cursor, Windsurf and VSCodium look.

Same rule as everywhere else — no bundled prices. If the catalog cannot be reached it says so and shows nothing, and the status bar carries the generation date at all times. See vscode/README.md.

Or on your phone

Native apps for iPhone and Android, free on the App Store and Google Play: paste a sample conversation, compare up to four models, and see the cost per conversation, day, month and year from the same catalog. Pasted text is processed on the device and never uploaded. Both are described at promptspend.com/app; the source is in apps/mobile/.

Or read the file the API reads. The catalog is plain, versioned JSON with a stable shape:

https://promptspend.com/data/pricing.json
{
  "schemaVersion": 2,
  "gene

Description taken from the repository README.

Ratings

–
0 ratings
5 0
4 0
3 0
2 0
1 0

Rate this app

Sign in to rate

Comments 0

Sign in to comment

No comments yet.

Related apps

#costs · #llm · #pricing