pr-create

Installation
SKILL.md

PR Create

Hard rules

These override anything else. No exceptions without an explicit user instruction.

  • Never append Claude attribution trailers. No 🤖 Generated with Claude Code, no Co-Authored-By: Claude …, no "Generated by" footers. The PR title and body contain nothing that identifies the author as an AI.
  • Never force-push unless the user explicitly asks this turn — and only --force-with-lease, never plain --force. Confirm the head branch is not main / master before the push.
  • Never open a PR from main / master. Stop and surface to the user.
  • Never auto-rebase or auto-merge the base branch. If the branch is behind, surface it and ask.
  • Never fill a checklist item you haven't verified. Leave [ ] unchecked; don't tick boxes on the user's behalf.
  • Never open a PR that contains secrets. If the diff touches .env*, *credentials*, *.pem, *.key, or id_rsa*, stop and surface to the user — even if the user asked you to proceed. Public PRs cache forever.

Workflow

  1. Preflight — validate branch state, remote state, and gh auth.
  2. Gather context — commits, diff, branch name, referenced issues, existing PR template.
  3. Draft title and body — Conventional Commits title + Summary covering why and what.
  4. Propose for approval — show the draft; wait for edits or OK.
  5. Push and create — push the branch, open the PR, return the URL.

Step 1 — Preflight

Run these in parallel and stop if any check fails:

gh auth status
git rev-parse --abbrev-ref HEAD
git status --porcelain
BRANCH=$(git rev-parse --abbrev-ref HEAD)
gh pr list --head "$BRANCH" --state open --json url,number

Fail-stop conditions:

Check Condition Action
Current branch main or master Stop. Tell the user to switch to a feature branch.
gh auth status not authenticated Stop. Tell the user to run gh auth login.
Existing PR a PR already exists for this branch Stop. Return the existing URL — don't open a duplicate.
Uncommitted changes git status --porcelain is non-empty Surface to the user. This skill is PR-only; don't auto-commit.

Determine the base branch (usually main, sometimes master or develop):

gh repo view --json defaultBranchRef --jq .defaultBranchRef.name

Check the branch is up to date with the base. Fetch first so the comparison is accurate:

git fetch origin
BASE=$(gh repo view --json defaultBranchRef --jq .defaultBranchRef.name)
BEHIND=$(git rev-list --count HEAD..origin/$BASE)

If BEHIND > 0, surface it: "Your branch is N commits behind origin/$BASE. Rebase or merge before opening the PR?"do not auto-rebase.


Step 2 — Gather context

Collect the material needed to write the title and body:

BASE=$(gh repo view --json defaultBranchRef --jq .defaultBranchRef.name)
git log --reverse --pretty=format:'%h %s%n%b%n---' origin/$BASE..HEAD
git diff --stat origin/$BASE...HEAD
git rev-parse --abbrev-ref HEAD

Sensitive-file scan. Check the file list from git diff --stat for paths matching .env*, *credentials*, *.pem, *.key, or id_rsa*. Any match → stop and surface to the user per the hard rule. Do not proceed even if the user tells you to; require a direct re-confirmation that the file is intentional.

Issue references. Scan commit subjects, commit bodies, and the branch name for #NNN patterns. Only promote to Closes #NNN when the signal is unambiguous:

  • A commit subject matches ^(fix|close|resolve)(\(.+\))?: and contains #NNN on the same line.
  • The branch name starts with fix/NNN-… or issue-NNN-….

Every other reference (#NNN in a body, a refactor commit mentioning an issue, a feat that relates to but doesn't close an issue) is Refs #NNN. Default to Refs when in doubt and flag for the user in Step 4 — a wrong Closes silently closes an issue on merge, a wrong Refs is harmless.

PR template. Check for a template and use it as the body scaffold if it exists. GitHub looks in several locations — check all of them:

ls .github/pull_request_template.md \
   .github/PULL_REQUEST_TEMPLATE.md \
   pull_request_template.md \
   PULL_REQUEST_TEMPLATE.md \
   docs/pull_request_template.md \
   docs/PULL_REQUEST_TEMPLATE.md \
   2>/dev/null
ls -d .github/PULL_REQUEST_TEMPLATE/ 2>/dev/null

If .github/PULL_REQUEST_TEMPLATE/ is a directory (multi-template repo), list its contents and ask the user which template applies before filling.

If a template is found, fill its sections from the gathered context. If it has a checklist, leave items unchecked unless you've verified them.


Step 3 — Draft title and body

Title

Conventional Commits: type(scope): subject

  • typefeat, fix, docs, refactor, test, chore, perf, build, ci.
  • scope — optional; the primary package/module/area touched. Derive from paths in git diff --stat.
  • subject — imperative mood, lowercase, no trailing period, under ~70 chars total.

If the branch has a single commit, reuse its subject when it already follows Conventional Commits. Otherwise, synthesize a new subject that covers the dominant change.

Body — default structure (when no repo template exists)

## Summary

<2–4 sentences. Lead with *why* — the problem, the user need, the constraint that forced this. Then *what* — the concrete change. Avoid restating the diff.>

## Changes

- <bullet per meaningful change, grouped by concern>
- <>

Closes #NNN

Summary rules:

  • Start with the motivation (why), not the implementation (what).
  • One paragraph, not a wall of text. If you need headings inside Summary, the change is probably two PRs.
  • Never write "This PR …" — write the change directly.
  • No hedging ("attempts to", "should hopefully"). State what it does.

Body — when a repo template exists

Fill the template's sections verbatim (don't rename or reorder). Map:

  • Template "Summary" / "Description" / "What" → the Summary content above.
  • Template "Why" / "Motivation" → the why from the Summary (split it if the template separates them).
  • Template "Testing" / "Test Plan" → describe what was tested if verified, otherwise leave blank with a note for the user to fill in. Do not fabricate test steps.
  • Template "Checklist" → unchecked [ ] unless verified.
  • Template "Issue" / "Related" → Closes #NNN / Refs #NNN.

Step 4 — Propose for approval

Print the full draft — exactly as it will be submitted — and wait. Format:

Title:  feat(tracer): stream spans to disk without blocking the agent loop
Base:   main ← <current-branch>
Draft:  no

---
## Summary

## Changes
- …

Closes #42
---

If there's any ambiguity (close vs refs, unclear scope, behind base), list it under the draft as numbered clarifications. The user edits by number or gives a free-form correction. Re-render the draft after edits and re-confirm before proceeding.

Do not proceed without explicit approval. A silent response is not approval.


Step 5 — Push and create

Push the branch (set upstream if missing). No --force variants.

git push -u origin HEAD

Create the PR with a HEREDOC so the body formats correctly:

gh pr create \
  --base "$BASE" \
  --title "feat(tracer): stream spans to disk without blocking the agent loop" \
  --body "$(cat <<'EOF'
## Summary

Span export was blocking the agent loop under load because the exporter flushed synchronously on every span. This moves writes to a background task with a bounded channel so the hot path stays non-blocking.

## Changes

- Replace synchronous `flush()` with a background writer task
- Add bounded channel with `warn!` on dropped sends
- Cover writer shutdown in `tracer::tests::shutdown_drains_queue`

Closes #42
EOF
)"

Return the PR URL to the user. Done.


Edge cases

Fail-stop conditions are already covered in Step 1 (main/master, uncommitted changes, existing PR, no auth). The cases below are the genuinely ambiguous ones.

Situation Handling
No upstream set Use git push -u origin HEAD — don't prompt.
Branch behind base Surface to user; do not auto-rebase or auto-merge.
Dirty commit history (WIP, "fix typo") Flag in Step 4 as a clarification; offer squash as a follow-up the user runs, not as an auto-action.
Template present but empty/malformed Fall back to the default body structure; note it in Step 4.
Multi-template repo (.github/PULL_REQUEST_TEMPLATE/ directory) List available templates; ask the user which one applies.
Issue reference is ambiguous (#42 in a refactor commit) Default to Refs #42, flag for the user.
User requests --draft Add --draft to gh pr create; leave everything else unchanged.
User requests force-push Only then, and only --force-with-lease; confirm the head (current) branch is not main / master.
Weekly Installs
2
GitHub Stars
3
First Seen
2 days ago