git-atrace
Capture AI coding sessions and link them to commits and lines.
Why
When AI tools generate code, we lose context of why and whence that code; and the final
artifact is often alienated from its inputs.
git-atrace captures the coding sessions and links them to the files that were edited.
Sessions are stored locally by default, and can be explicitly shared like any git object.
This tool is small, follows git conventions, and is written in bash. Requires jq for viewing sessions.
How It Works
- Capture: A post-tool hook copies the conversation transcript when you edit files
- Store: Sessions are saved locally in
.git/trace/sessions/ (private by default)
- Share: Explicitly share sessions to a tracked location (syncs with git)
- View: CLI or web UI to browse sessions and see which files they touched
Installation
curl -fsSL https://raw.githubusercontent.com/tnm/git-atrace/main/install.sh | bash
This installs git-atrace and git-atrace-hook to ~/.local/bin/.
Or clone manually:
git clone https://github.com/tnm/git-atrace
cd git-atrace
export PATH="$PATH:$(pwd)"
Claude Code
Install as a plugin from GitHub:
/plugin marketplace add tnm/git-atrace
/plugin install git-atrace@git-atrace
Or clone and point to it:
git clone https://github.com/tnm/git-atrace ~/.local/share/git-atrace
claude --plugin-dir ~/.local/share/git-atrace
OpenCode
Copy the hook config to your project or user config:
cp hooks/opencode/oh-my-opencode.json .opencode/
# Edit paths to point to your git-atrace installation
The config includes hooks for both session capture (on file edits) and auto-linking (on git commit).
Gemini CLI
Copy the hook config:
cp hooks/gemini/settings.json .gemini/
# Edit paths to point to your git-atrace installation
The config includes hooks for both session capture and auto-linking.
Hook Summary
Each tool needs two hooks:
| Hook | Trigger | Purpose |
|---|
git-atrace-hook | File edits | Captures session transcript |
git-atrace-commit-hook | Git commit | Links session to commit |
Sessions are captured automatically when the AI assistant edits files, and linked to commits when committing from within the AI tool.
Usage
When git-atrace is in your PATH, git picks it up as a subcommand (git atrace).
List sessions
git atrace
Shows recent sessions with timestamps and file counts:
Sessions
3ea80c57 2024-01-23T03:52:52Z (3 files) [local]
a1b2c3d4 2024-01-22T22:30:00Z (1 files) [shared]
Show sessions for a file
git atrace show src/auth.py
View a session
git atrace view 3ea80c57
Shows the full conversation:
Session: 3ea80c57-6b85-4ca6-bec1-d6d471d207e2
> Add login with rate limiting
I'll create a login function with rate limiting...
[Edit]
> The SQL looks injectable
You're right, let me fix that with parameterized queries...
[Edit]
List files in a session
git atrace files 3ea80c57
Share a session
git atrace share 3ea80c57
Copies the session to a tracked location and stages it for commit. Now it syncs with your repo.
By default, sharing goes to .agents/sessions/ if a .agents/ directory exists (common with AI tooling). Otherwise, configure a location:
git config atrace.sharedir .trace/sessions
Delete a session
git atrace delete 3ea80c57
Removes the session (checks local first, then shared).
Export a session
git atrace export 3ea80c57 > session.json
Exports to Agent Trace spec format for interoperability.
Import a session
git atrace import session.json
Imports an Agent Trace spec file as a local session.
Link a session to a commit
git atrace link 3ea80c57 # links to HEAD
git atrace link 3ea80c57 abc123 # links to specific commit
Associates a session with a commit using git notes (refs/notes/atrace).
Show commits with linked sessions
git atrace log
Commits with sessions
7490404 Add test2.c for attribution testing
↳ 3ea80c57
Blame with session attribution
git atrace blame src/auth.py
Shows each line with its commit and linked session (if any):
Blame: src/auth.py
(commits with linked sessions shown in cyan)
055a2d0 d5eb95cd def login(user, password):
055a2d0 d5eb95cd # Rate limiting added per review
01d6eb9 05fac6aa if is_rate_limited(user):
01d6eb9 05fac6aa raise RateLimitError()
(local) return check_password(user, password)
Uncommitted changes show as (local) in yellow.