A command-line tool to track and analyze AI coding assistants' contributions in your codebase (macOS/Linux/Windows). Supports Claude Code, Codex CLI, Cursor, Gemini CLI, and Opencode.
# Run directly with npx (no installation required)
npx ai-credit
# Or install globally
npm install -g ai-credit
ai-credit- 🔍 Auto-detection: Automatically finds AI tool session data on your system (macOS/Linux/Windows)
- 📊 Detailed Statistics: Lines of code, files modified, contribution ratios
- 🤖 Multi-tool Support: Claude Code, Codex CLI, Cursor, Gemini CLI, Opencode
- 📈 Visual Reports: Console, JSON, and Markdown output formats
- 📅 Timeline View: Track AI contributions over time
- 📁 File-level Analysis: See which files have the most AI contributions
# Analyze current directory
npx ai-credit
# Analyze a specific repository
npx ai-credit /path/to/your/repo
# Export as JSON
npx ai-credit -f json -o report.json
# Only analyze specific tools
npx ai-credit -t claude,codex
# Show detailed file-level analysis
npx ai-credit -vnpx ai-credit [path]
npx ai-credit [path] --verification relaxed
# Options:
# -f, --format Output format (console/json/markdown)
# -o, --output Output file path
# -t, --tools AI tools to analyze (claude,codex,cursor,gemini,opencode,all)
# --verification Verification mode (strict/relaxed/historical, default: relaxed)
# -v, --verbose Show detailed outputnpx ai-credit listShows which AI tools have data available on your system:
🔍 Detected AI Tools
Claude Code ~/.claude/projects/ ✓ Available
Codex CLI ~/.codex/sessions/ ✓ Available
Cursor Cursor/User/workspaceStorage ✓ Available
Gemini CLI ~/.gemini/tmp/ ✗ Not found
Opencode ~/.local/share/opencode/ ✓ Available
npx ai-credit files [path] [-n LIMIT] [--verification MODE]
npx ai-credit files [path] --verification strictShows which files have the most AI contributions.
npx ai-credit history [path] [-n LIMIT] [--verification MODE]
npx ai-credit history [path] --verification historicalShows a timeline of AI contributions.
npx ai-credit sessions [path] [-t TOOL]Lists all AI sessions for the repository.
ai-credit (main) npx ai-credit
Leave a 🌟 star if you like it: https://github.com/debugtheworldbot/ai-credit
╭──────────────────────────────────────────────────╮
│ AI Contribution Analysis │
│ Repository: /Users/eric/Developer/ai-credit │
│ Scan time: 2/2/2026, 4:22:53 PM │
│ Verification: relaxed │
╰──────────────────────────────────────────────────╯
📊 Overview
┌─────────────┬───────┬─────────────────┐
│ Metric │ Value │ AI Contribution │
├─────────────┼───────┼─────────────────┤
│ Total Files │ 18 │ 15 (83.3%) │
├─────────────┼───────┼─────────────────┤
│ Total Lines │ 3496 │ 1660 (47.5%) │
├─────────────┼───────┼─────────────────┤
│ AI Sessions │ 6 │ - │
└─────────────┴───────┴─────────────────┘
🤖 Contribution by AI Tool
┌───────────────────────────────┬──────────┬───────┬─────────────┬───────────────┬──────────────────┐
│ Tool / Model │ Sessions │ Files │ Lines Added │ Lines Removed │ Share │
├───────────────────────────────┼──────────┼───────┼─────────────┼───────────────┼──────────────────┤
│ Opencode │ 2 │ 12 │ +558 │ -128 │ 32.2% │
├───────────────────────────────┼──────────┼───────┼─────────────┼───────────────┼──────────────────┤
│ └─ kimi-k2.5-free │ 2 │ 12 │ +558 │ -128 │ 100.0% (of tool) │
├───────────────────────────────┼──────────┼───────┼─────────────┼───────────────┼──────────────────┤
│ Codex CLI │ 1 │ 11 │ +482 │ -303 │ 27.8% │
├───────────────────────────────┼──────────┼───────┼─────────────┼───────────────┼──────────────────┤
│ └─ gpt-5.2-codex │ 1 │ 11 │ +482 │ -303 │ 100.0% (of tool) │
├───────────────────────────────┼──────────┼───────┼─────────────┼───────────────┼──────────────────┤
│ Gemini CLI │ 2 │ 11 │ +357 │ -262 │ 20.6% │
├───────────────────────────────┼──────────┼───────┼─────────────┼───────────────┼──────────────────┤
│ └─ gemini-2.5-pro │ 1 │ 8 │ +330 │ -237 │ 92.4% (of tool) │
├───────────────────────────────┼──────────┼───────┼─────────────┼───────────────┼──────────────────┤
│ └─ gemini-3-pro-preview │ 1 │ 5 │ +27 │ -25 │ 7.6% (of tool) │
├───────────────────────────────┼──────────┼───────┼─────────────┼───────────────┼──────────────────┤
│ Claude Code │ 1 │ 5 │ +338 │ -452 │ 19.5% │
├───────────────────────────────┼──────────┼───────┼─────────────┼───────────────┼──────────────────┤
│ └─ claude-opus-4-5-20251101 │ 1 │ 5 │ +338 │ -452 │ 100.0% (of tool) │
└───────────────────────────────┴──────────┴───────┴─────────────┴───────────────┴──────────────────┘
📈 Contribution Distribution
🟧🟧🟧🟧🟧🟧🟦🟦🟦🟦🟦🟪🟪🟪🟪🟪🟪🟩🟩🟩⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜
🟠 Opencode 15.3% (534 lines)
🔵 Codex CLI 13.2% (461 lines)
🟣 Gemini CLI 9.8% (342 lines)
🟢 Claude Code 9.2% (323 lines)
⚪ Unknown/Human 52.5% (1836 lines)
| Tool | Storage Location | Format |
|---|---|---|
| Claude Code | ~/.claude/projects/<path>/ |
JSONL |
| Codex CLI | ~/.codex/sessions/YYYY/MM/DD/ |
JSONL |
| Cursor | ~/Library/Application Support/Cursor/User/workspaceStorage |
SQLite (state.vscdb) |
| Gemini CLI | ~/.gemini/tmp/<hash>/chats/ |
JSON |
| Opencode | ~/.local/share/opencode/ |
JSON |
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.
Here's a detailed breakdown of the parsing method for each supported tool:
-
File Format: JSONL (
.jsonl), one JSON object per line. -
Scan Path:
~/.claude/projects/<path-encoded-project-name>/*.jsonl -
Parsing Logic:
- The scanner iterates through all
.jsonlsession files in the project's directory. - It reads the file line by line, parsing each line into a JSON object.
- The scanner focuses on log entries with
"type": "assistant", as these represent the AI's responses. - Within the assistant's response (
message.contentarray), it looks for blocks of"type": "tool_use". This indicates the AI decided to use a tool. - In the
tool_useblock, the"name"field identifies the specific action, such aswrite,write_file, oredit_file. - It extracts parameters from the
"input"field, including:pathorfile_path: The target file path.contentornew_str: The new content to be written or to replace existing content.old_str: (In edit operations only) The old content being replaced.
- The scanner iterates through all
-
Contribution Calculation:
- Lines Added: Calculated by counting the lines in the
contentornew_str. - Lines Removed: For edit operations, calculated by counting the lines in
old_str.
- Lines Added: Calculated by counting the lines in the
Example (Simplified Claude Code JSONL Entry):
{
"timestamp": 1706860810000,
"type": "assistant",
"message": {
"content": [
{
"type": "tool_use",
"name": "write",
"input": {
"path": "src/main.py",
"content": "def hello():\n print(\"Hello, AI!\")\n"
}
}
]
}
}- File Format: JSONL (
.jsonl). - Scan Path:
~/.codex/sessions/YYYY/MM/DD/*.jsonl - Parsing Logic:
- The tool recursively scans the
sessionsdirectory for all.jsonlfiles. - In each JSON object, the scanner looks for a
"tool_calls"array, which contains all tools called by the AI in that turn. - Each
tool_callobject 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. - The scanner must first parse this
argumentsstring into a JSON object. - From the parsed
argumentsobject, it extracts thepath(file path) andcontent(file content).
- The tool recursively scans the
Example (Simplified Codex CLI JSONL Entry):
{
"timestamp": 1706947210000,
"tool_calls": [
{
"function": {
"name": "write_file",
"arguments": "{\"path\": \"src/utils.py\", \"content\": \"def helper():\\n return True\\n\"}"
}
}
]
}-
File Format: SQLite (
state.vscdb). -
Scan Paths:
- Workspace metadata:
~/Library/Application Support/Cursor/User/workspaceStorage/<id>/state.vscdb - Global content:
~/Library/Application Support/Cursor/User/globalStorage/state.vscdb
- Workspace metadata:
-
Parsing Logic:
- Match Cursor workspaces to the target repo using
workspace.json. - Read
composer.composerDatato get composer IDs tied to that workspace. - Load
composerData:<composerId>from the global DB. - For each file, read
codeBlockDiff:<composerId>:<diffId>and aggregate diff segments. - Fallback to original/current file contents when diffs are unavailable.
- Match Cursor workspaces to the target repo using
-
Contribution Calculation:
- Lines Added/Removed: Derived from
codeBlockDiffsegments; fallback uses diff against current file contents.
- Lines Added/Removed: Derived from
Note: The Cursor scanner relies on the sqlite3 CLI being available.
Note: Cursor tab completions are not included in the statistics.
Example (Simplified Cursor codeBlockDiff JSON):
{
"newModelDiffWrtV0": [
{
"original": { "startLineNumber": 10, "endLineNumberExclusive": 12 },
"modified": [
"const enabled = true;",
"console.log('cursor');"
]
}
]
}- File Format: JSON (
.json), where one file represents a complete session. - Scan Paths:
~/.gemini/tmp/<hash>/chats/*.json,~/.gemini/history/*.json,~/.gemini/sessions/*.json - Parsing Logic:
- The scanner searches Gemini’s session JSON files under common locations (
tmp,history,sessions). - It parses the entire JSON file, which typically contains a
"messages"or"turns"array logging the conversation history. - It iterates through the
messagesarray, looking for"parts"arrays within messages from the"assistant"role. - Within the
partsarray, it searches for an object containing a"functionCall"(ortoolCalls). This object's structure is similar to Codex CLI. - It extracts the
"name"(function name) and"args"(arguments dictionary) from thefunctionCallobject. - Project matching: if the session JSON has an explicit project path (
projectPath/cwd/...), it must match the target repo. If not, the scanner only keeps tool calls whosefile_pathis inside the target repo.
- The scanner searches Gemini’s session JSON files under common locations (
Example (Simplified Gemini CLI JSON Fragment):
{
"created_at": 1707033600000,
"projectPath": "/home/ubuntu/my-project",
"messages": [
{
"role": "assistant",
"parts": [
{
"functionCall": {
"name": "write_file",
"args": {
"path": "src/scanner.py",
"content": "class Scanner:\n pass\n"
}
}
}
]
}
]
}- File Format: JSON (
.json) session and message files. - Scan Paths:
- Sessions:
~/.local/share/opencode/storage/session/**/*.json - Messages:
~/.local/share/opencode/storage/message/<session-id>/*.json
- Sessions:
- Parsing Logic:
- The scanner reads all session JSON files (stored under project-hash subfolders).
- It filters sessions by project path using
directoryorprojectPathin the session metadata. - If message files exist for the session, it parses each message and looks for
summary.diffs. - If no message-level diffs are found, it falls back to
summary.diffsin the session file. - Each diff entry provides:
file: relative file pathbefore: previous contentafter: new contentadditions/deletions: optional precomputed line counts
- Lines added/removed are taken from
additions/deletionswhen present, otherwise computed frombefore/after. - The scanner also extracts the model from message data (e.g.,
model.modelID) when available.
Example (Simplified Opencode Message JSON):
{
"sessionID": "sess_abc123",
"time": { "created": "2026-02-02T10:15:00Z" },
"model": { "modelID": "kimi-k2.5-free" },
"summary": {
"diffs": [
{
"file": "src/index.ts",
"before": "console.log('old');\n",
"after": "console.log('new');\n",
"additions": 1,
"deletions": 1
}
]
}
}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.
The tool applies a verification rule when calculating AI contribution statistics. The default is relaxed.
Only lines that currently exist in the codebase are counted as AI contributions.
-
Parse AI Session Logs: The scanner reads session files from each AI tool and extracts file change events (writes, edits, patches).
-
Build Repository File Set: The tool gathers repository files using text-file extensions, excluding common build/vendor folders and honoring the root
.gitignore. -
Extract Changed Content: For each file change, the tool captures:
- The file path
- Lines added (new content)
- Lines removed (old content)
-
Verify Against Current Codebase: Before counting any line as an AI contribution, the tool:
- Reads the current content of the target file from the repository
- For each line that AI claims to have added, checks if a matching line exists in the current file
- In relaxed mode, matching ignores whitespace-only differences (trim + collapse spaces)
- In strict mode, matching is character-for-character
-
Calculate Statistics: The verified lines are then aggregated into:
- Per-file contribution counts
- Per-tool contribution totals
- Overall repository contribution ratios
- Sessions, files, and models are counted only when at least one verified line exists
If an AI tool's log shows it added these lines to src/utils.py:
def helper():
return TrueBut the current src/utils.py in the repository contains:
def helper():
return False # Changed from TrueThen 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.
You can switch modes with --verification.
relaxed(default): Match lines after normalizing whitespace.strict: Match lines exactly (character-for-character).historical: Count tool-reported added lines for files that still exist, capped by the current file’s non-empty line count.
This methodology ensures that:
- Statistics reflect actual, surviving AI contributions
- Code that was later modified or removed by humans (or other AI tools) is not attributed to the original AI
- Contribution ratios are accurate and meaningful for understanding the current state of the codebase
- Only tracks AI contributions that are recorded in local session files
- Cannot detect AI-generated code that was copy-pasted manually
- Accuracy depends on the completeness of AI tool session logs
- Some AI tools may not record all file operations
- Files ignored by the root
.gitignoreare excluded from Total Files/Lines - Windows support for some tools depends on their session storage format compatibility
Contributions are welcome! Please feel free to submit issues and pull requests.
- Create a new scanner in
src/scanners/ - Extend the
BaseScannerclass - Implement
tool,storagePath,scan(), andparseSessionFile()methods - Add the scanner to
analyzer.ts
MIT License - see LICENSE for details.