ccgauge 1.0.2 → 1.0.3
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/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-build-manifest.json +26 -26
- package/.next/standalone/.next/app-path-routes-manifest.json +7 -7
- package/.next/standalone/.next/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/blocks/route.js +1 -1
- package/.next/standalone/.next/server/app/api/blocks/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/blocks/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/export/usage/route.js +1 -1
- package/.next/standalone/.next/server/app/api/export/usage/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/export/usage/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/pricing/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/route.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/scan/route.js +1 -1
- package/.next/standalone/.next/server/app/api/scan/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/scan/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/sessions/route.js +1 -1
- package/.next/standalone/.next/server/app/api/sessions/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/sessions/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/usage/route.js +1 -1
- package/.next/standalone/.next/server/app/api/usage/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/usage/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/models/page.js +2 -2
- package/.next/standalone/.next/server/app/models/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/models/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/page.js +2 -2
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/[id]/page.js +2 -2
- package/.next/standalone/.next/server/app/projects/[id]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/sessions/[id]/page.js +2 -2
- package/.next/standalone/.next/server/app/sessions/[id]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/sessions/[id]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/sessions/page.js +1 -1
- package/.next/standalone/.next/server/app/sessions/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/sessions/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings/page.js +1 -1
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/usage/page.js +2 -2
- package/.next/standalone/.next/server/app/usage/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/usage/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +7 -7
- package/.next/standalone/.next/server/chunks/971.js +1 -1
- package/.next/standalone/.next/server/chunks/98.js +1 -0
- package/.next/standalone/.next/server/functions-config-manifest.json +2 -2
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/package.json +1 -1
- package/CHANGELOG.md +148 -0
- package/README.md +19 -6
- package/README.zh-CN.md +19 -6
- package/bin/cli.mjs +37 -17
- package/dist/mcp/server.mjs +40 -23699
- package/dist/report/index.mjs +38 -18
- package/package.json +1 -1
- package/.next/standalone/.next/server/chunks/155.js +0 -1
- /package/.next/standalone/.next/static/{4YjiQrRI-CsVEPC1UOUEJ → alqi5oQtTQUdpxp2x0yAt}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{4YjiQrRI-CsVEPC1UOUEJ → alqi5oQtTQUdpxp2x0yAt}/_ssgManifest.js +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,153 @@ All notable changes to **ccgauge** are documented here.
|
|
|
5
5
|
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and
|
|
6
6
|
this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [1.0.3] — 2026-05-15
|
|
9
|
+
|
|
10
|
+
A focused **MCP server** correctness + performance + ergonomics pass,
|
|
11
|
+
plus a docs catch-up for the marketing site and the bundled READMEs.
|
|
12
|
+
Dashboard runtime is unchanged from 1.0.2. The MCP server adds a 9th
|
|
13
|
+
tool (`cost_estimator`), gets ~4× faster on weekly summaries, halves
|
|
14
|
+
its bundle size, and ships a `ccgauge mcp --check` self-test.
|
|
15
|
+
|
|
16
|
+
### Highlights
|
|
17
|
+
|
|
18
|
+
- **9 MCP tools** — added `cost_estimator(source, model, input_tokens,
|
|
19
|
+
output_tokens, …)` for pure pricing what-ifs (no record lookup).
|
|
20
|
+
Pairs with `usage_summary` for "if I run X more on Opus 4.7, what
|
|
21
|
+
does it add to my month-to-date?".
|
|
22
|
+
- **`weekly_summary` is ~4× faster.** Rewrote the per-day trend from
|
|
23
|
+
8 full record-set passes (1 totals + 7 daily totals × 2 internal
|
|
24
|
+
source filters) down to a single `timeBuckets('day')` call + a
|
|
25
|
+
7-slot skeleton merge. Same JSON shape out, including zero-fill
|
|
26
|
+
for empty days.
|
|
27
|
+
- **MCP bundle 810 KB → 379 KB.** esbuild `minify: true` +
|
|
28
|
+
`external: ['fsevents']` shaves 53% off the published tarball's
|
|
29
|
+
MCP slice with no runtime behaviour change.
|
|
30
|
+
- **`ccgauge mcp --check`** — verifies the bundle, boots the indexer,
|
|
31
|
+
and prints one line per provider (files / records / scanned dirs).
|
|
32
|
+
Lets users debug "Claude Desktop doesn't see ccgauge tools"
|
|
33
|
+
without spinning up an MCP client first.
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- `cost_estimator` MCP tool — uses the provider's built-in
|
|
38
|
+
per-1M-token pricing table; does NOT consult usage history.
|
|
39
|
+
Useful for budgeting and cap planning.
|
|
40
|
+
- `ccgauge mcp --check` self-test command.
|
|
41
|
+
- README cross-references for both new entry points (`mcp --check`,
|
|
42
|
+
`cost_estimator`) in en + zh.
|
|
43
|
+
- `__SERVER_VERSION__` injected by esbuild from `package.json#version`
|
|
44
|
+
so the server's MCP handshake always agrees with the npm release.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- **`ccgauge mcp` runs in-process.** The CLI subcommand used to
|
|
49
|
+
spawn a second Node process for the bundled server (`spawn(node,
|
|
50
|
+
[bundle])`); it now `await import()`s the bundle and calls
|
|
51
|
+
`runStdioServer()` directly. Saves ~80–150 ms per invocation and
|
|
52
|
+
removes a brittle signal-forwarding shim.
|
|
53
|
+
- **MCP responses are compact JSON.** Drop the `JSON.stringify(...,
|
|
54
|
+
null, 2)` pretty-print on every tool response — LLMs don't read
|
|
55
|
+
indentation but pay for it. ~30–50% smaller responses for the
|
|
56
|
+
heavier tools (`weekly_summary`, `usage_by_session`).
|
|
57
|
+
`CCGAUGE_MCP_PRETTY=1` re-enables.
|
|
58
|
+
- **Default limits on `usage_by_model` (20) and `usage_by_project`
|
|
59
|
+
(20).** The cap existed as a max; the default is now the same
|
|
60
|
+
value. A user asking "what did I work on this year" with hundreds
|
|
61
|
+
of projects no longer gets a 200-entry payload.
|
|
62
|
+
- **`recent_activity` defaults to a 30-day window** (`days` arg to
|
|
63
|
+
widen). Previously aggregated every session across the user's
|
|
64
|
+
full CLI lifetime just to return the top 10 by `end_time` — cost
|
|
65
|
+
grew linearly with history.
|
|
66
|
+
- **Day-aligned named ranges.** `7d` / `30d` / `90d` now map to
|
|
67
|
+
`[start-of(N-1 days ago), end-of-today]` like `today` /
|
|
68
|
+
`yesterday` / `this_week` already did. Previously `7d` was a
|
|
69
|
+
rolling 7×24h window, so summing seven `daily_summary` calls
|
|
70
|
+
didn't equal one `usage_summary({range:"7d"})` — they do now.
|
|
71
|
+
- **README Highlights refreshed** (en + zh). New top-level subsections
|
|
72
|
+
for `ccgauge report` (CLI) and `ccgauge mcp` (MCP server) so the
|
|
73
|
+
two no-server entry points are visible in the first scroll.
|
|
74
|
+
Cross-provider section updated for 1.0.2's tri-state switcher +
|
|
75
|
+
real provider logos + worktree-aware Projects collapsing.
|
|
76
|
+
Drill-down section mentions the Tokens / Conversations trend toggle.
|
|
77
|
+
|
|
78
|
+
### Fixed
|
|
79
|
+
|
|
80
|
+
- **`parseDateLike` no longer accepts calendar-overflow dates with
|
|
81
|
+
a time suffix.** `2026-02-31T00:00:00` used to silently roll
|
|
82
|
+
forward to March 3 (JS `new Date()` normalises invalid dates);
|
|
83
|
+
now both the bare-date branch and the time-suffix branch reject
|
|
84
|
+
it. Affects every MCP date arg, the dashboard's `from`/`to` URL
|
|
85
|
+
params, and `ccgauge report --since`/`--until`.
|
|
86
|
+
- **`SERVER_VERSION` no longer hardcoded** to `0.4.0`. Now sourced
|
|
87
|
+
from `package.json#version` at bundle time, so the MCP server's
|
|
88
|
+
`initialize` response reports the same version as the npm release
|
|
89
|
+
it shipped in.
|
|
90
|
+
- **README `range: "14d"` example was bogus** — the schema enum
|
|
91
|
+
doesn't accept `14d`, so following the README's project-breakdown
|
|
92
|
+
prompt produced an error. Replaced with the explicit-`from`/`to`
|
|
93
|
+
form. Same fix in `README.zh-CN.md`.
|
|
94
|
+
|
|
95
|
+
### Performance
|
|
96
|
+
|
|
97
|
+
| Metric | Before | After |
|
|
98
|
+
| --- | --- | --- |
|
|
99
|
+
| `dist/mcp/server.mjs` size | 810 KB | **379 KB** (-53%) |
|
|
100
|
+
| `weekly_summary` record-set passes | 8 (+ 2 internal source filters each) | **2** |
|
|
101
|
+
| `recent_activity` aggregation scope | every session ever | **last 30 days** |
|
|
102
|
+
| MCP response JSON byte count (typical) | indented | **~half** |
|
|
103
|
+
| Aggregator `withinRange` Date#toISOString() calls | per record × N filters | **once per call** |
|
|
104
|
+
|
|
105
|
+
### Security / privacy
|
|
106
|
+
|
|
107
|
+
- **MCP tool errors are scrubbed of `$HOME` paths** before they
|
|
108
|
+
reach the SDK's error envelope. Belt-and-suspenders today (the
|
|
109
|
+
only user-visible throws are clean date-arg validators), but
|
|
110
|
+
defends against future error paths that might wrap an indexer
|
|
111
|
+
error. Extracted the existing `sanitizeForUser` from the indexer
|
|
112
|
+
module into a shared `lib/sanitize` so both layers use one
|
|
113
|
+
definition.
|
|
114
|
+
|
|
115
|
+
### Internal
|
|
116
|
+
|
|
117
|
+
- `lib/aggregator/index.ts` — entry-point functions now hoist
|
|
118
|
+
`from/to → ISO string` and `models/projects → Set` once per
|
|
119
|
+
call instead of recomputing them per record. Measurable on the
|
|
120
|
+
`weekly_summary` hot path; invisible for the dashboard's
|
|
121
|
+
single-pass aggregators.
|
|
122
|
+
- New `lib/mcp/text-result.ts` — single source of truth for the
|
|
123
|
+
MCP response wrapper. `lib/mcp/safe-handler.ts` — HOF that wraps
|
|
124
|
+
tool callbacks with the path-scrub guard.
|
|
125
|
+
- `parseDayArg` moved from `tools/activity.ts` to `mcp/context.ts`
|
|
126
|
+
next to `parseDateRange` so the two share a single implementation
|
|
127
|
+
of the "today / yesterday / monday / YYYY-MM-DD" parser.
|
|
128
|
+
- 30 s polling fallback in the indexer is now **off by default for
|
|
129
|
+
the MCP instance** and **on by default for the dashboard**.
|
|
130
|
+
Override with `CCGAUGE_POLL_FALLBACK={0,1}`. The MCP server runs
|
|
131
|
+
in a background daemon spawned by an LLM client and shouldn't
|
|
132
|
+
keep the host warm just to catch the rare `fs.watch(recursive)`
|
|
133
|
+
miss.
|
|
134
|
+
- `AGENTS.md` documents the `site/` sub-project, the v4 sidechain
|
|
135
|
+
merge invariant, a release checklist, and the
|
|
136
|
+
`raw.githubusercontent.com` hero-image fragility. Two new
|
|
137
|
+
"intentionally NOT supported" items: folding `site/` into a pnpm
|
|
138
|
+
workspace, and letting `site/` leak into the npm tarball.
|
|
139
|
+
|
|
140
|
+
### Docs (doesn't ship to npm)
|
|
141
|
+
|
|
142
|
+
- Marketing site (`site/`) catches up to 1.0.2: features page
|
|
143
|
+
covers All view + conversation-count toggle + worktree merging;
|
|
144
|
+
homepage hero, "Multi-source analytics" card, and ScreenshotFrame
|
|
145
|
+
now use three distinct screenshots; hardcoded `v1.0.0` eyebrows
|
|
146
|
+
removed.
|
|
147
|
+
- `site/public/images/README.md` rewritten as a single-source-of-
|
|
148
|
+
truth inventory (file → used-by → source), with the prompt
|
|
149
|
+
catalogue trimmed to filenames that actually exist. Legacy
|
|
150
|
+
placeholder SVGs moved to an explicit "kept but unused"
|
|
151
|
+
subsection.
|
|
152
|
+
- `site/public/robots.txt` no longer points at a non-existent
|
|
153
|
+
`sitemap-index.xml`.
|
|
154
|
+
|
|
8
155
|
## [1.0.2] — 2026-05-15
|
|
9
156
|
|
|
10
157
|
This release brings the dashboard the long-requested **All view** (one
|
|
@@ -531,6 +678,7 @@ of HTML to the browser.
|
|
|
531
678
|
- Initial public release as `ccgauge`: local Next.js dashboard for
|
|
532
679
|
Claude Code token usage, cost, and 5-hour block tracking.
|
|
533
680
|
|
|
681
|
+
[1.0.3]: https://github.com/chengzuopeng/ccgauge/compare/v1.0.2...v1.0.3
|
|
534
682
|
[1.0.2]: https://github.com/chengzuopeng/ccgauge/compare/v1.0.1...v1.0.2
|
|
535
683
|
[1.0.1]: https://github.com/chengzuopeng/ccgauge/compare/v1.0.0...v1.0.1
|
|
536
684
|
[1.0.0]: https://github.com/chengzuopeng/ccgauge/compare/v0.4.0...v1.0.0
|
package/README.md
CHANGED
|
@@ -38,8 +38,9 @@ Everything runs locally as a Next.js app. Your conversation transcripts never le
|
|
|
38
38
|
## Highlights
|
|
39
39
|
|
|
40
40
|
### Cross-provider analytics
|
|
41
|
-
- One dashboard for both **Claude Code** and **OpenAI Codex CLI**
|
|
42
|
-
- Toggle data source from the nav bar; URL persists via `?source=`, last choice cached in cookie
|
|
41
|
+
- One dashboard for both **Claude Code** and **OpenAI Codex CLI**, plus an **All view** that merges the two
|
|
42
|
+
- Toggle data source from the nav bar (Claude · Codex · All), each button rendered with the real provider logo; URL persists via `?source=`, last choice cached in cookie
|
|
43
|
+
- **Worktree-aware Projects** — all worktrees of the same repo collapse into a single project row
|
|
43
44
|
- Built-in **provider adapter layer** (`lib/providers/`) — adding a third CLI (Gemini CLI, Cursor, Aider, …) is one new file plus a single registry line
|
|
44
45
|
|
|
45
46
|
### At-a-glance KPIs
|
|
@@ -51,7 +52,7 @@ Everything runs locally as a Next.js app. Your conversation transcripts never le
|
|
|
51
52
|
- **Sessions** — per-conversation list with model / tokens / cost / duration, plus a message-level timeline
|
|
52
53
|
- **Projects** — per-`cwd` aggregation cards with sparkline and spend share
|
|
53
54
|
- **Models** — side-by-side comparison: cost share, tokens share, cache hit, USD pricing
|
|
54
|
-
- **Usage** — turn-grouped table with expandable tool-call breakdown, CSV export
|
|
55
|
+
- **Usage** — turn-grouped table with expandable tool-call breakdown, CSV export. **Tokens / Conversations** toggle on the trend chart so you can count rows the way the usage table counts them
|
|
55
56
|
|
|
56
57
|
### Cost transparency
|
|
57
58
|
- **Cache savings** is its own KPI — quantifies how much Anthropic prompt caching saved you vs. paying full input price
|
|
@@ -63,6 +64,17 @@ Everything runs locally as a Next.js app. Your conversation transcripts never le
|
|
|
63
64
|
- **English / 中文** (cookie + localStorage)
|
|
64
65
|
- Filters: time range (today / 7d / 30d / 90d / all), granularity (hour / day / week / month), model and project multi-select
|
|
65
66
|
|
|
67
|
+
### CLI report (no server)
|
|
68
|
+
- `ccgauge report` prints a colored, aligned terminal usage report in ~0.2 s from the same JSONL the dashboard reads
|
|
69
|
+
- `--range / --source / --by / --since / --until / --model / --project` filters
|
|
70
|
+
- `--json` for machine-readable output; `--no-color` auto-applied when piped — drops cleanly into shell scripts and CI
|
|
71
|
+
|
|
72
|
+
### MCP server (for LLMs)
|
|
73
|
+
- `ccgauge mcp` runs a stdio JSON-RPC server so **Claude Desktop / Cursor / Cline** can query your local usage directly
|
|
74
|
+
- Nine MCP tools: `usage_summary`, `usage_by_time`, `usage_by_model`, `usage_by_project`, `usage_by_session`, `daily_summary`, `weekly_summary`, `recent_activity`, `cost_estimator`
|
|
75
|
+
- Reasoning-token breakdown surfaced for the models that emit one
|
|
76
|
+
- Separate named cache (`index-mcp-v2.json`) so MCP runs don't contend with the dashboard
|
|
77
|
+
|
|
66
78
|
### Privacy by design
|
|
67
79
|
- 100 % local: read-only access to existing JSONL files, zero outbound network calls
|
|
68
80
|
- Open source, MIT-licensed
|
|
@@ -217,6 +229,7 @@ English with real numbers from your machine.
|
|
|
217
229
|
| `daily_summary` | "What did I do today / yesterday / Monday / on YYYY-MM-DD?" Sessions grouped by project + models + top tool calls. |
|
|
218
230
|
| `weekly_summary` | 7-day roll-up: per-day cost trend, top sessions, top projects, models. `week_offset=-1` for last week. |
|
|
219
231
|
| `recent_activity` | The N most recently active sessions across providers. |
|
|
232
|
+
| `cost_estimator` | Compute the USD cost of a hypothetical request (`{ source, model, input_tokens, output_tokens, cache_* }`). Uses built-in per-1M-token pricing; does NOT consult usage history. |
|
|
220
233
|
|
|
221
234
|
| Resource URI | Content |
|
|
222
235
|
| --- | --- |
|
|
@@ -334,8 +347,8 @@ debug "why did it answer X".
|
|
|
334
347
|
→ `daily_summary({ date: "yesterday" })`
|
|
335
348
|
- *"Generate a Monday stand-up bullet list of what I shipped last week."*
|
|
336
349
|
→ `weekly_summary({ week_offset: -1 })`
|
|
337
|
-
- *"Which 3 projects have I touched most in the last
|
|
338
|
-
→ `usage_by_project({
|
|
350
|
+
- *"Which 3 projects have I touched most in the last two weeks?"*
|
|
351
|
+
→ `usage_by_project({ from: "2026-05-01", to: "2026-05-15", limit: 3 })` — pass explicit `from`/`to` for any window not covered by the named ranges (`7d` / `30d` / `90d` / `this_week` / `last_week` / …).
|
|
339
352
|
- *"What was my last coding session about?"*
|
|
340
353
|
→ `recent_activity({ limit: 1 })`
|
|
341
354
|
|
|
@@ -351,7 +364,7 @@ debug "why did it answer X".
|
|
|
351
364
|
- *"At my current burn rate, how much will I spend this month?"*
|
|
352
365
|
→ `usage_summary({ range: "this_month" })` + `usage_by_time({ range: "this_month", granularity: "day" })` — LLM extrapolates.
|
|
353
366
|
- *"If I run another 200K input + 50K output on Opus 4.7 today, what does that add to my month-to-date cost?"*
|
|
354
|
-
→ `usage_summary({ range: "this_month" })`
|
|
367
|
+
→ `cost_estimator({ source: "claude", model: "claude-opus-4-7", input_tokens: 200000, output_tokens: 50000 })` + `usage_summary({ range: "this_month" })` — the estimator returns the dollar cost for the hypothetical request without touching your usage history.
|
|
355
368
|
|
|
356
369
|
#### Cross-source comparisons
|
|
357
370
|
|
package/README.zh-CN.md
CHANGED
|
@@ -38,8 +38,9 @@ npx ccgauge
|
|
|
38
38
|
## 亮点
|
|
39
39
|
|
|
40
40
|
### 多 CLI 数据源
|
|
41
|
-
- 一份看板覆盖 **Claude Code** 与 **OpenAI Codex CLI**
|
|
42
|
-
-
|
|
41
|
+
- 一份看板覆盖 **Claude Code** 与 **OpenAI Codex CLI**,并提供 **All 视图**把两者合并查看
|
|
42
|
+
- 顶部三档切换(Claude · Codex · All),每个按钮都带真品牌 logo;URL 用 `?source=` 持久化,cookie 记忆上次选择
|
|
43
|
+
- **Worktree 感知的 Projects 合并** —— 同一个 repo 的所有 worktree 自动并到同一个项目行
|
|
43
44
|
- 内置 **Provider 适配层**(`lib/providers/`)—— 增加第三个 CLI(Gemini CLI / Cursor / Aider …)只需一个新文件加注册表一行
|
|
44
45
|
|
|
45
46
|
### KPI 一眼看完
|
|
@@ -51,7 +52,7 @@ npx ccgauge
|
|
|
51
52
|
- **会话页** —— 每场对话单独成行(模型 / token / 花费 / 时长),点进去看消息级时间线
|
|
52
53
|
- **项目页** —— 按 `cwd` 聚合成卡片网格,含趋势条与花费占比
|
|
53
54
|
- **模型页** —— 各模型并排对比:成本占比、token 占比、缓存命中、官方单价
|
|
54
|
-
- **用量页** —— 按对话轮次分组的明细表,可展开看每次工具调用,支持 CSV
|
|
55
|
+
- **用量页** —— 按对话轮次分组的明细表,可展开看每次工具调用,支持 CSV 导出。趋势图支持 **Token / 对话数** 切换,让条形图行数和用量表 1:1 对齐
|
|
55
56
|
|
|
56
57
|
### 成本透明
|
|
57
58
|
- **缓存节省** 单独成卡 —— 量化 Anthropic prompt caching 实际帮你节省了多少美元
|
|
@@ -63,6 +64,17 @@ npx ccgauge
|
|
|
63
64
|
- **English / 中文** 双语,cookie + localStorage 双向同步
|
|
64
65
|
- 完整筛选:时间区间(今天 / 7 天 / 30 天 / 90 天 / 全部)、粒度(小时 / 天 / 周 / 月)、模型 / 项目 multi-select
|
|
65
66
|
|
|
67
|
+
### 命令行报告(无 server)
|
|
68
|
+
- `ccgauge report` 读取同一份 JSONL,在 ~0.2 秒内打出彩色对齐的终端报告
|
|
69
|
+
- `--range / --source / --by / --since / --until / --model / --project` 滤波参数
|
|
70
|
+
- `--json` 输出给脚本;`--no-color` 走管道时自动开启 —— 可以直接塞进 shell 和 CI
|
|
71
|
+
|
|
72
|
+
### MCP 服务(给 LLM 用)
|
|
73
|
+
- `ccgauge mcp` 起一个 stdio JSON-RPC 服务,让 **Claude Desktop / Cursor / Cline** 等 MCP 客户端直接查你本地的 ccgauge 历史
|
|
74
|
+
- 9 个 MCP tool:`usage_summary`、`usage_by_time`、`usage_by_model`、`usage_by_project`、`usage_by_session`、`daily_summary`、`weekly_summary`、`recent_activity`、`cost_estimator`
|
|
75
|
+
- 支持模型有 reasoning token 时单独折算
|
|
76
|
+
- 独立命名缓存(`index-mcp-v2.json`),MCP 进程不会和仪表盘抢同一份磁盘索引
|
|
77
|
+
|
|
66
78
|
### 隐私优先
|
|
67
79
|
- 100 % 本地:只读访问已有 JSONL 文件,零外网调用
|
|
68
80
|
- 开源,MIT 协议
|
|
@@ -213,7 +225,8 @@ LLM 会自动选合适的 tool、本地调用、用大白话给你带真实数
|
|
|
213
225
|
| `usage_by_session` | 会话列表,含标题(首条用户消息)/ 模型 / 时长 / 花费。可按 recent / cost / tokens / duration 排序。 |
|
|
214
226
|
| `daily_summary` | "今天 / 昨天 / 周一 / YYYY-MM-DD 我都干了啥?" 按项目分组的会话 + 模型 + top 工具调用。 |
|
|
215
227
|
| `weekly_summary` | 7 天 roll-up:每日花费趋势 + top 会话 + top 项目 + 模型分布。`week_offset=-1` 看上周。 |
|
|
216
|
-
| `recent_activity` | 最近 N
|
|
228
|
+
| `recent_activity` | 最近 N 条活跃会话(默认最近 30 天,可显式给 `from`/`to`)。 |
|
|
229
|
+
| `cost_estimator` | 计算"假设我用 X 模型发 N 个 token 要花多少钱"。直接读内置 per-1M-token 单价表,不查历史。常用于额度规划 / what-if。 |
|
|
217
230
|
|
|
218
231
|
| Resource URI | 内容 |
|
|
219
232
|
| --- | --- |
|
|
@@ -329,7 +342,7 @@ LLM 大概率会调的工具——方便你"为什么会这样回答"反查。
|
|
|
329
342
|
- *"给我一份周一 standup 用的 bullet list,列我上周完成的事。"*
|
|
330
343
|
→ `weekly_summary({ week_offset: -1 })`
|
|
331
344
|
- *"过去两周我接触最多的 3 个项目是什么?"*
|
|
332
|
-
→ `usage_by_project({
|
|
345
|
+
→ `usage_by_project({ from: "2026-05-01", to: "2026-05-15", limit: 3 })`——非 `7d` / `30d` / `90d` / `this_week` / `last_week` 等命名窗口时,传显式 `from` / `to`。
|
|
333
346
|
- *"我最近一次的编码会话是关于什么的?"*
|
|
334
347
|
→ `recent_activity({ limit: 1 })`
|
|
335
348
|
|
|
@@ -345,7 +358,7 @@ LLM 大概率会调的工具——方便你"为什么会这样回答"反查。
|
|
|
345
358
|
- *"按当前消耗速度,本月预计花多少?"*
|
|
346
359
|
→ `usage_summary({ range: "this_month" })` + `usage_by_time({ range: "this_month", granularity: "day" })`——LLM 自己外推。
|
|
347
360
|
- *"如果我今天再在 Opus 4.7 上跑 200K input + 50K output,本月累计要多少?"*
|
|
348
|
-
→ `
|
|
361
|
+
→ `cost_estimator({ source: "claude", model: "claude-opus-4-7", input_tokens: 200000, output_tokens: 50000 })` + `usage_summary({ range: "this_month" })`——estimator 直接按内置单价表返回这笔假设请求的美元成本,不查历史。
|
|
349
362
|
|
|
350
363
|
#### 跨数据源对比
|
|
351
364
|
|
package/bin/cli.mjs
CHANGED
|
@@ -142,8 +142,9 @@ program
|
|
|
142
142
|
program
|
|
143
143
|
.command('mcp')
|
|
144
144
|
.description('start the MCP server (stdio) so LLMs can query usage data')
|
|
145
|
-
.
|
|
146
|
-
|
|
145
|
+
.option('--check', 'verify the bundle + indexer; print one line per provider and exit')
|
|
146
|
+
.action(async (opts) => {
|
|
147
|
+
await startMcp(opts);
|
|
147
148
|
});
|
|
148
149
|
|
|
149
150
|
function addReportOptions(cmd) {
|
|
@@ -438,7 +439,7 @@ or run the full build with
|
|
|
438
439
|
}
|
|
439
440
|
}
|
|
440
441
|
|
|
441
|
-
async function startMcp() {
|
|
442
|
+
async function startMcp(opts = {}) {
|
|
442
443
|
const bundle = join(packageRoot, 'dist', 'mcp', 'server.mjs');
|
|
443
444
|
if (!existsSync(bundle)) {
|
|
444
445
|
console.error(`
|
|
@@ -455,20 +456,39 @@ or run the full build with
|
|
|
455
456
|
`);
|
|
456
457
|
process.exit(1);
|
|
457
458
|
}
|
|
458
|
-
|
|
459
|
-
//
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
459
|
+
|
|
460
|
+
// --check: don't actually run the JSON-RPC server — load the bundle,
|
|
461
|
+
// boot the indexer, print one line per provider, and exit. Lets users
|
|
462
|
+
// verify their install without wiring up an MCP client.
|
|
463
|
+
if (opts.check) {
|
|
464
|
+
const mod = await import(pathToFileURL(bundle).href);
|
|
465
|
+
if (typeof mod.printCheck !== 'function') {
|
|
466
|
+
console.error('[ccgauge-mcp] this bundle was built without --check support');
|
|
467
|
+
process.exit(1);
|
|
468
|
+
}
|
|
469
|
+
const code = await mod.printCheck();
|
|
470
|
+
process.exit(typeof code === 'number' ? code : 0);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
// Run the bundled MCP server **in this process** — the bundle exposes a
|
|
474
|
+
// top-level `runStdioServer()` so we just import + invoke it. Spawning a
|
|
475
|
+
// second Node process here is wasted memory/latency (LLM clients already
|
|
476
|
+
// spawn `ccgauge mcp` per conversation), and forwarding signals across
|
|
477
|
+
// processes is brittle (e.g. SIGHUP isn't covered by the old shim).
|
|
478
|
+
try {
|
|
479
|
+
const mod = await import(pathToFileURL(bundle).href);
|
|
480
|
+
if (typeof mod.runStdioServer !== 'function') {
|
|
481
|
+
console.error('[ccgauge-mcp] bundle missing runStdioServer export');
|
|
482
|
+
process.exit(1);
|
|
483
|
+
}
|
|
484
|
+
await mod.runStdioServer();
|
|
485
|
+
// runStdioServer keeps the loop alive via the stdio transport; if it
|
|
486
|
+
// ever returns it means the transport closed cleanly.
|
|
487
|
+
process.exit(0);
|
|
488
|
+
} catch (err) {
|
|
489
|
+
console.error('[ccgauge-mcp] failed to start:', err?.message ?? err);
|
|
490
|
+
process.exit(1);
|
|
491
|
+
}
|
|
472
492
|
}
|
|
473
493
|
|
|
474
494
|
async function resolvePort(opts) {
|