Use when setting or resetting what a product or service charges and how it is packaged — list price, margin floor, tiers, the value metric, the pricing model (flat, seat, usage, outcome or hybrid), discount rules and purchasing-power localisation. NOT issuing the actual bill (that is `invoicing`), NOT implementing prices in a billing system (that is `stripe`).
npx skills add https://github.com/ericrisco/rsc-harness --skill pricing
You decide two things here: the number (the list price) and the shape (packaging, tiers, model, and the floor underneath each price). You produce a *price card* — a table where every tier has a price, a cost, a value metric, and a margin that someone else can recompute and disagree with. That artifact is the deliverable; opinions without a recomputable margin are not.
You do not charge the money (that is ../invoicing/SKILL.md), build the billing objects (that is ../stripe/SKILL.md), record revenue in the books, or validate the number against acquisition cost (that is ../unit-economics/SKILL.md). Stay on the decision: what should this cost, and how is it boxed.
The order matters because each step constrains the next. Skip a step and you set a price you cannot defend.
If you cannot answer step 1, stop and get the cost. Everything downstream is guesswork without it.
Markup and margin use different denominators. Conflating them is the single most common pricing error.
markup % = (price - cost) / cost <- denominator is COST
margin % = (price - cost) / price <- denominator is PRICE
Reference points to sanity-check any card (verify.sh uses these):
| Markup | Margin |
|--------|--------|
| 30% | 23% |
| 43% | 30% |
| 100% | 50% |
A 50% markup is only a 33% margin. A 50% margin needs a 100% markup. They diverge fast.
Bad: cost $70, want "30% margin", apply 30% markup -> price $91
actual margin = (91-70)/91 = 23%. You undershot by 7 points.
Good: cost $70, want 30% margin -> price = cost / (1 - 0.30)
= 70 / 0.70 = $100. Margin = (100-70)/100 = 30%. Correct.
The price-from-margin formula: price = cost / (1 - target_margin). Memorize it; never apply a markup percentage when someone said "margin".
Decide the model *before* drawing tiers — it determines what the tiers vary along.
| Model | Use when | Value metric | Watch out |
|-------|----------|--------------|-----------|
| Flat | One persona, predictable use, simple sell | none (one price) | Leaves money on the table at the high end |
| Per-seat | Value scales with users; collaboration tools | seats | Eroding — buyers cap seats and share logins; revenue stalls |
| Usage / consumption | Value scales with volume; infra, API, AI | units consumed | Estimate anxiety + overage shock; needs a meter |
| Outcome-based | You can attribute a result (resolutions, leads) | outcomes delivered | Attribution disputes; needs a credible counter |
| Hybrid | Platform value + variable use (most AI products) | base + usage/outcome | Two dials to explain; keep the base legible |
The market is moving off pure per-seat. ~85% of SaaS used some usage-based pricing by 2024 (up from ~30% in 2019), and Gartner expects ~40% of enterprise SaaS spend on usage/agent/outcome models by 2030. If you are defaulting to per-seat for an AI product, justify it.
AI-COGS caveat — the margin assumption changes. Classic SaaS runs 80-90% gross margin. AI products run 50-60% because every query has real compute cost. A "we'll just take 80% margin" plan is wrong for AI: the cost floor (step 1) becomes load-bearing, and you reprice when compute cost moves. See references/pricing-models.md for the outcome credit + overage formula (platform fee ≈ 2× delivery cost, e.g. $12K/yr incl. 100 resolutions then $5K per additional 100) and seat-compression math.
Good/Better/Best is the dominant SaaS shape; the average SaaS company offers ~3.5 tiers. Three is the safe default — enough to anchor, not enough to paralyze.
Good Better Best
$0/$X $Y $Z (anchor)
3 seats 25 seats unlimited seats
1K calls 50K calls 500K calls + overage
email + Slack + SSO, SLA, CSM
A discount needs a floor, not a vibe. Reps will give away the business if the only rule is "use judgment".
Tier "Better": list $1,000, cost floor $400
max discount = (1000 - 400) / 1000 = 60%
A rep offering 35% off ($650) is fine; 65% off ($350) breaks the floor -> sign-off.
Only if you sell across markets. Localizing beats raw FX conversion — PPP-adjusted regional pricing lifts revenue ~30% over straight currency math.
The per-region rounding conventions, PPP sourcing, and arbitrage guards live in references/localization.md — most operators skip this branch, so it is offloaded.
You usually do not need a survey. Two paths:
| Anti-pattern | Why it is wrong | Do instead |
|--------------|-----------------|------------|
| Applying markup % when someone said "margin" | 30% markup is only a 23% margin — you undershoot every time | price = cost / (1 - margin); recompute, never assume |
| Cost-plus only, ignoring willingness-to-pay | Leaves money on the table or prices below what buyers gladly pay | Floor from cost, ceiling from WTP, set price between |
| Five+ tiers to "cover everyone" | Choice paralysis; nobody self-selects | ~3 tiers, distinct on features + limits + price |
| Per-seat by default for an AI product | Seat revenue erodes and AI COGS breaks the 80% assumption | Pick the value metric first; consider usage/outcome/hybrid |
| Discount "by judgment" with no floor | Reps give away the business deal by deal | Floor = COGS+must-cover; max discount = (list−floor)/list; below = sign-off |
| Converting price by spot FX across markets | Mispriced vs local purchasing power; ~30% revenue left behind | PPP factor × home price; round per local convention |
| Assuming 80-90% margin for AI compute | Real per-query COGS makes it 50-60%; you over-promise margin | Use the cost floor as load-bearing; reprice when compute moves |
Emit a price-card.csv (or .md table / .yaml) — one row per tier:
tier,price,cost,value_metric,margin
Good,29,11,seats,0.62
Better,99,38,seats,0.62
Best,299,110,seats,0.63
Rules the card must satisfy:
price, cost, value_metric, and a stated margin.(price − cost) / price within 0.5pt.price <= cost and no price < floor.margin is a margin, not a markup (the classic conflation).scripts/verify.sh <price-card> recomputes every margin, flags any tier below its floor, and warns when a stated "margin" is actually a markup. Run it before you ship the card. It is read-only and exits 0 on an empty or clean card.
../invoicing/SKILL.md../stripe/SKILL.md../unit-economics/SKILL.md../proposals/SKILL.md../forecasting/SKILL.md../sales-pipeline/SKILL.mdTake ericrisco/pricing from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.