AI PR Descriptions — From Diff to Reviewable

Turn a git diff into a PR body a reviewer will actually read, with prompts that don't invent test plans for tests that don't exist.

What this covers

A reliable workflow for using an AI coding tool — Claude Code, Cursor, or Codex — to turn a finished branch into a PR description that a reviewer will actually open and read. The pain: most AI-generated PR bodies are either three bullets of feat: did the thing boilerplate, or a hallucinated test plan describing tests that don’t exist. This guide is the prompt structure, the verification pass, and the edit-in-place habit that produces PR descriptions reviewers prefer to your hand-written ones.

Key concepts:

  • Diff scoping: feed only the diff against the merge base, not the whole repo.
  • Structured body: Summary / Why / Test plan / Risks — same four sections every time.
  • Verification pass: a second prompt that fact-checks the test plan against actual test files.

Who this is for

Engineers shipping more than one PR a day, especially on teams where review SLA matters. Also senior reviewers who keep bouncing PRs back with “what does this actually change?” — a structured AI-assisted PR body fixes the upstream problem. If your team has a code review workflow already, this slots in as the step right before “open PR.”

When to reach for it

Reach for it on any non-trivial PR — more than three files changed, or any change touching public APIs or data. Skip it on one-line typo fixes; the PR body is shorter than the prompt. Especially valuable for refactor PRs and dependency-bump PRs where the diff is large but the intent is small.

Before you start

  • The branch is rebased on main (or your default branch) and the diff is clean — no merge commits cluttering the history.
  • Tests pass locally on the branch. If they don’t, fix that first; an AI PR body won’t paper over red CI.
  • You know the merge base: git merge-base HEAD main. The diff against the merge base is what reviewers see.
  • An AI coding tool already configured: Claude Code, Cursor Composer, Codex, or Aider. The prompt below works in all of them with minor tweaks.

Step by step

  1. From the branch, generate the diff against main into a tempfile so it’s easy to feed to the AI:
git diff main...HEAD > /tmp/pr.diff
git log main..HEAD --oneline > /tmp/pr.commits
wc -l /tmp/pr.diff  # sanity-check size
  1. If the diff is over ~3000 lines, split it. Either by directory (git diff main...HEAD -- src/api/ then -- src/web/) or summarize per-commit. Feeding 10k lines of diff produces vague output.
  2. Open your AI tool in the repo. For Claude Code: claude then paste the prompt below. For Cursor: open Composer with the diff file @-mentioned. For Aider: /add /tmp/pr.diff then ask.
  3. Use a structured prompt (see next section) that asks for Summary / Why / Test plan / Risks and forbids inventing tests.
  4. Read the output critically. The Summary and Why are usually decent. The Test plan is where AI lies most — check every bullet against actual test files in the diff.
  5. Edit in place. Tighten the Summary to one sentence. Cut Why down to two sentences. Rewrite any Test plan bullet that doesn’t map to a real test file. Add Risks the AI missed (you know your codebase; it doesn’t).
  6. Paste the final body into your PR. If your tool has a gh pr create integration (Claude Code does via shell, Codex sometimes natively), feed it the body directly.

A prompt that produces honest output

This is the prompt that consistently produces reviewable PR bodies. Save it as a reusable snippet — Claude Code slash command, Cursor rules snippet, or shell function:

You are writing a PR description. Input: a git diff and commit list.

Output exactly this structure, no preamble:

## Summary
<one sentence — what this PR does, in user-visible terms if possible>

## Why
<2-3 sentences — the underlying reason. Bug fix? Refactor for X? Unblocking Y?>

## Test plan
<bulleted list. ONLY include items that correspond to actual test files in the diff, OR manual test steps a reviewer can reproduce. Do NOT invent tests that aren't in the diff. If no tests were added, write "No automated tests added. Manual verification: <steps>".>

## Risks
<bulleted list of things that could break. Be specific — name files, name behaviors, name affected users. If genuinely low-risk, write "Low risk: <reason>".>

Constraints:
- Do not use marketing language ("enhances", "improves", "leverages").
- Quote file paths in backticks.
- If the diff is unclear about intent, say so — do not guess.

The “do not invent tests” line is the load-bearing one. Without it, almost every AI tool will hallucinate test coverage that doesn’t exist.

Quality check

  • Summary is one sentence and a reviewer could repeat it back without re-reading the diff.
  • Why explains motivation, not mechanics. If Why repeats the Summary, rewrite it.
  • Every Test plan bullet corresponds to either a test file in the diff (verify with git diff main...HEAD -- '**/*test*') or a manual step.
  • Risks names specific files or behaviors, not platitudes like “could affect performance.”
  • No marketing language. “Enhances,” “leverages,” “robust” — strip them.
  • Length: 6-15 lines total for medium PRs. Longer = reviewer skip; shorter = nothing said.

How to reuse this workflow

  • Save the prompt above as a Claude Code slash command (~/.claude/commands/prdesc.md) or Cursor snippet. One-key invocation matters.
  • For repeated PR types (dependency bumps, generated code updates), make a tighter variant of the prompt that just fills in the type-specific bits.
  • Pair this with an AI pre-commit review workflow — review the diff for issues, then describe it.
  • For huge PRs (handling PRs too large to merge), generate the PR description first; if you can’t summarize it in one sentence, the PR needs splitting.

Rebase → diff against merge base → feed to AI with the structured prompt → fact-check the Test plan → edit in place → paste into PR.

Common mistakes

  • Trusting the AI’s Test plan without checking. The single most common hallucination is “Added unit tests for X” when no test file exists in the diff.
  • Pasting the whole repo into context instead of just the diff. You get a generic description because the AI dilutes its attention across unchanged code.
  • Skipping the rebase. A messy diff with merge commits produces a messy description.
  • Using a vague prompt (“write a PR description for this”). Without the structured shape, the AI defaults to marketing copy.
  • Not editing the output. Even good drafts need 30 seconds of human cleanup; raw AI PR bodies have a faint smell that reviewers notice.
  • Running this on tiny PRs. A one-line fix doesn’t need a four-section PR body; just write the sentence.

FAQ

  • Which model is best for this?: Sonnet 4.6 or GPT-5 are fine; Opus 4.7 if the diff is unusually complex. Faster models (GPT-5.4) sometimes drop the “no inventing tests” constraint — watch for it.
  • Does this work for Conventional Commits projects?: Yes — add “Output as Conventional Commit format: type(scope): summary, then the body” to the prompt.
  • What about CI-generated PR bodies?: Tools like Claude Code’s --message or the GitHub Actions Claude integration can run this prompt unattended. Be extra strict about the verification pass when humans aren’t in the loop.
  • How do I keep the Test plan honest in automation?: Pipe git diff main...HEAD -- '**/*test*' into the prompt and instruct: “Test plan must only reference filenames that appear in this diff.”

Tags: #AI coding #Workflow