# Pricing Update

> Sync OpenUsage's pricing supplement with Cursor's published model pricing. Pulls https://cursor.com/docs/models-and-pricing.md, diffs it against pricing_supplement.json, updates entries/aliases/multipliers, validates, and opens a PR. Use when Cursor adds or re-prices models, a spend tile shows a warning triangle for an unpriced model, or a periodic pricing check is due.

- Skill: `robinebers/pricing-update` (Agent Skill)
- Install (CLI): `npx skillmds@latest add robinebers/pricing-update`
- Raw SKILL.md: https://api.skillmd.com/api/skills/robinebers/pricing-update/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: robinebers (https://skillmd.com/u/robinebers)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/robinebers/pricing-update

---


# Pricing Update

`Sources/OpenUsage/Resources/pricing_supplement.json` prices the models no public catalog carries (Cursor-native models like `auto`, `composer-*`, `github_bugbot`), supplies fast-variant multipliers, and maps provider log/CSV slugs to canonical pricing keys. On merge to `main`, `.github/workflows/pricing-supplement.yml` validates it and publishes it to GitHub Pages; installed apps pick it up within about an hour — no release needed. Full background: `docs/pricing.md`.

Only the supplement needs manual care. Normal API models (new Claude/GPT/Gemini/Grok releases) are priced automatically by the daily LiteLLM and models.dev fetches — do not add them to the supplement unless they need an alias rule or the catalogs are wrong.

## Steps

### 1. Pull the source of truth into context

Fetch https://cursor.com/docs/models-and-pricing.md and read the whole thing. This is the canonical source for:

- Cursor-native model prices (`auto`, `composer-*`, Bugbot) — input, cache write, cache read, output, all USD per million tokens.
- Which models have a fast variant and what the fast pricing is.
- Long-context tiers (e.g. Sonnet 1M) that bill the whole request at the >200k rate.
- Model names/slugs as Cursor spells them (needed for alias rules).

### 2. Diff against the current supplement

Read `Sources/OpenUsage/Resources/pricing_supplement.json` and compare:

- **Price changes** on existing `pricing` entries.
- **New Cursor-native models** missing from `pricing`.
- **Removed/renamed models** — never delete an entry that old usage data may still reference; keep it so historical days keep their dollars. Only remove an entry if it was outright wrong.
- **`fast_multipliers`** — for API models whose fast variant is priced as a multiplier of the base rate. Only needed when the catalogs don't carry a `-fast` key themselves.
- **`alias_rules`** — a new model usually needs one, because Cursor CSV slugs and Codex/Claude log names rarely match catalog keys exactly (thinking suffixes, effort levels like `-low`/`-high`/`-xhigh`, dot vs dash versions). Follow the existing patterns: anchored regex, escaped dots, optional effort/thinking groups. `-fast` variants need their own rule ordered BEFORE the base rule (first match wins).

Where a model exists in LiteLLM or models.dev, prefer an alias to that canonical key over duplicating prices in the supplement.

### 3. Edit the supplement

- Update `updated_at` to today (YYYY-MM-DD).
- Keep the file's style: 2-space indent, rates as plain numbers, `$comment` explanations for non-obvious entries.
- Rates are USD per million tokens; cache read defaults matter — copy the exact numbers from the Cursor page, don't infer.

### 4. Validate

Run the same checks CI runs, plus the pricing tests:

```sh
python3 - << 'PY'
import json, re, sys
with open("Sources/OpenUsage/Resources/pricing_supplement.json") as f:
    s = json.load(f)
problems = []
for m, e in s["pricing"].items():
    for f_ in ("input_per_million", "output_per_million"):
        if not isinstance(e.get(f_), (int, float)):
            problems.append(f"pricing[{m}].{f_} missing or not a number")
for r in s["alias_rules"]:
    try: re.compile(r["pattern"])
    except re.error as err: problems.append(f"{r['pattern']!r}: {err}")
    if not r.get("canonical"): problems.append(f"{r['pattern']!r} has no canonical")
for m, x in (s.get("fast_multipliers") or {}).items():
    if not isinstance(x, (int, float)) or x <= 0:
        problems.append(f"fast_multipliers[{m}] must be positive")
sys.exit("FAILED:\n" + "\n".join(problems)) if problems else print("Supplement OK")
PY

swift test --filter "ModelPricing|PricingBundledResource"
```

If a new alias rule maps a slug that appears in real usage, add a resolution test case in `Tests/OpenUsageTests/ModelPricingTests.swift`.

### 5. Open a PR

Branch from `main`, commit (`fix(pricing): ...` or `feat(pricing): ...`), and open a PR following the repo's PR description structure (TL;DR / What was happening / What this changes). Cite the Cursor doc as the source and list each price or alias change explicitly so the owner can verify numbers at a glance. Never push pricing changes directly to `main`.

### 6. Verify publication after merge

Once merged, the `Publish pricing supplement` workflow runs. Confirm it landed:

```sh
gh run list --workflow=pricing-supplement.yml --limit 1
curl -s https://robinebers.github.io/openusage/pricing_supplement.json | python3 -c "import json,sys; print(json.load(sys.stdin)['updated_at'])"
```

The `updated_at` served must match the merged file. Publishing is two hops: the supplement workflow pushes the file to the `gh-pages` branch, then `.github/workflows/deploy-pages.yml` on `main` deploys that branch to the live site (Pages source is "GitHub Actions"). If the URL is stale after ~10 minutes, check `gh run list --workflow=deploy-pages.yml` and re-run **`gh workflow run deploy-pages.yml --ref main`** (not `--ref gh-pages`).

## Optional: refresh bundled snapshots

The bundled LiteLLM/models.dev snapshots (`pricing_*_snapshot.json`) are a separate concern — offline fallbacks refreshed with `./script/update_pricing_snapshots.sh`, typically before a release. Staleness is harmless; only regenerate them if asked or as part of release prep, in their own commit.

## Rules

- USD per million tokens everywhere; exact numbers from the Cursor page, never inferred.
- Prefer aliasing to LiteLLM/models.dev keys over duplicating prices in the supplement.
- Never delete pricing entries that historical usage may reference.
- `-fast` alias rules come before their base-model rules.
- Always bump `updated_at`; always go through a PR.

