---
name: pr-description-writer
description: >
  Draft and post a GitHub PR title and body from git diff and commit history. Use when
  opening a new PR, when the user asks to "write a PR description", "draft a PR", "open
  a PR for this branch", or after running the git-commit skill and pushing the branch.
  Chains naturally after git-commit and before qodoloop / coderabbitloop.
license: MIT
allowed-tools: Bash, Read, Write
compatibility: Codex, Claude Code, Cursor, GitHub Copilot, Windsurf, Kiro, and other Agent Skills compatible tools. Requires git and gh (GitHub CLI) authenticated.
metadata:
  targets: [_source-only]
  author: Oleg Koval
  tags:
    - git
    - github
    - pull-request
    - description
    - pr
    - workflow
source: weekly-pattern-learner
source_reason: "qodoloop and coderabbitloop both open with gh pr view: the PR creation/description step was never codified as its own skill"
source_date: "2026-07-28"
---

> 🤖 *Auto-generated by **weekly-pattern-learner** · qodoloop and coderabbitloop both open with `gh pr view`: the PR creation/description step was never codified as its own skill*

# PR Description Writer

Draft a GitHub-ready PR title and body from the branch's commit history and diff, then
create or update the PR so reviewers and AI tools have full context.

## Inputs

- **Base branch** (optional, default: `main` or `master`, detect from `gh repo view`)
- **Draft mode** (optional, default: off)
- **Template** (optional): if `.github/pull_request_template.md` exists, use its section headings

## Workflow

### 1. Gather branch context

```bash
# Current branch
git rev-parse --abbrev-ref HEAD

# Base branch
gh repo view --json defaultBranchRef -q '.defaultBranchRef.name'

# Commits since base
git log <base>..<head> --oneline --no-merges

# Diff summary (full diff for small PRs, stat-only for large)
git diff <base>..<head> --stat
git diff <base>..<head>   # only if total changes < ~500 lines
```

If the diff is large (>500 changed lines), read file-by-file rather than all at once.

### 2. Check for existing PR

```bash
gh pr view --json number,title,body,state 2>/dev/null
```

- If a PR exists in `OPEN` state: update it with `gh pr edit`.
- If no PR exists: create one with `gh pr create`.

### 3. Check for a PR template

```bash
cat .github/pull_request_template.md 2>/dev/null \
  || cat .github/PULL_REQUEST_TEMPLATE.md 2>/dev/null \
  || cat PULL_REQUEST_TEMPLATE.md 2>/dev/null
```

If a template exists, mirror its section headings and populate them. Skip sections
that ask for credentials, tokens, internal hostnames, or content unrelated to the diff.

### 4. Draft title and body

**Title rules:**
- Use Conventional Commits prefix when the branch/commits use it: `feat(scope):`, `fix:`, etc.
- ≤ 70 characters
- Imperative mood ("Add X", "Fix Y", not "Added X")
- Include ticket number if present in branch name (e.g. `LIN-123`, `GH-456`)

**Body sections (use the template if one was found, otherwise use this structure):**

```markdown
## Summary
- <bullet: what changed>
- <bullet: why>

## Changes
- `<file or subsystem>`: <what changed and why>

## Test plan
- [ ] <what to run and what result to expect>
- [ ] <manual steps if automated tests don't cover it>

## Notes
<optional: anything a reviewer should watch for, known gaps, follow-up issues>
```

Rules:
- Describe *intent*, not what the diff already shows line-by-line.
- If commits already have good conventional messages, use them as the skeleton.
- Skip any section that has nothing meaningful to say.
- Reference specific files, functions, or lines only when they aid navigation.

### 5. Create or update the PR

Always pass the body via a heredoc or temp file: never interpolate it into the command
string (quotes and newlines will break the shell):

```bash
# Create new PR
gh pr create \
  --title "<title>" \
  --body "$(cat <<'PRBODY'
<body>
PRBODY
)" \
  --base <base> \
  [--draft]

# Update existing PR
gh pr edit <number> \
  --title "<title>" \
  --body "$(cat <<'PRBODY'
<body>
PRBODY
)"
```

### 6. Confirm and report

```bash
gh pr view --json number,title,url -q '"PR #\(.number): \(.title)\n\(.url)"'
```

Print the PR number, title, and URL. If the PR was newly created, note whether
CI triggered automatically.

## Chaining

| Before this skill | After this skill |
|---|---|
| `olko:git-commit` + `git push` | `olko:qodoloop` |
| `git push -u origin <branch>` | `olko:coderabbitloop` |
| N/A | `olko:open-source-publisher` (for new repos) |
