@juliantanx/aiusage 1.2.0 → 1.3.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 (100) hide show
  1. package/README.md +159 -26
  2. package/dist/index.js +2568 -1478
  3. package/dist/web/_app/immutable/assets/0.C5PeBlns.css +1 -0
  4. package/dist/web/_app/immutable/assets/10.D4XIqeEN.css +1 -0
  5. package/dist/web/_app/immutable/assets/11.CR85TxeS.css +1 -0
  6. package/dist/web/_app/immutable/assets/12.DAmfvZ5J.css +1 -0
  7. package/dist/web/_app/immutable/assets/2.G6nSchsK.css +1 -0
  8. package/dist/web/_app/immutable/assets/3.DQh9JikT.css +1 -0
  9. package/dist/web/_app/immutable/assets/4.CnA4GaE5.css +1 -0
  10. package/dist/web/_app/immutable/assets/5.D4N7n6x9.css +1 -0
  11. package/dist/web/_app/immutable/assets/6.CrsKlz6Y.css +1 -0
  12. package/dist/web/_app/immutable/assets/7.CQvfgmQf.css +1 -0
  13. package/dist/web/_app/immutable/assets/8.DDodt1Wn.css +1 -0
  14. package/dist/web/_app/immutable/assets/9.ApFevNUr.css +1 -0
  15. package/dist/web/_app/immutable/assets/ToolSelector.BRqFUj1Q.css +1 -0
  16. package/dist/web/_app/immutable/assets/ToolSelector.Bqx3ytrl.css +1 -0
  17. package/dist/web/_app/immutable/assets/_layout.C2s9Ry1h.css +1 -0
  18. package/dist/web/_app/immutable/assets/_page.ApFevNUr.css +1 -0
  19. package/dist/web/_app/immutable/assets/_page.CQvfgmQf.css +1 -0
  20. package/dist/web/_app/immutable/assets/_page.CR85TxeS.css +1 -0
  21. package/dist/web/_app/immutable/assets/_page.CmayGpOu.css +1 -0
  22. package/dist/web/_app/immutable/assets/_page.CnA4GaE5.css +1 -0
  23. package/dist/web/_app/immutable/assets/_page.CrsKlz6Y.css +1 -0
  24. package/dist/web/_app/immutable/assets/_page.D4N7n6x9.css +1 -0
  25. package/dist/web/_app/immutable/assets/_page.DAmfvZ5J.css +1 -0
  26. package/dist/web/_app/immutable/assets/_page.DDodt1Wn.css +1 -0
  27. package/dist/web/_app/immutable/assets/_page.DQh9JikT.css +1 -0
  28. package/dist/web/_app/immutable/assets/_page.DewAUGiJ.css +1 -0
  29. package/dist/web/_app/immutable/chunks/ToolSelector.CnQ-eszE.js +2 -0
  30. package/dist/web/_app/immutable/chunks/{api.Cv9iCeAW.js → api.OwJBmtEN.js} +1 -1
  31. package/dist/web/_app/immutable/chunks/entry.DWbp2XzC.js +3 -0
  32. package/dist/web/_app/immutable/chunks/i18n.BOq44pYI.js +1 -0
  33. package/dist/web/_app/immutable/chunks/{index.BjVwNvJa.js → index.CPsgU-fv.js} +1 -1
  34. package/dist/web/_app/immutable/chunks/{index.CUfK07C5.js → index.wix8pgil.js} +1 -1
  35. package/dist/web/_app/immutable/chunks/scheduler.DFD7qxcZ.js +1 -0
  36. package/dist/web/_app/immutable/chunks/stores.B1g8D8DV.js +1 -0
  37. package/dist/web/_app/immutable/chunks/{stores.Js_X6JN8.js → stores.C3ZtRBEM.js} +1 -1
  38. package/dist/web/_app/immutable/entry/{app.D2r0s5MX.js → app.7Tmcb_qs.js} +2 -2
  39. package/dist/web/_app/immutable/entry/start.CuMG7ijt.js +1 -0
  40. package/dist/web/_app/immutable/nodes/0.GiWuXD22.js +1 -0
  41. package/dist/web/_app/immutable/nodes/{1.CRZFpn26.js → 1.CNbcoUIj.js} +1 -1
  42. package/dist/web/_app/immutable/nodes/10.DgPr3L-S.js +1 -0
  43. package/dist/web/_app/immutable/nodes/11.TrX-RGQX.js +1 -0
  44. package/dist/web/_app/immutable/nodes/12.ZW7n1TLF.js +1 -0
  45. package/dist/web/_app/immutable/nodes/2.D0gEY9nh.js +3 -0
  46. package/dist/web/_app/immutable/nodes/3.CcnPu3DZ.js +1 -0
  47. package/dist/web/_app/immutable/nodes/4.CCaCZRNi.js +13 -0
  48. package/dist/web/_app/immutable/nodes/5.Bxx7TNGK.js +1 -0
  49. package/dist/web/_app/immutable/nodes/6.8zY9a_YX.js +1 -0
  50. package/dist/web/_app/immutable/nodes/7.bOnMUP4_.js +9 -0
  51. package/dist/web/_app/immutable/nodes/8.01X9rJRT.js +1 -0
  52. package/dist/web/_app/immutable/nodes/9.DabFUxt3.js +1 -0
  53. package/dist/web/_app/version.json +1 -1
  54. package/dist/web/index.html +12 -11
  55. package/package.json +5 -3
  56. package/dist/chunk-2DX56FB6.js +0 -522
  57. package/dist/dist-4I33E46P.js +0 -42
  58. package/dist/web/_app/immutable/assets/0.Cynllvu4.css +0 -1
  59. package/dist/web/_app/immutable/assets/10.Doxq00gF.css +0 -1
  60. package/dist/web/_app/immutable/assets/11.D5bUq0yE.css +0 -1
  61. package/dist/web/_app/immutable/assets/12.BA90S8v7.css +0 -1
  62. package/dist/web/_app/immutable/assets/2.fho1OPpm.css +0 -1
  63. package/dist/web/_app/immutable/assets/3.DwwXF_G1.css +0 -1
  64. package/dist/web/_app/immutable/assets/4.CVp0A8QV.css +0 -1
  65. package/dist/web/_app/immutable/assets/5.DM2hVWjt.css +0 -1
  66. package/dist/web/_app/immutable/assets/6.NdKfVCiG.css +0 -1
  67. package/dist/web/_app/immutable/assets/7.CeV8yHSX.css +0 -1
  68. package/dist/web/_app/immutable/assets/8.BCdjuhVX.css +0 -1
  69. package/dist/web/_app/immutable/assets/9.ClvwkhDe.css +0 -1
  70. package/dist/web/_app/immutable/assets/ToolSelector.BKgB2QVk.css +0 -1
  71. package/dist/web/_app/immutable/assets/ToolSelector.HSbC8-q9.css +0 -1
  72. package/dist/web/_app/immutable/assets/_layout.BpydV4rl.css +0 -1
  73. package/dist/web/_app/immutable/assets/_page.BA90S8v7.css +0 -1
  74. package/dist/web/_app/immutable/assets/_page.BCdjuhVX.css +0 -1
  75. package/dist/web/_app/immutable/assets/_page.CVp0A8QV.css +0 -1
  76. package/dist/web/_app/immutable/assets/_page.CeV8yHSX.css +0 -1
  77. package/dist/web/_app/immutable/assets/_page.ClvwkhDe.css +0 -1
  78. package/dist/web/_app/immutable/assets/_page.D5bUq0yE.css +0 -1
  79. package/dist/web/_app/immutable/assets/_page.DM2hVWjt.css +0 -1
  80. package/dist/web/_app/immutable/assets/_page.DTuZozBR.css +0 -1
  81. package/dist/web/_app/immutable/assets/_page.Doxq00gF.css +0 -1
  82. package/dist/web/_app/immutable/assets/_page.DwwXF_G1.css +0 -1
  83. package/dist/web/_app/immutable/assets/_page.NdKfVCiG.css +0 -1
  84. package/dist/web/_app/immutable/chunks/ToolSelector.RXWBkdpM.js +0 -2
  85. package/dist/web/_app/immutable/chunks/entry.C9S4R-C0.js +0 -3
  86. package/dist/web/_app/immutable/chunks/i18n.CrmYDWvg.js +0 -1
  87. package/dist/web/_app/immutable/chunks/scheduler.DukoKnjQ.js +0 -1
  88. package/dist/web/_app/immutable/entry/start.DosCYfdN.js +0 -1
  89. package/dist/web/_app/immutable/nodes/0.CQBqRzIr.js +0 -1
  90. package/dist/web/_app/immutable/nodes/10.Jb_wogsG.js +0 -1
  91. package/dist/web/_app/immutable/nodes/11.CpuiQa6R.js +0 -1
  92. package/dist/web/_app/immutable/nodes/12.BiWlfD7q.js +0 -1
  93. package/dist/web/_app/immutable/nodes/2.CQudsTBz.js +0 -3
  94. package/dist/web/_app/immutable/nodes/3.Dg9c_XQX.js +0 -1
  95. package/dist/web/_app/immutable/nodes/4.DE3OvqSg.js +0 -11
  96. package/dist/web/_app/immutable/nodes/5.sGu0NOiv.js +0 -1
  97. package/dist/web/_app/immutable/nodes/6.BOL9Fhgv.js +0 -1
  98. package/dist/web/_app/immutable/nodes/7.B2wRNntO.js +0 -1
  99. package/dist/web/_app/immutable/nodes/8.BVACtdPg.js +0 -1
  100. package/dist/web/_app/immutable/nodes/9.DXxXyKe4.js +0 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # aiusage
2
2
 
3
- Track AI coding assistant usage, token consumption, cost, and tool calls in one place across Claude Code, Codex, OpenClaw, OpenCode, and Hermes.
3
+ Track AI coding assistant usage, token consumption, cost, and tool calls in one place across Claude Code, Codex, OpenClaw, OpenCode, Hermes, and Qoder.
4
4
 
5
5
  English | [中文](https://github.com/juliantanx/aiusage/blob/main/README_zh.md)
6
6
 
@@ -14,7 +14,7 @@ English | [中文](https://github.com/juliantanx/aiusage/blob/main/README_zh.md)
14
14
 
15
15
  ## Quick Start
16
16
 
17
- **Prerequisites:** Node.js >= 18 (tested on v18 LTS and v22 LTS; Node.js 16 and below are not supported)
17
+ **Prerequisites:** Node.js 18 or later
18
18
 
19
19
  ```bash
20
20
  # Install
@@ -55,30 +55,154 @@ After pulling updates, rebuild to pick up changes:
55
55
  pnpm build
56
56
  ```
57
57
 
58
+ If you switch Node.js versions locally, recompile the `better-sqlite3` native module for the new version:
59
+
60
+ ```bash
61
+ pnpm rebuild:sqlite
62
+ ```
63
+
64
+ > 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.
65
+
58
66
  </details>
59
67
 
60
68
  ## Screenshots
61
69
 
62
- ![Homepage dashboard](https://cdn.jsdelivr.net/gh/juliantanx/aiusage@main/docs/assets/readme/home.png)
70
+ ![Homepage dashboard](https://cdn.jsdelivr.net/gh/juliantanx/aiusage@0ae8299/docs/assets/readme/home.png)
71
+
72
+ ![Overview page](https://cdn.jsdelivr.net/gh/juliantanx/aiusage@0ae8299/docs/assets/readme/overview.png)
73
+
74
+ ![Token usage page](https://cdn.jsdelivr.net/gh/juliantanx/aiusage@0ae8299/docs/assets/readme/token.png)
75
+
76
+ ## CLI Reference
77
+
78
+ ### `aiusage` (default)
79
+
80
+ Print a usage summary to the terminal (same as `aiusage summary`).
81
+
82
+ ### `aiusage parse`
83
+
84
+ Import newly appended local session data from discovered source paths.
85
+
86
+ | Option | Description |
87
+ |--------|-------------|
88
+ | `--tool <tool>` | Only parse a specific tool: `claude-code`, `codex`, `openclaw`, `opencode`, `hermes`, `qoder` |
89
+ | `--progress` | Show real-time progress bar on stderr (TTY only, silent in pipes/CI) |
90
+
91
+ ```bash
92
+ aiusage parse # Parse all tools
93
+ aiusage parse --tool claude-code # Only parse Claude Code logs
94
+ aiusage parse --progress # Show progress bar while parsing
95
+ ```
96
+
97
+ ### `aiusage serve`
98
+
99
+ Start the local web dashboard and runtime settings controller.
100
+
101
+ | Option | Description | Default |
102
+ |--------|-------------|---------|
103
+ | `-p, --port <port>` | Port number | `3847` |
104
+
105
+ ```bash
106
+ aiusage serve # Start on port 3847
107
+ aiusage serve -p 8080 # Start on port 8080
108
+ ```
109
+
110
+ ### `aiusage summary`
111
+
112
+ Print a usage summary in the terminal.
113
+
114
+ | Option | Description |
115
+ |--------|-------------|
116
+ | `--device <id>` | Filter by device instance ID |
117
+ | `--tool <tool>` | Filter by tool type |
118
+
119
+ ```bash
120
+ aiusage summary # All-time summary
121
+ aiusage summary --tool claude-code # Single tool
122
+ ```
123
+
124
+ ### `aiusage status`
125
+
126
+ Show version, device name, DB path, schema version, table/view counts, record count, DB size, and sync status.
127
+
128
+ ### `aiusage export`
63
129
 
64
- ![Overview page](https://cdn.jsdelivr.net/gh/juliantanx/aiusage@main/docs/assets/readme/overview.png)
130
+ Export records as CSV, JSON, or NDJSON.
65
131
 
66
- ![Token usage page](https://cdn.jsdelivr.net/gh/juliantanx/aiusage@main/docs/assets/readme/token.png)
132
+ | Option | Description | Required |
133
+ |--------|-------------|----------|
134
+ | `--format <format>` | Output format: `csv`, `json`, `ndjson` | Yes |
135
+ | `-o, --output <file>` | Output file path (default: stdout) | No |
67
136
 
68
- ## Common Commands
137
+ ```bash
138
+ aiusage export --format csv # CSV to stdout
139
+ aiusage export --format json -o report.json # JSON to file
140
+ aiusage export --format ndjson # NDJSON to stdout
141
+ ```
142
+
143
+ ### `aiusage clean`
144
+
145
+ Remove old records from the local database based on age.
146
+
147
+ | Option | Description | Default |
148
+ |--------|-------------|---------|
149
+ | `--before <duration>` | Delete data older than this duration (e.g. `30d`, `180d`) | `180d` |
150
+
151
+ ```bash
152
+ aiusage clean # Delete records older than 180 days
153
+ aiusage clean --before 30d # Delete records older than 30 days
154
+ aiusage clean --before 90d --yes # Delete records older than 90 days, skip confirm
155
+ ```
69
156
 
70
- | Command | Purpose |
71
- | --- | --- |
72
- | `aiusage` | Print the same terminal summary as `aiusage summary` |
73
- | `aiusage parse` | Import newly appended local session data from discovered source paths |
74
- | `aiusage serve` | Start the local dashboard and runtime settings controller |
75
- | `aiusage summary` | Print a usage summary in the terminal |
76
- | `aiusage status` | Show database path, schema version, and record counts |
77
- | `aiusage sync` | Push and pull data with a configured remote backend |
78
- | `aiusage export` | Export records as CSV, JSON, or NDJSON |
79
- | `aiusage clean` | Remove old data |
80
- | `aiusage recalc` | Recalculate costs with updated pricing |
81
- | `aiusage init` | Configure a sync backend |
157
+ ### `aiusage reset`
158
+
159
+ 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.
160
+
161
+ | Option | Description |
162
+ |--------|-------------|
163
+ | `--yes` | Skip confirmation prompt (required to execute) |
164
+
165
+ ```bash
166
+ aiusage reset --yes # Wipe all data, then run `aiusage parse` to re-import
167
+ ```
168
+
169
+ ### `aiusage recalc`
170
+
171
+ Recalculate costs using the latest pricing data.
172
+
173
+ ```bash
174
+ aiusage recalc
175
+ ```
176
+
177
+ ### `aiusage init`
178
+
179
+ Configure a sync backend for multi-machine data aggregation.
180
+
181
+ | Option | Description |
182
+ |--------|-------------|
183
+ | `--backend <backend>` | Sync backend: `github`, `s3`, `skip` |
184
+ | `--repo <repo>` | GitHub repository (format: `username/repo-name`) |
185
+ | `--token <token>` | GitHub Personal Access Token |
186
+ | `--bucket <bucket>` | S3 bucket name |
187
+ | `--prefix <prefix>` | S3 object prefix (default: `aiusage/`) |
188
+ | `--endpoint <endpoint>` | S3 endpoint URL |
189
+ | `--region <region>` | S3 region (default: `auto`) |
190
+ | `--access-key-id <id>` | S3 access key ID |
191
+ | `--secret-access-key <key>` | S3 secret access key |
192
+ | `--device <alias>` | Device alias |
193
+
194
+ ```bash
195
+ aiusage init --backend github --repo user/aiusage-data --token ghp_xxx
196
+ aiusage init --backend s3 --bucket my-bucket --endpoint https://xxx.r2.cloudflarestorage.com --access-key-id AKIAxxx --secret-access-key xxx
197
+ ```
198
+
199
+ ### `aiusage sync`
200
+
201
+ Push and pull data with the configured remote backend.
202
+
203
+ ```bash
204
+ aiusage sync
205
+ ```
82
206
 
83
207
  ## Web Dashboard
84
208
 
@@ -124,7 +248,7 @@ For single-machine usage, Quick Start is enough.
124
248
 
125
249
  ### Multi-Machine Sync
126
250
 
127
- Use this to aggregate token usage from multiple machines into one dashboard. Works with Claude Code, Codex, OpenClaw, OpenCode, and Hermes.
251
+ Use this to aggregate token usage from multiple machines into one dashboard. Works with Claude Code, Codex, OpenClaw, OpenCode, Hermes, and Qoder.
128
252
 
129
253
  **Architecture:**
130
254
 
@@ -149,7 +273,7 @@ Machine C ──┘
149
273
 
150
274
  **Step 2 — Install and configure on each machine**
151
275
 
152
- On every machine that uses Claude Code, Codex, OpenClaw, OpenCode, or Hermes:
276
+ On every machine that uses Claude Code, Codex, OpenClaw, OpenCode, Hermes, or Qoder:
153
277
 
154
278
  ```bash
155
279
  # Install aiusage CLI
@@ -312,7 +436,8 @@ docker build -t aiusage .
312
436
  |------|------|
313
437
  | Local database | `~/.aiusage/cache.db` |
314
438
  | Config | `~/.aiusage/config.json` |
315
- | State (watermarks, sync) | `~/.aiusage/state.json` |
439
+ | Sync state | `~/.aiusage/state.json` |
440
+ | Parse watermarks | `~/.aiusage/watermark.json` |
316
441
 
317
442
  ### Default Source Paths
318
443
 
@@ -325,6 +450,8 @@ docker build -t aiusage .
325
450
  | OpenClaw | `~/.openclaw/agents/*/sessions/` | `~/.openclaw/agents/*/sessions/` | `%USERPROFILE%\.openclaw\agents\*\sessions\` |
326
451
  | OpenCode | `~/Library/Application Support/opencode/opencode.db` | `~/.local/share/opencode/opencode.db` | `%APPDATA%\opencode\opencode.db` |
327
452
  | Hermes | `~/.hermes/state.db` | `~/.hermes/state.db` | `%USERPROFILE%\.hermes\state.db` |
453
+ | Qoder (sessions) | `~/.qoder/logs/sessions/` | `~/.qoder/logs/sessions/` plus WSL-mounted Windows user homes | `%USERPROFILE%\.qoder\logs\sessions\` |
454
+ | 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` |
328
455
 
329
456
  Discovery behavior:
330
457
 
@@ -333,9 +460,13 @@ Discovery behavior:
333
460
  - **OpenClaw** — scans each agent's `sessions/` directory under `~/.openclaw/agents/*/sessions/` and skips checkpoint files.
334
461
  - **OpenCode** — reads the SQLite database file directly instead of `.jsonl` logs.
335
462
  - **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).
463
+ - **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.
464
+ - **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.
336
465
 
337
466
  > On Linux, OpenCode respects `$XDG_DATA_HOME` if set.
338
467
 
468
+ 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.
469
+
339
470
  ### Custom Source Paths
340
471
 
341
472
  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:
@@ -347,12 +478,14 @@ If you installed a tool to a non-default location, override the paths in the **S
347
478
  "codex": "/custom/path/.codex/sessions",
348
479
  "openclaw": "/custom/sessions-dir",
349
480
  "opencode": "/custom/path/opencode.db",
350
- "hermes": "/custom/path/.hermes/state.db"
481
+ "hermes": "/custom/path/.hermes/state.db",
482
+ "qoder": "/custom/path/.qoder/logs/sessions",
483
+ "qoder-db": "/custom/path/local.db"
351
484
  }
352
485
  }
353
486
  ```
354
487
 
355
- Only the paths you specify are overridden; unspecified tools fall back to their defaults.
488
+ 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.
356
489
 
357
490
  ## Database Visualization
358
491
 
@@ -402,9 +535,9 @@ packages/
402
535
 
403
536
  <a href="https://www.star-history.com/?repos=juliantanx%2Faiusage&type=date&logscale=&legend=top-left">
404
537
  <picture>
405
- <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=juliantanx/aiusage&type=date&theme=dark&legend=top-left" />
406
- <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=juliantanx/aiusage&type=date&legend=top-left" />
407
- <img alt="Star History Chart" src="https://api.star-history.com/chart?repos=juliantanx/aiusage&type=date&legend=top-left" />
538
+ <source media="(prefers-color-scheme: dark)" srcset="https://api.star-history.com/chart?repos=juliantanx/aiusage&type=date&theme=dark&legend=top-left&t=20260524" />
539
+ <source media="(prefers-color-scheme: light)" srcset="https://api.star-history.com/chart?repos=juliantanx/aiusage&type=date&legend=top-left&t=20260524" />
540
+ <img alt="Star History Chart" src="https://api.star-history.com/chart?repos=juliantanx/aiusage&type=date&legend=top-left&t=20260524" />
408
541
  </picture>
409
542
  </a>
410
543