From pr
Commit all changes (if needed), push to remote, and create a GitHub pull request in one automated step with no prompts. Handles plan files automatically (renaming, moving completed plans to done). Use when the user says "pr", "create a pr", "open a pr", "submit a pr", "push and create pr", "commit and create pr", or any variant involving creating a pull request from the current branch. Requires the gh CLI to be installed.
How this skill is triggered — by the user, by Claude, or both
Slash command
/pr:prThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Commit, push, and create a pull request in one automated step. Never prompt the user for input — make opinionated decisions at every step.
Commit, push, and create a pull request in one automated step. Never prompt the user for input — make opinionated decisions at every step.
First, detect the repository's base branch:
gh repo view --json defaultBranchRef --jq '.defaultBranchRef.name'
If gh is not available or the command fails, fall back to:
git remote show origin | grep 'HEAD branch' | sed 's/.*: //'
Use the detected value as <default-branch>.
The current branch may have been created from a non-default branch (e.g., for stacked PRs). Check the reflog for the branch creation point:
git reflog show $(git branch --show-current) --format='%gs' | tail -1
This produces output like branch: Created from develop, branch: Created from origin/develop, or branch: Created from refs/heads/feature/parent. If the last entry matches branch: Created from <name>, extract <name> and normalize it by stripping any refs/heads/, refs/remotes/origin/, or leading origin/ prefix.
If a source branch name was extracted, verify it is a valid base for the PR. Run these checks in order, stopping at the first failure:
Not the current branch: The source branch must differ from the current branch.
Exists on the remote: Note that git ls-remote always exits 0 regardless of whether the branch exists, so check for non-empty output:
git ls-remote --heads origin <source-branch> | grep -q .
Not already merged into the default branch: The source branch may have been merged into the default branch since this branch was created (e.g., a parent feature branch that has since landed). Check whether the source branch is an ancestor of the default branch:
git fetch origin <default-branch> <source-branch> --quiet
git merge-base --is-ancestor origin/<source-branch> origin/<default-branch>
If the exit code is 0, the source branch has been fully merged into the default branch. Skip it and use <default-branch> as <base-branch> instead.
If all three checks pass, use the source branch as <base-branch>. If any check fails, use <default-branch> as <base-branch>.
Then run these commands in parallel to understand the current state:
# Current branch and changed files
git status
# Staged changes
git diff --cached
# Unstaged changes
git diff
# Recent commit messages for style reference
git log --oneline -10
# Full diff of this branch against the base branch
git diff < base-branch > ...HEAD
# Commit history of this branch since diverging from the base branch
git log --oneline < base-branch > ..HEAD
# Check remote tracking status
git rev-parse --abbrev-ref --symbolic-full-name @{u} 2> /dev/null || echo "no upstream"
Search for GitHub issues that this branch addresses. Combine results from the strategies below, deduplicate by issue number, and record the final list for use in the commit message (step 4) and PR body (step 7).
Extract the current branch name. Look for issue numbers in patterns like:
TYPE/N-description (e.g., fix/42-login-bug → #42)TYPE/description-N (e.g., feature/login-bug-42 → #42)TYPE/issue-N or TYPE/issue-N-description (e.g., fix/issue-42 → #42)N-description (e.g., 42-add-login → #42)For each candidate number, verify it refers to an existing issue:
gh issue view NUMBER --json number,title,state --jq '.number' 2> /dev/null
Only include it if the command succeeds (the issue exists).
Scan the git log <base-branch>..HEAD output (already gathered in step 1) for #N references. Collect all unique issue numbers. For each, verify it refers to an actual issue:
gh issue view NUMBER --json number,title,state --jq '.number' 2> /dev/null
Only run this strategy if strategies 1 and 2 found zero issues.
Extract the slug portion of the branch name (everything after the first /). Convert hyphens to spaces to form search keywords. Search for matching open issues:
gh issue list --search "KEYWORDS" --state open --json number,title --limit 5
Evaluate the results:
Merge issue numbers from all three strategies into a single deduplicated list. Preserve the order: branch-name issues first, then commit-message issues, then search-matched issues. Note the branch type prefix (fix/* vs other) for choosing the closing keyword later.
Stop and report an error if any of these are true:
If there are no staged changes, unstaged changes, or untracked files, skip this step.
Never stage files that likely contain secrets (.env, credentials.json, *.pem, *.key, etc.). If such files are detected, warn the user and exclude them.
Before identifying logical chunks, check for plan files among the uncommitted changes. Plan files live under docs/plans/ and its subdirectories (todo/, done/). If any Markdown files in these directories are among the staged, unstaged, or untracked files, apply Plan-Aware Commits rules to them.
Plan files always form their own logical chunk, committed separately from code changes. Process the plan file chunk first, then proceed with the remaining changes.
Review all uncommitted changes (excluding any plan files already handled above) and group them into the smallest logical chunks. Each chunk should be a self-contained, coherent change that makes sense on its own:
If all changes form a single logical chunk, create one commit. If they form multiple chunks, create a commit for each, processing them sequentially.
For each chunk:
git add with specific file paths.git log --oneline -10 output to match the repository's commit message style.feat, fix, docs, refactor, test, chore, style) based on the changes.fix/* branches, use fixes #N; for other branch types, use closes #N. If no connected issues were detected, omit issue references from the commit message. Only reference issues in the commit that most directly addresses them.git commit -S -m "$(
cat << 'EOF'
type: description here
EOF
)"
CRITICAL: Never use git commit --amend. Always create a new commit. If a pre-commit hook fails, fix the issue, re-stage, and create a new commit.
Run the lint-and-fix skill to catch lint and formatting errors before pushing. This prevents CI failures from code that does not pass project linters.
Invoke the lint-and-fix skill using the Skill tool with --no-push:
lint-and-fix --no-push
Parent continuation:
- Caller: pr
- Resume target: Step 6, push branch, then Step 7, create the pull request.
- On lint success: Continue immediately to Step 6 without asking the user for confirmation.
- On lint failure or skipped required lint work: Stop before push and PR creation, then report the unresolved lint state.
This runs all detected project linters and formatters, auto-fixes what it can, manually resolves remaining issues, and commits the fixes without pushing.
If no linters are detected: Proceed to step 6. The absence of linters is not an error.
If all linters pass (with or without auto-fixes) and no issues remain unresolved or skipped: Proceed to step 6. Any fix commits created by lint-and-fix will be included in the push.
If any linting issues remain unresolved, any required lint work is skipped, or a required linter cannot run: Stop and report the unresolved lint state. Do not push or create the PR. The user must resolve the remaining issues before retrying.
Push the branch to the remote:
git push
If the branch has no upstream, use:
git push -u origin HEAD
If the push is rejected because the remote has diverged, report the error and stop. Never force push.
Analyze all commits on the branch (from git log <base-branch>..HEAD and git diff <base-branch>...HEAD) to generate the PR title and body.
Use the following format:
## Summary
- Bullet point describing key change 1
- Bullet point describing key change 2
- Bullet point describing key change 3
## Test plan
- [ ] TODO: describe how to verify this change
## Closes
Closes #N
Keep the summary to 1-4 bullet points. Focus on what changed and why.
If connected issues were detected in step 2, add a ## Closes section after ## Test plan. Use one line per issue with the appropriate keyword:
fix/* branch: Fixes #NCloses #NIf no connected issues were detected, omit the ## Closes section entirely.
First, generate a unique temporary file path using mktemp:
mktemp /tmp/pr-body-XXXXXX
# Returns a unique path, e.g.: /tmp/pr-body-x4y5z6
Then use the Write tool to write the full PR body (Summary, Test plan, and Closes sections) to the exact path returned by mktemp. In the examples below, TMPFILE is a placeholder for that path.
Then create the PR with --body-file:
gh pr create --title "the pr title" --body-file TMPFILE
Pass --base <base-branch> if <base-branch> differs from <default-branch>. Do not pass --draft. Do not add labels or reviewers.
Always remove the tmpfile after the PR creation attempt, regardless of whether it succeeded or failed. Issue the cleanup as a separate Bash tool call, not chained onto gh pr create:
rm -f TMPFILE
Each Bash tool call runs unconditionally and the prior call's exit code is preserved by the harness, so a separate call cleans up after both successful and failed PR creations without any shell-level wrapping. Never combine the two with ; followed by an exit-code preservation idiom such as gh pr create ...; status=$?; rm -f TMPFILE; exit $status. In zsh (the macOS default shell), status is a read-only built-in alias for $?, so the assignment fails with read-only variable: status and falsely reports a successful PR creation as failed. See plugins/use-git/skills/use-git/references/tmpfile-pattern.md for the full rationale.
After the PR is created, report:
gh pr create).When plan files are detected among uncommitted changes, apply the rules in this section during step 4.
Plan files live under docs/plans/ and its subdirectories (todo/, done/). Look for Markdown files in these directories among the changed or untracked files.
Well-named plans follow the pattern YYYY-MM-DD-meaningful-description.md. Auto-generated names use nonsensical word combinations (e.g., ethereal-booping-sunbeam.md, quizzical-imagining-cerf.md).
Every time a plan file is part of a commit, check its filename. If the name lacks a datestamp prefix or uses a nonsensical auto-generated name:
consolidate-ci-workflows, add-user-authentication).YYYY-MM-DD-<slug>.md, using the current date for new plans or the date from the plan's title/content if one is stated.If the filename already has a datestamp prefix and a meaningful description, leave it as-is.
Creating a PR typically means the work described in a plan is complete. When plan files are detected among the changes:
docs/plans/done/ (creating the directory if it does not exist). If both a rename and a move apply, perform a single git mv from the original path directly to the final destination (e.g., docs/plans/done/YYYY-MM-DD-slug.md).docs/plans/todo/, the move goes from todo/ to done/.docs/plans/ root, the move goes from there to done/.Do not move a plan to done/ if the work is only partially complete. Plans for work still in progress should stay in docs/plans/todo/ or the docs/plans/ root.
When committing plan files, use a message like docs: add plan for <meaningful-description> for new plans, or docs: move plan to done for <meaningful-description> when moving a completed plan.
lint-and-fix skill reports unresolved issues, skipped items, or a required linter that cannot run, stop before pushing. Report the remaining lint errors and suggest the user fix them manually before retrying /pr.git pull --rebase if the remote has diverged. Never force push.gh pr create fails because a PR already exists for this branch, run gh pr view --web to open the existing PR and report it to the user.gh CLI is required and link to https://cli.github.com/.gh issue view or gh issue list commands fail (network error, auth issue), skip issue detection silently and proceed without the ## Closes section. Issue detection is best-effort and must never block PR creation.## Closes section. GitHub handles this gracefully (the keyword is a no-op for already-closed issues, and it still creates a visible cross-reference).Guides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.
npx claudepluginhub cboone/agent-harness-plugins --plugin pr