claude-roi 0.5.0 → 0.7.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.
package/CLAUDE.md ADDED
@@ -0,0 +1,119 @@
1
+ # CLAUDE.md — Codelens-AI
2
+
3
+ ## Project Overview
4
+
5
+ **Codelens AI** (`claude-roi` on npm) is a CLI tool that measures ROI from AI coding agents by correlating Claude Code token usage with git commit output. It parses Claude Code session files, analyzes git history, and serves an interactive dashboard at `http://localhost:3457`.
6
+
7
+ **Version:** 0.6.0
8
+ **License:** MIT
9
+ **npm package:** `claude-roi`
10
+
11
+ ## Tech Stack
12
+
13
+ - **Runtime:** Node.js >= 18, ES modules (`"type": "module"`)
14
+ - **Backend:** Express.js 5.0.0
15
+ - **CLI:** Commander.js 13.0.0
16
+ - **Frontend:** Single-file HTML (`src/dashboard.html`) with vanilla JS + Chart.js 4.4.7
17
+ - **Testing:** Playwright (E2E)
18
+ - **Styling:** Inline CSS with CSS variables, glassmorphism design, dark/light theme
19
+
20
+ ## Project Structure
21
+
22
+ ```
23
+ src/
24
+ ├── index.js # CLI entry point & orchestration (Commander)
25
+ ├── claude-parser.js # Parses JSONL session files from ~/.claude/projects/
26
+ ├── git-analyzer.js # Git log analysis, branch detection, diff stats
27
+ ├── correlator.js # Matches sessions to commits via file overlap + time window
28
+ ├── metrics.js # ROI calculations, grades, insights, heatmap, survival rate
29
+ ├── server.js # Express REST API routes
30
+ ├── cache.js # Smart caching with stale file detection
31
+ ├── dashboard.html # Single-file SPA dashboard (3000+ lines)
32
+ └── agents/ # Agent integration stubs (claude/, cursor/)
33
+
34
+ tests/
35
+ └── dashboard.spec.js # Playwright E2E tests
36
+
37
+ .github/workflows/
38
+ ├── ci.yml # CI: syntax check, Node 18/20/22 matrix
39
+ └── release.yml # npm publish on version tag push
40
+ ```
41
+
42
+ ## Data Flow
43
+
44
+ ```
45
+ Claude Sessions (JSONL) → claude-parser.js → [Cache] → git-analyzer.js
46
+ → correlator.js → metrics.js → server.js (REST API) → dashboard.html
47
+ ```
48
+
49
+ ## Key API Routes (server.js)
50
+
51
+ - `GET /` — dashboard HTML
52
+ - `GET /api/all` — full payload
53
+ - `GET /api/summary` — hero stats + insights
54
+ - `GET /api/timeline` — daily cost/output chart data
55
+ - `GET /api/sessions` — paginated sessions with sorting
56
+ - `GET /api/models` — model breakdown
57
+ - `GET /api/heatmap` — productivity heatmap
58
+ - `GET /api/tools` — tool usage breakdown
59
+ - `GET /api/survival` — line survival stats
60
+ - `GET /api/tokens` — detailed token analytics
61
+ - `POST /api/refresh` — force re-parse
62
+
63
+ ## CLI Usage
64
+
65
+ ```bash
66
+ npx claude-roi # defaults: 30 days, port 3457
67
+ npx claude-roi --days 90 # custom lookback
68
+ npx claude-roi --port 8080 # custom port
69
+ npx claude-roi --no-open # don't auto-open browser
70
+ npx claude-roi --json # dump raw JSON to stdout
71
+ npx claude-roi --project X # filter by project name
72
+ npx claude-roi --refresh # force full re-parse
73
+ ```
74
+
75
+ ## Development Commands
76
+
77
+ ```bash
78
+ npm install # install dependencies
79
+ npm test # run Playwright E2E tests (needs fixtures)
80
+ node src/index.js # run locally
81
+ node --check src/*.js # syntax validation
82
+ ```
83
+
84
+ ## Key Design Decisions
85
+
86
+ - **Single-file dashboard** — no build step, served directly by Express
87
+ - **Zero-config** — auto-discovers `~/.claude/projects/`
88
+ - **Smart caching** — incremental parsing, only re-processes changed JSONL files (`~/.cache/agent-analytics/`)
89
+ - **File-first correlation** — sessions matched to commits by file overlap, 2-hour temporal buffer
90
+ - **Privacy-first** — all data stays local, no telemetry
91
+ - **Version-aware pricing** — token costs reflect Anthropic's pricing tiers per model
92
+
93
+ ## Coding Conventions
94
+
95
+ - ES module imports (`import`/`export`)
96
+ - No build tooling or transpilation
97
+ - Inline styles and scripts in dashboard.html (no external CSS/JS bundles)
98
+ - Express 5 (path params, async error handling)
99
+ - Functions and variables use camelCase
100
+ - Constants defined at module top
101
+
102
+ ## Available Skills
103
+
104
+ Use these skills when working on this project:
105
+
106
+ - **`/simplify`** — Review changed code for reuse, quality, and efficiency, then fix issues found. Use after writing or modifying code.
107
+ - **`/frontend-design`** — Create distinctive, production-grade frontend interfaces. Use when modifying `dashboard.html` or building new UI components.
108
+ - **`/claude-developer-platform`** — Build apps with the Claude API or Anthropic SDK. Use when working on agent integrations in `src/agents/`.
109
+ - **`/find-skills`** — Discover and install new agent skills for extended capabilities.
110
+ - **`/keybindings-help`** — Configure keyboard shortcuts for Claude Code.
111
+
112
+ ## Important Notes
113
+
114
+ - The dashboard is a single 3000+ line HTML file — changes should maintain the inline architecture
115
+ - Cache is stored at `~/.cache/agent-analytics/parsed-sessions.json`
116
+ - Session JSONL files are at `~/.claude/projects/`
117
+ - Token pricing is hardcoded in `claude-parser.js` — update when Anthropic changes pricing
118
+ - Playwright tests require Claude session fixtures to run (run locally, not in CI)
119
+ - CI runs syntax checks only; E2E tests are local-only
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Codelens AI
2
2
 
3
+ **[codelensai-dev.vercel.app](https://codelensai-dev.vercel.app/)**
4
+
3
5
  **Agent Productivity-to-Cost Correlator** — Is your AI coding agent actually shipping code?
4
6
 
5
7
  Codelens AI ties Claude Code token usage to actual git output. It reads your local Claude Code session files, correlates them with git commits by timestamp, and serves a dashboard answering: *"Am I getting ROI from my AI coding agent?"*
@@ -77,6 +79,11 @@ This parses your `~/.claude/projects/` session data, analyzes your git repos, an
77
79
  | **Model Comparison** | Efficiency breakdown across Opus, Sonnet, and Haiku |
78
80
  | **Branch Awareness** | What % of AI commits landed on production |
79
81
  | **Peak Hours** | Hour-of-day x day-of-week productivity heatmap |
82
+ | **Autonomy Score** | Composite A-F grade measuring how independently the agent works |
83
+ | **Autopilot Ratio** | Assistant messages per user prompt (higher = more autonomous) |
84
+ | **Self-Heal Score** | % of bash calls that are test/lint commands (self-verification) |
85
+ | **Toolbelt Coverage** | % of available tools used per session (workflow breadth) |
86
+ | **Commit Velocity** | Tool calls per commit (lower = more efficient) |
80
87
 
81
88
  ## CLI Options
82
89
 
@@ -88,6 +95,7 @@ claude-roi --no-open # don't auto-open browser
88
95
  claude-roi --json # dump all metrics as JSON to stdout
89
96
  claude-roi --project techops # filter to a specific project
90
97
  claude-roi --refresh # force full re-parse (ignore cache)
98
+ claude-roi --autonomy # print autonomy score to terminal and exit
91
99
  ```
92
100
 
93
101
  ## Dashboard
@@ -100,7 +108,8 @@ The dashboard includes:
100
108
  - **Model comparison** — cost breakdown by Claude model
101
109
  - **Session length analysis** — which session sizes have the best ROI
102
110
  - **Productivity heatmap** — GitHub-style grid showing when you're most productive
103
- - **Sessions table** — sortable, expandable table with per-session metrics and matched commits
111
+ - **Agent Autonomy** — autonomy score badge, autopilot ratio, self-heal score, toolbelt coverage, commit velocity, and top verification commands
112
+ - **Sessions table** — sortable, expandable table with per-session metrics, matched commits, and autopilot ratio
104
113
 
105
114
  ## How It Works
106
115
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-roi",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Correlate Claude Code token usage with git output to measure AI coding agent ROI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -31,7 +31,7 @@
31
31
  "bugs": {
32
32
  "url": "https://github.com/Akshat2634/Codelens-AI/issues"
33
33
  },
34
- "homepage": "https://github.com/Akshat2634/Codelens-AI#readme",
34
+ "homepage": "https://codelensai-dev.vercel.app/",
35
35
  "engines": {
36
36
  "node": ">=18.0.0"
37
37
  },
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 1,
3
+ "skills": {
4
+ "frontend-design": {
5
+ "source": "anthropics/skills",
6
+ "sourceType": "github",
7
+ "computedHash": "063a0e6448123cd359ad0044cc46b0e490cc7964d45ef4bb9fd842bd2ffbca67"
8
+ }
9
+ }
10
+ }
package/src/cache.js CHANGED
@@ -4,7 +4,7 @@ import os from 'node:os';
4
4
 
5
5
  const CACHE_DIR = path.join(os.homedir(), '.cache', 'agent-analytics');
6
6
  const CACHE_FILE = path.join(CACHE_DIR, 'parsed-sessions.json');
7
- const CACHE_VERSION = 1;
7
+ const CACHE_VERSION = 2;
8
8
 
9
9
  export function loadCache() {
10
10
  if (!existsSync(CACHE_FILE)) {
@@ -96,6 +96,43 @@ function toRelativePath(absolutePath, repoPath) {
96
96
  return absolutePath.split('/').pop();
97
97
  }
98
98
 
99
+ // Commands that are clearly NOT verification even if they contain matching keywords
100
+ const NON_VERIFICATION_PATTERNS = [
101
+ /^\s*node\s+-e\b/, // inline JS eval
102
+ /^\s*find\s+/, // file search
103
+ /^\s*cat\s+/, // file display
104
+ /^\s*echo\s+/, // printing
105
+ /^\s*ls\b/, // listing
106
+ /^\s*rm\s+/, // file deletion
107
+ ];
108
+
109
+ // Patterns that identify test/lint/typecheck commands (for autonomy self-heal score)
110
+ const VERIFICATION_PATTERNS = [
111
+ /\bnpm\s+(test|run\s+(test|lint|check|typecheck))\b/,
112
+ /\b(pnpm|yarn|bun)\s+(run\s+)?(test|lint|check|typecheck)\b/,
113
+ /\b(jest|vitest|mocha|ava)\b/,
114
+ /\b(pytest|python\s+-m\s+(pytest|unittest))\b/,
115
+ /\b(go\s+test|cargo\s+(test|clippy))\b/,
116
+ /\b(eslint|biome|prettier\b.*--check)/,
117
+ /\btsc(\s+--noEmit|\s+-p)\b/,
118
+ /\b(mypy|ruff|flake8|pylint|rubocop)\b/,
119
+ /\bnode\s+--check\b/,
120
+ /\bmake\s+(test|check|lint)\b/,
121
+ ];
122
+
123
+ function isVerificationCommand(command) {
124
+ if (!command || typeof command !== 'string') return false;
125
+ // Strip cd/path and env var prefixes to get the core command
126
+ const core = command
127
+ .replace(/^(?:cd\s+\S+\s*&&\s*)+/g, '')
128
+ .replace(/^(?:cd\s+\S+\s*;\s*)+/g, '')
129
+ .replace(/^(?:\w+=\S+\s+)+/g, '')
130
+ .trim();
131
+ // Exclude commands that are clearly not verification
132
+ if (NON_VERIFICATION_PATTERNS.some(p => p.test(core))) return false;
133
+ return VERIFICATION_PATTERNS.some(p => p.test(core));
134
+ }
135
+
99
136
  function extractToolUse(session, msg) {
100
137
  const content = msg.content;
101
138
  if (!Array.isArray(content)) return;
@@ -108,6 +145,17 @@ function extractToolUse(session, msg) {
108
145
  // Count tool calls
109
146
  session.toolCalls[toolName] = (session.toolCalls[toolName] || 0) + 1;
110
147
 
148
+ // Track Bash commands for autonomy self-heal scoring
149
+ if (toolName === 'Bash') {
150
+ const command = block.input?.command || block.input?.content;
151
+ if (command) {
152
+ session.totalBashCalls++;
153
+ const isVerif = isVerificationCommand(command);
154
+ if (isVerif) session.verificationBashCalls++;
155
+ session.bashCommands.push({ command: command.slice(0, 200), isVerification: isVerif });
156
+ }
157
+ }
158
+
111
159
  // Track files written/read
112
160
  const filePath = block.input?.file_path;
113
161
  if (!filePath) continue;
@@ -145,6 +193,9 @@ function createEmptySession(sessionId) {
145
193
  filesRead: [],
146
194
  userMessageCount: 0,
147
195
  assistantMessageCount: 0,
196
+ bashCommands: [],
197
+ totalBashCalls: 0,
198
+ verificationBashCalls: 0,
148
199
  };
149
200
  }
150
201
 
@@ -380,6 +431,11 @@ function mergeSubagentIntoSession(parent, sub) {
380
431
  parent.toolCalls[tool] = (parent.toolCalls[tool] || 0) + count;
381
432
  }
382
433
 
434
+ // Merge bash command tracking
435
+ parent.totalBashCalls += sub.totalBashCalls;
436
+ parent.verificationBashCalls += sub.verificationBashCalls;
437
+ parent.bashCommands.push(...sub.bashCommands);
438
+
383
439
  // Merge files
384
440
  for (const f of sub.filesWritten) {
385
441
  if (!parent.filesWritten.includes(f)) parent.filesWritten.push(f);