npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

git-why

v0.1.3

Published

Git blame tells you who. git-why tells you WHY. AI-powered git history explainer.

Readme

git-why

Git blame tells you who. git-why tells you WHY.

npm version npm downloads License: MIT Node.js Version

The Problem

You open a file. Line 87 has a bizarre regex. The variable name makes no sense. There's a try-catch wrapping a single assignment.

You run git blame. Now you know who wrote it and when. Congratulations — you still have no idea why.

You could dig through commit messages, PRs, and Slack history. Or you could:

git-why src/validators.js:87

What It Does

git-why analyzes git blame, commit messages, and diffs — then uses AI to explain the reasoning behind the code. It turns raw git history into a human-readable narrative.

📖 Git History Explanation
────────────────────────────────────────────────

This unusual email regex was added after discovering that
RFC 5322 validation rejected corporate emails with + signs
(e.g., "[email protected]").

The commented-out "strict mode" was an attempted fix that
broke too many legitimate addresses in production — kept as
documentation of what NOT to do.

────────────────────────────────────────────────

Think of it as having a senior developer explain the archaeological layers of your codebase — except they actually read all the commit messages.

Installation

npm install -g git-why

Or run without installing:

npx git-why src/auth.js:42

Setup

You need an Anthropic API key. Get one at console.anthropic.com.

export ANTHROPIC_API_KEY="sk-ant-..."

Add to ~/.bashrc or ~/.zshrc to make it permanent.

Quick Start

# Explain a specific line
git-why src/auth.js:42

# Explain a range
git-why src/auth.js:42-58

# Explain a function
git-why --function validateUser src/auth.js

# Explain an entire file
git-why src/auth.js

# Multiple files at once
git-why src/auth.js src/utils.js src/api.js

Examples

1. Understanding mysterious code

You find a 200-line payment handler full of null checks and retry logic. Before you "clean it up":

$ git-why --function handlePayment src/payment.js
📖 Git History Explanation
────────────────────────────────────────────────

This payment handler accumulated defensive checks over time
due to several production incidents:

1. The null check for `amount` — added after undefined amounts
   caused Stripe to charge $0.00, creating accounting chaos.

2. The retry logic — payment webhooks occasionally fail due to
   network timeouts. Immediate retries succeed 90% of the time.
   Without this, users saw "payment failed" despite successful charges.

3. The database transaction wrapper — added after a race condition
   where duplicate form submissions created multiple charges.

Each "ugly" part solved a real production problem.

────────────────────────────────────────────────

Now you know the landmines before you refactor.

2. Code review context

Reviewing a PR with suspicious-looking changes:

$ git-why src/api/rate-limiter.js:42
📖 Git History Explanation
────────────────────────────────────────────────

This Redis-based rate limiter replaced an in-memory solution
after the app scaled to multiple servers.

The 60-second window / 100 request limit was chosen based on
actual API usage patterns — 99% of legitimate users make fewer
than 50 requests/minute, but bots exceed 200/minute.

The sliding window algorithm (vs fixed window) prevents the
"reset boundary exploit" where users could make 200 requests
in 2 seconds by timing requests around the minute boundary.

────────────────────────────────────────────────

3. Onboarding to a legacy codebase

New to the team. Everything looks like spaghetti:

$ git-why src/legacy/parser.js
📖 Git History Explanation
────────────────────────────────────────────────

This parser handles data from an old third-party API
(deprecated 2024). It remains because:

1. 200+ customers still use the legacy integration
2. Migration is phased over 2 years
3. New code should use src/parsers/v2/ instead

The unusual regex patterns handle malformed XML from the old
vendor (who never fixed their output despite bug reports).

DO NOT refactor — this code is intentionally defensive and
will be removed entirely in Q4 2026.

────────────────────────────────────────────────
18 commits across 3 years, 4 contributors

4. Verbose mode — full commit details

$ git-why --verbose src/cache.js:67
📖 Git History Explanation
────────────────────────────────────────────────

This cache invalidation is intentionally aggressive after
a production bug where stale data persisted for hours.

────────────────────────────────────────────────
Commits analyzed:

f3a7b2c1 - 2026-01-20 14:45
  Alice Wong — Fix cache invalidation for nested relationships

  Original implementation only cleared exact keys:
  - cache.del(`user:${id}`)

  But didn't clear related keys like user:{id}:posts,
  user:{id}:settings — leading to stale data bugs.

d4e9c8b7 - 2025-11-12 09:23
  Bob Smith — Add Redis caching layer

────────────────────────────────────────────────

5. JSON output for automation

$ git-why --json src/config.js:15 | jq -r '.explanation'

Pipe to scripts, CI pipelines, or documentation generators:

# Generate history docs for core files
for file in src/core/*.js; do
  git-why "$file" --json | jq -r '.explanation' >> docs/architecture-decisions.md
done

How It Works

  1. Git Blame — finds which commits touched the target code
  2. Git Log — pulls commit messages and diffs
  3. Context Analysis — gathers surrounding code for context
  4. AI Explanation — Claude analyzes everything and explains the "why"

Options

Arguments:
  target                  file:line, file:start-end, or file

Options:
  -f, --function <name>   Explain a specific function
  -v, --verbose           Show detailed commit history
  --json                  Output as JSON
  --no-color              Disable colors
  -V, --version           Output version
  -h, --help              Display help

vs Alternatives

| | git-why | git blame | git log | |---|---|---|---| | Shows who | ✅ | ✅ | ✅ | | Shows when | ✅ | ✅ | ✅ | | Shows why | ✅ | ❌ | Sometimes | | Human-readable narrative | ✅ | ❌ | ❌ | | Connects multiple commits | ✅ | ❌ | Manual | | Function-level analysis | ✅ | ❌ | ❌ | | Works offline | ❌ | ✅ | ✅ | | Cost | ~$0.01/file | Free | Free |

Use git blame when you need quick authorship info. Use git log when you need raw commit details. Use git-why when you need to understand the reasoning and evolution behind code.

Integration

Git alias

git config --global alias.why '!f() { git-why "$@"; }; f'

Now: git why src/auth.js:42

VS Code task

{
  "label": "git-why: Explain Current Line",
  "type": "shell",
  "command": "git-why ${relativeFile}:${lineNumber}"
}

Cmd+Shift+P → "Run Task" → "git-why: Explain Current Line"

Shell function

# Add to ~/.zshrc
gwhy() { git-why "$@"; }

Requirements

  • Node.js 18+
  • Git repository with at least one commit
  • Anthropic API key

Limitations

  • Requires internet (API call to Claude)
  • Doesn't follow file renames (yet)
  • Can't explain deleted code
  • Binary files not supported
  • AI explanations may occasionally misinterpret context

Also From MUIN

Love git-why? Check out our other developer CLI tools:

  • roast-cli — AI code reviews with Gordon Ramsay energy. Brutally honest feedback from your terminal.
  • portguard — Monitor and kill zombie processes hogging your ports. Fix EADDRINUSE in one command.
  • oops — Pipe any error to AI for instant fixes. Debug faster with AI-powered error analysis.

Featured On

📰 Read the launch article on Dev.to: 4 CLI Tools Every Developer Needs (That You've Never Heard Of)

License

MIT

Credits

Built with Anthropic Claude, Commander.js, and Chalk.


Made by muin · Good code tells you what. Great code tells you why.