Data Formats
This document describes the JSON schemas used by whogitit.
AIAttribution (Git Notes)
The primary data structure stored in git notes:
{
"schema_version": 2,
"session": {
"session_id": "7f3a4b2c-9d1e-8a7b-c3d4-e5f6a7b8c9d0",
"model": {
"id": "claude-opus-4-5-20251101",
"provider": "anthropic"
},
"started_at": "2026-01-30T14:23:17Z",
"cwd": "/path/to/project"
},
"prompts": [
{
"index": 0,
"text": "Add user authentication with bcrypt...",
"affected_files": ["src/auth.rs", "src/main.rs"],
"timestamp": "2026-01-30T14:23:45Z"
}
],
"files": [
{
"path": "src/auth.rs",
"lines": [
{"line_number": 1, "source": "AI", "prompt_index": 0},
{"line_number": 2, "source": "AI", "prompt_index": 0},
{"line_number": 3, "source": "AIModified", "prompt_index": 0},
{"line_number": 4, "source": "Human", "prompt_index": null},
{"line_number": 5, "source": "Original", "prompt_index": null}
],
"summary": {
"ai_lines": 2,
"ai_modified_lines": 1,
"human_lines": 1,
"original_lines": 1
}
}
]
}
Schema Fields
| Field | Type | Description |
|---|---|---|
schema_version | number | Format version (currently 2) |
session | object | AI session information |
prompts | array | Prompts used in this commit |
files | array | Per-file attribution |
Session Object
| Field | Type | Description |
|---|---|---|
session_id | string | Unique session identifier |
model.id | string | Model identifier |
model.provider | string | Model provider |
started_at | string | ISO 8601 timestamp |
cwd | string | Working directory |
Prompt Object
| Field | Type | Description |
|---|---|---|
index | number | Order within session |
text | string | Prompt text (may be redacted) |
affected_files | array | Files changed by this prompt |
timestamp | string | When prompt was given |
LineAttribution Object
| Field | Type | Description |
|---|---|---|
line_number | number | 1-indexed line number |
source | string | AI, AIModified, Human, Original, Unknown |
prompt_index | number|null | Index of generating prompt |
PendingBuffer
Temporary storage during editing session:
{
"schema_version": 2,
"session": {
"session_id": "7f3a4b2c-9d1e-8a7b-c3d4-e5f6a7b8c9d0",
"model": {
"id": "claude-opus-4-5-20251101",
"provider": "anthropic"
},
"started_at": "2026-01-30T14:23:17Z",
"cwd": "/path/to/project"
},
"files": {
"src/auth.rs": {
"original_content": "// Original file content\n...",
"edits": [
{
"content": "// After first AI edit\n...",
"prompt_index": 0,
"timestamp": "2026-01-30T14:23:45Z",
"tool": "Edit"
},
{
"content": "// After second AI edit\n...",
"prompt_index": 1,
"timestamp": "2026-01-30T14:25:00Z",
"tool": "Write"
}
]
}
},
"prompts": [
{
"index": 0,
"text": "Add user authentication...",
"affected_files": ["src/auth.rs"],
"timestamp": "2026-01-30T14:23:45Z"
}
]
}
FileEditHistory
| Field | Type | Description |
|---|---|---|
original_content | string | File content before AI session |
edits | array | Sequence of AI edits |
AIEdit
| Field | Type | Description |
|---|---|---|
content | string | File content after this edit |
prompt_index | number | Which prompt triggered this |
timestamp | string | When edit occurred |
tool | string | Edit or Write |
Export Format
Output of whogitit export:
{
"export_version": 1,
"exported_at": "2026-01-30T15:00:00Z",
"date_range": {
"since": "2026-01-01",
"until": "2026-01-31"
},
"commits": [
{
"commit_id": "abc123def456789...",
"commit_short": "abc123d",
"message": "Add user authentication",
"author": "Greg King",
"committed_at": "2026-01-30T14:30:00Z",
"session_id": "7f3a4b2c-9d1e-8a7b-c3d4-e5f6a7b8c9d0",
"model": "claude-opus-4-5-20251101",
"ai_lines": 145,
"ai_modified_lines": 12,
"human_lines": 43,
"original_lines": 50,
"files": ["src/auth.rs", "src/main.rs"],
"prompts": [
{
"index": 0,
"text": "Add user authentication...",
"affected_files": ["src/auth.rs"]
}
]
}
],
"summary": {
"total_commits": 10,
"commits_with_ai": 7,
"total_ai_lines": 523,
"total_ai_modified_lines": 45,
"total_human_lines": 128,
"total_original_lines": 89,
"total_prompts": 15
}
}
Annotations Output Format
Output of whogitit annotations --format github-checks:
{
"annotations": [
{
"path": "src/main.rs",
"start_line": 42,
"end_line": 48,
"annotation_level": "notice",
"title": "AI Generated (7 lines)",
"message": "Model: claude-opus-4-5-20251101 | Session: 2024-01-15\n\n**Breakdown:** 5 AI, 2 AI-modified, 0 human, 0 original\n\n**Prompt:** Add error handling...",
"raw_details": "Add error handling with retry logic..."
}
],
"summary": {
"files_analyzed": 5,
"models": ["claude-opus-4-5-20251101", "claude-sonnet-4-20250514"],
"session_range": "2024-01-15 to 2024-01-20"
}
}
Annotation Object
| Field | Type | Description |
|---|---|---|
path | string | File path relative to repository root |
start_line | number | Starting line number (1-indexed) |
end_line | number | Ending line number (inclusive) |
annotation_level | string | Always notice for AI attribution |
title | string | Short title (e.g., “AI Generated (7 lines)”) |
message | string | Detailed message with model, breakdown, and prompt |
raw_details | string|null | Full prompt text (optional) |
Summary Object
| Field | Type | Description |
|---|---|---|
files_analyzed | number | Number of files with AI attribution |
models | array | All AI models used across the commits |
session_range | string|null | Date range (e.g., “2024-01-15 to 2024-01-20”) |
Annotation Title Formats
| Source Type | Title Format |
|---|---|
| AI | “AI Generated (N lines)” |
| AIModified | “AI Modified (N lines)” |
| AIRelated (grouped) | “AI Related (N lines: X AI, Y AI-modified)” |
| File-level (new) | “New file (N lines) generated by AI” |
| File-level (existing) | “X% AI-generated (N of M lines)” |
Audit Log Format
Each line in .whogitit/audit.jsonl is a JSON object, including prev_hash and
event_hash fields for tamper‑evident chaining:
event_hash is computed over the event content including prev_hash, so any
reordering or tampering breaks the chain. Malformed lines cause verification
to fail.
{"timestamp":"2026-01-30T14:23:15Z","event":"Delete","details":{"commit":"abc123d","user":"greg","reason":"Retention policy"}}
{"timestamp":"2026-01-28T10:15:00Z","event":"Export","details":{"commit_count":45,"format":"json","user":"greg"}}
{"timestamp":"2026-01-25T09:00:00Z","event":"RetentionApply","details":{"commits":12,"user":"greg","reason":"Quarterly"}}
{"timestamp":"2026-01-20T16:30:00Z","event":"ConfigChange","details":{"user":"greg","field":"max_age_days"}}
{"timestamp":"2026-01-15T11:45:00Z","event":"Redaction","details":{"pattern_name":"API_KEY","redaction_count":3}}
Event Types
| Type | Description | Details Fields |
|---|---|---|
Delete | Attribution deleted | commit, user, reason |
Export | Data exported | commit_count, format, user |
RetentionApply | Retention policy applied | commits, user, reason |
ConfigChange | Configuration changed | user, field |
Redaction | Sensitive data redacted | pattern_name, redaction_count |
Configuration Format
.whogitit.toml:
[privacy]
enabled = true
use_builtin_patterns = true
disabled_patterns = ["EMAIL"]
audit_log = true
[[privacy.custom_patterns]]
name = "INTERNAL_ID"
pattern = "INT-[A-Z0-9]{8}"
description = "Internal IDs"
[retention]
max_age_days = 365
auto_purge = false
retain_refs = ["refs/heads/main"]
min_commits = 100
See Configuration for full reference.
Hook Input Format
JSON passed to hooks via stdin:
{
"tool_name": "Edit",
"tool_input": {
"file_path": "/path/to/file.rs",
"old_string": "...",
"new_string": "..."
},
"transcript_path": "/tmp/claude-transcript-xyz.jsonl"
}
For Write tool:
{
"tool_name": "Write",
"tool_input": {
"file_path": "/path/to/file.rs",
"content": "..."
},
"transcript_path": "/tmp/claude-transcript-xyz.jsonl"
}
Version History
| Version | Changes |
|---|---|
| 2 | Current version. Full content snapshots. |
| 1 | Initial version. Diff-based storage. (deprecated) |
See Also
- Architecture - System design
- Git Notes Storage - Notes implementation