|
| 1 | +--- |
| 2 | +name: sdlc:create-pr |
| 3 | +description: Use when creating a pull request -- reads the PR template, auto-fills from git context and linked issue, confirms with the user, then creates via gh CLI. |
| 4 | +--- |
| 5 | + |
| 6 | +# /sdlc:create-pr |
| 7 | + |
| 8 | +Create a well-structured GitHub pull request by reading the repo's PR template and filling it from context. |
| 9 | + |
| 10 | +**Core principle:** Templates own the format. Context owns the content. User owns the final word. |
| 11 | + |
| 12 | +## Template Location |
| 13 | + |
| 14 | +Read `.github/PULL_REQUEST_TEMPLATE.md` relative to the project root on every invocation. This path is fixed -- do not search for it. |
| 15 | + |
| 16 | +## Core Pattern |
| 17 | + |
| 18 | +1. **Gather** -- Collect all inputs silently. Ask only when auto-derivation fails. |
| 19 | +2. **Draft** -- Fill every template section from the gathered context. |
| 20 | +3. **Confirm** -- Show the full draft. Wait for explicit approval. Iterate. |
| 21 | +4. **Create** -- Run `gh pr create` with `--body-file`. Report the URL. |
| 22 | + |
| 23 | +## Step 1: Gather |
| 24 | + |
| 25 | +**Auto-derive (no user interaction):** |
| 26 | + |
| 27 | +- Read `.github/PULL_REQUEST_TEMPLATE.md` |
| 28 | +- Run `git diff <base>...HEAD` -- the branch diff |
| 29 | +- Run `git log <base>..HEAD --oneline` -- the commit history |
| 30 | +- Extract issue number from branch name (pattern: `type/NNN-description`, e.g., `feat/17-add-skill` → `#17`) |
| 31 | +- If issue number found, run `gh issue view NNN --json title,body,labels` and extract acceptance criteria from the body |
| 32 | + |
| 33 | +**Ask when needed (use multiple-choice where possible):** |
| 34 | + |
| 35 | +| Question | When | Options | |
| 36 | +|----------|------|---------| |
| 37 | +| "Which issue does this PR close?" | Branch name has no issue number | List of recent open issues (via `gh issue list --state open --limit 5 --json number,title`) + "None" + Other | |
| 38 | +| "PR type?" | Always; pre-select "Ready for review" | "Ready for review" / "Draft" | |
| 39 | +| "Base branch?" | Always; **must be asked even when auto-detected** -- the auto-detected value is the pre-selected default, not a reason to skip | Branch we branched from (auto-detected via `git merge-base` against known remote branches; pre-selected as default) / `develop` (if present in remote) / `main` / Other | |
| 40 | +| "Who should review this PR?" | Always; multi-select | All reviewers returned by script (see below), in order, plus "Other" as the last option | |
| 41 | +| "Who should this PR be assigned to?" | Always; pre-select "Me" | "Me" (resolved via `gh api user --jq '.login'`) / "Nobody" (default if "Me" feels presumptuous) / Other | |
| 42 | +| "Which checklist items have you completed?" | Always; multi-select; zero selections is valid (means none completed yet) | "Self-reviewed my own diff" / "Tests added or updated" / "Docs updated (if applicable)" / "No unrelated changes bundled in" | |
| 43 | +| "Will you add screenshots to this PR?" | Always | "Yes, I'll add them after creation" / "No" (default) | |
| 44 | + |
| 45 | +### Helper scripts |
| 46 | + |
| 47 | +**IMPORTANT:** Do NOT run `bash .claude/skills/create-pr/*.sh` directly -- that path only works for project-local installs. Always use the commands below, which resolve the script location first. |
| 48 | + |
| 49 | +Auto-detect base branch: |
| 50 | + |
| 51 | +```bash |
| 52 | +if [[ -f .claude/skills/create-pr/get-base-branch.sh ]]; then bash .claude/skills/create-pr/get-base-branch.sh; elif [[ -f "$HOME/.claude/skills/create-pr/get-base-branch.sh" ]]; then bash "$HOME/.claude/skills/create-pr/get-base-branch.sh"; fi |
| 53 | +``` |
| 54 | + |
| 55 | +It outputs the branch name (e.g., `main`, `develop`) whose merge-base with HEAD is most recent -- i.e., the branch we most likely forked from. Present it as the pre-selected default in the base branch question. |
| 56 | + |
| 57 | +Fetch recent reviewers: |
| 58 | + |
| 59 | +```bash |
| 60 | +if [[ -f .claude/skills/create-pr/get-reviewers.sh ]]; then bash .claude/skills/create-pr/get-reviewers.sh; elif [[ -f "$HOME/.claude/skills/create-pr/get-reviewers.sh" ]]; then bash "$HOME/.claude/skills/create-pr/get-reviewers.sh"; fi |
| 61 | +``` |
| 62 | + |
| 63 | +It outputs up to 4 reviewer logins, one per line, ordered most-recent-first (excludes the current user; falls back to alphabetical collaborators for new repos). Show every login the script returns as an option, in the exact order returned. Add "Other" as the last option. Do not add a "Skip" or "None" option -- if the user wants no reviewers, they select only "Other" and leave it empty. |
| 64 | + |
| 65 | +Do not add labels to the PR. Labels are managed separately. |
| 66 | + |
| 67 | +## Step 2: Draft |
| 68 | + |
| 69 | +### PR Title |
| 70 | + |
| 71 | +Conventional commit format: `type(scope): subject` or `type: subject`. |
| 72 | + |
| 73 | +Allowed types: `feat`, `fix`, `docs`, `test`, `ci`, `refactor`, `perf`, `chore`, `revert`, `wip`, `build`, `style`, `release`. |
| 74 | + |
| 75 | +<!-- Standard Conventional Commits prefixes only, matching the types documented in CLAUDE.md. Projects adopting this starter kit can extend this list to suit their conventions. --> |
| 76 | + |
| 77 | +- Derive from branch name and commit history |
| 78 | +- Scope is optional |
| 79 | +- Subject: lowercase, imperative mood, no trailing period |
| 80 | + |
| 81 | +### PR Body |
| 82 | + |
| 83 | +Fill every section in template order. Strip all HTML comments (`<!-- ... -->`). |
| 84 | + |
| 85 | +#### Summary |
| 86 | + |
| 87 | +First line: `Closes #` |
| 88 | + |
| 89 | +If no linked issue, first line: `No related issue. <one sentence motivation>` |
| 90 | + |
| 91 | +Followed by 1-3 sentences synthesizing commits and issue description, focused on *why* not *what*. If no issue is linked, derive from commits and branch name only. |
| 92 | + |
| 93 | +#### Changes |
| 94 | + |
| 95 | +Bullet list. Each bullet = one discrete change from the diff or commit messages. |
| 96 | + |
| 97 | +#### Acceptance criteria |
| 98 | + |
| 99 | +- **Issue has AC:** Mirror as checkboxes. Check off items the diff demonstrates are fulfilled. |
| 100 | +- **Issue has no AC, or no issue:** Suggest AC based on the changes made. Present as unchecked checkboxes. |
| 101 | +- **AC diverged from issue:** Note it explicitly. Example: "Note: criterion X was moved to #M" or "Added: Y discovered during implementation." |
| 102 | + |
| 103 | +#### Test plan |
| 104 | + |
| 105 | +Two subsections, always present: |
| 106 | + |
| 107 | +##### Automated tests |
| 108 | +List test files added/modified in the diff and the command to run them. If none: `No automated tests added.` |
| 109 | + |
| 110 | +##### Manual verification |
| 111 | +If the change has user-facing or integration behavior, list manual steps. If purely internal: `No manual steps required.` |
| 112 | + |
| 113 | +#### Breaking changes |
| 114 | + |
| 115 | +If breaking changes detected (API changes, removed exports, schema changes): describe what breaks and migration steps. |
| 116 | + |
| 117 | +If none: `None.` |
| 118 | + |
| 119 | +#### Checklist |
| 120 | + |
| 121 | +Render all four items based on the user's selections from the Gather step: |
| 122 | + |
| 123 | +- Items selected by the user → `- [x] <item>` |
| 124 | +- Items not selected → `- [ ] <item>` |
| 125 | + |
| 126 | +The four items, in order: |
| 127 | + |
| 128 | +1. Self-reviewed my own diff |
| 129 | +2. Tests added or updated |
| 130 | +3. Docs updated (if applicable) |
| 131 | +4. No unrelated changes bundled in |
| 132 | + |
| 133 | +#### Screenshots |
| 134 | + |
| 135 | +Based on the Step 1 answer: |
| 136 | + |
| 137 | +- "Yes": `To be added after PR creation.` (remind user to attach via GitHub UI) |
| 138 | +- "No" (default): `None.` |
| 139 | + |
| 140 | +**The section is always present.** |
| 141 | + |
| 142 | +## Step 3: Confirm |
| 143 | + |
| 144 | +Show to the user: |
| 145 | +- PR title |
| 146 | +- Complete body (all sections, no HTML comments) |
| 147 | +- Target base branch |
| 148 | +- The exact `gh pr create` command that will run |
| 149 | + |
| 150 | +Wait for explicit approval. Accept edits to any section. Loop until approved. |
| 151 | + |
| 152 | +## Step 4: Create |
| 153 | + |
| 154 | +```bash |
| 155 | +BODY_FILE=$(mktemp /tmp/gh_pr_body_XXXXXX) |
| 156 | + |
| 157 | +# Replace the placeholder below with the actual drafted PR body: |
| 158 | +cat > "$BODY_FILE" << 'EOF' |
| 159 | +{{PR_BODY}} |
| 160 | +EOF |
| 161 | + |
| 162 | +gh pr create \ |
| 163 | + --title "<title>" \ |
| 164 | + --base "<base-branch>" \ |
| 165 | + --body-file "$BODY_FILE" \ |
| 166 | + [--reviewer <handle> ...] \ |
| 167 | + [--assignee <handle>] |
| 168 | +``` |
| 169 | + |
| 170 | +Add `--draft` if user selected "Draft" in Step 1. Add one `--reviewer <handle>` flag per reviewer selected in Step 1; if "Other" was selected, use the handle the user provided. Add `--assignee <handle>` using the resolved login if "Me" or "Other" was selected; omit if "Nobody". |
| 171 | + |
| 172 | +After reporting the PR URL: if the user selected "Yes" for screenshots in Step 1, remind them to attach screenshots via the GitHub UI. |
| 173 | + |
| 174 | +## Edge Cases |
| 175 | + |
| 176 | +### Branch is behind base |
| 177 | +Present options: |
| 178 | +1. **Continue as-is** -- create the PR and note it's behind |
| 179 | +2. **Rebase onto base** -- run `git rebase <base>`; if conflicts, help resolve |
| 180 | +3. **Merge base in** -- run `git merge <base>`; if conflicts, help resolve |
| 181 | +4. **Abort** -- stop; do not create the PR |
| 182 | + |
| 183 | +### No commits ahead of base |
| 184 | +Stop. "No commits ahead of `<base>`. Nothing to create a PR from." |
| 185 | + |
| 186 | +## Common Mistakes |
| 187 | + |
| 188 | +- **Reconstructing the template from memory** -- read `.github/PULL_REQUEST_TEMPLATE.md` every time. |
| 189 | +- **Generating an ad-hoc format** -- every section from the template must appear, in template order. |
| 190 | +- **Creating before confirmation** -- never run `gh pr create` without explicit user approval. |
| 191 | +- **Leaving HTML comments** -- strip all `<!-- ... -->` from the output. |
| 192 | +- **Silently omitting `Closes #`** -- if no issue, say so explicitly on the first line. |
| 193 | +- **Deleting empty sections** -- Breaking changes and Screenshots are always present; use `None.` |
| 194 | +- **Ignoring AC divergence** -- note explicitly when PR criteria differ from the issue's. |
| 195 | +- **Skipping the base-branch question** -- always present it. Auto-detection provides the default, not the answer. |
| 196 | + |
| 197 | +## Installation |
| 198 | + |
| 199 | +This skill includes helper scripts alongside `SKILL.md`. When installing or updating, copy (or symlink) the **entire `create-pr/` directory** -- not just `SKILL.md`. All files in this directory are required: |
| 200 | + |
| 201 | +- `SKILL.md` -- skill definition |
| 202 | +- `get-base-branch.sh` -- auto-detects the base branch |
| 203 | +- `get-reviewers.sh` -- fetches recent reviewer logins |
0 commit comments