agentdiff — Know What Every AI Agent Wrote
agentdiff hooks into every major AI coding agent — Claude Code, Cursor, Codex, Copilot, Windsurf, OpenCode, Gemini — and writes a permanent, commit-scoped attribution record to your repository. Each record captures the agent name, model, prompt excerpt, and exact line ranges. All of it queryable from the CLI, no server required.
agentdiff list
agentdiff list — 5 entries
# COMMIT TIME AGENT MODEL FILE(S) LINES TRUST PROMPT
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 a1b2c3d4 Apr 14 09:12 claude-code claude-sonnet-4-6 src/commands/push.rs 1-47 92 "fix ordering: write local ref before…"
2 b2c3d4e5 Apr 14 09:44 codex o4-mini src/store.rs +2 112-198, 201-230 — "add fetch_ref_content helper"
3 c3d4e5f6 Apr 13 18:01 cursor cursor-fast src/cli.rs 305-381 — "add remote-status args struct"
4 d4e5f6a7 Apr 13 17:30 opencode claude-sonnet-4-6 src/main.rs 80-94 88 "wire remote_status dispatch"
5 e5f6a7b8 Apr 13 14:22 human — README.md — — —
Install
|
# Specific version
|
# From source (requires Rust 1.85+)
Requirements: Python 3.7+ on PATH, Git 2.20+
Quick Start
# 1. Configure global agent hooks — run once per machine
# 2. Initialize a repository
# 3. Work normally — make AI-assisted edits, then commit
&&
# 4. Inspect attribution
That's it. From here every commit is attributed to whichever agent (or human) wrote it.
Commands
| Command | Description |
|---|---|
agentdiff configure |
Install global agent hooks — run once per machine |
agentdiff init |
Initialize tracking in current repository |
agentdiff list |
List attribution entries |
agentdiff blame <file> |
Line-level attribution, like git blame |
agentdiff stats |
Aggregate stats by agent, model, file |
agentdiff log |
Chronological AI contribution history |
agentdiff diff [<sha>] |
Attribution diff for a commit or range |
agentdiff show <sha> |
Full details for one trace entry |
agentdiff report |
CI report in Markdown or GitHub annotations |
agentdiff status |
Health check — hooks, keys, traces |
agentdiff push |
Push local traces to per-branch ref on origin |
agentdiff consolidate |
Merge per-branch traces into permanent store (CI) |
agentdiff verify |
Verify ed25519 signatures on trace entries |
agentdiff keys init |
Generate a local signing keypair |
agentdiff keys register |
Register your public key in the git key registry |
agentdiff keys rotate |
Rotate your keypair and register the new key |
agentdiff policy check |
Enforce AI attribution policy rules |
agentdiff export |
Export traces in Agent Trace JSONL format |
agentdiff remote-status |
Show remote trace ref state (refs/agentdiff/* on origin) |
agentdiff migrate |
Import legacy ledger.jsonl into new storage |
agentdiff config |
Manage global configuration |
# Filter list by agent or file
# Blame for a specific agent only
# Stats broken down by file and model
# Stats from a specific date
# CI report to file
# Attribution diff for last 3 commits
# Verify signatures since merge-base with main
# Policy check (reads .agentdiff/policy.toml)
# Push traces from current branch to GitHub
# Consolidate a branch's traces into permanent store (CI step)
# Skip specific agents during configure
# Skip git hook install during init
# Check remote trace ref state after pushing
Supported Agents
| Agent | Hook mechanism | Captures |
|---|---|---|
| Claude Code | PostToolUse hook (~/.claude/settings.json) |
Edit, Write, MultiEdit |
| Cursor | afterFileEdit, afterTabFileEdit hooks |
Agent edits + Tab completions |
| GitHub Copilot | VS Code extension (~/.vscode/extensions/) |
Inline completions, chat edits |
| Windsurf | post_write_code hook (~/.codeium/windsurf/hooks.json) |
Cascade agent writes |
| OpenCode | tool.execute.after plugin (~/.config/opencode/plugins/) |
All tool writes |
| Codex CLI | notify hook (~/.codex/config.toml) |
Task-level file changes |
| Gemini / Antigravity | BeforeTool/AfterTool hooks (~/.gemini/settings.json) |
write_file, replace |
Agent hooks for Claude, Cursor, Codex, Windsurf, OpenCode, and Gemini are all installed globally once via agentdiff configure — no per-repo setup needed for those.
Example Output
agentdiff list
agentdiff list — 6 entries
# COMMIT TIME AGENT MODEL FILE(S) LINES TRUST PROMPT
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 a1b2c3d4 Apr 14 09:12 claude-code claude-sonnet-4-6 src/commands/push.rs 1-47 92 "fix ordering: write local ref befor…"
2 b2c3d4e5 Apr 14 09:44 codex o4-mini src/store.rs +2 112-198, 201-230 — "add fetch_ref_content helper"
3 c3d4e5f6 Apr 13 18:01 cursor cursor-fast src/cli.rs 305-381 — "add remote-status args struct"
4 d4e5f6a7 Apr 13 17:30 opencode claude-sonnet-4-6 src/main.rs 80-94 88 "wire remote_status dispatch"
5 e5f6a7b8 Apr 12 11:04 windsurf claude-sonnet-4-6 src/init.rs 44-68 — "remove legacy .agentdiff dir creat…"
6 f6a7b8c9 Apr 11 16:22 human — README.md — — —
# Filter to a specific agent
# Filter to files matching a path substring
# Show the 10 most recent entries
# Show only uncommitted (in-progress session) entries
agentdiff stats — 4,231 lines tracked
By Agent:
claude-code 2,741 (65%) ████████████████████
codex 892 (21%) ███████
opencode 282 (7%) ██
cursor 148 (3%) █
human 168 (4%) █
By Model:
claude-sonnet-4-6 3,023 (72%)
o4-mini 892 (21%)
cursor-fast 148 (3%)
— 168 (4%)
agentdiff remote-status — github.com/org/repo
REF TRACES LOCAL
────────────────────────────────────────────────────────────────────────────
refs/agentdiff/meta 18 synced
refs/agentdiff/traces/main 6 synced
refs/agentdiff/traces/feature%2Fauth-rewrite 3 synced
agentdiff blame — src/main.rs
1 human fn main() {
2 human let cli = Cli::parse();
3 claude-code let config = Config::load()?; (Edit)
4 claude-code let store = Store::new(repo_root, config); (Edit)
5 human
6 cursor match cli.command { (afterFileEdit)
7 cursor Command::Init(args) => init::run_init(&repo_root, &mut cfg), (afterFileEdit)
8 human }
9 human }
ok 550e8400 — valid
ok b2c3d4e5 — valid
warn d4e5f6a7 — no signature
Verified 4 entries: 3 valid, 1 missing sig, 0 invalid
**Total lines tracked:** 4,231 across 47 commits
- -
How It Works
1. agentdiff configure — one-time global setup
Installs Python capture scripts to ~/.agentdiff/scripts/ and registers hooks with each agent:
- Claude Code →
~/.claude/settings.json(PostToolUse) - Cursor →
~/.cursor/hooks.json(afterFileEdit, afterTabFileEdit) - Codex →
~/.codex/config.toml(notify) - Gemini →
~/.gemini/settings.json(BeforeTool, AfterTool) - Windsurf →
~/.codeium/windsurf/hooks.json(post_write_code) - OpenCode →
~/.config/opencode/plugins/agentdiff.ts(tool.execute.after) - Copilot → VS Code extension in
~/.vscode/extensions/agentdiff-copilot-0.1.0/
2. agentdiff init — per-repo setup
Installs git pre-commit, post-commit, and pre-push hooks. Configures a refs/agentdiff/* fetch refspec so teammates' traces are visible after git fetch.
3. Capture flow
When an AI agent makes an edit, its hook fires and writes a JSON entry to <repo>/.git/agentdiff/session.jsonl:
4. Commit → sign → push
On git commit:
- Pre-commit hook: matches session entries against staged diff → writes
pending-ledger.json - Post-commit hook: finalizes one trace entry (UUID-keyed, Agent Trace v0.1 format) into the local buffer at
.git/agentdiff/traces/{branch}.jsonl; signs it with ed25519 if keys are configured
On git push:
- Pre-push hook: uploads the local trace buffer to
refs/agentdiff/traces/{branch}on origin via the GitHub Git Database API; auto-consolidates on direct pushes to main/master
5. Three-tier storage
Tier 1 — local buffer (ephemeral)
.git/agentdiff/traces/{branch}.jsonl
Tier 2 — per-branch ref (on GitHub, per developer)
refs/agentdiff/traces/{branch}:traces.jsonl
Tier 3 — permanent meta store (consolidated by CI)
refs/agentdiff/meta:traces.jsonl
The refs/agentdiff/* namespace sits outside refs/heads/*, so branch protection rules never block it. UUIDs survive squash/rebase/cherry-pick — a trace is never lost due to SHA rewriting.
6. Key registry
Signing keys are registered per-developer in refs/agentdiff/keys/{key_id}:pub.key. agentdiff verify looks up each signature's key_id in the registry, so you can verify traces signed by any team member's key without manually exchanging public keys.
7. Directory layout
~/.agentdiff/
├── config.toml ← global config
├── keys/
│ ├── private.key ← ed25519 signing key (chmod 600)
│ └── public.key ← ed25519 verifying key
└── scripts/ ← capture scripts (Python)
<repo>/.agentdiff/
└── policy.toml ← optional policy rules
<repo>/.git/agentdiff/
├── session.jsonl ← live capture buffer (not committed)
├── pending.json ← MCP context handoff (ephemeral)
├── pending-ledger.json ← pre-commit snapshot (ephemeral)
└── traces/
└── {branch}.jsonl ← local trace buffer (pushed by pre-push hook)
Signing & Verification
agentdiff can sign each trace entry with an ed25519 key so tampering is detectable:
# One-time setup per developer
# Register your public key so teammates can verify your signatures
# Rotate keys (backs up old keys, generates new ones, registers them)
# Verify the current branch's trace history
# Strict mode — exit immediately on any missing or invalid signature
# Verify a specific range
Each trace record stores sig.key_id (first 16 hex chars of SHA-256 of the public key). agentdiff verify looks up the matching key from the git key registry (refs/agentdiff/keys/{key_id}) — no manual key exchange required.
Policy Enforcement
Define AI attribution rules in .agentdiff/policy.toml:
# Fail CI if AI wrote more than 80% of lines in this PR
= 80.0
# Every trace must have at least one attributed file
= true
# Every trace must carry an ed25519 signature
= true
# Override the default branch for merge-base calculation
# base_branch = "develop"
Run in CI:
Exits 0 on pass, 1 on violation. Use --since <sha> to scope to a specific range.
CI Integration
Full pipeline — report, verify, and enforce policy on every PR:
# .github/workflows/agentdiff.yml
on:
jobs:
agentdiff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install agentdiff
run: |
curl -fsSL https://raw.githubusercontent.com/codeprakhar25/agentdiff/master/install.sh | bash
echo "$HOME/.local/bin" >> $GITHUB_PATH
- name: Init repo
run: agentdiff init --no-git-hook
- name: Fetch agentdiff refs
run: git fetch origin 'refs/agentdiff/*:refs/agentdiff/*'
- name: Consolidate traces
run: agentdiff consolidate --branch ${{ github.head_ref }} --push
- name: Verify signatures
run: agentdiff verify
- name: Policy check
run: agentdiff policy check --format github-annotations
- name: Generate report
run: agentdiff report --format markdown --out-md ai-report.md
- name: Post as PR comment
uses: marocchino/sticky-pull-request-comment@v2
with:
path: ai-report.md
Configuration
Config lives at ~/.agentdiff/config.toml:
= "1.0"
= "~/.agentdiff/scripts"
= true # include ledger in same commit automatically
= "~/.agentdiff/spillover"
[[]]
= "/home/user/my-project"
= "-home-user-my-project"
# Disable auto-amend
# View current config
MCP Server
agentdiff-mcp is a stdio MCP server for richer context capture. It exposes a record_context tool that writes structured metadata before a commit:
When an agent calls record_context, the prompt, model, session ID, files read, intent, and trust score are stored and attached to the next ledger entry:
Debugging
# Enable verbose logging for all capture scripts
# Then make an AI edit and commit, then check logs
# Check what was captured before committing
# Check agentdiff health (hooks, keys, pending traces)
Contributing
See CONTRIBUTING.md.
License
Dual-licensed under MIT and Apache-2.0.