ai-usage-analyzer 0.2.0 → 0.2.1

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/README.md CHANGED
@@ -17,60 +17,13 @@ TUI analyzer for local AI coding agent token consumption. Auto-detects
17
17
 
18
18
  Requires **Node.js ≥ 22.5** (for built-in `node:sqlite`).
19
19
 
20
- Pick whichever fits your workflow:
21
-
22
- ### Option 1: `npx` from GitHub (zero install, fastest to try)
23
-
24
20
  ```bash
21
+ # Try it (no install)
25
22
  npx -y github:adetxt/ai-usage-analyzer
26
- # or with a specific ref
27
- npx -y github:adetxt/ai-usage-analyzer#v0.1.0
28
- ```
29
-
30
- No clone, no `node_modules`, no global install. npx downloads the repo
31
- on first run and caches it. Subsequent runs are instant.
32
23
 
33
- ### Option 2: Clone + install (best for development / contribution)
34
-
35
- ```bash
36
- git clone https://github.com/adetxt/ai-usage-analyzer.git
37
- cd ai-usage-analyzer
38
- pnpm install
39
- pnpm link --global # exposes the `ai-usage` command globally
40
- ```
41
-
42
- > Uses `pnpm` (declared in the `packageManager` field). `pnpm-lock.yaml`
43
- > is committed as the source of truth for reproducible installs.
44
-
45
- ### Option 3: Install globally from GitHub (no clone)
46
-
47
- ```bash
24
+ # Or install globally
48
25
  pnpm add -g git+https://github.com/adetxt/ai-usage-analyzer.git
49
- # or with npm
50
- npm install -g git+https://github.com/adetxt/ai-usage-analyzer.git
51
- # then
52
- ai-usage
53
- ```
54
-
55
- ### Option 4: From npm registry (when published)
56
-
57
- ```bash
58
- npx -y ai-usage-analyzer
59
- # or
60
- pnpm add -g ai-usage-analyzer
61
- ```
62
-
63
- To publish your own copy: `npm login && npm publish --access public`
64
- (requires the `ai-usage-analyzer` name to be available on npmjs.com,
65
- or use a scoped name like `@yourname/ai-usage-analyzer` and update
66
- the `name` field in `package.json` first).
67
-
68
- ### Verify install
69
-
70
- ```bash
71
26
  ai-usage --help
72
- # or via npx
73
- npx -y github:adetxt/ai-usage-analyzer --help
74
27
  ```
75
28
 
76
29
  ## Usage
@@ -78,139 +31,48 @@ npx -y github:adetxt/ai-usage-analyzer --help
78
31
  ```bash
79
32
  ai-usage # default TUI
80
33
  ai-usage --top 10 # show top 10 heaviest sessions
81
- ai-usage --json # machine-readable JSON output
82
- ai-usage --markdown # GitHub-flavored Markdown report
83
- ai-usage --md > report.md # same, save to file
84
- ai-usage -h # help (also --help)
34
+ ai-usage --json # machine-readable JSON
35
+ ai-usage --md > report.md # save as markdown
85
36
  ```
86
37
 
87
- ### Environment overrides
38
+ ## Supported tools
88
39
 
89
- If a tool's data lives outside the default location, override its base path:
40
+ | Tool | Default path | Tokens |
41
+ |---|---|---|
42
+ | Claude Code | `~/.claude/projects` | presence only |
43
+ | Codex | `~/.codex/sessions/YYYY/MM/DD/` | yes |
44
+ | OpenCode | `~/.local/share/opencode/opencode.db` | yes (+cost) |
45
+ | MimoCode | `~/.local/share/mimocode/mimocode.db` | yes (+cost) |
46
+ | GitHub Copilot | `~/.copilot/session-state/` | presence only |
47
+ | Antigravity | `~/Library/Application Support/Antigravity` | presence only |
48
+ | Gemini CLI | `~/.gemini/antigravity/conversations` | presence only |
90
49
 
91
- ```bash
92
- export CLAUDE_HOME=/custom/path/to/.claude
93
- export CODEX_HOME=/custom/path/to/.codex
94
- export OPENCODE_HOME=/custom/path/to/.local/share/opencode
95
- export MIMOCODE_HOME=/custom/path/to/.local/share/mimocode
96
- export COPILOT_HOME=/custom/path/to/.copilot
97
- export ANTIGRAVITY_HOME=/custom/path/to/Antigravity
98
- export GEMINI_HOME=/custom/path/to/.gemini
99
- ```
50
+ ## Path overrides
100
51
 
101
- Or pass all at once via JSON:
52
+ Override any tool's base path with an env var (`CLAUDE_HOME`, `CODEX_HOME`,
53
+ `OPENCODE_HOME`, `MIMOCODE_HOME`, `COPILOT_HOME`, `ANTIGRAVITY_HOME`,
54
+ `GEMINI_HOME`), or pass all at once via JSON:
102
55
 
103
56
  ```bash
104
57
  export AI_USAGE_PATHS_JSON='{"codex":"/data/codex","opencode":"/data/oc.db"}'
105
58
  ```
106
59
 
107
- ## Supported tools
108
-
109
- | Tool | Path | Token data | Source format |
110
- |---|---|---|---|
111
- | Claude Code | `~/.claude/transcripts` | presence only | `ses_*.jsonl` |
112
- | Codex | `~/.codex/sessions/YYYY/MM/DD/` | **yes** | `rollout-*.jsonl` `token_count` events |
113
- | OpenCode | `~/.local/share/opencode/opencode.db` | **yes** (+cost) | SQLite |
114
- | MimoCode | `~/.local/share/mimocode/mimocode.db` | **yes** (+cost, when present) | SQLite |
115
- | GitHub Copilot | `~/.copilot/session-state/` | presence only | `events.jsonl` |
116
- | Antigravity | `~/Library/Application Support/Antigravity` | presence only | dir scan |
117
- | Gemini CLI | `~/.gemini/antigravity/conversations` | presence only | `*.pb` protobuf |
118
-
119
60
  ## Token breakdown
120
61
 
121
- For tools that record token data, the analyzer shows the full breakdown:
62
+ For tools that record token data, the analyzer shows input, output, cache
63
+ read, cache write, and reasoning tokens. Cache hits are cheap; reasoning is
64
+ the extended-thinking/chain-of-thought cost.
122
65
 
123
- - **Input** prompt tokens sent to the model
124
- - **Output** — completion tokens generated by the model
125
- - **Cache Read** — prompt tokens served from the provider's cache (cheap)
126
- - **Cache Write** — prompt tokens cached for future use (OpenCode only)
127
- - **Reasoning** — extended thinking / chain-of-thought tokens
128
-
129
- The TUI is adaptive: at terminal widths below 110 columns it drops
130
- non-essential columns; at 110+ it shows the full breakdown with project
131
- paths, per-tool token columns, and longer distribution bars.
132
-
133
- ## Architecture
66
+ ## How it works
134
67
 
135
68
  ```
136
69
  src/
137
- ├── detectors.js auto-path discovery (env → well-known locations)
138
- ├── loaders.js SQLite + JSONL parsers → unified session record
139
- ├── aggregate.js per-project / per-week / per-month grouping
140
- ├── render.js TUI (chalk + cli-table3 + boxen + gradient-string)
70
+ ├── detectors.js auto-path discovery (env → well-known locations)
71
+ ├── loaders.js SQLite + JSONL parsers → unified session record
72
+ ├── aggregate.js per-project / per-week / per-month grouping
73
+ ├── render.js TUI • markdown.js → Markdown report
141
74
  bin/
142
- └── ai-usage.js entry point
143
- ```
144
-
145
- The loader produces a unified record shape:
146
-
147
- ```ts
148
- {
149
- tool, sessionId, project, title, week, month, ts,
150
- tokensInput, tokensOutput, tokensCacheRead, tokensCacheWrite,
151
- tokensReasoning, tokensTotal, cost, model
152
- }
153
- ```
154
-
155
- The aggregator then groups by project / week / month, and the renderer
156
- turns each grouping into a colored table with a distribution bar.
157
-
158
- ## Output modes
159
-
160
- ### TUI (default)
161
-
162
- Color-coded, boxed tables with bar charts. Adapts to terminal width.
163
-
164
- ### JSON (`--json`)
165
-
166
- Single JSON object with detection results, summary, raw sessions, and errors.
167
- Suitable for piping into `jq` or feeding a dashboard.
168
-
169
- ```bash
170
- ai-usage --json | jq '.summary'
171
- # {
172
- # "n": 411,
173
- # "tokensTotal": 1558000000,
174
- # "tokensInput": 420900000,
175
- # "tokensOutput": 4450000,
176
- # "tokensCacheRead": 1130000000,
177
- # "tokensCacheWrite": 49000,
178
- # "tokensReasoning": 2210000,
179
- # "cost": 29.4,
180
- # "avg": 3790000
181
- # }
182
- ```
183
-
184
- ### Markdown (`--markdown` / `--md`)
185
-
186
- GitHub-flavored markdown report with the same sections as the TUI (header,
187
- detected tools, overview, token breakdown, per-project, per-month, per-week,
188
- top sessions, notes). Designed to be pasted into GitHub issues, PRs, or
189
- Notion pages.
190
-
191
- ```bash
192
- ai-usage --md > report.md
193
- cat report.md # or just paste the output into a GitHub comment
194
- ```
195
-
196
- Distribution bars use Unicode block characters (`█░`) so they render in
197
- plain markdown without colors. Sample output:
198
-
199
- ```markdown
200
- # AI Token Usage Report
201
-
202
- **Range**: 2026-04-01 → 2026-06-27
203
- **Sessions**: 411
204
- **Total tokens**: 1.58B
205
- **Cost**: $29.40 (opencode only)
206
-
207
- ## Detected AI Tools
208
-
209
- | Tool | Status | Path | Count | Tokens |
210
- |---|---|---|---:|---|
211
- | Codex | ✅ present | `~/.codex/sessions` | 94 | ✅ |
212
- | OpenCode | ✅ present | `~/.local/share/opencode/opencode.db` | 328 | ✅ |
213
- | ...
75
+ └── ai-usage.js entry point
214
76
  ```
215
77
 
216
78
  ## License
package/bin/ai-usage.js CHANGED
@@ -49,7 +49,7 @@ Environment overrides (per-tool data path):
49
49
  AI_USAGE_PATHS_JSON='{"codex":"/custom/path",...}'
50
50
 
51
51
  Supported tools:
52
- • Claude Code — ~/.claude/transcripts (presence only)
52
+ • Claude Code — ~/.claude/projects (presence only)
53
53
  • Codex — ~/.codex/sessions (tokens from token_count events)
54
54
  • OpenCode — ~/.local/share/opencode/opencode.db (tokens + cost)
55
55
  • MimoCode — ~/.local/share/mimocode/mimocode.db (tokens + cost)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-usage-analyzer",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "TUI analyzer for local AI coding agent token usage. Auto-detects Claude Code, Codex, OpenCode, MimoCode, Copilot, Antigravity, and Gemini.",
5
5
  "type": "module",
6
6
  "packageManager": "pnpm@10.33.0",
package/src/detectors.js CHANGED
@@ -56,25 +56,28 @@ const DETECTORS = [
56
56
  name: 'Claude Code',
57
57
  kind: 'jsonl',
58
58
  envVar: 'CLAUDE_HOME',
59
- candidatePaths: () => {
60
- const base = env.CLAUDE_HOME || join(HOME, '.claude');
61
- return [
62
- join(base, 'transcripts'),
63
- join(base, 'projects'),
64
- ];
65
- },
59
+ candidatePaths: () => [
60
+ env.CLAUDE_HOME
61
+ ? join(env.CLAUDE_HOME, 'projects')
62
+ : join(HOME, '.claude', 'projects'),
63
+ ],
66
64
  count: (p) => {
67
65
  if (!p) return 0;
68
66
  let n = 0;
69
- try {
70
- for (const f of readdirSync(p)) {
71
- if (f.startsWith('ses_') && f.endsWith('.jsonl')) n++;
72
- }
73
- } catch {}
67
+ function walk(dir) {
68
+ try {
69
+ for (const e of readdirSync(dir, { withFileTypes: true })) {
70
+ const full = join(dir, e.name);
71
+ if (e.isDirectory()) walk(full);
72
+ else if (e.isFile() && e.name.endsWith('.jsonl')) n++;
73
+ }
74
+ } catch {}
75
+ }
76
+ walk(p);
74
77
  return n;
75
78
  },
76
79
  hasTokens: false, // transcripts only contain text, no token counts
77
- description: '~/.claude/transcripts/*.jsonl (no token data stored locally)',
80
+ description: '~/.claude/projects/*/<UUID>.jsonl (no token data stored locally)',
78
81
  },
79
82
 
80
83
  // -----------------------------------------------------------------------