git-why is an open protocol for storing reasoning traces alongside your source code. It preserves the conversations and decisions that shaped every line.
AI-assisted development creates two artifacts. Only one survives.
$ git blame src/auth.py a3f1c9d2 Pierre line 42: @retry(max=3, backoff="expo") a3f1c9d2 Pierre line 43: def refresh_token(self): $ git log --oneline -1 a3f1c9d2 Add retry to auth refresh
$ git why show src/auth.py ## Add retry with exponential backoff Reasoning: Considered circuit breaker (too heavy), fixed delay (thundering herd risk), and exponential backoff with jitter (chosen). Prompt: "Add retry logic when the auth token refresh fails"
Designed around the constraints that matter in practice.
Traces are plain Markdown files in .why/. Read them with cat, browse on GitHub, or use the CLI.
Works with Claude Code, Cursor, Copilot, Aider, or manual annotations. The protocol is the product.
Append-only, prepend-newest format means git diff output is always readable and reviewable.
Never captures API keys, tokens, file contents, or command output. Exclusion patterns via .whyignore.
Uses git's union merge strategy. Independent entries from different authors combine without conflicts.
Pre-commit hook detects AI sessions and writes traces automatically. No workflow changes needed.
Everyone on the team picks their own AI coding assistant. git-why captures reasoning from all of them into the same shared format.
The provider plugin system auto-detects which tool is active and extracts reasoning traces transparently. No configuration, no coordination — each developer uses what they prefer, and the .why/ files stay consistent.
git why capture -m "..."
Every entry records which tool produced it via the tool attribute. Readers don't need to know or care — traces from all tools look the same and work with the same git why show, blame, search commands.
Adding a provider is a single shell script with 5 functions. Copy the template, implement session detection and parsing, submit a PR. The contribution guide walks through every step.
Three concepts: a directory, a format, and a hook.
The .why/ directory mirrors your project structure. Each source file gets a corresponding .why/path/to/file.md containing its reasoning traces.
repo/ src/ auth.py utils.py .why/ # merge=union # exclude patterns _sessions/ # full transcripts src/ auth.py.md # traces for auth.py utils.py.md # traces for utils.py
Each entry captures the prompt, the reasoning behind the decision, and a summary of changes. Entries are prepended so the most recent context is always first.
<!-- why:entry session="a21f..." date="2026-04-11" tool="claude-code" --> ## 2026-04-11 — Add retry with exponential backoff ### Prompt > Add retry logic when the auth token refresh fails. > The IDP is flaky under load. ### Reasoning Current refresh_token() calls the IDP once and raises on failure. Three options considered: - Circuit breaker — too heavy for a single call - Fixed delay retry — thundering herd risk - Exponential backoff + jitter — chosen ### Changes - line 5: added @retry import - lines 42-58: wrapped with @retry(max=3) <!-- /why:entry -->
A pre-commit hook detects your AI session, extracts reasoning for each staged file, and writes .why entries automatically. No extra steps in your workflow.
$ git why init Created .why/ directory Installed pre-commit hook Ready. $ git commit -m "Add retry to auth" [git-why] Capturing reasoning for 1 file... [git-why] Wrote .why/src/auth.py.md [main a3f1c9d] Add retry to auth 2 files changed, 28 insertions(+) $ git why show src/auth.py ━━━ 2026-04-11 — Add retry with exponential backoff ━━━ Considered circuit breaker (too heavy), fixed delay (thundering herd), exponential backoff with jitter (chosen).
git-why adds one invisible step to your existing workflow. Everything else stays the same.
Chat with your AI tool, iterate on the implementation, explore tradeoffs together.
Stage your changes, write a short commit message, push to the remote.
The conversation, rejected alternatives, and reasoning behind decisions disappear when the session ends.
Someone reads your code in a review or months later. The commit message says what, never why. They guess, or they ping you.
Nothing changes. Use Claude Code, Cursor, Copilot, Aider — whatever you prefer.
Same workflow. The pre-commit hook silently captures reasoning from your AI session and stages .why files alongside your code.
Reasoning traces are committed, pushed, and versioned just like source code. They survive across sessions, machines, and team members.
git why show newThey see the original prompt, the alternatives considered, and why this approach was chosen — instantly, without asking anyone.
A git subcommand that feels native.
git why init
Set up .why/, install the pre-commit hook, create .whyignore
git why show <file>
Display reasoning traces for a file, formatted and color-coded
git why blame <file>
Enhanced git blame with inline links to reasoning traces
git why log
Annotated commit log showing which commits have reasoning attached
git why search <query>
Full-text search across all .why files in the repository
git why capture
Manually capture reasoning from the current AI session or a message
git why status
Show configuration, trace count, active session, and installed providers
Every decision in the protocol traces back to one of these.
The .why format is the product. The CLI is just one implementation. Any tool can read and write conforming files.
New entries never rewrite old ones. History accumulates in the file, deeper history lives in git log.
No databases, no binary formats. Plain text that works with cat, grep, and your favorite editor.
Zero config to read traces. Writers opt in once with git why init. Skip anytime with GIT_WHY_SKIP=1.
git-why is under active development. The RFC and reference CLI are available now.
Installation instructions and detailed documentation coming soon.