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. Verified workflow, June 2026.

TL;DR

Generate the diff against the merge base, feed only that diff (plus the commit list) to an AI tool with a four-section prompt (Summary / Why / Test plan / Risks), then fact-check the Test plan against real test files before you paste. The one prompt line that does most of the work: “Do NOT invent tests that aren’t in the diff.” Sonnet 4.6 and GPT-5.5 both handle this well; pipe the result straight to gh pr create --body-file -.

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 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 over hand-written ones.

Three concepts carry the whole workflow:

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

The four-section shape is not arbitrary. GitHub’s own guidance on helping others review your changes and most 2026 PR-template guides converge on the same core: a synthesized summary, the reason, a test plan, and a risk/rollback note. A good description lets a reviewer predict roughly what the diff looks like before they open it.

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 that problem at the source. If your team already runs a pre-commit review workflow, 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. It is 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, with 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 is configured: Claude Code, Cursor Composer, Codex, or Aider. The prompt below works in all of them with minor tweaks. As of June 2026 the relevant defaults are Claude Code on Sonnet 4.6 / Opus 4.7, Cursor on Sonnet 4.6 or GPT-5.5, and Codex on GPT-5.5.

Step by step

  1. From the branch, write the diff against main to 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 because attention spreads too thin.
  2. Open your AI tool in the repo. For Claude Code: run claude, then paste the prompt below. For Cursor: open Composer with the diff file @-mentioned. For Aider: /add /tmp/pr.diff, then ask. Inside Claude Code you can skip the tempfile entirely and pass the diff inline with !git diff main...HEAD if you wire it into a slash command (see the reuse section).
  3. Use the structured prompt (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, so check every bullet against the actual test files in the diff.
  5. Edit in place. Tighten the Summary to one sentence. Cut Why 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, or pipe it directly: gh pr create --title "..." --body-file pr-body.md. To stream from stdin without a tempfile, use --body-file -.

A prompt that produces honest output

This prompt consistently produces reviewable PR bodies. Save it as a reusable snippet: a Claude Code slash command, a Cursor rules snippet, or a 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 a change is breaking, flag it under its own line, do not bury it. If genuinely low-risk, write "Low risk: <reason>".>

Constraints:
- Do not synthesize a narrative from the commit messages alone; read the diff.
- 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 load-bearing. Without it, almost every AI tool will hallucinate test coverage that doesn’t exist. Faster models (GPT-5.4, Sonnet at the cheap tier) drop the constraint more often than the flagship models, so watch the Test plan harder when you trade down for speed.

Quality check

Run through this before you hit “create”:

  • 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 maps to either a test file in the diff (verify with git diff main...HEAD -- '**/*test*') or a reproducible manual step.
  • Risks names specific files or behaviors, not platitudes like “could affect performance.” Breaking changes are flagged on their own line.
  • No marketing language. “Enhances,” “leverages,” “robust” get cut.
  • Length: 6-15 lines total for medium PRs. Longer and reviewers skip; shorter and nothing was said.

How to reuse this workflow

Save the prompt as a Claude Code slash command so it is one keystroke away. Drop a file at ~/.claude/commands/prdesc.md (or .claude/commands/prdesc.md to share it with the repo) with YAML frontmatter that grants the git and gh tools up front, so Claude doesn’t stop to ask for permission mid-run:

---
description: Write a reviewable PR description from the current branch diff
allowed-tools: Bash(git diff:*), Bash(git log:*), Bash(gh pr:*)
---
Run `git diff main...HEAD` and `git log main..HEAD --oneline`, then write a PR
description using the Summary / Why / Test plan / Risks structure. Do NOT invent
tests that aren't in the diff.
  • For repeated PR types (dependency bumps, generated-code updates), make a tighter variant of the prompt that fills only the type-specific bits.
  • Pair this with a pre-commit review workflow: review the diff for issues first, then describe it.
  • For huge PRs, generate the PR description first. If you can’t summarize it in one sentence, the PR needs splitting before review. See how to review AI-generated diffs for the reviewer’s side of the same problem.

Rebase, diff against the merge base, feed to the AI with the structured prompt, fact-check the Test plan, edit in place, then gh pr create --body-file.

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 reviewers notice.
  • Running this on tiny PRs. A one-line fix doesn’t need a four-section body; just write the sentence.

FAQ

  • Which model is best for this?: Sonnet 4.6 or GPT-5.5 are both fine; reach for Opus 4.7 if the diff is unusually complex or spans many files. Faster, cheaper tiers (GPT-5.4) sometimes drop the “no inventing tests” constraint, so verify the Test plan more carefully when you use them.
  • Does this work for Conventional Commits projects?: Yes. Add “Output the title as a Conventional Commit: type(scope): summary, then the body” to the prompt.
  • How do I run it unattended in CI?: Claude Code’s headless mode (claude -p with --allowedTools) or the GitHub Actions Claude integration can run this prompt without a human. Be extra strict about the verification pass when nobody is in the loop, because there is no manual edit step to catch a hallucinated test.
  • How do I keep the Test plan honest in automation?: Pipe git diff main...HEAD -- '**/*test*' into the prompt and instruct: “The Test plan may only reference filenames that appear in this diff.” If that diff is empty, the only valid Test plan is manual steps.
  • Can I generate and open the PR in one command?: Yes. Generate the body to stdout, then ... | gh pr create --title "..." --body-file -. Claude Code can run the gh pr create step itself once the command is in its allowed-tools.

Tags: #AI coding #Workflow