Overview
Commit messages tell you what changed; why tells you the reasoning behind it. It runs `git log -L` locally to find every commit that touched the target line (or file), then fetches each commit's AIFlare capture — intent, alternatives, diff metadata, conversation — and returns them as a timeline with the most recent commit on top. Commits without captures fall back to a plain commit list.
When to use
Reach for it before changing AI-written code — debug and refactor on top of recorded intent instead of guesses.
When a line looks wrong, check whether it was an intentional workaround or an actual mistake using the commit's recorded intent and rejected alternatives.
Before restructuring code you didn't write, surface the constraints and trade-offs that shaped its current form so you don't break invisible contracts.
Trace how a single line came to exist in a module you didn't author, with the conversation snippets that led to each commit.
An AI agent should call `why` before patching code that looks suspect — pull up its own (or another agent's) prior intent first, then decide whether to change anything.
Usage
Syntax
Invoke it as a slash command from Claude Code, or let the agent call the tool directly. Add `:<line>` after the file path to track a single line.
/why <file>[:<line>]Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
| file | string | Required | - | File path to inspect (relative to the git root, or an absolute path). |
| line | number | Optional | - | Line number to explain. Omit to use the file's full history (still capped at the 5 most recent commits). |
Flow
Common errors
When `aiflare.yml` is missing or has no `api_key`. Returns: "AIFlare is not configured. Place aiflare.yml in your project root."
When the git root can't be located. Returns: "Not in a git repository."
When the file doesn't exist or the line is out of range. Returns: "git query failed — check the file path …"
Output format
Returned as a Markdown string. There are two shapes: one when captures exist, one when they don't.
Each commit becomes a card with Title / Tag / Intent / Alternatives considered / Diff around this line / Conversation behind this commit. The newest commit sits on top; entries are labeled `only` (single capture) or `latest` / `earlier` / `oldest` when there are several.
Used when commits exist but none are captured in AIFlare. Shows "N commits touched this line, but none are captured in AIFlare." followed by a plain list of commit hash · date · subject. (Commits made before AIFlare was set up, or outside Claude Code.)
When more than 5 commits touched the target, the timeline adds "Showing the 5 most recent of N commits." and the fallback shows "Checked the 5 most recent of N commits, but none are captured in AIFlare."
Errors & fallbacks
Every error is returned as tool response text — never raised to halt the Claude Code session. The agent reads the message and continues with regular debugging.
| Situation | Returned text |
|---|---|
| AIFlare not configured | AIFlare is not configured. Place aiflare.yml in your project root. |
| Not a git repository | Not in a git repository. |
| git log failed (bad path or line) | git query failed — check the file path … |
| No commit history | No commit history found for {file}:{line}. (or …for {file}.) |
| Backend timeout / network error | Error querying AIFlare: {message} |
| git show failed for one commit | Only that commit's diff section is omitted; the rest of the timeline still renders. |