@juliantanx/aiusage 1.0.3 → 1.0.5

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 (51) hide show
  1. package/README.md +393 -0
  2. package/dist/index.js +241 -38
  3. package/dist/web/_app/immutable/assets/0.DDbFsqNI.css +1 -0
  4. package/dist/web/_app/immutable/assets/2.fho1OPpm.css +1 -0
  5. package/dist/web/_app/immutable/assets/8.9sovMx-u.css +1 -0
  6. package/dist/web/_app/immutable/assets/9.Doxq00gF.css +1 -0
  7. package/dist/web/_app/immutable/assets/_layout.RgD-pTKj.css +1 -0
  8. package/dist/web/_app/immutable/assets/_page.9sovMx-u.css +1 -0
  9. package/dist/web/_app/immutable/assets/_page.DTuZozBR.css +1 -0
  10. package/dist/web/_app/immutable/assets/_page.Doxq00gF.css +1 -0
  11. package/dist/web/_app/immutable/chunks/ToolSelector.DIzQsA4_.js +2 -0
  12. package/dist/web/_app/immutable/chunks/api.D-M_rVlI.js +1 -0
  13. package/dist/web/_app/immutable/chunks/entry.DYaPgmil.js +3 -0
  14. package/dist/web/_app/immutable/chunks/{index.Dm-3G3np.js → index.BjVwNvJa.js} +1 -1
  15. package/dist/web/_app/immutable/chunks/{index.CzqoKkoo.js → index.CUfK07C5.js} +1 -1
  16. package/dist/web/_app/immutable/chunks/scheduler.DukoKnjQ.js +1 -0
  17. package/dist/web/_app/immutable/chunks/{stores.6YXFe6HN.js → stores.WJ5dxJwL.js} +1 -1
  18. package/dist/web/_app/immutable/entry/app.C6dQgA3c.js +2 -0
  19. package/dist/web/_app/immutable/entry/start.DIxZ9qE_.js +1 -0
  20. package/dist/web/_app/immutable/nodes/0.Dk6-dCHu.js +1 -0
  21. package/dist/web/_app/immutable/nodes/{1.CA3EXHZg.js → 1.CjGQp8zu.js} +1 -1
  22. package/dist/web/_app/immutable/nodes/{8.BSeUhVCa.js → 10.1LgqVOtM.js} +1 -1
  23. package/dist/web/_app/immutable/nodes/{9.DJXBgSiY.js → 11.BOfGogcw.js} +1 -1
  24. package/dist/web/_app/immutable/nodes/2.C_8jrQsV.js +3 -0
  25. package/dist/web/_app/immutable/nodes/{3.Bqg88zQg.js → 3.Lz_pbSpS.js} +1 -1
  26. package/dist/web/_app/immutable/nodes/{4.B3zrG0ip.js → 4.BCB36ta_.js} +1 -1
  27. package/dist/web/_app/immutable/nodes/{2.CJyBxUXd.js → 5.CykeLKzi.js} +1 -1
  28. package/dist/web/_app/immutable/nodes/{5.C3h9wXyF.js → 6.De73932o.js} +1 -1
  29. package/dist/web/_app/immutable/nodes/{6.C8xhym7b.js → 7.6OEKXCWR.js} +1 -1
  30. package/dist/web/_app/immutable/nodes/8.niqPZkB9.js +1 -0
  31. package/dist/web/_app/immutable/nodes/9.DRZSbXAV.js +1 -0
  32. package/dist/web/_app/version.json +1 -1
  33. package/dist/web/index.html +9 -9
  34. package/package.json +6 -3
  35. package/dist/web/_app/immutable/assets/0.BTUc0PXb.css +0 -1
  36. package/dist/web/_app/immutable/assets/7.8R_5Laqi.css +0 -1
  37. package/dist/web/_app/immutable/assets/_layout.DLyrrG29.css +0 -1
  38. package/dist/web/_app/immutable/assets/_page.8R_5Laqi.css +0 -1
  39. package/dist/web/_app/immutable/chunks/ToolSelector.kb97TteP.js +0 -2
  40. package/dist/web/_app/immutable/chunks/api.DyoIo4nG.js +0 -1
  41. package/dist/web/_app/immutable/chunks/entry.JnN5paQ1.js +0 -3
  42. package/dist/web/_app/immutable/chunks/scheduler.Dx1bs0RQ.js +0 -1
  43. package/dist/web/_app/immutable/entry/app.MBvJGLMp.js +0 -2
  44. package/dist/web/_app/immutable/entry/start.BQY9CnVO.js +0 -1
  45. package/dist/web/_app/immutable/nodes/0.BcLtzgbo.js +0 -1
  46. package/dist/web/_app/immutable/nodes/7.C950CTxa.js +0 -1
  47. /package/dist/web/_app/immutable/assets/{8.BcbNCOTS.css → 10.BcbNCOTS.css} +0 -0
  48. /package/dist/web/_app/immutable/assets/{9.QhlpTtkf.css → 11.QhlpTtkf.css} +0 -0
  49. /package/dist/web/_app/immutable/assets/{2.I4bgY8QS.css → 5.I4bgY8QS.css} +0 -0
  50. /package/dist/web/_app/immutable/assets/{5.BeDwa7mS.css → 6.BeDwa7mS.css} +0 -0
  51. /package/dist/web/_app/immutable/assets/{6.BYQidWiw.css → 7.BYQidWiw.css} +0 -0
package/README.md ADDED
@@ -0,0 +1,393 @@
1
+ # aiusage
2
+
3
+ Track AI coding assistant usage, token consumption, cost, and tool calls in one place across Claude Code, Codex, OpenClaw, and OpenCode.
4
+
5
+ English | [中文](./README_zh.md)
6
+
7
+ ## Why aiusage
8
+
9
+ - Aggregate local session logs from multiple AI coding assistants into one view.
10
+ - Analyze token usage, cost, model mix, and tool call activity.
11
+ - Explore the data through a local dashboard with overview ranges from Today to All Time.
12
+ - Sync usage data across multiple machines with GitHub, S3, or R2.
13
+ - Keep everything local-first, with optional cloud sync when you need shared visibility.
14
+
15
+ ## Quick Start
16
+
17
+ **Prerequisites:** Node.js >= 18
18
+
19
+ ```bash
20
+ # Install
21
+ npm install -g @juliantanx/aiusage
22
+
23
+ # Parse local session logs
24
+ aiusage parse
25
+
26
+ # Start the dashboard
27
+ aiusage serve
28
+ # Open http://localhost:3847
29
+ ```
30
+
31
+ Day-to-day usage is usually just:
32
+
33
+ ```bash
34
+ aiusage parse
35
+ aiusage serve
36
+ ```
37
+
38
+ `aiusage` does not run a built-in background parser. If you want automatic imports, schedule `aiusage parse` with cron or Task Scheduler.
39
+
40
+ <details>
41
+ <summary>Build from source</summary>
42
+
43
+ ```bash
44
+ git clone https://github.com/juliantanx/aiusage.git
45
+ cd aiusage
46
+ pnpm install
47
+ pnpm build
48
+ cd packages/cli
49
+ npm link
50
+ ```
51
+
52
+ After pulling updates, rebuild to pick up changes:
53
+
54
+ ```bash
55
+ pnpm build
56
+ ```
57
+
58
+ </details>
59
+
60
+ ## Screenshot
61
+
62
+ ![This Week homepage dashboard](https://cdn.jsdelivr.net/gh/juliantanx/aiusage@main/docs/assets/readme/weekly-overview.png)
63
+
64
+ Homepage dashboard filtered to This Week, showing real local usage data across assistants.
65
+
66
+ ## Common Commands
67
+
68
+ | Command | Purpose |
69
+ | --- | --- |
70
+ | `aiusage` | Print the same terminal summary as `aiusage summary` |
71
+ | `aiusage parse` | Import newly appended local session data from discovered source paths |
72
+ | `aiusage serve` | Start the local dashboard and runtime settings controller |
73
+ | `aiusage summary` | Print a usage summary in the terminal |
74
+ | `aiusage status` | Show database path, schema version, and record counts |
75
+ | `aiusage sync` | Push and pull data with a configured remote backend |
76
+ | `aiusage export` | Export records as CSV, JSON, or NDJSON |
77
+ | `aiusage clean` | Remove old data |
78
+ | `aiusage recalc` | Recalculate costs with updated pricing |
79
+ | `aiusage init` | Configure a sync backend |
80
+
81
+ ## Web Dashboard
82
+
83
+ ```bash
84
+ aiusage serve
85
+ # Open http://localhost:3847
86
+ ```
87
+
88
+ `aiusage serve` hosts two top-level dashboard entry points:
89
+
90
+ - **Home (`/`)** — live counter homepage. On first load it calls `/api/refresh`, runs one incremental local parse, then loads summary data. After that, it refreshes on the configured dashboard poll interval.
91
+ - **Overview (`/overview`)** — totals, cost, active days, and per-tool breakdowns for Today, This Week, This Month, Last 30d, or All Time.
92
+ - **Tokens** — token usage trends over time.
93
+ - **Cost** — cost trends with by-tool and by-model breakdowns.
94
+ - **Models** — model share and distribution.
95
+ - **Tool Calls** — tool call frequency and ranking.
96
+ - **Projects** — project-level usage rollups.
97
+ - **Sessions** — session browsing with filters and pagination.
98
+ - **Pricing** — active model pricing reference.
99
+ - **Settings** — configure device name, week start day, dashboard poll interval, auto-parse interval, source paths, sync backend, credentials, and local data retention without editing config files manually.
100
+
101
+ **Settings behavior**
102
+
103
+ - **Dashboard Poll Interval** is in milliseconds and only controls the homepage refresh cycle after the initial load.
104
+ - **Auto-Parse Interval** is in milliseconds and schedules background `aiusage parse` runs only while `aiusage serve` is running. Set `0` or leave it blank to disable it.
105
+ - **Local Data Retention** runs periodic cleanup only while `aiusage serve` is running. Set `0` or leave it blank to keep data forever.
106
+ - **Source path** changes take effect on the next parse.
107
+ - **Sync backend and credential** changes take effect on the next sync.
108
+
109
+ ---
110
+
111
+ ## Deployment
112
+
113
+ Need multi-machine aggregation or cloud access? Choose your scenario:
114
+
115
+ | Scenario | Method | Description |
116
+ |----------|--------|-------------|
117
+ | Multiple machines, aggregate data | [Multi-Machine Sync](#multi-machine-sync) | Sync via GitHub/S3/R2 |
118
+ | Multiple machines + unified dashboard | [Docker Deployment](#docker-deployment) | Run a 24/7 dashboard from synced data |
119
+
120
+ For single-machine usage, Quick Start is enough.
121
+
122
+ ### Multi-Machine Sync
123
+
124
+ Use this to aggregate token usage from multiple machines into one dashboard. Works with Claude Code, Codex, OpenClaw, and OpenCode.
125
+
126
+ **Architecture:**
127
+
128
+ ```
129
+ Machine A ──┐
130
+ Machine B ──┼──▶ GitHub / S3 / R2 (shared storage) ──▶ Any machine: aiusage summary / serve
131
+ Machine C ──┘
132
+ ```
133
+
134
+ **Step 1 — Choose a sync backend**
135
+
136
+ **Option A: GitHub (recommended)**
137
+
138
+ 1. Create a **private** repository on GitHub (for example `aiusage-data`)
139
+ 2. Generate a [Personal Access Token](https://github.com/settings/tokens) with `repo` scope
140
+
141
+ **Option B: AWS S3 / Cloudflare R2**
142
+
143
+ 1. Create an S3 or R2 bucket
144
+ 2. Create an IAM user or role with read/write permissions
145
+ 3. Note the access key ID, secret access key, and endpoint
146
+
147
+ **Step 2 — Install and configure on each machine**
148
+
149
+ On every machine that uses Claude Code, Codex, OpenClaw, or OpenCode:
150
+
151
+ ```bash
152
+ # Install aiusage CLI
153
+ npm install -g @juliantanx/aiusage
154
+
155
+ # Configure sync backend — GitHub
156
+ aiusage init --backend github \
157
+ --repo <user>/aiusage-data \
158
+ --token ghp_xxxxxxxxxxxxxxxxxxxx
159
+
160
+ # OR configure sync backend — S3 / R2
161
+ aiusage init --backend s3 \
162
+ --bucket my-aiusage-bucket \
163
+ --prefix aiusage/ \
164
+ --endpoint https://<account-id>.r2.cloudflarestorage.com \
165
+ --region auto \
166
+ --access-key-id AKIAxxxxxxxxxxxx \
167
+ --secret-access-key xxxxxxxxxxxxxxxxxxxxxxxxxx
168
+ ```
169
+
170
+ **Step 3 — Parse and sync on each machine**
171
+
172
+ ```bash
173
+ aiusage parse
174
+ aiusage sync
175
+ ```
176
+
177
+ **Step 4 — View aggregated data on any machine**
178
+
179
+ ```bash
180
+ aiusage sync
181
+ aiusage summary
182
+ aiusage serve
183
+ ```
184
+
185
+ **Automate (recommended)**
186
+
187
+ ```bash
188
+ # Linux/macOS
189
+ crontab -e
190
+ # Add:
191
+ */30 * * * * /usr/local/bin/aiusage parse && /usr/local/bin/aiusage sync >> ~/.aiusage/cron.log 2>&1
192
+
193
+ # Windows
194
+ schtasks /create /tn "AiusageSync" /tr "aiusage parse && aiusage sync" /sc minute /mo 30
195
+ ```
196
+
197
+ **How sync works**
198
+
199
+ - Each machine has a unique `deviceInstanceId` generated on first run.
200
+ - Each device writes to its own daily file (`{deviceInstanceId}/YYYY/MM/DD.ndjson`) in the remote backend.
201
+ - Pull reads other devices' files into the local `synced_records` table; upload writes only this device's files.
202
+ - Device-partitioned files avoid write conflicts, so no locking is needed.
203
+ - Sync frequency comes from your external scheduler or manual runs; aiusage does not include a built-in sync daemon.
204
+ - Session IDs are anonymized via `sha256(device + sessionId)`.
205
+
206
+ ---
207
+
208
+ ### Docker Deployment
209
+
210
+ Run the pre-built image on a server for a 24/7 dashboard. The container does **not** run any AI coding tools itself — it serves the web dashboard, can run the same runtime settings controller as `aiusage serve`, and can pull synced data from GitHub, S3, or R2.
211
+
212
+ **Architecture:**
213
+
214
+ ```
215
+ Machine A ──┐ ┌── Browser: https://aiusage.your-domain.com
216
+ Machine B ──┼──▶ GitHub / S3 / R2 ──▶ Cloud Server (Docker)
217
+ Machine C ──┘ └── port 3847
218
+ ```
219
+
220
+ **How data flows**
221
+
222
+ 1. Each dev machine runs `aiusage parse && aiusage sync` to upload local usage data.
223
+ 2. The Docker container runs `aiusage sync` to pull that data into its local SQLite database.
224
+ 3. The web dashboard reads from the local database and displays aggregated stats.
225
+
226
+ **Data storage in Docker**
227
+
228
+ | Item | Container path | Description |
229
+ |------|---------------|-------------|
230
+ | Database | `/root/.aiusage/cache.db` | SQLite database with aggregated usage data |
231
+ | Config | `/root/.aiusage/config.json` | Sync backend config, runtime settings, and credentials |
232
+ | State | `/root/.aiusage/state.json` | Consent and sync runtime state |
233
+ | Watermarks | `/root/.aiusage/watermark.json` | Incremental parse cursors |
234
+
235
+ All data lives under `/root/.aiusage`, which is declared as a `VOLUME`. You **must** mount this volume to persist data across container restarts.
236
+
237
+ **Step 1 — Pull image and run**
238
+
239
+ ```bash
240
+ # Pull image
241
+ docker pull juliantanx/aiusage
242
+
243
+ # Run container (mount volume for data persistence)
244
+ docker run -d \
245
+ --name aiusage \
246
+ -p 3847:3847 \
247
+ -v aiusage-data:/root/.aiusage \
248
+ juliantanx/aiusage
249
+
250
+ # Configure sync backend
251
+ docker exec -it aiusage aiusage init \
252
+ --backend github \
253
+ --repo <user>/aiusage-data \
254
+ --token ghp_xxxxxxxxxxxxxxxxxxxx
255
+
256
+ # Initial data pull
257
+ docker exec -it aiusage aiusage sync
258
+ ```
259
+
260
+ > Without the `-v` flag, data is lost when the container is removed.
261
+
262
+ **Step 2 — Scheduled sync**
263
+
264
+ ```bash
265
+ # Install cron in container and create scheduled task
266
+ docker exec -it aiusage bash -c "apt-get update && apt-get install -y cron"
267
+ docker exec -it aiusage bash -c \
268
+ 'echo "*/30 * * * * aiusage sync >> /root/.aiusage/cron.log 2>&1" | crontab -'
269
+ docker restart aiusage
270
+ ```
271
+
272
+ > Note: `parse` is not needed here unless you also mount local AI session logs into the container. In the standard deployment, only `sync` is needed to pull data from the remote backend.
273
+
274
+ **Step 3 — Access**
275
+
276
+ Open `http://<server-ip>:3847`.
277
+
278
+ For HTTPS with a custom domain:
279
+
280
+ ```bash
281
+ # Caddy (auto HTTPS, recommended)
282
+ caddy reverse-proxy --from aiusage.your-domain.com --to localhost:3847
283
+
284
+ # Or Nginx
285
+ server {
286
+ listen 80;
287
+ server_name aiusage.your-domain.com;
288
+ location / {
289
+ proxy_pass http://127.0.0.1:3847;
290
+ proxy_set_header Host $host;
291
+ proxy_set_header X-Real-IP $remote_addr;
292
+ }
293
+ }
294
+ ```
295
+
296
+ **Build image yourself (optional)**
297
+
298
+ A `Dockerfile` is included in the project root:
299
+
300
+ ```bash
301
+ docker build -t aiusage .
302
+ ```
303
+
304
+ ---
305
+
306
+ ## Data Storage
307
+
308
+ | Item | Path |
309
+ |------|------|
310
+ | Local database | `~/.aiusage/cache.db` |
311
+ | Config | `~/.aiusage/config.json` |
312
+ | State (watermarks, sync) | `~/.aiusage/state.json` |
313
+
314
+ ### Default Source Paths
315
+
316
+ `aiusage parse` auto-discovers session logs from the following default locations:
317
+
318
+ | Tool | macOS | Linux | Windows |
319
+ |------|-------|-------|---------|
320
+ | Claude Code | `~/.claude/projects/` | `~/.claude/projects/` | `%USERPROFILE%\.claude\projects\` |
321
+ | Codex | `~/.codex/sessions/` | `~/.codex/sessions/` | `%USERPROFILE%\.codex\sessions\` |
322
+ | OpenClaw | `~/.openclaw/agents/*/sessions/` | `~/.openclaw/agents/*/sessions/` | `%USERPROFILE%\.openclaw\agents\*\sessions\` |
323
+ | OpenCode | `~/Library/Application Support/opencode/opencode.db` | `~/.local/share/opencode/opencode.db` | `%APPDATA%\opencode\opencode.db` |
324
+
325
+ Discovery behavior:
326
+
327
+ - **Claude Code** — recursively scans `~/.claude/projects/**` for `.jsonl` files, including nested subagent logs.
328
+ - **Codex** — recursively scans `~/.codex/sessions/**` for `.jsonl` files.
329
+ - **OpenClaw** — scans each agent's `sessions/` directory under `~/.openclaw/agents/*/sessions/` and skips checkpoint files.
330
+ - **OpenCode** — reads the SQLite database file directly instead of `.jsonl` logs.
331
+
332
+ > On Linux, OpenCode respects `$XDG_DATA_HOME` if set.
333
+
334
+ ### Custom Source Paths
335
+
336
+ If you installed a tool to a non-default location, override the paths in the **Settings** page of the web dashboard (`http://localhost:3847/settings` → Sources section), or edit `~/.aiusage/config.json` directly:
337
+
338
+ ```json
339
+ {
340
+ "sources": {
341
+ "claude-code": "/custom/path/.claude/projects",
342
+ "codex": "/custom/path/.codex/sessions",
343
+ "openclaw": "/custom/sessions-dir",
344
+ "opencode": "/custom/path/opencode.db"
345
+ }
346
+ }
347
+ ```
348
+
349
+ Only the paths you specify are overridden; unspecified tools fall back to their defaults.
350
+
351
+ ## Database Visualization
352
+
353
+ The local database is a standard SQLite file, so you can open it directly in DBeaver, TablePlus, DataGrip, DB Browser for SQLite, or any similar tool.
354
+
355
+ ```bash
356
+ aiusage status
357
+ # Shows the exact DB Path, schema version, and object counts
358
+ ```
359
+
360
+ - Open `~/.aiusage/cache.db` as a SQLite database.
361
+ - Prefer read-only mode in your database tool. `aiusage` writes to the same file and uses WAL mode.
362
+ - If your tool asks about sidecar files, keep `cache.db-wal` and `cache.db-shm` alongside the main database file.
363
+ - Start with the read-only views:
364
+ - `v_usage_records`: one row per usage record with normalized timestamp and token totals
365
+ - `v_tool_calls`: tool call rows joined with their parent usage record
366
+ - `v_sessions`: session-level aggregates for pivoting and charting
367
+ - Raw internal tables remain available for advanced inspection:
368
+ - `records`
369
+ - `tool_calls`
370
+ - `synced_records`
371
+ - `sync_tombstones`
372
+
373
+ ## Tech Stack
374
+
375
+ - **Runtime:** Node.js, TypeScript
376
+ - **Database:** better-sqlite3 (local, WAL mode)
377
+ - **CLI:** Commander.js
378
+ - **Web:** SvelteKit + adapter-static
379
+ - **Build:** tsup (core/cli), Vite (web)
380
+ - **Sync:** GitHub API, AWS S3 / Cloudflare R2
381
+
382
+ ## Project Structure
383
+
384
+ ```text
385
+ packages/
386
+ core/ - Shared types, database schema, pricing data
387
+ cli/ - CLI tool for parsing logs, querying data, cloud sync
388
+ web/ - SvelteKit web dashboard (SPA)
389
+ ```
390
+
391
+ ## License
392
+
393
+ MIT