{"_id":"@acemarke/diffloupe","name":"@acemarke/diffloupe","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@acemarke/diffloupe","version":"0.1.0","type":"module","description":"Understand your diffs before you merge them","bin":{"diffloupe":"dist/index.js"},"exports":{".":"./dist/index.js"},"scripts":{"start":"bun run src/index.ts","dev":"bun run --watch src/index.ts","prebuild":"rm -rf dist","build":"bun build src/index.ts --outdir=dist --target=node --minify --banner '#!/usr/bin/env node'","prepublishOnly":"bun run build && bun run typecheck","test":"bun test","typecheck":"tsgo --noEmit","lint":"oxlint src/"},"engines":{"node":">=18.0.0"},"repository":{"type":"git","url":"git+https://github.com/acemarke/diffloupe.git"},"keywords":["cli","diff","code-review","ai","git","llm"],"author":{"name":"Mark Erikson"},"license":"MIT","devDependencies":{"@typescript/native-preview":"^7.0.0-dev.20260127.1","bun-types":"^1.3.7","oxlint":"^1.42.0"},"dependencies":{"@tanstack/ai":"^0.2.2","@tanstack/ai-anthropic":"^0.2.0","arktype":"^2.1.29","commander":"^14.0.2","picocolors":"^1.1.1","simple-git":"^3.30.0","tinyexec":"^1.0.2"},"gitHead":"0167a60c11c3418859c07eb7db52ac6c13bda750","_id":"@acemarke/diffloupe@0.1.0","bugs":{"url":"https://github.com/acemarke/diffloupe/issues"},"homepage":"https://github.com/acemarke/diffloupe#readme","_nodeVersion":"24.13.0","_npmVersion":"11.6.2","dist":{"integrity":"sha512-NwtRwhEKZ91N6XZaMpCDYx/pZjzp0yhb1/MBFIP3O3XQQVF/uouXbMeZBBapYFMl7OtVjxyJtsHaPfh0RYJpYw==","shasum":"09b00e14e8123dafe6babe219628aa0c7b3b2f07","tarball":"https://registry.npmjs.org/@acemarke/diffloupe/-/diffloupe-0.1.0.tgz","fileCount":4,"unpackedSize":457724,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCPCbL9LFBT044TC54QgCUEHASRb7hWmOhkX/ia0/YXPAIgCjdwk04YC1d4/4CT28xrWCOEZyt+zyE4WaT9IpHiJRE="}]},"_npmUser":{"name":"acemarke","email":"mark.erikson@gmail.com"},"directories":{},"maintainers":[{"name":"acemarke","email":"mark.erikson@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/diffloupe_0.1.0_1769708152065_0.2392461687613927"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-29T17:35:51.940Z","0.1.0":"2026-01-29T17:35:52.305Z","modified":"2026-01-29T17:35:52.531Z"},"maintainers":[{"name":"acemarke","email":"mark.erikson@gmail.com"}],"description":"Understand your diffs before you merge them","homepage":"https://github.com/acemarke/diffloupe#readme","keywords":["cli","diff","code-review","ai","git","llm"],"repository":{"type":"git","url":"git+https://github.com/acemarke/diffloupe.git"},"author":{"name":"Mark Erikson"},"bugs":{"url":"https://github.com/acemarke/diffloupe/issues"},"license":"MIT","readme":"# DiffLoupe\n\nUnderstand your diffs before you merge them.\n\n## The Problem\n\nReading diffs is hard. You're staring at fragments of code without the full picture, trying to reconstruct what the change *actually does* and whether it's correct.\n\nGood code review requires a mental model of the existing system - understanding where features live, how components interact, what a change will impact. But diffs show you disconnected hunks across files, and you're left mentally stitching them together.\n\nThis problem gets worse with AI-generated code. When an AI assistant produces 50 files of changes, you can't just skim and approve. You need to understand what was built, verify it matches your intent, and catch the subtle issues that LLMs introduce.\n\n## The Solution\n\nDiffLoupe uses AI to analyze diffs and tell you what they *mean*:\n\n- **\"What does this change do?\"** - Get a clear summary of purpose, scope, and affected areas\n- **\"What could go wrong?\"** - Surface risks with concrete evidence, not vague warnings\n- **\"Does it match my intent?\"** - Compare what you asked for against what was actually built\n\nThe key differentiator is **intent alignment**: provide your stated intent (commit message, PR description, or explicit description), and DiffLoupe compares it against what the code actually does. This surfaces scope creep, incomplete implementations, and mislabeled changes before they cause problems.\n\n## Features\n\n- **Intent Derivation** - Analyzes diffs to determine purpose, scope, and affected areas\n- **Risk Assessment** - Identifies potential issues with severity levels and concrete evidence\n- **Intent Alignment** - Compares stated intent vs derived intent to catch mismatches\n- **Smart Context Loading** - Includes sibling files and new file source to reduce false positives\n- **Large Diff Handling** - Automatic decomposition strategies (two-pass, flow-based) for big changes\n- **GitHub PR Support** - Analyze PRs directly using PR metadata as stated intent\n\n## Installation\n\n```bash\nnpm install -g @acemarke/diffloupe\n```\n\nRequires Node.js 18+.\n\n## Configuration\n\nSet your Anthropic API key as an environment variable:\n\n```bash\nexport ANTHROPIC_API_KEY=sk-ant-api03-...\n```\n\nAdd to your shell profile (`~/.bashrc`, `~/.zshrc`) for persistence.\n\n## Quick Start\n\n```bash\n# Analyze staged changes\ndiffloupe analyze\n\n# Analyze with your stated intent\ndiffloupe analyze --intent \"Add rate limiting to API endpoints\"\n\n# Analyze a commit (uses commit message as intent)\ndiffloupe analyze commit:HEAD\n\n# Analyze a GitHub PR (uses title + description as intent)\ndiffloupe pr 123\n\n# Preview what will be sent to the LLM (no API call)\ndiffloupe summarize --stats\n```\n\n## Commands\n\n### `diffloupe analyze [target]`\n\nAnalyze code changes with AI assistance.\n\n**Targets:**\n\n| Target | Description |\n|--------|-------------|\n| `staged` | Staged changes (default) |\n| `unstaged` | Unstaged working tree changes |\n| `HEAD` | All uncommitted changes |\n| `branch:name` | Compare current HEAD to branch |\n| `commit:hash` | Analyze a specific commit |\n| `range:a..b` | Analyze a commit range |\n\n**Options:**\n\n| Option | Description |\n|--------|-------------|\n| `-i, --intent <text>` | Describe the intent of the changes |\n| `--intent-file <path>` | Read intent from a file |\n| `-v, --verbose` | Show detailed output |\n| `--json` | Output results as JSON |\n| `-C, --cwd <path>` | Run in a different directory |\n| `--strategy <name>` | Force decomposition strategy (direct, two-pass, flow-based) |\n| `--demo` | Show example output without API call |\n\n**Intent sources** (in priority order):\n1. `--intent` flag\n2. `--intent-file` contents\n3. Commit message (for `commit:` targets)\n4. Piped stdin\n\n### `diffloupe pr <identifier>`\n\nAnalyze a GitHub PR. Requires `gh` CLI to be installed and authenticated.\n\n**Identifier formats:**\n\n```bash\ndiffloupe pr 123                                    # PR in current repo\ndiffloupe pr owner/repo#123                         # Cross-repo PR\ndiffloupe pr https://github.com/owner/repo/pull/123 # Full URL\n```\n\n**Options:**\n\n| Option | Description |\n|--------|-------------|\n| `-R, --repo <owner/repo>` | Specify repository |\n| `-v, --verbose` | Show detailed output |\n| `--json` | Output results as JSON |\n\nThe PR's title and description are automatically used as stated intent.\n\n### `diffloupe summarize [target]`\n\nPreview diff formatting without running LLM analysis. Useful for debugging and understanding token usage.\n\n**Options:**\n\n| Option | Description |\n|--------|-------------|\n| `--stats` | Show only file list and token estimates |\n| `--files-only` | Show only file list |\n| `--json` | Output as JSON |\n| `--no-tokens` | Skip token estimates |\n\n## Output\n\nDiffLoupe provides three types of analysis:\n\n**Derived Intent** - What the change actually does:\n- Summary and purpose\n- Scope (feature, bugfix, refactor, etc.)\n- Affected areas\n- Suggested review order\n\n**Risk Assessment** - Potential issues:\n- Severity (low, medium, high, critical)\n- Category (security, performance, error-handling, etc.)\n- Evidence from the actual code\n- Suggested mitigations\n\n**Intent Alignment** (when stated intent provided):\n- Alignment level (aligned, partial, misaligned)\n- What matches between stated and actual\n- Mismatches, missing implementations, and unstated changes (scope creep)\n\n## How It Works\n\n1. **Parse** - Load and parse the git diff\n2. **Classify** - Tier files by importance (skip lock files, generated code)\n3. **Gather Context** - Load sibling files in touched directories\n4. **Select Strategy** - Choose decomposition approach based on diff size\n5. **Analyze** - Run intent derivation and risk assessment\n6. **Align** - Compare stated intent vs derived intent (if provided)\n\nFor large diffs, DiffLoupe automatically selects a decomposition strategy:\n- **Direct** - Small diffs analyzed in one pass\n- **Two-pass** - Medium diffs: quick overview, then deep-dive on flagged files\n- **Flow-based** - Large diffs: group files by logical flow, analyze each flow\n\n## Inspirations\n\nDiffLoupe builds on ideas from several excellent tools:\n\n- [LaReview](https://github.com/puemos/lareview) - Flow-based grouping concept\n- [GitHuman](https://github.com/mcollina/githuman) - Pre-commit review philosophy\n- [Diffray](https://github.com/diffray/diffray) - Validation patterns, confidence scoring\n- [Critique](https://github.com/remorses/critique) - Prompt engineering principles\n- [CodeRabbit](https://coderabbit.ai) - Incremental review patterns\n\n## Development\n\nDiffLoupe is built with Bun and TypeScript, published as a Node.js-compatible package.\n\n```bash\n# Install dependencies\nbun install\n\n# Run in dev mode\nbun run dev\n\n# Run tests\nbun test\n\n# Type check\nbun run typecheck\n\n# Build for distribution\nbun run build\n```\n\n**Tech stack:** Bun, TypeScript, TanStack AI, ArkType, Commander\n\n## License\n\nMIT\n","readmeFilename":"README.md","_rev":"1-1530e9778c09e355f5cd6d175bf78160"}