@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.
- package/PRE_RELEASE.md +6 -6
- package/README.md +7 -5
- package/dist/PRICING.md +15 -16
- package/dist/packages/cli/src/index.js +109 -20
- package/dist/packages/cli/src/protocol.js +13 -0
- package/dist/packages/cli/src/runtime.js +44 -14
- package/dist/packages/cli/src/server.js +306 -62
- package/dist/packages/core/src/calendar.js +47 -0
- package/dist/packages/core/src/coverage.js +12 -0
- package/dist/packages/core/src/demo.js +61 -9
- package/dist/packages/core/src/metadata.js +52 -9
- package/dist/packages/core/src/pricing/current.js +346 -297
- package/dist/packages/core/src/pricing/index.js +373 -73
- package/dist/packages/core/src/providers/claude/index.js +93 -21
- package/dist/packages/core/src/providers/codex/index.js +213 -46
- package/dist/packages/core/src/scanner.js +226 -46
- package/dist/packages/core/src/security.js +127 -34
- package/dist/packages/core/src/storage.js +215 -47
- package/dist/packages/core/src/subscriptions.js +146 -21
- package/dist/packages/core/src/summary.js +409 -51
- package/dist/packages/core/src/types.js +71 -17
- package/dist/packages/core/src/usage-json.js +166 -47
- package/dist/packages/receipt/src/index.js +387 -80
- package/dist/packages/ui/src/brand.js +48 -3
- package/dist/public/app.css +2280 -56
- package/dist/public/apps/web/src/landing.js +200 -8
- package/dist/public/apps/web/src/main.js +1143 -63
- package/dist/public/index.html +24 -1
- package/dist/public/landing.css +3235 -70
- package/dist/public/landing.html +21 -1
- package/dist/public/logo/wordmark-monochrome.svg +1 -0
- package/dist/public/logo/wordmark.svg +1 -0
- package/dist/public/packages/core/src/calendar.js +47 -0
- package/dist/public/packages/core/src/coverage.js +12 -0
- package/dist/public/packages/core/src/subscriptions.js +146 -21
- package/dist/public/packages/receipt/src/index.js +387 -80
- package/dist/public/packages/ui/src/brand.js +48 -3
- package/dist/public/privacy.css +197 -6
- package/dist/public/privacy.html +1 -1
- package/package.json +1 -1
|
@@ -1,10 +1,202 @@
|
|
|
1
1
|
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
import {
|
|
3
|
+
product,
|
|
4
|
+
productMark,
|
|
5
|
+
productNameMarkup,
|
|
6
|
+
productTitleMarkup,
|
|
7
|
+
} from '../../../packages/ui/src/brand.js';
|
|
8
|
+
document.title = product.name + ' — Know what your AI subscription is worth';
|
|
9
|
+
import {
|
|
10
|
+
drawReceipt,
|
|
11
|
+
receiptModel,
|
|
12
|
+
receiptFonts,
|
|
13
|
+
|
|
14
|
+
} from '../../../packages/receipt/src/index.js';
|
|
15
|
+
const example = {
|
|
16
|
+
range: {
|
|
17
|
+
from: new Date(2026, 9, 1).toISOString(),
|
|
18
|
+
until: new Date(2026, 10, 1).toISOString(),
|
|
19
|
+
label: 'October 2026',
|
|
20
|
+
calendarFrom: '2026-10-01',
|
|
21
|
+
calendarTo: '2026-10-31',
|
|
22
|
+
calendarMonths: 1,
|
|
23
|
+
preset: 'month',
|
|
24
|
+
},
|
|
25
|
+
providers: [
|
|
26
|
+
{
|
|
27
|
+
provider: 'codex',
|
|
28
|
+
visible: true,
|
|
29
|
+
records: 1,
|
|
30
|
+
tokens: 20530000,
|
|
31
|
+
tokensPartial: false,
|
|
32
|
+
apiEquivalent: 201.36,
|
|
33
|
+
knownSubtotal: 201.36,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
provider: 'claude',
|
|
37
|
+
visible: true,
|
|
38
|
+
records: 1,
|
|
39
|
+
tokens: 7840000,
|
|
40
|
+
tokensPartial: false,
|
|
41
|
+
apiEquivalent: 86.06,
|
|
42
|
+
knownSubtotal: 86.06,
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
total: {
|
|
46
|
+
apiEquivalent: 287.42,
|
|
47
|
+
knownSubtotal: 287.42,
|
|
48
|
+
priceCoverage: 1,
|
|
49
|
+
comparison: {
|
|
50
|
+
subscription: 220,
|
|
51
|
+
value: 67.42,
|
|
52
|
+
roi: 287.42 / 220,
|
|
53
|
+
breakEven: '2026-10-24',
|
|
54
|
+
outcome: 'positive',
|
|
55
|
+
reason: null,
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
historyPartial: false,
|
|
59
|
+
confidence: 'HIGH',
|
|
60
|
+
demo: true,
|
|
61
|
+
};
|
|
62
|
+
document.querySelector('#landing') .innerHTML = /* HTML */ `<header class="landing-nav">
|
|
63
|
+
<a class="brand" href="#"><span class="brand-mark">${productMark}</span>${productNameMarkup}</a
|
|
64
|
+
><a class="github-link" href="#release">Install <span>↓</span></a>
|
|
65
|
+
</header>
|
|
66
|
+
<main>
|
|
67
|
+
<section class="hero">
|
|
68
|
+
<h1>${productTitleMarkup}</h1>
|
|
69
|
+
<h2>
|
|
70
|
+
Know what your AI<br class="desktop-break" />
|
|
71
|
+
<span class="hero-emphasis">subscription is worth.</span>
|
|
72
|
+
</h2>
|
|
73
|
+
<p>See what your Codex and Claude Code usage would have cost via API.</p>
|
|
74
|
+
<div class="install-command">
|
|
75
|
+
<code><span>$</span> npx @subvalue/cli</code
|
|
76
|
+
><button class="copy-command" aria-label="Copy install command">
|
|
77
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
78
|
+
<rect x="8" y="8" width="12" height="12" rx="2" />
|
|
79
|
+
<path d="M16 8V4H4v12h4" />
|
|
80
|
+
</svg>
|
|
81
|
+
</button>
|
|
82
|
+
</div>
|
|
83
|
+
<div class="trust-row">
|
|
84
|
+
<span>✓ Local</span><span>✓ Read-only</span><span>✓ No telemetry</span>
|
|
85
|
+
</div>
|
|
86
|
+
<span class="release-note">Node.js 24.13+ · Windows · macOS · Linux</span>
|
|
87
|
+
</section>
|
|
88
|
+
<section class="product-preview" aria-label="Illustrative dashboard preview">
|
|
89
|
+
<div class="preview-label"><span>PRODUCT PREVIEW</span><span>EXAMPLE DATA</span></div>
|
|
90
|
+
<div class="preview-window">
|
|
91
|
+
<div class="preview-topbar">
|
|
92
|
+
<span class="brand"
|
|
93
|
+
><span class="brand-mark">${productMark}</span>${productNameMarkup}</span
|
|
94
|
+
><span class="preview-tab">Overview</span><span>Receipt</span><span>Settings</span
|
|
95
|
+
><span class="preview-date">October 2026</span>
|
|
96
|
+
</div>
|
|
97
|
+
<div class="preview-body">
|
|
98
|
+
<div class="preview-main">
|
|
99
|
+
<div class="preview-metrics">
|
|
100
|
+
<div><span>API equivalent</span><strong>$287.42</strong></div>
|
|
101
|
+
<div><span>Subscription</span><strong>$220.00</strong></div>
|
|
102
|
+
<div><span>Value</span><strong class="green-text">+$67.42</strong></div>
|
|
103
|
+
<div><span>Value multiple</span><strong>1.31×</strong></div>
|
|
104
|
+
</div>
|
|
105
|
+
<div class="preview-providers">
|
|
106
|
+
<div class="preview-provider">
|
|
107
|
+
<span class="preview-provider-mark"
|
|
108
|
+
><img
|
|
109
|
+
class="codex-product-mark"
|
|
110
|
+
src="/brands/codex-outline.svg"
|
|
111
|
+
alt=""
|
|
112
|
+
aria-hidden="true"
|
|
113
|
+
/></span>
|
|
114
|
+
<div>
|
|
115
|
+
<strong class="codex-product-name">Codex</strong><span>API equivalent</span>
|
|
116
|
+
</div>
|
|
117
|
+
<b>$201.36</b><span class="preview-active">Usage found</span>
|
|
118
|
+
</div>
|
|
119
|
+
<div class="preview-provider">
|
|
120
|
+
<span class="preview-provider-mark"
|
|
121
|
+
><img src="/brands/claude-code-clawd.svg" alt="" aria-hidden="true"
|
|
122
|
+
/></span>
|
|
123
|
+
<div><strong>Claude Code</strong><span>API equivalent</span></div>
|
|
124
|
+
<b>$86.06</b><span class="preview-active">Usage found</span>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
<div class="preview-chart">
|
|
128
|
+
<div>
|
|
129
|
+
<strong>Daily API equivalent</strong
|
|
130
|
+
><span class="preview-legend"
|
|
131
|
+
><span>● Codex</span><span class="claude">● Claude Code</span></span
|
|
132
|
+
>
|
|
133
|
+
</div>
|
|
134
|
+
<div class="preview-bars" aria-hidden="true">
|
|
135
|
+
${[15, 24, 19, 34, 29, 38, 21, 25, 39, 26, 32, 28, 43, 25, 31, 38, 49, 44, 52, 36, 41, 29, 45, 40, 53, 45, 66, 51, 57, 49].map((h) => /* HTML */ `<i style="height:${h}%"><span class="preview-codex-bar"></span><span class="preview-claude-bar"></span></i>`).join('')}
|
|
136
|
+
</div>
|
|
137
|
+
<div class="preview-chart-axis">
|
|
138
|
+
<span>Oct 1</span><span>Oct 15</span><span>Oct 31</span>
|
|
139
|
+
</div>
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
<div class="preview-receipt">
|
|
143
|
+
<canvas
|
|
144
|
+
id="example-receipt"
|
|
145
|
+
role="img"
|
|
146
|
+
aria-label="Illustrative ${product.name} receipt: API equivalent 287 dollars 42 cents, subscription 220 dollars, value 67 dollars 42 cents. Codex and Claude Code example data."
|
|
147
|
+
></canvas
|
|
148
|
+
><span>Export PNG ↓</span>
|
|
149
|
+
</div>
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
</section>
|
|
153
|
+
<section class="landing-privacy">
|
|
154
|
+
<h2>Your data stays<br />on your machine.</h2>
|
|
155
|
+
<div>
|
|
156
|
+
<span>No account</span><span>No API keys</span><span>No uploads</span
|
|
157
|
+
><span>No telemetry</span>
|
|
158
|
+
</div>
|
|
159
|
+
<details class="privacy-details">
|
|
160
|
+
<summary>Details</summary>
|
|
161
|
+
<p>
|
|
162
|
+
Usage is processed locally. Vercel hosts this page and can log website connections.
|
|
163
|
+
<a href="/privacy.html" target="_blank" rel="noreferrer">Data access ↗</a>
|
|
164
|
+
</p>
|
|
165
|
+
</details>
|
|
166
|
+
</section>
|
|
167
|
+
<section class="install-section" id="release">
|
|
168
|
+
<div class="install-command">
|
|
169
|
+
<code><span>$</span> npx @subvalue/cli</code
|
|
170
|
+
><button class="copy-command" aria-label="Copy install command">
|
|
171
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
|
|
172
|
+
<rect x="8" y="8" width="12" height="12" rx="2" />
|
|
173
|
+
<path d="M16 8V4H4v12h4" />
|
|
174
|
+
</svg>
|
|
175
|
+
</button>
|
|
176
|
+
</div>
|
|
177
|
+
<span class="release-note">Node.js 24.13+ · Windows · macOS · Linux</span>
|
|
178
|
+
</section>
|
|
179
|
+
</main>
|
|
180
|
+
<div class="copy-status" role="status" aria-live="polite"></div>`;
|
|
8
181
|
await receiptFonts();
|
|
9
|
-
drawReceipt(
|
|
10
|
-
document.
|
|
182
|
+
drawReceipt(
|
|
183
|
+
document.querySelector ('#example-receipt') ,
|
|
184
|
+
receiptModel(example, new Date(2026, 10, 1, 9, 30)),
|
|
185
|
+
);
|
|
186
|
+
document.querySelectorAll ('.copy-command').forEach((b) =>
|
|
187
|
+
b.addEventListener('click', async () => {
|
|
188
|
+
try {
|
|
189
|
+
await navigator.clipboard.writeText('npx @subvalue/cli');
|
|
190
|
+
const status = document.querySelector('.copy-status') ;
|
|
191
|
+
status.textContent = 'Copied';
|
|
192
|
+
b.setAttribute('aria-label', 'Copied');
|
|
193
|
+
setTimeout(() => {
|
|
194
|
+
status.textContent = '';
|
|
195
|
+
b.setAttribute('aria-label', 'Copy install command');
|
|
196
|
+
}, 2000);
|
|
197
|
+
} catch {
|
|
198
|
+
const status = document.querySelector('.copy-status') ;
|
|
199
|
+
status.textContent = 'npx @subvalue/cli';
|
|
200
|
+
}
|
|
201
|
+
}),
|
|
202
|
+
);
|