ai-credit 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 AI Contribution Tracker
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,330 @@
1
+ # AI Contribution Tracker
2
+
3
+ [![npm version](https://img.shields.io/npm/v/ai-credit.svg)](https://www.npmjs.com/package/ai-credit)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ A command-line tool to track and analyze AI coding assistants' contributions in your codebase. Supports **Claude Code**, **Codex CLI**, **Gemini CLI**, and **Aider**.
7
+
8
+ ## Quick Start
9
+
10
+ ```bash
11
+ # Run directly with npx (no installation required)
12
+ npx ai-credit
13
+
14
+ # Or install globally
15
+ npm install -g ai-credit
16
+ ai-credit
17
+ ```
18
+
19
+ ## Features
20
+
21
+ - 🔍 **Auto-detection**: Automatically finds AI tool session data on your system
22
+ - 📊 **Detailed Statistics**: Lines of code, files modified, contribution ratios
23
+ - 🤖 **Multi-tool Support**: Claude Code, Codex CLI, Gemini CLI, Aider
24
+ - 📈 **Visual Reports**: Console, JSON, and Markdown output formats
25
+ - 📅 **Timeline View**: Track AI contributions over time
26
+ - 📁 **File-level Analysis**: See which files have the most AI contributions
27
+
28
+ ## Usage
29
+
30
+ ```bash
31
+ # Analyze current directory
32
+ npx ai-credit
33
+
34
+ # Analyze a specific repository
35
+ npx ai-credit /path/to/your/repo
36
+
37
+ # Export as JSON
38
+ npx ai-credit -f json -o report.json
39
+
40
+ # Only analyze specific tools
41
+ npx ai-credit -t claude,codex
42
+
43
+ # Show detailed file-level analysis
44
+ npx ai-credit -v
45
+ ```
46
+
47
+ ## Commands
48
+
49
+ ### Main Analysis
50
+
51
+ ```bash
52
+ npx ai-credit [path]
53
+
54
+ # Options:
55
+ # -f, --format Output format (console/json/markdown)
56
+ # -o, --output Output file path
57
+ # -t, --tools AI tools to analyze (claude,codex,gemini,aider,all)
58
+ # -v, --verbose Show detailed output
59
+ ```
60
+
61
+ ### List Detected Tools
62
+
63
+ ```bash
64
+ npx ai-credit list
65
+ ```
66
+
67
+ Shows which AI tools have data available on your system:
68
+
69
+ ```
70
+ 🔍 Detected AI Tools
71
+
72
+ Claude Code ~/.claude/projects/ ✓ Available
73
+ Codex CLI ~/.codex/sessions/ ✓ Available
74
+ Gemini CLI ~/.gemini/tmp/ ✗ Not found
75
+ Aider .aider.chat.history.md ✗ Not found
76
+ ```
77
+
78
+ ### File-level Analysis
79
+
80
+ ```bash
81
+ npx ai-credit files [path] [-n LIMIT]
82
+ ```
83
+
84
+ Shows which files have the most AI contributions.
85
+
86
+ ### Contribution History
87
+
88
+ ```bash
89
+ npx ai-credit history [path] [-n LIMIT]
90
+ ```
91
+
92
+ Shows a timeline of AI contributions.
93
+
94
+ ### Session List
95
+
96
+ ```bash
97
+ npx ai-credit sessions [path] [-t TOOL]
98
+ ```
99
+
100
+ Lists all AI sessions for the repository.
101
+
102
+ ## Output Example
103
+
104
+ ```
105
+ ╭─────────────────────────────────────────────────╮
106
+ │ AI Contribution Analysis │
107
+ │ Repository: /path/to/your/repo │
108
+ │ Scan time: 2024-01-15 14:30:00 │
109
+ ╰─────────────────────────────────────────────────╯
110
+
111
+ 📊 Overview
112
+ ┏━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┓
113
+ ┃ Metric ┃ Value ┃ AI Contribution ┃
114
+ ┡━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━┩
115
+ │ Total Files │ 150 │ 45 (30.0%) │
116
+ │ Total Lines │ 12500 │ 3750 (30.0%) │
117
+ │ AI Sessions │ 28 │ - │
118
+ └──────────────┴─────────┴─────────────────────┘
119
+
120
+ 🤖 Contribution by AI Tool
121
+ ┏━━━━━━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━━━━┓
122
+ ┃ Tool ┃ Sessions ┃ Files ┃ Lines Added ┃
123
+ ┡━━━━━━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━━━━┩
124
+ │ Claude Code │ 15 │ 30 │ +2500 │
125
+ │ Codex CLI │ 10 │ 20 │ +1000 │
126
+ │ Aider │ 3 │ 5 │ +250 │
127
+ └──────────────┴──────────┴───────┴─────────────┘
128
+
129
+ 📈 Contribution Distribution
130
+
131
+ Claude Code ████████████████████████████░░░░░░░░░░░░░░░░░░░░░░ 66.7%
132
+ Codex CLI ████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 26.7%
133
+ Aider ███░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 6.7%
134
+ ```
135
+
136
+ ## Supported AI Tools
137
+
138
+ | Tool | Storage Location | Format |
139
+ |------|------------------|--------|
140
+ | Claude Code | `~/.claude/projects/<path>/` | JSONL |
141
+ | Codex CLI | `~/.codex/sessions/YYYY/MM/DD/` | JSONL |
142
+ | Gemini CLI | `~/.gemini/tmp/<hash>/chats/` | JSON |
143
+ | Aider | `.aider.chat.history.md` | Markdown |
144
+
145
+ ## How It Works: The JSON Parsing Logic
146
+
147
+ `ai-credit`'s core is a multi-adapter parsing engine. It works by analyzing the session log files generated by different AI coding assistants. While each tool has a slightly different log format, they share a common pattern: recording interactions, especially AI tool calls (like file writing or editing), as structured data (JSON or JSONL). This tool identifies and parses these specific tool-call records to quantify code contributions.
148
+
149
+ Here's a detailed breakdown of the parsing method for each supported tool:
150
+
151
+ ### 1. Claude Code
152
+
153
+ - **File Format**: JSONL (`.jsonl`), one JSON object per line.
154
+ - **Scan Path**: `~/.claude/projects/<path-encoded-project-name>/*.jsonl`
155
+ - **Parsing Logic**:
156
+ 1. The scanner iterates through all `.jsonl` session files in the project's directory.
157
+ 2. It reads the file line by line, parsing each line into a JSON object.
158
+ 3. The scanner focuses on log entries with `"type": "assistant"`, as these represent the AI's responses.
159
+ 4. Within the assistant's response (`message.content` array), it looks for blocks of `"type": "tool_use"`. This indicates the AI decided to use a tool.
160
+ 5. In the `tool_use` block, the `"name"` field identifies the specific action, such as `write`, `write_file`, or `edit_file`.
161
+ 6. It extracts parameters from the `"input"` field, including:
162
+ - `path` or `file_path`: The target file path.
163
+ - `content` or `new_str`: The new content to be written or to replace existing content.
164
+ - `old_str`: (In edit operations only) The old content being replaced.
165
+
166
+ - **Contribution Calculation**:
167
+ - **Lines Added**: Calculated by counting the lines in the `content` or `new_str`.
168
+ - **Lines Removed**: For edit operations, calculated by counting the lines in `old_str`.
169
+
170
+ **Example (Simplified Claude Code JSONL Entry):**
171
+
172
+ ```json
173
+ {
174
+ "timestamp": 1706860810000,
175
+ "type": "assistant",
176
+ "message": {
177
+ "content": [
178
+ {
179
+ "type": "tool_use",
180
+ "name": "write",
181
+ "input": {
182
+ "path": "src/main.py",
183
+ "content": "def hello():\n print(\"Hello, AI!\")\n"
184
+ }
185
+ }
186
+ ]
187
+ }
188
+ }
189
+ ```
190
+
191
+ ### 2. OpenAI Codex CLI
192
+
193
+ - **File Format**: JSONL (`.jsonl`).
194
+ - **Scan Path**: `~/.codex/sessions/YYYY/MM/DD/*.jsonl`
195
+ - **Parsing Logic**:
196
+ 1. The tool recursively scans the `sessions` directory for all `.jsonl` files.
197
+ 2. In each JSON object, the scanner looks for a `"tool_calls"` array, which contains all tools called by the AI in that turn.
198
+ 3. Each `tool_call` object contains a `"function"` field, where `"name"` specifies the function called (e.g., `write_file`, `apply_diff`) and `"arguments"` is a **JSON string** containing all parameters.
199
+ 4. The scanner must first parse this `arguments` string into a JSON object.
200
+ 5. From the parsed `arguments` object, it extracts the `path` (file path) and `content` (file content).
201
+
202
+ **Example (Simplified Codex CLI JSONL Entry):**
203
+
204
+ ```json
205
+ {
206
+ "timestamp": 1706947210000,
207
+ "tool_calls": [
208
+ {
209
+ "function": {
210
+ "name": "write_file",
211
+ "arguments": "{\"path\": \"src/utils.py\", \"content\": \"def helper():\\n return True\\n\"}"
212
+ }
213
+ }
214
+ ]
215
+ }
216
+ ```
217
+
218
+ ### 3. Gemini CLI
219
+
220
+ - **File Format**: JSON (`.json`), where one file represents a complete session.
221
+ - **Scan Path**: `~/.gemini/tmp/<project_hash>/chats/*.json`
222
+ - **Parsing Logic**:
223
+ 1. The tool first calculates the corresponding `<project_hash>` from the target project path to locate the specific `chats` directory.
224
+ 2. It parses the entire JSON file, which typically contains a `"messages"` or `"turns"` array logging the conversation history.
225
+ 3. It iterates through the `messages` array, looking for `"parts"` arrays within messages from the `"assistant"` role.
226
+ 4. Within the `parts` array, it searches for an object containing a `"functionCall"`. This object's structure is similar to that of Codex CLI.
227
+ 5. It extracts the `"name"` (function name) and `"args"` (arguments dictionary) from the `functionCall` object.
228
+
229
+ **Example (Simplified Gemini CLI JSON Fragment):**
230
+
231
+ ```json
232
+ {
233
+ "created_at": 1707033600000,
234
+ "projectPath": "/home/ubuntu/my-project",
235
+ "messages": [
236
+ {
237
+ "role": "assistant",
238
+ "parts": [
239
+ {
240
+ "functionCall": {
241
+ "name": "write_file",
242
+ "args": {
243
+ "path": "src/scanner.py",
244
+ "content": "class Scanner:\n pass\n"
245
+ }
246
+ }
247
+ }
248
+ ]
249
+ }
250
+ ]
251
+ }
252
+ ```
253
+
254
+ ### Summary
255
+
256
+ In essence, `ai-credit` features a specialized scanner for each supported AI tool. Each scanner is programmed to know its corresponding tool's log storage location and data structure. During analysis, the main program invokes all available scanners, collects all `FileChange` events related to the target project, and then aggregates, deduplicates, and analyzes these events to generate the final contribution report.
257
+
258
+ ## Contribution Statistics Methodology
259
+
260
+ ### Core Principle: Verified Existence
261
+
262
+ The tool applies a strict verification rule when calculating AI contribution statistics:
263
+
264
+ > **Only lines that currently exist in the codebase with exactly the same content are counted as AI contributions.**
265
+
266
+ ### How It Works
267
+
268
+ 1. **Parse AI Session Logs**: The scanner reads session files from each AI tool and extracts file change events (writes, edits, patches).
269
+
270
+ 2. **Extract Changed Content**: For each file change, the tool captures:
271
+ - The file path
272
+ - Lines added (new content)
273
+ - Lines removed (old content)
274
+
275
+ 3. **Verify Against Current Codebase**: Before counting any line as an AI contribution, the tool:
276
+ - Reads the current content of the target file from the repository
277
+ - For each line that AI claims to have added, checks if an **identical line** exists in the current file
278
+ - Only lines that match exactly (character-for-character) are counted
279
+
280
+ 4. **Calculate Statistics**: The verified lines are then aggregated into:
281
+ - Per-file contribution counts
282
+ - Per-tool contribution totals
283
+ - Overall repository contribution ratios
284
+
285
+ ### Example
286
+
287
+ If an AI tool's log shows it added these lines to `src/utils.py`:
288
+
289
+ ```python
290
+ def helper():
291
+ return True
292
+ ```
293
+
294
+ But the current `src/utils.py` in the repository contains:
295
+
296
+ ```python
297
+ def helper():
298
+ return False # Changed from True
299
+ ```
300
+
301
+ Then the line `return True` will **NOT** be counted as an AI contribution because it no longer exists in the codebase. Only if the line matches exactly will it be included in the statistics.
302
+
303
+ ### Why This Approach?
304
+
305
+ This methodology ensures that:
306
+ - Statistics reflect **actual, surviving** AI contributions
307
+ - Code that was later modified or removed by humans (or other AI tools) is not attributed to the original AI
308
+ - Contribution ratios are accurate and meaningful for understanding the current state of the codebase
309
+
310
+ ## Limitations
311
+
312
+ - Only tracks AI contributions that are recorded in local session files
313
+ - Cannot detect AI-generated code that was copy-pasted manually
314
+ - Accuracy depends on the completeness of AI tool session logs
315
+ - Some AI tools may not record all file operations
316
+
317
+ ## Contributing
318
+
319
+ Contributions are welcome! Please feel free to submit issues and pull requests.
320
+
321
+ ### Adding Support for New AI Tools
322
+
323
+ 1. Create a new scanner in `src/scanners/`
324
+ 2. Extend the `BaseScanner` class
325
+ 3. Implement `tool`, `storagePath`, `scan()`, and `parseSessionFile()` methods
326
+ 4. Add the scanner to `analyzer.ts`
327
+
328
+ ## License
329
+
330
+ MIT License - see [LICENSE](LICENSE) for details.
@@ -0,0 +1,37 @@
1
+ import { AISession, AITool, ContributionStats } from './types.js';
2
+ /**
3
+ * Main analyzer that coordinates all scanners and computes statistics
4
+ */
5
+ export declare class ContributionAnalyzer {
6
+ private projectPath;
7
+ private scanners;
8
+ constructor(projectPath: string);
9
+ /**
10
+ * Get list of available AI tools
11
+ */
12
+ getAvailableTools(): AITool[];
13
+ /**
14
+ * Scan all sessions from all tools
15
+ */
16
+ scanAllSessions(tools?: AITool[]): AISession[];
17
+ /**
18
+ * Analyze the repository and compute contribution statistics
19
+ */
20
+ analyze(tools?: AITool[]): ContributionStats;
21
+ /**
22
+ * Get all files in the repository (excluding common ignore patterns)
23
+ */
24
+ private getRepoFiles;
25
+ /**
26
+ * Count total lines in all repository files
27
+ */
28
+ private countTotalLines;
29
+ /**
30
+ * Compute statistics by AI tool
31
+ */
32
+ private computeToolStats;
33
+ /**
34
+ * Compute statistics by file using Verified Existence logic
35
+ */
36
+ private computeFileStats;
37
+ }