pr-message
Draft a PR message for merging the current branch into main and hand
the user a single fenced Markdown block they can paste into the GitHub
UI or into gh pr create --body-file -.
This skill is repo-local to py-cv-claw. It does not call gh and
does not open or edit PRs.
Defaults
- base =
main
- head = the current branch (typically
dev; whatever
git rev-parse --abbrev-ref HEAD returns)
Print what you inferred at the top of your reply. Do not ask the user
to confirm base/head unless head is main itself (in which case stop
and ask — there's nothing to merge).
Procedure
Discover scope. Run these in parallel and read the results:
git rev-parse --abbrev-ref HEAD — confirm head branch.
git log --oneline main..HEAD — commits on the branch.
git diff main...HEAD --stat — file-level shape (note the
triple-dot: changes on HEAD relative to the merge base, ignoring
work added to main since the branch diverged).
git diff main...HEAD — read enough of the actual diff to
verify commit messages tell the truth. Commits sometimes
mis-describe their scope; the diff is ground truth.
Sanity-check the state. Stop and tell the user (don't draft)
when any of these hold:
git log main..HEAD is empty — no commits to describe.
- Head branch is
main.
- The branch contains merge commits from
main that muddy the
diff. Offer: "Want me to describe only commits authored on this
branch (git log main..HEAD --no-merges), or include the merges?"
Decide whether to ask for framing. Ask the user before
drafting only when:
- The diff spans clearly unrelated themes and the commit titles
don't unify them (e.g. one commit is a dep bump, another is an
unrelated feature, no shared narrative).
- The diff is large (>~30 changed files) and commits are
terse / generic.
Otherwise: draft silently. Most branches in this repo are tightly
themed — don't manufacture ambiguity.
Pick the title.
- One line, ≤70 chars, imperative mood, no trailing period.
- Prefer the dominant conventional-commit prefix from the branch
(
feat:, fix:, refactor:, docs:, chore:). Fall back to
descriptive prose if commits are mixed types.
- The title should stand on its own — a reader scanning the PR list
should understand what's in this PR without opening it.
Write the body. Exactly three H2 sections, in this order:
## Summary
1–2 sentences. The "why," not the "what." Name specs implemented,
issues closed, or design docs referenced — but only if they're
actually present in the diff or commit messages. Never invent links
or issue numbers.
## Changes
Grouped bullets by area. Group labels are derived from the diff;
typical groups in this repo:
- **Code** — anything under `src/cvclaw/`.
- **Skills** — `skills/cv-claw/` and `.claude/skills/`.
- **Docs** — README.md, CLAUDE.md, `.claude/specifications/`.
- **Templates** — `src/cvclaw/templates/` (the bundled root).
- **Build/CI** — pyproject.toml, Makefile, .github/.
Skip groups with no changes. Each bullet ≤1 line; reference files
or subsystems (`src/cvclaw/cli.py`, "ingest.md") rather than commit
hashes. Bold the group label.
## Test plan
Markdown checklist. Use only steps the repo actually supports —
read `Makefile` and `pyproject.toml` to ground each step. For this
repo that's typically:
- [ ] `make lint` is clean.
- [ ] `uv run cv-claw render resumes/example.json` succeeds.
- [ ] Any spec-specific manual smoke tests called out in the
relevant `.claude/specifications/SPEC-*.md`.
Do not invent CI jobs, test suites, or pytest invocations that
don't exist in this repo.
Output. Reply with:
- A single preamble line:
PR message for →, drafted from N commit(s) across M changed file(s).
- A single fenced code block (
markdown … ) containing the
title on the first line, a blank line, then the body. This makes
the whole thing one copy-paste.
Output template
<title>
## Summary
<1–2 sentences>
## Changes
- **<Group>** — <bullet>
- **<Group>** — <bullet>
## Test plan
- [ ] <step>
- [ ] <step>
Conventions (must follow)
- No emojis anywhere in the title or body.
- No "🤖 Generated with Claude Code" trailer. That's for
gh pr create invocations; this skill produces hand-drafted
Markdown the user pastes manually.
- No
Co-Authored-By trailers. Those go on commits, not PR bodies.
- Three sections only. No Notes / Open questions / Followups
section. Caveats fold into Summary or as inline bullets in Changes.
- Don't fabricate test steps. If a verification step isn't real
(no test suite exists, no CI workflow exists), don't list it.
- Don't reference specs or issues that aren't in the diff or
commits. If
.claude/specifications/SPEC-foo.md is touched in
this PR, mention it; if it isn't, don't.
- Don't open or edit a PR. This skill writes text. If the user
wants the PR opened, they will say so separately and the global
gh pr create flow handles it.
Out of scope
- Running
gh pr create / gh pr edit / gh pr view.
- Choosing reviewers, labels, assignees, milestones, or draft state.
- Cross-repo PRs or stacked PR chains.
- Updating an existing PR body in place.
Edge cases
- Branch is up-to-date with main (no commits ahead). Don't draft;
tell the user there's nothing to merge.
- Branch is behind main. Draft normally, but note in the preamble
that the branch is behind and may need a rebase before opening the
PR.
- User asks for a PR message targeting a base other than
main
(e.g. "PR message into release/0.2"). Honor the requested base;
use <base>...HEAD for the diff range.
- User asks while on
main. Stop; ask which branch they meant.
- Detached HEAD. Stop; ask the user to check out a branch first.
1---2name: pr-message3description: Draft a pull-request message (title + Markdown body) for the current branch into main. Use when the user asks for a "PR message", "PR description", "pull request message", or says "write a PR message" / "give me a PR message". Output is Markdown text only — does not call `gh` or open a PR.4---56# pr-message78Draft a PR message for merging the current branch into `main` and hand9the user a single fenced Markdown block they can paste into the GitHub10UI or into `gh pr create --body-file -`.1112This skill is **repo-local** to py-cv-claw. It does not call `gh` and13does not open or edit PRs.1415## Defaults1617- **base** = `main`18- **head** = the current branch (typically `dev`; whatever19 `git rev-parse --abbrev-ref HEAD` returns)2021Print what you inferred at the top of your reply. Do not ask the user22to confirm base/head unless head is `main` itself (in which case stop23and ask — there's nothing to merge).2425## Procedure26271. **Discover scope.** Run these in parallel and read the results:28 - `git rev-parse --abbrev-ref HEAD` — confirm head branch.29 - `git log --oneline main..HEAD` — commits on the branch.30 - `git diff main...HEAD --stat` — file-level shape (note the31 triple-dot: changes on HEAD relative to the merge base, ignoring32 work added to `main` since the branch diverged).33 - `git diff main...HEAD` — read enough of the actual diff to34 verify commit messages tell the truth. Commits sometimes35 mis-describe their scope; the diff is ground truth.36372. **Sanity-check the state.** Stop and tell the user (don't draft)38 when any of these hold:39 - `git log main..HEAD` is empty — no commits to describe.40 - Head branch is `main`.41 - The branch contains merge commits *from* `main` that muddy the42 diff. Offer: "Want me to describe only commits authored on this43 branch (`git log main..HEAD --no-merges`), or include the merges?"44453. **Decide whether to ask for framing.** Ask the user *before*46 drafting only when:47 - The diff spans clearly unrelated themes and the commit titles48 don't unify them (e.g. one commit is a dep bump, another is an49 unrelated feature, no shared narrative).50 - The diff is large (>~30 changed files) **and** commits are51 terse / generic.5253 Otherwise: draft silently. Most branches in this repo are tightly54 themed — don't manufacture ambiguity.55564. **Pick the title.**57 - One line, ≤70 chars, imperative mood, no trailing period.58 - Prefer the dominant conventional-commit prefix from the branch59 (`feat:`, `fix:`, `refactor:`, `docs:`, `chore:`). Fall back to60 descriptive prose if commits are mixed types.61 - The title should stand on its own — a reader scanning the PR list62 should understand what's in this PR without opening it.63645. **Write the body.** Exactly three H2 sections, in this order:6566 ```markdown67 ## Summary6869 1–2 sentences. The "why," not the "what." Name specs implemented,70 issues closed, or design docs referenced — but only if they're71 actually present in the diff or commit messages. Never invent links72 or issue numbers.7374 ## Changes7576 Grouped bullets by area. Group labels are derived from the diff;77 typical groups in this repo:7879 - **Code** — anything under `src/cvclaw/`.80 - **Skills** — `skills/cv-claw/` and `.claude/skills/`.81 - **Docs** — README.md, CLAUDE.md, `.claude/specifications/`.82 - **Templates** — `src/cvclaw/templates/` (the bundled root).83 - **Build/CI** — pyproject.toml, Makefile, .github/.8485 Skip groups with no changes. Each bullet ≤1 line; reference files86 or subsystems (`src/cvclaw/cli.py`, "ingest.md") rather than commit87 hashes. Bold the group label.8889 ## Test plan9091 Markdown checklist. Use only steps the repo actually supports —92 read `Makefile` and `pyproject.toml` to ground each step. For this93 repo that's typically:9495 - [ ] `make lint` is clean.96 - [ ] `uv run cv-claw render resumes/example.json` succeeds.97 - [ ] Any spec-specific manual smoke tests called out in the98 relevant `.claude/specifications/SPEC-*.md`.99100 Do not invent CI jobs, test suites, or pytest invocations that101 don't exist in this repo.102 ```1031046. **Output.** Reply with:105 - A single preamble line: `PR message for `<head>` → `<base>`,106 drafted from N commit(s) across M changed file(s).`107 - A single fenced code block (```markdown … ```) containing the108 title on the first line, a blank line, then the body. This makes109 the whole thing one copy-paste.110111## Output template112113```markdown114<title>115116## Summary117118<1–2 sentences>119120## Changes121122- **<Group>** — <bullet>123- **<Group>** — <bullet>124125## Test plan126127- [ ] <step>128- [ ] <step>129```130131## Conventions (must follow)132133- **No emojis** anywhere in the title or body.134- **No "🤖 Generated with Claude Code" trailer.** That's for135 `gh pr create` invocations; this skill produces hand-drafted136 Markdown the user pastes manually.137- **No `Co-Authored-By` trailers.** Those go on commits, not PR bodies.138- **Three sections only.** No Notes / Open questions / Followups139 section. Caveats fold into Summary or as inline bullets in Changes.140- **Don't fabricate test steps.** If a verification step isn't real141 (no test suite exists, no CI workflow exists), don't list it.142- **Don't reference specs or issues that aren't in the diff or143 commits.** If `.claude/specifications/SPEC-foo.md` is touched in144 this PR, mention it; if it isn't, don't.145- **Don't open or edit a PR.** This skill writes text. If the user146 wants the PR opened, they will say so separately and the global147 `gh pr create` flow handles it.148149## Out of scope150151- Running `gh pr create` / `gh pr edit` / `gh pr view`.152- Choosing reviewers, labels, assignees, milestones, or draft state.153- Cross-repo PRs or stacked PR chains.154- Updating an existing PR body in place.155156## Edge cases157158- **Branch is up-to-date with main** (no commits ahead). Don't draft;159 tell the user there's nothing to merge.160- **Branch is behind main.** Draft normally, but note in the preamble161 that the branch is behind and may need a rebase before opening the162 PR.163- **User asks for a PR message targeting a base other than `main`**164 (e.g. "PR message into `release/0.2`"). Honor the requested base;165 use `<base>...HEAD` for the diff range.166- **User asks while on `main`.** Stop; ask which branch they meant.167- **Detached HEAD.** Stop; ask the user to check out a branch first.