@juliantanx/aiusage 1.3.3 → 1.4.0

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 (54) hide show
  1. package/README.md +22 -558
  2. package/dist/index.js +3744 -1943
  3. package/dist/web/_app/immutable/assets/0.C3RIkHY2.css +1 -0
  4. package/dist/web/_app/immutable/assets/11.D51Gzh6j.css +1 -0
  5. package/dist/web/_app/immutable/assets/4.CUknm1Jh.css +1 -0
  6. package/dist/web/_app/immutable/assets/6.BETPk561.css +1 -0
  7. package/dist/web/_app/immutable/assets/_layout.BqRkZ3UP.css +1 -0
  8. package/dist/web/_app/immutable/assets/_page.BETPk561.css +1 -0
  9. package/dist/web/_app/immutable/assets/_page.CQBzp_Oe.css +1 -0
  10. package/dist/web/_app/immutable/assets/_page.CUknm1Jh.css +1 -0
  11. package/dist/web/_app/immutable/chunks/ToolSelector.CCE1hHr0.js +2 -0
  12. package/dist/web/_app/immutable/chunks/api.CTjBjPiU.js +1 -0
  13. package/dist/web/_app/immutable/chunks/{entry.CYXgDR4m.js → entry.BDsSAg1a.js} +2 -2
  14. package/dist/web/_app/immutable/chunks/{index.B0Aytz_K.js → index.BXQEgizy.js} +1 -1
  15. package/dist/web/_app/immutable/chunks/{index.CPsgU-fv.js → index.CNvYz5e_.js} +1 -1
  16. package/dist/web/_app/immutable/chunks/{scheduler.DFD7qxcZ.js → scheduler.DeaWU70L.js} +1 -1
  17. package/dist/web/_app/immutable/chunks/{stores.BRyx8O-B.js → stores.BYIFXXy3.js} +1 -1
  18. package/dist/web/_app/immutable/chunks/stores.mBipGgjw.js +1 -0
  19. package/dist/web/_app/immutable/entry/{app.CKzft-DT.js → app.CCbAFnKJ.js} +2 -2
  20. package/dist/web/_app/immutable/entry/start.BDGHATsW.js +1 -0
  21. package/dist/web/_app/immutable/nodes/0.vOgxhWzP.js +1 -0
  22. package/dist/web/_app/immutable/nodes/{1.oJbQIZvn.js → 1.C4vnvuzM.js} +1 -1
  23. package/dist/web/_app/immutable/nodes/{10.Dd5wl9TB.js → 10.BejenNwL.js} +1 -1
  24. package/dist/web/_app/immutable/nodes/11.Dx1YcRkP.js +1 -0
  25. package/dist/web/_app/immutable/nodes/{12.DoQ9E1LV.js → 12.C9dQuDmx.js} +1 -1
  26. package/dist/web/_app/immutable/nodes/13.VP7fU2h5.js +1 -0
  27. package/dist/web/_app/immutable/nodes/{2.BB8OyOCP.js → 2.DniTC2eC.js} +1 -1
  28. package/dist/web/_app/immutable/nodes/{3.Cfms9ru5.js → 3.BY0PLmXV.js} +1 -1
  29. package/dist/web/_app/immutable/nodes/4.BUb_3Atw.js +1 -0
  30. package/dist/web/_app/immutable/nodes/{5.BvbSC3f6.js → 5.DJ0O-s5e.js} +1 -1
  31. package/dist/web/_app/immutable/nodes/6.nquf-x9G.js +9 -0
  32. package/dist/web/_app/immutable/nodes/{7.Civ32duh.js → 7.BDm05vE_.js} +1 -1
  33. package/dist/web/_app/immutable/nodes/{8.TXFmgrFA.js → 8.mB-sVW7r.js} +1 -1
  34. package/dist/web/_app/immutable/nodes/{9.B9_1-2xn.js → 9.8PYvwJik.js} +1 -1
  35. package/dist/web/_app/version.json +1 -1
  36. package/dist/web/index.html +9 -9
  37. package/package.json +2 -2
  38. package/dist/web/_app/immutable/assets/0.bPTGJZag.css +0 -1
  39. package/dist/web/_app/immutable/assets/11.DoWxheGb.css +0 -1
  40. package/dist/web/_app/immutable/assets/4.D4N7n6x9.css +0 -1
  41. package/dist/web/_app/immutable/assets/6.CcFk1fVK.css +0 -1
  42. package/dist/web/_app/immutable/assets/_layout.QS8Tu4KK.css +0 -1
  43. package/dist/web/_app/immutable/assets/_page.CGsCDBRD.css +0 -1
  44. package/dist/web/_app/immutable/assets/_page.CcFk1fVK.css +0 -1
  45. package/dist/web/_app/immutable/assets/_page.D4N7n6x9.css +0 -1
  46. package/dist/web/_app/immutable/chunks/ToolSelector.D-ihlQCZ.js +0 -2
  47. package/dist/web/_app/immutable/chunks/api.BR248OCH.js +0 -1
  48. package/dist/web/_app/immutable/chunks/stores.B1g8D8DV.js +0 -1
  49. package/dist/web/_app/immutable/entry/start.DZoco_ES.js +0 -1
  50. package/dist/web/_app/immutable/nodes/0.CeyqogwF.js +0 -1
  51. package/dist/web/_app/immutable/nodes/11.Uz-0jVL7.js +0 -1
  52. package/dist/web/_app/immutable/nodes/13.6lDoUYy7.js +0 -1
  53. package/dist/web/_app/immutable/nodes/4.BRcdKGbJ.js +0 -1
  54. package/dist/web/_app/immutable/nodes/6.B4H7Hfou.js +0 -9
package/README.md CHANGED
@@ -1,28 +1,12 @@
1
1
  # aiusage — AI Coding Assistant Usage Tracker
2
2
 
3
- **Website: [aiusage.jtanx.com](https://aiusage.jtanx.com)**
4
-
5
- Track token usage, cost, and sessions across **7 AI coding tools** — local-first, no accounts required.
6
-
7
3
  [![npm version](https://img.shields.io/npm/v/@juliantanx/aiusage)](https://www.npmjs.com/package/@juliantanx/aiusage)
8
4
  [![CI](https://github.com/juliantanx/aiusage/actions/workflows/test.yml/badge.svg)](https://github.com/juliantanx/aiusage/actions/workflows/test.yml)
9
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
10
- [![Node.js](https://img.shields.io/badge/Node.js-20%2B-green.svg)](https://nodejs.org/)
11
- [![Website](https://img.shields.io/badge/Website-aiusage.jtanx.com-blue.svg)](https://aiusage.jtanx.com)
12
6
 
13
- English | [中文](https://github.com/juliantanx/aiusage/blob/main/README_zh.md)
14
-
15
- ## Quick Start
16
-
17
- **Prerequisites:** Node.js 20 or later
18
-
19
- ```bash
20
- npm install -g @juliantanx/aiusage
21
- aiusage parse
22
- aiusage serve
23
- ```
7
+ **[aiusage.jtanx.com](https://aiusage.jtanx.com)** · English | [中文](https://github.com/juliantanx/aiusage/blob/main/README_zh.md)
24
8
 
25
- Open `http://localhost:3847` to explore the dashboard.
9
+ Track token usage, cost, and sessions across **22 AI coding tools** in one local dashboard. No accounts. No telemetry. No cloud required.
26
10
 
27
11
  <p align="center">
28
12
  <img src="https://raw.githubusercontent.com/juliantanx/aiusage/a527444cf87a9c1e92f1440282ed4e94f744b910/packages/site/static/screenshots/dashboard-home.png" alt="aiusage dashboard home" width="32%" />
@@ -30,559 +14,39 @@ Open `http://localhost:3847` to explore the dashboard.
30
14
  <img src="https://raw.githubusercontent.com/juliantanx/aiusage/a527444cf87a9c1e92f1440282ed4e94f744b910/packages/site/static/screenshots/sessions.png" alt="aiusage sessions dashboard" width="32%" />
31
15
  </p>
32
16
 
33
- > If aiusage is useful, **[star this repo](https://github.com/juliantanx/aiusage)** to help more developers discover it.
34
-
35
- `aiusage` does not run a built-in background parser. If you want automatic imports, schedule `aiusage parse` with cron or Task Scheduler.
36
-
37
- ### Running in Background (PM2)
38
-
39
- `aiusage serve` runs in the foreground and stops when you close the terminal. To keep it running in the background on **Windows, macOS, and Linux**, use [PM2](https://pm2.keymetrics.io/):
40
-
41
- ```bash
42
- # Install PM2 (one-time)
43
- npm install -g pm2
44
-
45
- # Start aiusage as background services (generates config + starts PM2)
46
- aiusage pm2-start
47
-
48
- # Set auto-start on boot (Linux / macOS: run directly; Windows: run the output command as Administrator)
49
- pm2 startup
50
-
51
- # Common commands
52
- pm2 list # View running status
53
- pm2 logs # View logs
54
- pm2 stop all # Stop all services
55
- pm2 restart all # Restart all services
56
- pm2 delete all # Remove all services
57
- ```
58
-
59
- <details>
60
- <summary>Build from source</summary>
61
-
62
- ```bash
63
- git clone https://github.com/juliantanx/aiusage.git
64
- cd aiusage
65
- pnpm install
66
- pnpm build
67
- cd packages/cli
68
- npm link
69
- ```
17
+ ## Quick Start
70
18
 
71
- After pulling updates, rebuild to pick up changes:
19
+ **Prerequisites:** Node.js 20+
72
20
 
73
21
  ```bash
74
- pnpm build
22
+ npm install -g @juliantanx/aiusage
23
+ aiusage parse
24
+ aiusage serve
75
25
  ```
76
26
 
77
- If you switch Node.js versions locally, recompile the `better-sqlite3` native module for the new version:
78
-
79
- ```bash
80
- pnpm rebuild:sqlite
81
- ```
27
+ Open `http://localhost:3847` to explore the dashboard.
82
28
 
83
- > This is only needed when developing from source. Users who install via `npm install -g` do not need to do this — the module is compiled automatically during installation.
29
+ ## Supported Tools
84
30
 
85
- </details>
31
+ | | | | | |
32
+ |---|---|---|---|---|
33
+ | `Claude Code` | `Codex` | `OpenCode` | `Cursor` | `Hermes` |
34
+ | `Qoder` | `OpenClaw` | `KiloCode` | `Copilot` | `Gemini CLI` |
35
+ | `Kimi Code` | `CodeBuddy` | `Kiro` | `Grok Build` | `Antigravity` |
36
+ | `Roo Code` | `Zed` | `Goose` | `oh-my-pi` | `pi` |
37
+ | `Craft` | `Droid` | | | |
86
38
 
87
39
  ## Why aiusage
88
40
 
89
- Your AI coding tools each log usage separately — different formats, different machines, no shared view. aiusage pulls it all into one local dashboard with no accounts, no telemetry, and no cloud required.
41
+ Your AI coding tools each log usage separately — different formats, different machines, no shared view. aiusage pulls it all into one local dashboard:
90
42
 
91
43
  - **One dashboard** for tokens, cost, model mix, and tool-call activity
92
44
  - **Multi-machine sync** via GitHub, S3, or R2 — entirely optional
93
45
  - **Your data stays local** by default
94
46
 
95
- ## Supported tools
96
-
97
- | Tool | Status |
98
- |------|--------|
99
- | Claude Code | ✅ |
100
- | Codex | ✅ |
101
- | OpenCode | ✅ |
102
- | Cursor | ✅ |
103
- | Hermes | ✅ |
104
- | Qoder | ✅ |
105
- | OpenClaw | ✅ |
106
-
107
-
108
- ## CLI Reference
109
-
110
- ### `aiusage` (default)
111
-
112
- Print a usage summary to the terminal (same as `aiusage summary`).
113
-
114
- ### `aiusage parse`
115
-
116
- Import newly appended local session data from discovered source paths.
117
-
118
- | Option | Description |
119
- |--------|-------------|
120
- | `--tool <tool>` | Only parse a specific tool: `claude-code`, `codex`, `openclaw`, `opencode`, `hermes`, `qoder`, `cursor` |
121
- | `--progress` | Show real-time progress bar on stderr (TTY only, silent in pipes/CI) |
122
-
123
- ```bash
124
- aiusage parse # Parse all tools
125
- aiusage parse --tool claude-code # Only parse Claude Code logs
126
- aiusage parse --progress # Show progress bar while parsing
127
- ```
128
-
129
- ### `aiusage serve`
130
-
131
- Start the local web dashboard and runtime settings controller.
132
-
133
- | Option | Description | Default |
134
- |--------|-------------|---------|
135
- | `-p, --port <port>` | Port number | `3847` |
136
-
137
- ```bash
138
- aiusage serve # Start on port 3847
139
- aiusage serve -p 8080 # Start on port 8080
140
- ```
141
-
142
- ### `aiusage summary`
143
-
144
- Print a usage summary in the terminal.
145
-
146
- | Option | Description |
147
- |--------|-------------|
148
- | `--device <id>` | Filter by device instance ID |
149
- | `--tool <tool>` | Filter by tool type (`claude-code`, `codex`, `openclaw`, `opencode`, `hermes`, `qoder`, `cursor`) |
150
-
151
- ```bash
152
- aiusage summary # All-time summary
153
- aiusage summary --tool claude-code # Single tool
154
- ```
155
-
156
- ### `aiusage status`
157
-
158
- Show version, device name, DB path, schema version, table/view counts, record count, DB size, and sync status.
159
-
160
- ### `aiusage export`
161
-
162
- Export records as CSV, JSON, or NDJSON.
163
-
164
- | Option | Description | Required |
165
- |--------|-------------|----------|
166
- | `--format <format>` | Output format: `csv`, `json`, `ndjson` | Yes |
167
- | `-o, --output <file>` | Output file path (default: stdout) | No |
168
-
169
- ```bash
170
- aiusage export --format csv # CSV to stdout
171
- aiusage export --format json -o report.json # JSON to file
172
- aiusage export --format ndjson # NDJSON to stdout
173
- ```
174
-
175
- ### `aiusage clean`
176
-
177
- Remove old records from the local database based on age.
178
-
179
- | Option | Description | Default |
180
- |--------|-------------|---------|
181
- | `--before <duration>` | Delete data older than this duration (e.g. `30d`, `180d`) | `180d` |
182
-
183
- ```bash
184
- aiusage clean # Delete records older than 180 days
185
- aiusage clean --before 30d # Delete records older than 30 days
186
- aiusage clean --before 90d --yes # Delete records older than 90 days, skip confirm
187
- ```
188
-
189
- ### `aiusage reset`
190
-
191
- Delete all parsed records, tool calls, synced data, and the parse watermark. Source log files (`~/.claude`, `~/.codex`, etc.) are **not** affected. Use this to re-import everything from scratch.
192
-
193
- | Option | Description |
194
- |--------|-------------|
195
- | `--yes` | Skip confirmation prompt (required to execute) |
196
-
197
- ```bash
198
- aiusage reset --yes # Wipe all data, then run `aiusage parse` to re-import
199
- ```
200
-
201
- ### `aiusage recalc`
202
-
203
- Recalculate costs using the latest pricing data.
204
-
205
- ```bash
206
- aiusage recalc
207
- ```
208
-
209
- ### `aiusage init`
210
-
211
- Configure a sync backend for multi-machine data aggregation.
212
-
213
- | Option | Description |
214
- |--------|-------------|
215
- | `--backend <backend>` | Sync backend: `github`, `s3`, `skip` |
216
- | `--repo <repo>` | GitHub repository (format: `username/repo-name`) |
217
- | `--token <token>` | GitHub Personal Access Token |
218
- | `--bucket <bucket>` | S3 bucket name |
219
- | `--prefix <prefix>` | S3 object prefix (default: `aiusage/`) |
220
- | `--endpoint <endpoint>` | S3 endpoint URL |
221
- | `--region <region>` | S3 region (default: `auto`) |
222
- | `--access-key-id <id>` | S3 access key ID |
223
- | `--secret-access-key <key>` | S3 secret access key |
224
- | `--device <alias>` | Device alias |
225
-
226
- ```bash
227
- aiusage init --backend github --repo user/aiusage-data --token ghp_xxx
228
- aiusage init --backend s3 --bucket my-bucket --endpoint https://xxx.r2.cloudflarestorage.com --access-key-id AKIAxxx --secret-access-key xxx
229
- ```
230
-
231
- ### `aiusage sync`
232
-
233
- Push and pull data with the configured remote backend.
234
-
235
- ```bash
236
- aiusage sync
237
- ```
238
-
239
- ## Web Dashboard
240
-
241
- ```bash
242
- aiusage serve
243
- # Open http://localhost:3847
244
- ```
245
-
246
- `aiusage serve` hosts the following dashboard pages:
247
-
248
- - **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.
249
- - **Overview (`/overview`)** — totals, cost, active days, and per-tool breakdowns for Today, This Week, This Month, Last 30d, or All Time.
250
- - **Tokens** — token usage trends over time, with breakdown-by-type or combined total view.
251
- - **Cost** — cost trends with by-tool and by-model breakdowns.
252
- - **Models** — model share and distribution.
253
- - **Tool Calls** — tool call frequency and ranking.
254
- - **Projects** — project-level usage rollups.
255
- - **Sessions** — session browsing with filters and pagination.
256
- - **Pricing** — active model pricing reference.
257
- - **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.
258
- - **Docs** — in-app documentation with CLI reference and feature guides.
259
-
260
- **Settings behavior**
261
-
262
- - **Dashboard Poll Interval** is in milliseconds and only controls the homepage refresh cycle after the initial load.
263
- - **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.
264
- - **Local Data Retention** runs periodic cleanup only while `aiusage serve` is running. Set `0` or leave it blank to keep data forever.
265
- - **Source path** changes take effect on the next parse.
266
- - **Sync backend and credential** changes take effect on the next sync.
267
-
268
- ---
269
-
270
- ## Deployment
271
-
272
- Need multi-machine aggregation or cloud access? Choose your scenario:
273
-
274
- | Scenario | Method | Description |
275
- |----------|--------|-------------|
276
- | Multiple machines, aggregate data | [Multi-Machine Sync](#multi-machine-sync) | Sync via GitHub/S3/R2 |
277
- | Multiple machines + unified dashboard | [Docker Deployment](#docker-deployment) | Run a 24/7 dashboard from synced data |
278
-
279
- For single-machine usage, Quick Start is enough.
280
-
281
- ### Multi-Machine Sync
282
-
283
- Use this to aggregate token usage from multiple machines into one dashboard. Works with Claude Code, Codex, OpenClaw, OpenCode, Hermes, and Qoder.
284
-
285
- **Architecture:**
286
-
287
- ```
288
- Machine A ──┐
289
- Machine B ──┼──▶ GitHub / S3 / R2 (shared storage) ──▶ Any machine: aiusage summary / serve
290
- Machine C ──┘
291
- ```
292
-
293
- **Step 1 — Choose a sync backend**
294
-
295
- **Option A: GitHub (recommended)**
296
-
297
- 1. Create a **private** repository on GitHub (for example `aiusage-data`)
298
- 2. Generate a [Personal Access Token](https://github.com/settings/tokens) with `repo` scope
299
-
300
- **Option B: AWS S3 / Cloudflare R2**
301
-
302
- 1. Create an S3 or R2 bucket
303
- 2. Create an IAM user or role with read/write permissions
304
- 3. Note the access key ID, secret access key, and endpoint
305
-
306
- **Step 2 — Install and configure on each machine**
307
-
308
- On every machine that uses Claude Code, Codex, OpenClaw, OpenCode, Hermes, or Qoder:
309
-
310
- ```bash
311
- # Install aiusage CLI
312
- npm install -g @juliantanx/aiusage
313
-
314
- # Configure sync backend — GitHub
315
- aiusage init --backend github \
316
- --repo <user>/aiusage-data \
317
- --token ghp_xxxxxxxxxxxxxxxxxxxx
318
-
319
- # OR configure sync backend — S3 / R2
320
- aiusage init --backend s3 \
321
- --bucket my-aiusage-bucket \
322
- --prefix aiusage/ \
323
- --endpoint https://<account-id>.r2.cloudflarestorage.com \
324
- --region auto \
325
- --access-key-id AKIAxxxxxxxxxxxx \
326
- --secret-access-key xxxxxxxxxxxxxxxxxxxxxxxxxx
327
- ```
328
-
329
- **Step 3 — Parse and sync on each machine**
330
-
331
- ```bash
332
- aiusage parse
333
- aiusage sync
334
- ```
335
-
336
- **Step 4 — View aggregated data on any machine**
337
-
338
- ```bash
339
- aiusage sync
340
- aiusage summary
341
- aiusage serve
342
- ```
343
-
344
- **Automate (recommended)**
345
-
346
- ```bash
347
- # Linux/macOS
348
- crontab -e
349
- # Add:
350
- */30 * * * * /usr/local/bin/aiusage parse && /usr/local/bin/aiusage sync >> ~/.aiusage/cron.log 2>&1
351
-
352
- # Windows
353
- schtasks /create /tn "AiusageSync" /tr "aiusage parse && aiusage sync" /sc minute /mo 30
354
- ```
355
-
356
- **How sync works**
357
-
358
- - Each machine has a unique `deviceInstanceId` generated on first run.
359
- - Each device writes to its own daily file (`{deviceInstanceId}/YYYY/MM/DD.ndjson`) in the remote backend.
360
- - Pull reads other devices' files into the local `synced_records` table; upload writes only this device's files.
361
- - Device-partitioned files avoid write conflicts, so no locking is needed.
362
- - Sync frequency comes from your external scheduler or manual runs; aiusage does not include a built-in sync daemon.
363
- - Session IDs are anonymized via `sha256(device + sessionId)`.
364
-
365
- ---
366
-
367
- ### Docker Deployment
368
-
369
- 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.
370
-
371
- **Architecture:**
372
-
373
- ```
374
- Machine A ──┐ ┌── Browser: https://aiusage.your-domain.com
375
- Machine B ──┼──▶ GitHub / S3 / R2 ──▶ Cloud Server (Docker)
376
- Machine C ──┘ └── port 3847
377
- ```
378
-
379
- **How data flows**
380
-
381
- 1. Each dev machine runs `aiusage parse && aiusage sync` to upload local usage data.
382
- 2. The Docker container runs `aiusage sync` to pull that data into its local SQLite database.
383
- 3. The web dashboard reads from the local database and displays aggregated stats.
384
-
385
- **Data storage in Docker**
386
-
387
- | Item | Container path | Description |
388
- |------|---------------|-------------|
389
- | Database | `/root/.aiusage/cache.db` | SQLite database with aggregated usage data |
390
- | Config | `/root/.aiusage/config.json` | Sync backend config, runtime settings, and credentials |
391
- | State | `/root/.aiusage/state.json` | Consent and sync runtime state |
392
- | Watermarks | `/root/.aiusage/watermark.json` | Incremental parse cursors |
393
-
394
- All data lives under `/root/.aiusage`, which is declared as a `VOLUME`. You **must** mount this volume to persist data across container restarts.
395
-
396
- **Step 1 — Pull image and run**
397
-
398
- ```bash
399
- # Pull image
400
- docker pull juliantanx/aiusage
401
-
402
- # Run container (mount volume for data persistence)
403
- docker run -d \
404
- --name aiusage \
405
- -p 3847:3847 \
406
- -v aiusage-data:/root/.aiusage \
407
- juliantanx/aiusage
408
-
409
- # Configure sync backend
410
- docker exec -it aiusage aiusage init \
411
- --backend github \
412
- --repo <user>/aiusage-data \
413
- --token ghp_xxxxxxxxxxxxxxxxxxxx
414
-
415
- # Initial data pull
416
- docker exec -it aiusage aiusage sync
417
- ```
418
-
419
- > Without the `-v` flag, data is lost when the container is removed.
420
-
421
- **Step 2 — Scheduled sync**
422
-
423
- ```bash
424
- # Install cron in container and create scheduled task
425
- docker exec -it aiusage bash -c "apt-get update && apt-get install -y cron"
426
- docker exec -it aiusage bash -c \
427
- 'echo "*/30 * * * * aiusage sync >> /root/.aiusage/cron.log 2>&1" | crontab -'
428
- docker restart aiusage
429
- ```
430
-
431
- > 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.
432
-
433
- **Step 3 — Access**
434
-
435
- Open `http://<server-ip>:3847`.
436
-
437
- For HTTPS with a custom domain:
438
-
439
- ```bash
440
- # Caddy (auto HTTPS, recommended)
441
- caddy reverse-proxy --from aiusage.your-domain.com --to localhost:3847
442
-
443
- # Or Nginx
444
- server {
445
- listen 80;
446
- server_name aiusage.your-domain.com;
447
- location / {
448
- proxy_pass http://127.0.0.1:3847;
449
- proxy_set_header Host $host;
450
- proxy_set_header X-Real-IP $remote_addr;
451
- }
452
- }
453
- ```
454
-
455
- **Build image yourself (optional)**
456
-
457
- A `Dockerfile` is included in the project root:
458
-
459
- ```bash
460
- docker build -t aiusage .
461
- ```
462
-
463
- ---
464
-
465
- ## Data Storage
466
-
467
- | Item | Path |
468
- |------|------|
469
- | Local database | `~/.aiusage/cache.db` |
470
- | Config | `~/.aiusage/config.json` |
471
- | Sync state | `~/.aiusage/state.json` |
472
- | Parse watermarks | `~/.aiusage/watermark.json` |
473
-
474
- ### Default Source Paths
475
-
476
- `aiusage parse` auto-discovers session logs from the following default locations:
477
-
478
- | Tool | macOS | Linux | Windows |
479
- |------|-------|-------|---------|
480
- | Claude Code | `~/.claude/projects/` | `~/.claude/projects/` | `%USERPROFILE%\.claude\projects\` |
481
- | Codex | `~/.codex/sessions/` | `~/.codex/sessions/` | `%USERPROFILE%\.codex\sessions\` |
482
- | OpenClaw | `~/.openclaw/agents/*/sessions/` | `~/.openclaw/agents/*/sessions/` | `%USERPROFILE%\.openclaw\agents\*\sessions\` |
483
- | OpenCode | `~/Library/Application Support/opencode/opencode.db` | `~/.local/share/opencode/opencode.db` | `%APPDATA%\opencode\opencode.db` |
484
- | Hermes | `~/.hermes/state.db` | `~/.hermes/state.db` | `%USERPROFILE%\.hermes\state.db` |
485
- | Qoder (sessions) | `~/.qoder/logs/sessions/` | `~/.qoder/logs/sessions/` plus WSL-mounted Windows user homes | `%USERPROFILE%\.qoder\logs\sessions\` |
486
- | Qoder (SQLite) | `~/Library/Application Support/Qoder/SharedClientCache/cache/db/local.db` | `~/.local/share/Qoder/SharedClientCache/cache/db/local.db` | `%LOCALAPPDATA%\Qoder\SharedClientCache\cache\db\local.db` |
487
- | Cursor | `~/Library/Application Support/Cursor/User/globalStorage/state.vscdb` | `~/.config/Cursor/User/globalStorage/state.vscdb` | `%APPDATA%\Cursor\User\globalStorage\state.vscdb` |
488
-
489
- Discovery behavior:
490
-
491
- - **Claude Code** — recursively scans `~/.claude/projects/**` for `.jsonl` files, including nested subagent logs.
492
- - **Codex** — recursively scans `~/.codex/sessions/**` for `.jsonl` files.
493
- - **OpenClaw** — scans each agent's `sessions/` directory under `~/.openclaw/agents/*/sessions/` and skips checkpoint files.
494
- - **OpenCode** — reads the SQLite database file directly instead of `.jsonl` logs.
495
- - **Hermes** — reads the SQLite database file (`state.db`) directly. Sessions without a recorded end time are still imported if they have token data (e.g. sessions from a force-quit).
496
- - **Qoder (sessions)** — recursively scans structured session segment logs (`logs/sessions/**/segments/*.jsonl`) and imports `model.response.completed` token events. On WSL, aiusage also checks mounted Windows user homes such as `/mnt/c/Users/<user>`, `/mnt/d/Users/<user>`, and `/mnt/e/Users/<user>` for the same Qoder session-log layout.
497
- - **Qoder (SQLite)** — reads the `local.db` SQLite database directly (`SharedClientCache/cache/db/local.db`) and imports assistant messages from the `chat_message` table, joined with `chat_record` for model information. This is the primary source on macOS and is tried alongside the sessions directory.
498
- - **Cursor** — reads Cursor's `state.vscdb` SQLite database directly and imports composer conversations with token usage data.
499
-
500
- > On Linux, OpenCode respects `$XDG_DATA_HOME` if set.
501
-
502
- Qoder Desktop also creates installation files under `Program Files`, UI/cache data under `AppData/Roaming/Qoder` and `AppData/Local/.qoder`, and transcripts under `%USERPROFILE%\.qoder\projects` or `%USERPROFILE%\.qoder\cache`. These are not imported as token records: desktop `Context usage update` log lines are repeated context-window snapshots, and transcripts/conversation-history files do not contain per-request token usage.
503
-
504
- ### Custom Source Paths
505
-
506
- 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:
507
-
508
- ```json
509
- {
510
- "sources": {
511
- "claude-code": "/custom/path/.claude/projects",
512
- "codex": "/custom/path/.codex/sessions",
513
- "openclaw": "/custom/sessions-dir",
514
- "opencode": "/custom/path/opencode.db",
515
- "hermes": "/custom/path/.hermes/state.db",
516
- "qoder": "/custom/path/.qoder/logs/sessions",
517
- "qoder-db": "/custom/path/local.db",
518
- "cursor": "/custom/path/state.vscdb"
519
- }
520
- }
521
- ```
522
-
523
- Only the paths you specify are overridden; unspecified tools fall back to their defaults. `qoder` points to the session logs directory; `qoder-db` points directly to the `local.db` SQLite file.
524
-
525
- ## Database Visualization
526
-
527
- 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.
528
-
529
- ```bash
530
- aiusage status
531
- # Shows the exact DB Path, schema version, and object counts
532
- ```
533
-
534
- - Open `~/.aiusage/cache.db` as a SQLite database.
535
- - Prefer read-only mode in your database tool. `aiusage` writes to the same file and uses WAL mode.
536
- - If your tool asks about sidecar files, keep `cache.db-wal` and `cache.db-shm` alongside the main database file.
537
- - Start with the read-only views:
538
- - `v_usage_records`: one row per usage record with normalized timestamp and token totals
539
- - `v_tool_calls`: tool call rows joined with their parent usage record
540
- - `v_sessions`: session-level aggregates for pivoting and charting
541
- - Raw internal tables remain available for advanced inspection:
542
- - `records`
543
- - `tool_calls`
544
- - `synced_records`
545
- - `sync_tombstones`
546
-
547
- ## Tech Stack
548
-
549
- - **Runtime:** Node.js, TypeScript
550
- - **Database:** better-sqlite3 (local, WAL mode)
551
- - **CLI:** Commander.js
552
- - **Web:** SvelteKit + adapter-static
553
- - **Build:** tsup (core/cli), Vite (web)
554
- - **Sync:** GitHub API, AWS S3 / Cloudflare R2
555
-
556
- ## Project Structure
557
-
558
- ```text
559
- packages/
560
- core/ - Shared types, database schema, pricing data
561
- cli/ - CLI tool for parsing logs, querying data, cloud sync
562
- web/ - SvelteKit web dashboard (SPA)
563
- ```
564
-
565
- ## FAQ
566
-
567
- ### Does aiusage upload my data?
568
-
569
- No. aiusage is local-first. Your usage data stays on your machine unless you explicitly configure a sync backend.
570
-
571
- ### Can I use aiusage across multiple machines?
572
-
573
- Yes. You can sync usage data through GitHub, S3, or R2 and then view the combined result from any configured machine or Docker deployment.
574
-
575
- ### Does aiusage run a background parser automatically?
576
-
577
- No. By default, you run `aiusage parse` manually. You can automate parsing and syncing with cron, Task Scheduler, or your own scheduler.
578
-
579
- ### Which assistants are supported?
580
-
581
- aiusage currently supports Claude Code, Codex, OpenClaw, OpenCode, Hermes, and Qoder.
582
-
583
- ### Can I inspect the raw database myself?
47
+ ## Documentation
584
48
 
585
- Yes. aiusage stores data in a local SQLite database, and the README already documents how to open it in tools like DBeaver, TablePlus, DataGrip, or DB Browser for SQLite.
49
+ Full documentation CLI reference, Docker deployment, sync setup, desktop widget, and more is available on the **[Docs page](https://aiusage.jtanx.com/docs)**.
586
50
 
587
51
  ## Friends
588
52
 
@@ -592,9 +56,9 @@ Yes. aiusage stores data in a local SQLite database, and the README already docu
592
56
 
593
57
  <a href="https://www.star-history.com/?repos=juliantanx%2Faiusage&type=date&logscale=&legend=top-left">
594
58
  <picture>
595
- <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=juliantanx/aiusage&type=date&theme=dark&legend=top-left&t=20260528" />
596
- <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=juliantanx/aiusage&type=date&legend=top-left&t=20260528" />
597
- <img alt="Star History Chart" src="https://api.star-history.com/chart?repos=juliantanx/aiusage&type=date&legend=top-left&t=20260528" />
59
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=juliantanx/aiusage&type=date&theme=dark&legend=top-left&t=20260603" />
60
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=juliantanx/aiusage&type=date&legend=top-left&t=20260603" />
61
+ <img alt="Star History Chart" src="https://api.star-history.com/chart?repos=juliantanx/aiusage&type=date&legend=top-left&t=20260603" />
598
62
  </picture>
599
63
  </a>
600
64