
Pr Description Writer
- 2 installs
- 1 repo stars
- Updated July 11, 2026
- simonlee2/claude-plugins
Generates and improves GitHub pull request descriptions by analyzing git commits, adding context, implementation notes, file prioritization, and testing strategy.
About
Generates reviewer-friendly PR descriptions by analyzing commits since the main branch and producing structured summary, context, implementation, and testing sections. A developer uses it to write, update, or improve a PR description.
- Analyzes commits via analyze_git_commits.py to extract key changes
- Prioritizes files to review and flags risks and breaking changes
Pr Description Writer by the numbers
- 2 all-time installs (skills.sh)
- Ranked #497 of 733 Git & Pull Requests skills by installs in the Skillselion catalog
- Data as of Jul 27, 2026 (Skillselion catalog sync)
npx skills add https://github.com/simonlee2/claude-plugins --skill pr-description-writerAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 2 |
|---|---|
| repo stars | ★ 1 |
| Last updated | July 11, 2026 |
| Repository | simonlee2/claude-plugins ↗ |
What it does
Generates and improves GitHub pull request descriptions by analyzing git commits, adding context, implementation notes, file prioritization, and testing strategy.
Files
PR Description Writer
Overview
This skill generates comprehensive, reviewer-friendly pull request descriptions by analyzing git commits and changes. It helps authors communicate their changes effectively, enabling reviewers to understand context, give better feedback, and spend less time orienting themselves to the code.
The skill handles three main scenarios: 1. Generate a new PR description from scratch based on commits since the main branch 2. Update an existing PR description when new commits are added to an in-flight PR 3. Review and improve an existing PR description for quality and completeness
When to Use This Skill
- Creating a new PR: You've made commits on a feature branch and need a description to open a PR
- PR in review with new commits: You've added commits to address feedback; the description needs updating
- Reviewing a PR description: You want to ensure a PR description meets quality standards and helps reviewers
How to Use This Skill
Scenario 1: Generate a New PR Description
User request: "Write a PR description for my changes"
What Claude will do: 1. Run scripts/analyze_git_commits.py to analyze commits and file changes 2. Extract key information about what was changed and why (from commit messages) 3. Identify files that need special attention (core logic vs. supporting changes) 4. Generate a comprehensive PR description following the structured template 5. Reference references/pr_description_guide.md for best practices
What to expect:
- A complete PR description with Summary, Context, Implementation, File organization, Testing strategy, and Risk assessment
- Clear guidance on what files to review first
- Specific testing instructions reviewers can follow
- Explicit risk flags (breaking changes, performance impacts, etc.)
Scenario 2: Update Existing PR with New Commits
User request: "Update the PR description to reflect the new commits I just added"
What Claude will do: 1. Analyze the new commits since the last PR description was written 2. Read the existing PR description to understand the original intent 3. Determine what sections need updating (usually Implementation and Testing) 4. Update the description while preserving the overall structure and context 5. Ensure file lists and risk assessment are current
What to expect:
- An updated PR description that acknowledges the new changes
- Maintains continuity with the original context and purpose
- Clearly shows what changed since the last description
- Ready to paste back into GitHub
Scenario 3: Review and Improve a PR Description
User request: "Review this PR description for quality" or "Improve this PR description"
What Claude will do: 1. Analyze the existing PR description against best practices in references/pr_description_guide.md 2. Identify gaps (missing context, unclear implementation, insufficient testing details) 3. Generate an improved version or provide specific feedback on what's missing 4. Suggest additions based on the actual git changes
What to expect:
- Comprehensive feedback on what's weak and why
- A revised description incorporating all best practices
- Suggestions for testing strategy or risk assessment if missing
- Comparison to best practices with examples
Key Principles
1. Follow the commits, don't invent The PR description is derived from what's actually in the git commits. Commit messages are the source of truth for what was changed and why.
2. Organize by importance, not just by file list For large PRs, explicitly call out which files contain critical logic that must be reviewed first. Distinguish core changes from supporting changes (tests, docs, configuration).
3. Explain the "why" before the "what" Context about business needs, design decisions, and tradeoffs is more important than a file-by-file breakdown of changes.
4. Provide actionable testing guidance Reviewers should be able to validate the changes by following the testing instructions without hunting for information.
Resources
scripts/analyze_git_commits.py
Python script that analyzes git commits and changes to extract structured information:
- Lists all commits on the current branch not in main/master
- Shows which files were added, modified, or deleted
- Provides diff statistics
- Outputs both human-readable summary and structured data
Run this script to gather input for PR descriptions.
references/pr_description_guide.md
Comprehensive guide documenting:
- Core principles of effective PR descriptions
- Recommended section structure (Summary, Context, Implementation, Review Priority, Testing, Risk Assessment)
- Best practices for PRs of different sizes
- Common anti-patterns to avoid
- Special guidance for large PRs with file prioritization
- Examples of good vs. weak PR descriptions (see assets/)
- Impact of good descriptions on code review quality
This is the authoritative reference for PR description best practices.
assets/
Example PR descriptions showing best practices:
pr_template.md– Basic template structureexample_good_pr.md– Comprehensive example of a well-written PR description with all sections properly filledexample_weak_pr.md– Example of weak description before improvement, with annotations on what's wrong and how to fix it
Use these examples to understand the expected level of detail and structure.
Example: Good Pull Request Description
Summary
Implement exponential backoff retry logic for failed payment transactions to reduce manual recovery time from 24 hours to 5 minutes. This improves customer experience and reduces support overhead for failed checkout attempts.
Context
Currently, failed payment transactions require manual intervention and aren't automatically retried. This leads to:
- Lost sales for customers who don't manually retry
- High support volume for payment failures
- Degraded customer experience
Competitors implement automatic retry logic with configurable backoff strategies. This change brings us to industry standard.
Related: Closes #2341, relates to #1999
Implementation
Added a new RetryManager class that:
- Tracks failed transactions with exponential backoff (1s, 2s, 4s, 8s, max 5 attempts)
- Stores retry state in a new
payment_retriestable - Runs retry attempts via a scheduled background job (every 30 seconds)
- Logs all retry attempts for debugging
The PaymentService now delegates to RetryManager for handling failed transactions. When a payment fails, it's automatically queued for retry rather than failing immediately.
Key architectural decisions:
- Database table vs. queue: Chose database for persistence and query-ability rather than Redis queue (allows retry history/analytics)
- Exponential backoff strategy: Standard approach to prevent thundering herd on downstream payment processor
- 5-minute max wait: Balances customer experience with processor load; informed by competitor benchmarking
Files Changed (Review Priority)
- Core Logic (start here):
src/payments/RetryManager.ts– New retry logic with exponential backoff calculationsrc/payments/PaymentService.ts– Updated to queue failed payments for retrysrc/jobs/ProcessPaymentRetries.ts– Background job that executes retries- Data Layer:
migrations/001_add_payment_retries_table.ts– Schema for retry trackingsrc/models/PaymentRetry.ts– ORM model- Testing:
tests/payments/RetryManager.test.ts– Unit tests for backoff calculation and state managementtests/payments/PaymentService.test.ts– Integration tests with RetryManagertests/jobs/ProcessPaymentRetries.test.ts– Job execution and timing tests- Configuration:
.env.example– New retry configuration variablessrc/config/payment.ts– Retry strategy configuration
Testing
To verify these changes:
1. Unit tests: pnpm test payments retry
- Tests exponential backoff calculation
- Tests retry state transitions
- Tests max retry limit
2. Integration tests: pnpm test payments integration
- Tests PaymentService queuing failed payments
- Tests job processing retries correctly
- Tests edge cases (job crashes, duplicate processing)
3. Manual testing:
- Create a test payment with a card that always fails (use test card 4000000000000002)
- Observe the transaction appears in retry queue
- Wait for background job to run (30 seconds)
- Verify retry attempt was made and logged
- Check database for retry history
4. Load testing:
- Simulate 100 concurrent failed payments
- Verify job processes them without errors
- Monitor database/processor load during retry window
Risk Assessment
- Breaking changes: None. This is purely additive; failed payments now auto-retry instead of failing immediately.
- Performance impact: Minimal. New background job runs every 30 seconds for <1ms per existing retry.
- Data migration: One migration required to create
payment_retriestable. Rollback is safe (just drops table). - Backwards compatible: Yes. Existing payment flow unchanged; only adds automatic retry layer.
- Concerns:
- If payment processor has downtime, retries will continue for up to 5 minutes (acceptable per stakeholder feedback)
- Potential duplicate charges if payment processor doesn't handle idempotency properly (mitigated by existing idempotency key implementation)
Additional Notes
- Retry strategy (backoff timing, max attempts) can be configured in
config/payment.ts - All retries are logged with timestamps for debugging and analytics
- Database queries are indexed on
statusandnext_retry_atfor efficient job querying
Example: Weak Pull Request Description (Before Improvement)
What Was Written
Updated payment handling
Changed the payment retry logic. Added new database table and updated service. See commits for details.
Files changed:
- RetryManager.ts
- PaymentService.ts
- PaymentRetry.ts
- migrations
- tests
All tests pass.Problems With This Description
1. No context on "why"
- Reviewers don't understand what problem this solves
- No link to the business need or issue
- No mention of competitors or alternative approaches
2. Vague summary
- "Updated payment handling" tells us nothing
- Reviewers have to read the code to understand intent
3. No file organization
- Just lists files without explaining which are critical
- Reviewers don't know where to start
- No distinction between core logic and supporting changes
4. Insufficient testing details
- "All tests pass" doesn't explain what was tested
- Reviewers can't understand how to validate manually
- No edge cases mentioned
5. Missing risk assessment
- Is this backwards compatible?
- Any breaking changes?
- Performance implications?
6. Implementation details unclear
- What's the actual retry strategy?
- Why this approach over alternatives?
- What are the key architectural decisions?
Result
- Reviewers give cursory approval without fully understanding the change
- Potential bugs are missed because context is lacking
- If something breaks in production, it's hard to understand why
- Knowledge about this feature is only in the author's head
How It Should Be Improved
See example_good_pr.md for the same change described well.
Key Improvements Made
1. ✅ Clear business context for why this change exists 2. ✅ High-level architecture explanation before code details 3. ✅ Files organized by importance and purpose 4. ✅ Detailed testing strategy with concrete steps 5. ✅ Explicit risk assessment and backwards compatibility notes 6. ✅ Design decisions explained with rationale 7. ✅ Issue links for traceability
This allows reviewers to give meaningful feedback instead of just approving.
Pull Request Template
Summary
[2-3 sentences about what this PR does and why it matters]
Context
[What problem does this solve? Why is this change needed?]
Implementation
[High-level description of how you solved it. What are the key changes?]
Files Changed (Review Priority)
For larger PRs, organize files by importance:
- Core (start here):
file1.ts– Brief description of what changedfile2.ts– Brief description of what changed- Supporting:
tests/*.test.ts– Test coveragedocs/– Documentation updates
Testing
[How can reviewers verify this works?]
- Setup steps (if needed)
- Test commands to run
- Key test scenarios
- Manual testing steps (if applicable)
Risk Assessment
[Any breaking changes, performance impacts, or concerns?]
- Breaking changes: None / [List any]
- Performance impact: None / [Describe]
- Migration needed: Yes / No
- Backwards compatible: Yes / No
Additional Notes
[Anything else reviewers should know?]
Pull Request Description Guide
Purpose of This Guide
This guide documents best practices for writing effective PR descriptions that help reviewers understand context and promote effective code reviews. A well-written PR description transforms a confusing diff into a coherent narrative about what changed and why.
Core Principles
1. Guide the reviewer through the code
- Highlight related files and group them into concepts or problems being solved
- Help reviewers spend less time orienting themselves and more time reviewing effectively
2. Provide high-level architectural context
- Explain the "why" behind changes, not just the "what"
- Discuss architectural decisions and their implications
3. Treat the reviewer as a customer
- Make their job easier by providing strategic context
- Save them from having to hunt through the codebase or dig through docs
4. Keep it concise enough to encourage genuine engagement
- Overly verbose descriptions lead to skimming
- Balance comprehensiveness with readability
Recommended PR Description Structure
1. Summary (2-3 sentences)
Brief, high-level overview of what the PR does and why it matters.
Example: "Implement new payment retry logic to reduce failed transaction recovery time from 24 hours to 5 minutes. This reduces customer support burden and improves checkout success rates."
2. Scope/Context (The "What" and "Why")
- Clearly state the motivation behind changes
- Link to related issues, domain logic, and prior discussions about alternatives
- Explain edge cases and constraints that influenced the approach
- Answer: What problem does this solve?
Include:
- References to related issues/PRs
- Context about why this change was needed
- Alternative approaches considered and why they were rejected
- Any constraints or limitations to be aware of
3. Implementation (The "How")
- Give a high-level description of program flow
- Highlight specific areas you want reviewers to pay close attention to
- Explain what may not be immediately obvious from the git diff
- Group related changes logically by component or concept
Include:
- Architecture decisions made
- Key data flow changes
- Any breaking changes or deprecations
- Notable implementation details
4. Review Priority & Navigation (For Large PRs)
When a PR is large or touches multiple components, provide a review entry point to help reviewers navigate efficiently.
Include:
- Identify critical files first – Call out which files contain the core logic changes. Reviewers should start here to understand the primary intent before examining supporting changes.
- Group by concept – Organize files into logical sections (e.g., "Core Feature Logic," "Tests," "Configuration," "Documentation") to show reviewers which files are most important.
- Specify review order – If changes depend on understanding certain files first, explicitly state the recommended review sequence.
- Highlight risky or complex sections – Flag files that introduce breaking changes, complex algorithms, or risky modifications that need extra attention.
- Note supporting vs. core changes – Clearly distinguish between essential changes and supporting changes (like tests, formatting, or documentation) so reviewers know where to allocate focus.
Example format:
## Files Changed (Review Priority)
- **Core** (start here):
- `src/payments/RetryManager.ts` – New retry logic with exponential backoff
- `src/payments/PaymentService.ts` – Updated to use new retry manager
- **Supporting**:
- `tests/payments/*.test.ts` – Full test coverage for retry scenarios
- `docs/PAYMENTS.md` – Updated documentation
- **Infrastructure**:
- `.env.example` – New retry configuration variables
- `migrations/` – Database schema for retry state tracking5. Testing Strategy
Explain how reviewers can verify the changes work:
- Detail setup steps and test commands
- List which code areas were tested and which environments were validated
- Describe any new test cases added
- Explain any manual testing approach
Include:
- Commands to run tests
- Test coverage changes
- Edge cases tested
- Environment-specific testing notes
6. Visual Documentation (For UI/Behavioral Changes)
- Include before/after screenshots showing UI and behavioral differences
- Makes the reviewer's job significantly easier
- Especially important for frontend changes
7. Risk Assessment & Breaking Changes
- Explicitly call out breaking changes
- Flag downstream integration impacts or compatibility considerations
- Document any concerns about the implementation
- Note any deprecated APIs or migration paths
Include:
- Breaking changes for users/consumers
- Database migration risks
- Performance implications
- Backward compatibility considerations
Best Practices
For All PRs
1. Start with a clear title - Make it obvious what's being solved at a high level 2. Use the git commits as your foundation - Follow what the commits actually describe; don't invent a narrative 3. Link to issues - Use keywords like "Closes #123" to automatically link and close issues 4. Keep related changes together - Don't mix unrelated changes in the same PR 5. Provide enough context - Reviewers shouldn't have to hunt through docs or code
For Large PRs (>400 lines)
1. Always include a review priority section - Reviewers need to know where to start 2. Consider splitting into smaller PRs - Reviewers can only effectively process 200-400 lines at a time 3. Group changes by concept - Don't just list every file changed; organize them logically 4. Annotate with comments in the code - Highlight why critical decisions were made 5. Provide clear testing strategy - Reviewers need to understand how to validate your work
For Small PRs (<100 lines)
1. Brief is okay - A sentence or two of context plus the testing approach may suffice 2. Still explain the "why" - Even small changes benefit from context 3. Don't over-explain - Keep it concise and to the point
Anti-Patterns to Avoid
- ❌ Leaving description blank or minimal
- ❌ Focusing only on code-level details without explaining architectural decisions
- ❌ Treating the description as merely a restatement of commit messages
- ❌ Writing vague descriptions that require reviewers to do detective work
- ❌ Burying critical file changes in a long list without calling them out
- ❌ Large PRs without guidance on what to review first
- ❌ Including deprecated code or commented-out sections without explanation
- ❌ Mixing formatting/cleanup changes with functional changes without separating them
Impact on Code Review Quality
Research shows: Code reviewers given good descriptions with context and reasoning gave significantly better feedback than those without.
A context vacuum forces reviewers to:
- Request clarification before reviewing
- Search the codebase independently
- Make assumptions about intent
- Give cursory approvals ("LGTM 👍") due to lack of understanding
Comprehensive PR descriptions prevent these issues and lead to more meaningful feedback.
Common Scenarios
Scenario 1: New Feature
1. What problem does this feature solve? 2. What are the key user flows? 3. What architectural changes were required? 4. How do you test it? 5. Any performance or security considerations?
Scenario 2: Bug Fix
1. What was the bug and how did it manifest? 2. What was the root cause? 3. How does your fix address it? 4. Could this bug have other manifestations? 5. How do you verify the fix works?
Scenario 3: Refactoring
1. Why was this refactoring necessary? 2. What's different about the new approach? 3. Is this backwards compatible? 4. Are there any performance implications? 5. How do you verify functionality is preserved?
Scenario 4: Dependency Update
1. What's being updated and why? 2. What's the breaking change (if any)? 3. What code had to change as a result? 4. Are there migration considerations? 5. How do you test compatibility?
Tools and Integration
GitHub PR Templates
Store a template in .github/pull_request_template.md to provide structure:
## Summary
[2-3 sentences about what this PR does]
## Context
[Why is this change needed? What problem does it solve?]
## Implementation
[High-level description of the changes]
## Testing
[How to verify these changes work]
## Additional Notes
[Risk assessment, breaking changes, etc.]Using the Git Analysis Script
The analyze_git_commits.py script helps gather PR information:
- Lists all commits on your branch
- Shows which files were added, modified, or deleted
- Provides diff statistics
- Helps identify what's truly important to review
Run it to extract information for writing your PR description.
#!/usr/bin/env python3
"""
Analyze git commits for the current branch and generate structured PR information.
This script helps generate or update PR descriptions by analyzing commit history and changes.
"""
import subprocess
import json
import sys
from pathlib import Path
def get_current_branch():
"""Get the current git branch name."""
try:
result = subprocess.run(
["git", "rev-parse", "--abbrev-ref", "HEAD"],
capture_output=True,
text=True,
check=True,
)
return result.stdout.strip()
except subprocess.CalledProcessError:
print("Error: Not in a git repository", file=sys.stderr)
sys.exit(1)
def get_main_branch():
"""Detect the main branch (main or master)."""
try:
result = subprocess.run(
["git", "rev-parse", "--verify", "main"],
capture_output=True,
text=True,
)
if result.returncode == 0:
return "main"
except:
pass
try:
result = subprocess.run(
["git", "rev-parse", "--verify", "master"],
capture_output=True,
text=True,
)
if result.returncode == 0:
return "master"
except:
pass
return "main" # Default assumption
def get_commits_for_branch(base_branch="main"):
"""Get all commits on current branch not in base branch."""
try:
result = subprocess.run(
["git", "log", f"{base_branch}..HEAD", "--pretty=format:%H|%s|%b|%an"],
capture_output=True,
text=True,
check=True,
)
commits = []
for line in result.stdout.strip().split("\n"):
if line:
parts = line.split("|", 3)
commits.append(
{
"hash": parts[0],
"subject": parts[1],
"body": parts[2] if len(parts) > 2 else "",
"author": parts[3] if len(parts) > 3 else "",
}
)
return commits
except subprocess.CalledProcessError as e:
print(f"Error getting commits: {e}", file=sys.stderr)
return []
def get_file_changes(base_branch="main"):
"""Get summary of file changes: added, modified, deleted."""
try:
result = subprocess.run(
["git", "diff", f"{base_branch}...HEAD", "--name-status"],
capture_output=True,
text=True,
check=True,
)
added = []
modified = []
deleted = []
for line in result.stdout.strip().split("\n"):
if not line:
continue
parts = line.split("\t")
status = parts[0]
filepath = parts[1] if len(parts) > 1 else ""
if status == "A":
added.append(filepath)
elif status == "M":
modified.append(filepath)
elif status == "D":
deleted.append(filepath)
return {"added": added, "modified": modified, "deleted": deleted}
except subprocess.CalledProcessError as e:
print(f"Error getting file changes: {e}", file=sys.stderr)
return {"added": [], "modified": [], "deleted": []}
def get_diff_stats(base_branch="main"):
"""Get statistics about the diff."""
try:
result = subprocess.run(
["git", "diff", f"{base_branch}...HEAD", "--stat"],
capture_output=True,
text=True,
check=True,
)
return result.stdout
except subprocess.CalledProcessError as e:
print(f"Error getting diff stats: {e}", file=sys.stderr)
return ""
def get_short_diff(base_branch="main", max_lines=500):
"""Get a short summary of the actual changes."""
try:
result = subprocess.run(
["git", "diff", f"{base_branch}...HEAD"],
capture_output=True,
text=True,
check=True,
)
lines = result.stdout.split("\n")
# Return first max_lines to keep output reasonable
return "\n".join(lines[:max_lines])
except subprocess.CalledProcessError as e:
print(f"Error getting diff: {e}", file=sys.stderr)
return ""
def analyze_pr_info():
"""Main function to analyze PR information."""
current_branch = get_current_branch()
main_branch = get_main_branch()
print(f"Current branch: {current_branch}")
print(f"Base branch: {main_branch}\n")
commits = get_commits_for_branch(main_branch)
file_changes = get_file_changes(main_branch)
diff_stats = get_diff_stats(main_branch)
print("=== COMMITS ===")
for i, commit in enumerate(commits, 1):
print(f"\n{i}. {commit['subject']}")
if commit["body"]:
print(f" {commit['body'][:200]}...")
print("\n\n=== FILE CHANGES ===")
print(f"Added ({len(file_changes['added'])} files):")
for f in file_changes["added"][:10]:
print(f" + {f}")
if len(file_changes["added"]) > 10:
print(f" ... and {len(file_changes['added']) - 10} more")
print(f"\nModified ({len(file_changes['modified'])} files):")
for f in file_changes["modified"][:10]:
print(f" M {f}")
if len(file_changes["modified"]) > 10:
print(f" ... and {len(file_changes['modified']) - 10} more")
if file_changes["deleted"]:
print(f"\nDeleted ({len(file_changes['deleted'])} files):")
for f in file_changes["deleted"][:10]:
print(f" - {f}")
if len(file_changes["deleted"]) > 10:
print(f" ... and {len(file_changes['deleted']) - 10} more")
print("\n\n=== DIFF STATS ===")
print(diff_stats)
# Output structured data as JSON for programmatic use
data = {
"current_branch": current_branch,
"base_branch": main_branch,
"commits": commits,
"file_changes": file_changes,
"stats": {
"total_commits": len(commits),
"files_added": len(file_changes["added"]),
"files_modified": len(file_changes["modified"]),
"files_deleted": len(file_changes["deleted"]),
},
}
return data
if __name__ == "__main__":
analyze_pr_info()