@subvalue/cli 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/PRE_RELEASE.md +6 -6
  2. package/README.md +7 -5
  3. package/dist/PRICING.md +15 -16
  4. package/dist/packages/cli/src/index.js +109 -20
  5. package/dist/packages/cli/src/protocol.js +13 -0
  6. package/dist/packages/cli/src/runtime.js +44 -14
  7. package/dist/packages/cli/src/server.js +306 -62
  8. package/dist/packages/core/src/calendar.js +47 -0
  9. package/dist/packages/core/src/coverage.js +12 -0
  10. package/dist/packages/core/src/demo.js +61 -9
  11. package/dist/packages/core/src/metadata.js +52 -9
  12. package/dist/packages/core/src/pricing/current.js +346 -297
  13. package/dist/packages/core/src/pricing/index.js +373 -73
  14. package/dist/packages/core/src/providers/claude/index.js +93 -21
  15. package/dist/packages/core/src/providers/codex/index.js +213 -46
  16. package/dist/packages/core/src/scanner.js +226 -46
  17. package/dist/packages/core/src/security.js +127 -34
  18. package/dist/packages/core/src/storage.js +215 -47
  19. package/dist/packages/core/src/subscriptions.js +146 -21
  20. package/dist/packages/core/src/summary.js +409 -51
  21. package/dist/packages/core/src/types.js +71 -17
  22. package/dist/packages/core/src/usage-json.js +166 -47
  23. package/dist/packages/receipt/src/index.js +387 -80
  24. package/dist/packages/ui/src/brand.js +48 -3
  25. package/dist/public/app.css +2280 -56
  26. package/dist/public/apps/web/src/landing.js +200 -8
  27. package/dist/public/apps/web/src/main.js +1143 -63
  28. package/dist/public/index.html +24 -1
  29. package/dist/public/landing.css +3235 -70
  30. package/dist/public/landing.html +21 -1
  31. package/dist/public/logo/wordmark-monochrome.svg +1 -0
  32. package/dist/public/logo/wordmark.svg +1 -0
  33. package/dist/public/packages/core/src/calendar.js +47 -0
  34. package/dist/public/packages/core/src/coverage.js +12 -0
  35. package/dist/public/packages/core/src/subscriptions.js +146 -21
  36. package/dist/public/packages/receipt/src/index.js +387 -80
  37. package/dist/public/packages/ui/src/brand.js +48 -3
  38. package/dist/public/privacy.css +197 -6
  39. package/dist/public/privacy.html +1 -1
  40. package/package.json +1 -1
@@ -1 +1,21 @@
1
- <!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"><meta name="theme-color" content="#080b0d"><meta name="description" content="See what your Codex and Claude Code usage would have cost via API. Local, read-only, no account."><title>SubValue — Know what your AI subscription is worth</title><link rel="icon" href="./icon.svg"><link rel="preload" href="/fonts/inter-latin.woff2" as="font" type="font/woff2" crossorigin><link rel="preload" href="/fonts/plex-mono.woff2" as="font" type="font/woff2" crossorigin><link rel="stylesheet" href="./landing.css"></head><body><div id="landing"></div><script type="module" src="./landing.js"></script></body></html>
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
6
+ <meta name="theme-color" content="#080b0d" />
7
+ <meta
8
+ name="description"
9
+ content="See what your Codex and Claude Code usage would have cost via API. Local, read-only, no account."
10
+ />
11
+ <title>SubValue — Know what your AI subscription is worth</title>
12
+ <link rel="icon" href="./icon.svg" />
13
+ <link rel="preload" href="/fonts/inter-latin.woff2" as="font" type="font/woff2" crossorigin />
14
+ <link rel="preload" href="/fonts/plex-mono.woff2" as="font" type="font/woff2" crossorigin />
15
+ <link rel="stylesheet" href="./landing.css" />
16
+ </head>
17
+ <body>
18
+ <div id="landing"></div>
19
+ <script type="module" src="./landing.js"></script>
20
+ </body>
21
+ </html>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" class="brand-wordmark" viewBox="0 0 46 7" fill="currentColor" shape-rendering="crispEdges" aria-hidden="true"><g><rect x="1" y="0" width="1" height="1"/><rect x="2" y="0" width="1" height="1"/><rect x="3" y="0" width="1" height="1"/><rect x="4" y="0" width="1" height="1"/><rect x="0" y="1" width="1" height="1"/><rect x="0" y="2" width="1" height="1"/><rect x="1" y="3" width="1" height="1"/><rect x="2" y="3" width="1" height="1"/><rect x="3" y="3" width="1" height="1"/><rect x="4" y="4" width="1" height="1"/><rect x="4" y="5" width="1" height="1"/><rect x="0" y="6" width="1" height="1"/><rect x="1" y="6" width="1" height="1"/><rect x="2" y="6" width="1" height="1"/><rect x="3" y="6" width="1" height="1"/></g><g><rect x="6" y="0" width="1" height="1"/><rect x="10" y="0" width="1" height="1"/><rect x="6" y="1" width="1" height="1"/><rect x="10" y="1" width="1" height="1"/><rect x="6" y="2" width="1" height="1"/><rect x="10" y="2" width="1" height="1"/><rect x="6" y="3" width="1" height="1"/><rect x="10" y="3" width="1" height="1"/><rect x="6" y="4" width="1" height="1"/><rect x="10" y="4" width="1" height="1"/><rect x="6" y="5" width="1" height="1"/><rect x="10" y="5" width="1" height="1"/><rect x="7" y="6" width="1" height="1"/><rect x="8" y="6" width="1" height="1"/><rect x="9" y="6" width="1" height="1"/></g><g><rect x="12" y="0" width="1" height="1"/><rect x="13" y="0" width="1" height="1"/><rect x="14" y="0" width="1" height="1"/><rect x="15" y="0" width="1" height="1"/><rect x="12" y="1" width="1" height="1"/><rect x="16" y="1" width="1" height="1"/><rect x="12" y="2" width="1" height="1"/><rect x="16" y="2" width="1" height="1"/><rect x="12" y="3" width="1" height="1"/><rect x="13" y="3" width="1" height="1"/><rect x="14" y="3" width="1" height="1"/><rect x="15" y="3" width="1" height="1"/><rect x="12" y="4" width="1" height="1"/><rect x="16" y="4" width="1" height="1"/><rect x="12" y="5" width="1" height="1"/><rect x="16" y="5" width="1" height="1"/><rect x="12" y="6" width="1" height="1"/><rect x="13" y="6" width="1" height="1"/><rect x="14" y="6" width="1" height="1"/><rect x="15" y="6" width="1" height="1"/></g><g><rect x="18" y="0" width="1" height="1"/><rect x="22" y="0" width="1" height="1"/><rect x="18" y="1" width="1" height="1"/><rect x="22" y="1" width="1" height="1"/><rect x="18" y="2" width="1" height="1"/><rect x="22" y="2" width="1" height="1"/><rect x="18" y="3" width="1" height="1"/><rect x="22" y="3" width="1" height="1"/><rect x="18" y="4" width="1" height="1"/><rect x="22" y="4" width="1" height="1"/><rect x="19" y="5" width="1" height="1"/><rect x="21" y="5" width="1" height="1"/><rect x="20" y="6" width="1" height="1"/></g><g><rect x="25" y="0" width="1" height="1"/><rect x="26" y="0" width="1" height="1"/><rect x="27" y="0" width="1" height="1"/><rect x="24" y="1" width="1" height="1"/><rect x="28" y="1" width="1" height="1"/><rect x="24" y="2" width="1" height="1"/><rect x="28" y="2" width="1" height="1"/><rect x="24" y="3" width="1" height="1"/><rect x="25" y="3" width="1" height="1"/><rect x="26" y="3" width="1" height="1"/><rect x="27" y="3" width="1" height="1"/><rect x="28" y="3" width="1" height="1"/><rect x="24" y="4" width="1" height="1"/><rect x="28" y="4" width="1" height="1"/><rect x="24" y="5" width="1" height="1"/><rect x="28" y="5" width="1" height="1"/><rect x="24" y="6" width="1" height="1"/><rect x="28" y="6" width="1" height="1"/></g><g><rect x="30" y="0" width="1" height="1"/><rect x="30" y="1" width="1" height="1"/><rect x="30" y="2" width="1" height="1"/><rect x="30" y="3" width="1" height="1"/><rect x="30" y="4" width="1" height="1"/><rect x="30" y="5" width="1" height="1"/><rect x="30" y="6" width="1" height="1"/><rect x="31" y="6" width="1" height="1"/><rect x="32" y="6" width="1" height="1"/><rect x="33" y="6" width="1" height="1"/></g><g><rect x="35" y="0" width="1" height="1"/><rect x="39" y="0" width="1" height="1"/><rect x="35" y="1" width="1" height="1"/><rect x="39" y="1" width="1" height="1"/><rect x="35" y="2" width="1" height="1"/><rect x="39" y="2" width="1" height="1"/><rect x="35" y="3" width="1" height="1"/><rect x="39" y="3" width="1" height="1"/><rect x="35" y="4" width="1" height="1"/><rect x="39" y="4" width="1" height="1"/><rect x="35" y="5" width="1" height="1"/><rect x="39" y="5" width="1" height="1"/><rect x="36" y="6" width="1" height="1"/><rect x="37" y="6" width="1" height="1"/><rect x="38" y="6" width="1" height="1"/></g><g><rect x="41" y="0" width="1" height="1"/><rect x="42" y="0" width="1" height="1"/><rect x="43" y="0" width="1" height="1"/><rect x="44" y="0" width="1" height="1"/><rect x="45" y="0" width="1" height="1"/><rect x="41" y="1" width="1" height="1"/><rect x="41" y="2" width="1" height="1"/><rect x="41" y="3" width="1" height="1"/><rect x="42" y="3" width="1" height="1"/><rect x="43" y="3" width="1" height="1"/><rect x="44" y="3" width="1" height="1"/><rect x="41" y="4" width="1" height="1"/><rect x="41" y="5" width="1" height="1"/><rect x="41" y="6" width="1" height="1"/><rect x="42" y="6" width="1" height="1"/><rect x="43" y="6" width="1" height="1"/><rect x="44" y="6" width="1" height="1"/><rect x="45" y="6" width="1" height="1"/></g></svg>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" class="brand-wordmark" viewBox="0 0 46 7" fill="#eef2f4" shape-rendering="crispEdges" aria-hidden="true"><g><rect x="1" y="0" width="1" height="1"/><rect x="2" y="0" width="1" height="1"/><rect x="3" y="0" width="1" height="1"/><rect x="4" y="0" width="1" height="1"/><rect x="0" y="1" width="1" height="1"/><rect x="0" y="2" width="1" height="1"/><rect x="1" y="3" width="1" height="1"/><rect x="2" y="3" width="1" height="1"/><rect x="3" y="3" width="1" height="1"/><rect x="4" y="4" width="1" height="1"/><rect x="4" y="5" width="1" height="1"/><rect x="0" y="6" width="1" height="1"/><rect x="1" y="6" width="1" height="1"/><rect x="2" y="6" width="1" height="1"/><rect x="3" y="6" width="1" height="1"/></g><g><rect x="6" y="0" width="1" height="1"/><rect x="10" y="0" width="1" height="1"/><rect x="6" y="1" width="1" height="1"/><rect x="10" y="1" width="1" height="1"/><rect x="6" y="2" width="1" height="1"/><rect x="10" y="2" width="1" height="1"/><rect x="6" y="3" width="1" height="1"/><rect x="10" y="3" width="1" height="1"/><rect x="6" y="4" width="1" height="1"/><rect x="10" y="4" width="1" height="1"/><rect x="6" y="5" width="1" height="1"/><rect x="10" y="5" width="1" height="1"/><rect x="7" y="6" width="1" height="1"/><rect x="8" y="6" width="1" height="1"/><rect x="9" y="6" width="1" height="1"/></g><g><rect x="12" y="0" width="1" height="1"/><rect x="13" y="0" width="1" height="1"/><rect x="14" y="0" width="1" height="1"/><rect x="15" y="0" width="1" height="1"/><rect x="12" y="1" width="1" height="1"/><rect x="16" y="1" width="1" height="1"/><rect x="12" y="2" width="1" height="1"/><rect x="16" y="2" width="1" height="1"/><rect x="12" y="3" width="1" height="1"/><rect x="13" y="3" width="1" height="1"/><rect x="14" y="3" width="1" height="1"/><rect x="15" y="3" width="1" height="1"/><rect x="12" y="4" width="1" height="1"/><rect x="16" y="4" width="1" height="1"/><rect x="12" y="5" width="1" height="1"/><rect x="16" y="5" width="1" height="1"/><rect x="12" y="6" width="1" height="1"/><rect x="13" y="6" width="1" height="1"/><rect x="14" y="6" width="1" height="1"/><rect x="15" y="6" width="1" height="1"/></g><g fill="#37ec85"><rect x="18" y="0" width="1" height="1"/><rect x="22" y="0" width="1" height="1"/><rect x="18" y="1" width="1" height="1"/><rect x="22" y="1" width="1" height="1"/><rect x="18" y="2" width="1" height="1"/><rect x="22" y="2" width="1" height="1"/><rect x="18" y="3" width="1" height="1"/><rect x="22" y="3" width="1" height="1"/><rect x="18" y="4" width="1" height="1"/><rect x="22" y="4" width="1" height="1"/><rect x="19" y="5" width="1" height="1"/><rect x="21" y="5" width="1" height="1"/><rect x="20" y="6" width="1" height="1"/></g><g fill="#37ec85"><rect x="25" y="0" width="1" height="1"/><rect x="26" y="0" width="1" height="1"/><rect x="27" y="0" width="1" height="1"/><rect x="24" y="1" width="1" height="1"/><rect x="28" y="1" width="1" height="1"/><rect x="24" y="2" width="1" height="1"/><rect x="28" y="2" width="1" height="1"/><rect x="24" y="3" width="1" height="1"/><rect x="25" y="3" width="1" height="1"/><rect x="26" y="3" width="1" height="1"/><rect x="27" y="3" width="1" height="1"/><rect x="28" y="3" width="1" height="1"/><rect x="24" y="4" width="1" height="1"/><rect x="28" y="4" width="1" height="1"/><rect x="24" y="5" width="1" height="1"/><rect x="28" y="5" width="1" height="1"/><rect x="24" y="6" width="1" height="1"/><rect x="28" y="6" width="1" height="1"/></g><g fill="#37ec85"><rect x="30" y="0" width="1" height="1"/><rect x="30" y="1" width="1" height="1"/><rect x="30" y="2" width="1" height="1"/><rect x="30" y="3" width="1" height="1"/><rect x="30" y="4" width="1" height="1"/><rect x="30" y="5" width="1" height="1"/><rect x="30" y="6" width="1" height="1"/><rect x="31" y="6" width="1" height="1"/><rect x="32" y="6" width="1" height="1"/><rect x="33" y="6" width="1" height="1"/></g><g fill="#37ec85"><rect x="35" y="0" width="1" height="1"/><rect x="39" y="0" width="1" height="1"/><rect x="35" y="1" width="1" height="1"/><rect x="39" y="1" width="1" height="1"/><rect x="35" y="2" width="1" height="1"/><rect x="39" y="2" width="1" height="1"/><rect x="35" y="3" width="1" height="1"/><rect x="39" y="3" width="1" height="1"/><rect x="35" y="4" width="1" height="1"/><rect x="39" y="4" width="1" height="1"/><rect x="35" y="5" width="1" height="1"/><rect x="39" y="5" width="1" height="1"/><rect x="36" y="6" width="1" height="1"/><rect x="37" y="6" width="1" height="1"/><rect x="38" y="6" width="1" height="1"/></g><g fill="#37ec85"><rect x="41" y="0" width="1" height="1"/><rect x="42" y="0" width="1" height="1"/><rect x="43" y="0" width="1" height="1"/><rect x="44" y="0" width="1" height="1"/><rect x="45" y="0" width="1" height="1"/><rect x="41" y="1" width="1" height="1"/><rect x="41" y="2" width="1" height="1"/><rect x="41" y="3" width="1" height="1"/><rect x="42" y="3" width="1" height="1"/><rect x="43" y="3" width="1" height="1"/><rect x="44" y="3" width="1" height="1"/><rect x="41" y="4" width="1" height="1"/><rect x="41" y="5" width="1" height="1"/><rect x="41" y="6" width="1" height="1"/><rect x="42" y="6" width="1" height="1"/><rect x="43" y="6" width="1" height="1"/><rect x="44" y="6" width="1" height="1"/><rect x="45" y="6" width="1" height="1"/></g></svg>
@@ -0,0 +1,47 @@
1
+ /** Count whole local calendar months; rolling presets are never subscription comparisons. */
2
+ export function fullCalendarMonths(range
3
+
4
+
5
+
6
+
7
+ ) {
8
+ if (range.preset === '7d' || range.preset === '30d') return null;
9
+ // Browser timezone overrides must not change the server's calendar selection.
10
+ if (range.calendarMonths !== undefined)
11
+ return Number.isInteger(range.calendarMonths) &&
12
+ range.calendarMonths > 0 &&
13
+ range.calendarMonths <= 1200
14
+ ? range.calendarMonths
15
+ : null;
16
+ const start = new Date(range.from),
17
+ end = new Date(range.until);
18
+ const boundary = (date ) =>
19
+ Number.isFinite(+date) &&
20
+ date.getDate() === 1 &&
21
+ date.getHours() === 0 &&
22
+ date.getMinutes() === 0 &&
23
+ date.getSeconds() === 0 &&
24
+ date.getMilliseconds() === 0;
25
+ if (!boundary(start) || !boundary(end)) return null;
26
+ const months = (end.getFullYear() - start.getFullYear()) * 12 + end.getMonth() - start.getMonth();
27
+ return months > 0 && months <= 1200 ? months : null;
28
+ }
29
+ /** Civil-date movement uses UTC arithmetic so DST never drops or repeats a day. */
30
+ export function shiftCalendarDays(day , days ) {
31
+ if (!/^\d{4}-\d{2}-\d{2}$/.test(day) || !Number.isInteger(days) || Math.abs(days) > 36600)
32
+ return null;
33
+ const date = new Date(day + 'T12:00:00.000Z');
34
+ if (!Number.isFinite(+date) || date.toISOString().slice(0, 10) !== day) return null;
35
+ date.setUTCDate(date.getUTCDate() + days);
36
+ const result = date.toISOString().slice(0, 10);
37
+ return /^\d{4}-\d{2}-\d{2}$/.test(result) ? result : null;
38
+ }
39
+ export function shiftCalendarMonth(month , months ) {
40
+ if (!/^(?:19|20|21)\d{2}-(?:0[1-9]|1[0-2])$/.test(month) || !Number.isInteger(months))
41
+ return null;
42
+ const ordinal = Number(month.slice(0, 4)) * 12 + Number(month.slice(5)) - 1 + months,
43
+ year = Math.floor(ordinal / 12);
44
+ return year >= 1900 && year <= 2199
45
+ ? `${year}-${String((ordinal % 12) + 1).padStart(2, '0')}`
46
+ : null;
47
+ }
@@ -0,0 +1,12 @@
1
+ /** Reserve 100% for fully priced usage; missing coverage never becomes zero. */
2
+ export function formatPricingCoverage(coverage ) {
3
+ if (coverage === null || !Number.isFinite(coverage) || coverage < 0 || coverage > 1) {
4
+ return 'Unknown';
5
+ }
6
+ if (coverage === 1) return '100%';
7
+ if (coverage === 0) return '0%';
8
+ const percent = Math.round(coverage * 100);
9
+ if (percent === 100) return '<100%';
10
+ if (percent === 0) return '<1%';
11
+ return `${percent}%`;
12
+ }
@@ -1,22 +1,147 @@
1
-
2
-
3
- export const subscriptionVerified='2026-10-05';
4
- const openai='https://learn.chatgpt.com/docs/pricing',claude='https://claude.com/pricing';
5
- export const subscriptionPlans =[
6
- {id:'chatgpt-free',provider:'codex',name:'ChatGPT Free',monthly:0,interval:'monthly',source:openai},
7
- {id:'chatgpt-go',provider:'codex',name:'ChatGPT Go',monthly:8,interval:'monthly',source:openai},
8
- {id:'chatgpt-plus',provider:'codex',name:'ChatGPT Plus',monthly:20,interval:'monthly',source:openai},
9
- ...[100,200,500].map(monthly=>({id:`chatgpt-pro-${monthly}`,provider:'codex' ,name:'ChatGPT Pro',monthly,interval:'monthly' ,source:openai})),
10
- {id:'chatgpt-business-monthly',provider:'codex',name:'ChatGPT Business',monthly:25,interval:'monthly',perSeat:true,source:openai},
11
- {id:'chatgpt-business-annual',provider:'codex',name:'ChatGPT Business',monthly:20,annual:240,interval:'annual',perSeat:true,source:openai},
12
- {id:'claude-pro-monthly',provider:'claude',name:'Claude Pro',monthly:20,interval:'monthly',source:claude},
13
- {id:'claude-pro-annual',provider:'claude',name:'Claude Pro',monthly:200/12,annual:200,interval:'annual',source:claude},
14
- {id:'claude-max-5x',provider:'claude',name:'Claude Max 5x',monthly:100,interval:'monthly',source:'https://support.claude.com/en/articles/11049741-what-is-the-max-plan'},
15
- {id:'claude-max-20x',provider:'claude',name:'Claude Max 20x',monthly:200,interval:'monthly',source:'https://support.claude.com/en/articles/11049741-what-is-the-max-plan'},
16
- {id:'claude-team-standard-monthly',provider:'claude',name:'Claude Team · Standard seat',monthly:25,interval:'monthly',perSeat:true,source:claude},
17
- {id:'claude-team-standard-annual',provider:'claude',name:'Claude Team · Standard seat',monthly:20,annual:240,interval:'annual',perSeat:true,source:claude},
18
- {id:'claude-team-premium-monthly',provider:'claude',name:'Claude Team · Premium seat',monthly:125,interval:'monthly',perSeat:true,source:claude},
19
- {id:'claude-team-premium-annual',provider:'claude',name:'Claude Team · Premium seat',monthly:100,annual:1200,interval:'annual',perSeat:true,source:claude}
1
+
2
+
3
+
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+
12
+ export const subscriptionVerified = '2026-10-05';
13
+ const openai = 'https://learn.chatgpt.com/docs/pricing',
14
+ claude = 'https://claude.com/pricing';
15
+ export const subscriptionPlans = [
16
+ {
17
+ id: 'chatgpt-free',
18
+ provider: 'codex',
19
+ name: 'ChatGPT Free',
20
+ monthly: 0,
21
+ interval: 'monthly',
22
+ source: openai,
23
+ },
24
+ {
25
+ id: 'chatgpt-go',
26
+ provider: 'codex',
27
+ name: 'ChatGPT Go',
28
+ monthly: 8,
29
+ interval: 'monthly',
30
+ source: openai,
31
+ },
32
+ {
33
+ id: 'chatgpt-plus',
34
+ provider: 'codex',
35
+ name: 'ChatGPT Plus',
36
+ monthly: 20,
37
+ interval: 'monthly',
38
+ source: openai,
39
+ },
40
+ ...[100, 200, 500].map((monthly) => ({
41
+ id: `chatgpt-pro-${monthly}`,
42
+ provider: 'codex' ,
43
+ name: 'ChatGPT Pro',
44
+ monthly,
45
+ interval: 'monthly' ,
46
+ source: openai,
47
+ })),
48
+ {
49
+ id: 'chatgpt-business-monthly',
50
+ provider: 'codex',
51
+ name: 'ChatGPT Business',
52
+ monthly: 25,
53
+ interval: 'monthly',
54
+ perSeat: true,
55
+ source: openai,
56
+ },
57
+ {
58
+ id: 'chatgpt-business-annual',
59
+ provider: 'codex',
60
+ name: 'ChatGPT Business',
61
+ monthly: 20,
62
+ annual: 240,
63
+ interval: 'annual',
64
+ perSeat: true,
65
+ source: openai,
66
+ },
67
+ {
68
+ id: 'claude-pro-monthly',
69
+ provider: 'claude',
70
+ name: 'Claude Pro',
71
+ monthly: 20,
72
+ interval: 'monthly',
73
+ source: claude,
74
+ },
75
+ {
76
+ id: 'claude-pro-annual',
77
+ provider: 'claude',
78
+ name: 'Claude Pro',
79
+ monthly: 200 / 12,
80
+ annual: 200,
81
+ interval: 'annual',
82
+ source: claude,
83
+ },
84
+ {
85
+ id: 'claude-max-5x',
86
+ provider: 'claude',
87
+ name: 'Claude Max 5x',
88
+ monthly: 100,
89
+ interval: 'monthly',
90
+ source: 'https://support.claude.com/en/articles/11049741-what-is-the-max-plan',
91
+ },
92
+ {
93
+ id: 'claude-max-20x',
94
+ provider: 'claude',
95
+ name: 'Claude Max 20x',
96
+ monthly: 200,
97
+ interval: 'monthly',
98
+ source: 'https://support.claude.com/en/articles/11049741-what-is-the-max-plan',
99
+ },
100
+ {
101
+ id: 'claude-team-standard-monthly',
102
+ provider: 'claude',
103
+ name: 'Claude Team · Standard seat',
104
+ monthly: 25,
105
+ interval: 'monthly',
106
+ perSeat: true,
107
+ source: claude,
108
+ },
109
+ {
110
+ id: 'claude-team-standard-annual',
111
+ provider: 'claude',
112
+ name: 'Claude Team · Standard seat',
113
+ monthly: 20,
114
+ annual: 240,
115
+ interval: 'annual',
116
+ perSeat: true,
117
+ source: claude,
118
+ },
119
+ {
120
+ id: 'claude-team-premium-monthly',
121
+ provider: 'claude',
122
+ name: 'Claude Team · Premium seat',
123
+ monthly: 125,
124
+ interval: 'monthly',
125
+ perSeat: true,
126
+ source: claude,
127
+ },
128
+ {
129
+ id: 'claude-team-premium-annual',
130
+ provider: 'claude',
131
+ name: 'Claude Team · Premium seat',
132
+ monthly: 100,
133
+ annual: 1200,
134
+ interval: 'annual',
135
+ perSeat: true,
136
+ source: claude,
137
+ },
20
138
  ];
21
- export function subscriptionPlan(provider ,id ) {return subscriptionPlans.find(p=>p.provider===provider&&p.id===id);}
22
- export function subscriptionPlanLabel(p ) {return `${p.name} · $${p.interval==='annual'?p.annual+'/year':p.monthly+'/month'}${p.perSeat?' / seat':''}`;}
139
+ export function subscriptionPlan(
140
+ provider ,
141
+ id ,
142
+ ) {
143
+ return subscriptionPlans.find((p) => p.provider === provider && p.id === id);
144
+ }
145
+ export function subscriptionPlanLabel(p ) {
146
+ return `${p.name} · $${p.interval === 'annual' ? p.annual + '/year' : p.monthly + '/month'}${p.perSeat ? ' / seat' : ''}`;
147
+ }