Skill v1.0.0
currentAutomated scan100/100version: "1.0.0" name: draft-pr description: > Draft a copy-paste PR description (title + body) for the current change, a diff, or an issue link — following the repo's own template and conventions where it has them, and a plain-language default style where it doesn't. Use when the user says "draft pr", "/draft-pr", "write a PR description", or hands over a change/link to turn into a PR. Never touches a git remote — output only.
draft-pr
Produce a ready-to-paste PR draft (title + Markdown body). This skill NEVER creates, pushes, or opens a PR. It does not run gh pr create, does not push branches, does not open compare URLs. Output only — the PR is the user's to open.
Input (any of)
- Nothing → use the current change (
git diffon the current branch vs base). - An issue link / id → read it for context on what's wrong, pair with the current diff.
- A compare/PR link → base the draft on that diff.
- A pasted diff or plain description → draft from that.
The repo outranks this file
Before drafting, look for what the project already requires and follow that instead of the defaults below:
- A PR template —
.github/PULL_REQUEST_TEMPLATE.md, aPULL_REQUEST_TEMPLATE/directory,.gitlab/merge_request_templates/, or one linked from the contributing docs. Fill its sections as written and keep its headings and checklists, even where they differ from the shape below. - Written rules —
CONTRIBUTING.md,CLAUDE.md,AGENTS.md: title conventions, a required issue link, required trailers or sign-off, labels, conventional-commit titles. - What actually gets merged —
gh pr list --state merged --limit 5 --json title,body. Real practice beats a stale written rule.
Where the repo is silent, use the style below. Where it conflicts, the repo wins. Two rules hold either way: never touch a remote, and never sign the draft as AI-authored.
Steps
- Locate the repo. cwd, or the relevant subdir. Confirm it's a git repo. If the request spans more than one repo, ask which one (or draft two separate blocks — never mix repos in one PR body).
- Find the base branch.
git symbolic-ref refs/remotes/origin/HEAD(usuallyorigin/main). Fall back tomain/master.
- Collect the change.
git branch --show-currentgit diff --stat <base>...HEADandgit diff <base>...HEAD(read it — understand what actually changed, root cause, side effects).git log <base>..HEAD --format='%s%n%b'for intent already written in commits.- If the working tree is dirty and that's the change, use
git diff(unstaged/staged) instead.
Source of truth: the CODE. The diff is the primary truth for what changed. An issue, if there is one, only informs ## Summary. If they disagree, the code wins.
- Write the draft — the repo's template if it has one, otherwise the house style below. Match scope: a small fix gets a short body.
- Check it before handing it over. Read it once as the reviewer would:
- The title alone says what the branch does.
- The first sentence of the summary alone is enough to decide whether to review now.
- It follows Formatting below: no broken lines, no dashes, bold only on categories.
- Nothing comes from the conversation rather than the branch, and nothing is invented.
- Write the draft to a file and link it (see Output). Put the title on the first line as
## Title:then the body. Keep the file self-contained — no commentary inside it.
House style
The default when the repo prescribes nothing.
Register — plain language by default
Write for a reviewer skimming on a phone, not for a compiler. Plain, everyday English. No type signatures, no class/method/resolver names, no internal mechanism unless a reviewer genuinely needs it to review.
The one override: if the invoking request asks for something more technical, follow the request. Same if the change itself is deeply technical (schema migration, protocol change, threading model) and the problem can't be stated any other way — then go as technical as the subject demands, and no further.
Title
Concise imperative or noun phrase. Concrete and specific. Examples:
Fix the active tab going blank after a reorderPer-user ordering for saved filters, with a drag-to-reorder sheetSpeed up the nightly cleanup job
No ticket ids. No (#NNNN) — the host assigns the PR number.
Body — DEFAULT SHORT
Most PRs are small: 0–4 body lines (trivial), ~10–25 lines (typical). Match that. Do NOT write a mega-PR body unless the change is genuinely large. Focus on the overall change, never a line-by-line tour.
The template — this is the shape, use it for everything:
## Summary<Short and plain, usually 1-2 sentences. What this branch adds or fixes, and why it matters. Go longer ONLY when the change is genuinely hard to state.>## Changes* <the more important changes, one line each>* <brief, not super technical, unless the change itself is technical or the request asked for technical>## Testing- <manual QA guide — only when hand-testing is the only way to verify; see rule below>
Cross-repo link. When the same work ships across two repos (e.g. a backend and a frontend PR), add a line at the very bottom of each PR pointing at its counterpart. You won't have the URL yet — use a placeholder to fill in:
Related PR: <link>Only add this when the change genuinely spans both repos.
Linked issue. When the branch fixes or delivers an issue, link it on one line at the bottom (Closes <link>, or the repo's own keyword) instead of restating the issue in ## Summary. The summary says what the branch does; the issue already says what was wrong.
Section rules
- `## Summary` — the opener, always. Simple and short. For a bug, the root cause goes here only when the cause is the interesting part.
- `## Changes` — a loose list of what the branch adds. Describe it the way you'd tell a teammate, not the way the diff reads. Keep bullets brief and not overly technical; go technical only where the change genuinely is, or where the request asked for it. When the bullets sort the change into distinct parts, bold each part's name, then a hyphen, then the rest:
* **Saved filters** - per-user order, kept across sessions.Otherwise plain bullets with no bold at all. Never enumerate call sites, file counts, or line numbers unless the count itself is the point. - `## Notes` — rare. Only when there is something a reviewer would otherwise trip over or ask about. Skip it for anything the team already agreed on: a thing that was intentionally left out is a settled decision, not PR news. When in doubt, omit the section entirely.
- `## Testing` — conditional, NOT always:
- Diff adds/updates automated tests → omit the section (or one line: "Covered by specs"). Don't restate what the specs assert.
- Nothing meaningful for a reviewer to click through → omit it. Don't invent QA steps to fill the template.
- UI or device work with no automated coverage → this is the valuable case. Write a checkbox list of the flows, states, and edge cases to walk through.
- Trivial change →
## Summaryplus one or two## Changesbullets. Nothing else. - Large change → expand
## Summaryand split## Changesinto named parts. Reach for this rarely — when in doubt, stay short.
Scope: the branch, not the conversation
A PR describes what the branch adds, full stop. Not the investigation that led to it, not bugs found along the way, not what was discussed while building it. If the work turned up problems that are being filed elsewhere, they belong in those issues, not in this body.
The scope is the branch's own commits against the branch it will merge into — on a long-lived feature line that base is often not main/master. Check where the branch actually forked (git log --oneline <base>..HEAD, and see whether the first commits below yours belong to someone else's line) before trusting a main...HEAD diff, which on such a branch can show hundreds of unrelated files.
Voice
- Say what it does for a human, not how it's wired. Prefer "the member list now shows who is muted, searchable by name" over a query signature. Prefer "admins only" over a policy method name.
- Use inline
codesparingly, only for a name a reviewer would grep for. - Concise, no filler. Call out what was intentionally NOT done only when a reviewer would otherwise ask.
Formatting
- Do not break a sentence across lines. Each paragraph and each bullet is one line in the file. GitHub renders every line break in a PR body, so a hard-wrapped draft shows up broken mid-sentence.
- No em dashes or en dashes. Use a plain hyphen, or the comma, colon or full stop the dash was standing in for.
Footer
Never sign the PR as AI-authored. Do NOT append a "Generated with Claude Code" line, a Co-authored-by: AI trailer, robot emoji credit, or any other AI attribution. The draft must read as the author's own. End the body at the last content line — no footer. A sign-off or trailer the repo requires (DCO, an issue link) is not attribution and still applies.
Output
Default: write the draft to a file git will never pick up, then link it. Do not paste the whole body into chat as well — the file is the deliverable.
- Make sure the scratch directory exists and is locally excluded (safe to repeat):
mkdir -p session-materials && grep -qxF 'session-materials/' .git/info/exclude || echo 'session-materials/' >> .git/info/exclude
.git/info/exclude is local to the clone and is never committed, so drafts stay out of git status, out of every diff, and out of every commit. Never add them to .gitignore instead — that file is committed.
- Write the draft to
session-materials/pr-<branch-slug>.md. If that path already exists, suffix it-2,-3rather than overwriting an earlier draft.
- Report the repo-relative path so it renders as a clickable link, with the title on one line next to it. Your own remarks go in chat beside the link, never inside the file.
When a manager is running you — manage-work or any other orchestrator — write to the path it gave you (fall back to the default above if it gave none) and report that path upstream to the manager, not to the user. The manager owns what the user sees; do not address the user directly in that mode.
No git repo, or the caller named a path → use the caller's path, otherwise a temp directory from mktemp -d. Say where it landed either way.
The file's content is exactly this, and nothing else:
Title: …
Summary
…
Changes
- …
Testing
- [ ] …
Open it with a header line naming the base branch and the head branch, so the draft is readable without the conversation that produced it.
Do not run any git remote / gh pr create command. Opening the PR is the user's to do.