ROI methodology
Pulse makes claims like 'your $200 Claude plan returned $4,000 in API value.' Those numbers are computed locally from your real token usage — not estimated, not aggregated. Here is exactly how, with sources, formulas, and limitations.
Last updated · 2026-05-15
frankfurter.dev, cached 24h. Everything is computed on your machine from the local ~/.claude/projects/*.jsonl log files — no upload, no estimation.1. Plan ROI
The headline number on the dashboard.
Plan ROI = Equivalent API Value (this billing period)
─────────────────────────────────────────
Subscription Cost (this billing period)A Plan ROI of 10.5× means: if you had paid per-token at Anthropic's published API rates for everything you used this month, the bill would have been 10.5× what your flat-rate Claude Max subscription cost you. Higher is better. Anything > 1× means the plan is paying for itself.
2. Equivalent API Value
For each Claude Code request logged in ~/.claude/projects/*.jsonl, pulse extracts five token counts and multiplies each by the model's published rate:
Equivalent API Value =
input_tokens × input_price / 1,000,000
+ output_tokens × output_price / 1,000,000
+ cache_creation_5m_tokens × cw_5m_price / 1,000,000
+ cache_creation_1h_tokens × cw_1h_price / 1,000,000
+ cache_read_tokens × cache_read_price / 1,000,000Token counts come straight from the request payload Anthropic writes to disk. No estimation.
3. Token pricing source
Prices are sourced from Anthropic's official pricing page and bundled with the app in sync_tokens.py as a static table — exact, not estimated.
USD per 1,000,000 tokens, current as of 2026-05:
| Model | Input | Output | Cache write (5m) | Cache write (1h) | Cache read |
|---|---|---|---|---|---|
| Claude Opus 4 / 4.6 / 4.7 | $15.00 | $75.00 | $18.75 | $30.00 | $1.50 |
| Claude Sonnet 4 / 4.5 / 4.6 | $3.00 | $15.00 | $3.75 | $6.00 | $0.30 |
| Claude Haiku 4 / 4.5 | $0.80 | $4.00 | $1.00 | $1.60 | $0.08 |
Pricing updates ship in pulse releases. If Anthropic changes prices and pulse hasn't shipped an update, the dashboard surfaces a banner suggesting you check for an update. You can also edit the PRICING table in sync_tokens.py directly — it's a plain Python dict.
Other providers (OpenAI, Cursor, Gemini, Copilot): tracked once their parsers ship in v1.1 (Q3 2026). Today pulse only computes equivalent API value for Claude Code usage. Other subscriptions are tracked as cost line-items without per-token ROI.
4. Cache TTL — why 5m and 1h are split
Anthropic's prompt caching offers two TTLs. The 5-minute cache is cheaper to write (1.25× input price) but expires quickly. The 1-hour cache is more expensive to write (2.0× input price) but persists. Both reads are billed at 0.10× input price.
Most cost trackers lump cache_creation_tokens together and use one rate — which is off by up to 60% on cache-heavy workloads. Pulse reads the TTL-split fields (cache_creation_5m_tokens + cache_creation_1h_tokens) directly from the log and prices them separately. If only the bulk field is present (older log format), pulse falls back to the cheaper 5-minute rate to avoid over-counting savings.
5. Subscription cost — exact, estimated, or per-tier?
Cost values entered by you in the Subscriptions tab are exact. Renewal dates, currency, and amount are taken straight from your input. If you select a plan from the built-in catalog (e.g. "Claude Max — $200/mo"), the price comes from a static table updated in pulse releases.
FX conversion: if your subscription is in THB and your display currency is USD, pulse uses the latest cached ECB rate from frankfurter.dev at the time of display. The rate is re-fetched daily (24h cache). Historical conversions on already-recorded charges use the rate on file at the time of recording, not today's rate.
6. Cost per active hour
Cost per active hour =
Subscription Cost (this billing period)
─────────────────────────────────────────
Foreground hours where this subscription's
linked app was the active window"Foreground hours" comes from pulse's local activity tracker — measured in 1-second polling intervals when the app is in the active window and the user is not idle. Idle is detected via OS-level idle-time APIs (Win32 GetLastInputInfo, macOS IOHIDIdleTime, Linux XScreenSaverQueryInfo) with a 5-minute threshold.
Hours where the subscription's linked app was running in the background are not counted — pulse only counts time you were actively in the window. This is intentionally conservative: cost-per-hour is meant to reflect real engagement, not passive presence.
Activity tracking is opt-in and can be paused, app-allowlisted, or fully disabled at any time. See Privacy.
7. Cancellation savings
Cancellation savings =
Sum across all subscriptions you've marked Cancelled, of:
monthly_cost × months_since_cancellation_datePulse counts savings from the cancellation date forward, not retroactively. Annual subscriptions are normalized to a monthly rate (annual_cost ÷ 12). This is a cumulative counter — once you cancel something, the savings climb every month until you re-activate it.
8. What's exact vs estimated
| Value | Source | Exact? |
|---|---|---|
| Token counts (Claude Code) | ~/.claude/projects/*.jsonl request payloads | Exact |
| Per-token pricing | Anthropic published rates (static table) | Exact |
| Subscription cost (user-entered) | Your input | Exact |
| Subscription cost (catalog) | Built-in plan table | Snapshot |
| FX conversions | ECB rates via frankfurter.dev, 24h cache | Snapshot |
| Foreground hours | 1s polling + idle detection | ±1% |
| Cache TTL split (older logs) | Falls back to 5m rate if 1h field missing | Conservative |
| Cancellation savings | monthly_cost × months_since_cancel | Projection |
9. Limitations and honest caveats
- Plan ROI assumes counterfactual API usage. If you used Claude Max heavily this month, the equivalent API bill would be high. But you might have used the API moreconservatively if you were paying per-token. ROI tells you what the same token volume would cost à la carte — not what you would have chosen to spend.
- ROI only covers Claude Code today. Other AI tools (ChatGPT, Cursor, Gemini, Copilot) appear on the dashboard as subscription line-items but don't yet contribute to equivalent API value. Multi-provider live tracking ships with Pro in Q3 2026.
- Cache TTL fallback can under-count savings. If your Claude logs predate TTL-split fields, pulse uses the cheaper 5-minute rate for all cache writes. Your real cache value is likely higher than what pulse reports.
- FX rates are end-of-day ECB, not real-time. Don't use pulse for currency arbitrage. Historical charges use the rate cached on the day they were recorded.
- Cost-per-hour ignores background usage. If a tool runs in the background and you find that valuable (e.g. a CLI daemon), pulse's foreground-only counter under-states its real utility.
- Cancellation savings is a projection. It assumes you would have kept paying. If you would have switched to a free tier instead, real savings are lower.
10. Verify it yourself
All ROI math is in plain Python in sync_tokens.py (the calc_cost() function and the PRICING table). The dashboard renders in dashboard.py. Pulse is MIT-licensed; fork it, audit it, or rip the formulas out for your own tool.
If you find a methodology bug, please open an issue at github.com/walight999/pulse/issues. ROI accuracy is the single most important thing this product gets right — corrections are welcome.