Create Pull Request
Create a GitHub pull request with an auto-generated description that follows the PR template.
Prerequisites
- GitHub CLI installed and authenticated (
gh auth status) - Changes committed and pushed to remote
- Current branch is not
mainormaster
Workflow
Step 1: Check for Existing PR
gh pr view --json number,url 2>/dev/null
If PR exists: Report the existing PR URL and ask if the user wants to update the description.
Step 2: Get Current Branch and Verify Remote
git branch --show-current
git status
If branch is main or master: STOP and warn the user.
If changes are not pushed: Push first:
git push -u origin HEAD
Step 3: Resolve Project Settings
Determine whether this project uses Jira or GitHub Issues by reading .project-settings.md. Follow the same lookup order as dev-workflow-initialize:
- Project root:
<workspace-root>/.project-settings.md— if it exists, use it. - User home:
~/.project-settings.md— if it exists and the current workspace directory name appears in the Workspaces table, use it. - Not found: Default to
githubtarget (use current repo fromgit remote get-url origin).
Extract from the matching project block:
| Field | Used for |
|-------|----------|
| Target | github or jira — determines ticket system |
| Repo (GitHub) | GitHub repo for links (default: current repo) |
| Project Key (Jira) | Jira project key for ticket prefixes |
| JIRA base URL (Jira) | For constructing ticket links |
Step 4: Determine Base Branch and Analyze Changes
The branch may have been created from main or from another feature branch. Determine the correct base branch:
# Option 1: Check git log for branch refs - other branch names appear in parentheses
# Example output: "8e6b394a (RNDCORE-12097) fix: update test"
# This indicates the branch was forked from RNDCORE-12097
git log --oneline --decorate HEAD | head -20
# Option 2: Check if there's an upstream tracking branch or PR target
gh pr view --json baseRefName --jq '.baseRefName' 2>/dev/null
# Option 3: Find the merge-base with main (may include unrelated commits if branch is stale)
git merge-base main HEAD
Important: Look for branch names in parentheses in the git log output. If you see a pattern like:
cd9c4c18 (HEAD -> RNDCORE-12097-suspense) refactor: migrate queries
8e6b394a (RNDCORE-12097) fix: update test
This means RNDCORE-12097-suspense was branched from RNDCORE-12097. The base branch is RNDCORE-12097, NOT main.
Once base branch is identified, run these commands:
# If parent branch is detected (e.g., RNDCORE-12097)
git diff PARENT_BRANCH..HEAD --stat
git log PARENT_BRANCH..HEAD --oneline
git diff PARENT_BRANCH..HEAD
# Example:
git diff RNDCORE-12097..HEAD --stat
Fallback: If no parent branch is detected in the log, use main:
git diff main...HEAD
git log main..HEAD --oneline
git diff main...HEAD --stat
Step 5: Generate PR Description
Generate the PR description directly from the diff gathered in Step 4.
5a. Extract ticket/issue reference based on the target system from Step 3.
If target is jira:
Extract Jira ticket from the branch name using pattern [A-Z]+-\d+ (e.g., RNDCORE-12345).
-
If not found, ALWAYS use the AskQuestion tool:
- Title: "JIRA Ticket"
- Question: "What's the JIRA ticket for this PR?"
- Options:
- id: "specify", label: "Let me specify the ticket"
- id: "skip", label: "Skip (use placeholder)"
- If "specify": Ask conversationally for the ticket
- If "skip": use
RND***-xxxx
-
Link format:
- If branch starts with
RETIRE: usehttps://gustohq.atlassian.net/browse/TICKET - Otherwise: use the JIRA base URL from project settings, or
https://internal.guideline.tools/jira/browse/TICKET
- If branch starts with
If target is github:
Extract GitHub issue number from the branch name using pattern ^(\d+)- (e.g., 5-add-widget-background → #5).
-
If not found, ALWAYS use the AskQuestion tool:
- Title: "GitHub Issue"
- Question: "Is there a GitHub issue for this PR?"
- Options:
- id: "specify", label: "Let me specify the issue number"
- id: "skip", label: "No issue — skip"
- If "specify": Ask conversationally for the issue number
- If "skip": omit the issue/ticket line from the description entirely
-
Link format:
https://github.com/OWNER/REPO/issues/NUMBER(or useCloses #Nshorthand)
5b. Analyze changes from the diff — understand what changed, why, and who it impacts.
5c. Generate the [[[...]]] block:
The block format depends on the target system:
Jira projects:
[[[
**jira:** [TICKET-123](https://internal.guideline.tools/jira/browse/TICKET-123)
**what:** concise summary of changes
**why:** business justification
**who:** affected users/teams
]]]
GitHub projects (with issue):
[[[
**issue:** #42
**what:** concise summary of changes
**why:** business justification
**who:** affected users/teams
]]]
GitHub projects (no issue) or unticketed:
[[[
**what:** concise summary of changes
**why:** business justification
**who:** affected users/teams
]]]
Description rules:
- Put
[[[and]]]on their own lines - Keep what/why/who concise (1-2 sentences each)
- Use backticks for code references (class names, methods, files)
- Only use bullet points for "what" if there are multiple distinct changes
- No indentation inside the block
- No agent preamble or headers outside the block
Examples:
Simple Jira change (no bullets):
[[[
**jira:** [RNDCORE-11727](https://internal.guideline.tools/jira/browse/RNDCORE-11727)
**what:** Fix null pointer in `TenantTransferPacket#process` when user has no address
**why:** Users without addresses were causing 500 errors during transfer
**who:** Participants transferring accounts
]]]
Multiple Jira changes (use bullets):
[[[
**jira:** [RNDCORE-11728](https://internal.guideline.tools/jira/browse/RNDCORE-11728)
**what:**
- Add `BillingCalculator` service to handle fee computations
- Update `Invoice#generate` to use new calculator
- Remove deprecated `LegacyBilling` module
**why:** Legacy billing code was unmaintainable and causing calculation errors
**who:** Internal billing team, sponsors receiving invoices
]]]
RETIRE branch (Jira):
[[[
**jira:** [RETIRE-456](https://gustohq.atlassian.net/browse/RETIRE-456)
**what:** Remove unused `OldAuthenticator` class and related specs
**why:** Dead code cleanup after migration to new auth system
**who:** No user impact, internal cleanup
]]]
GitHub issue:
[[[
**issue:** #5
**what:** Add widget background style setting with none, solid, and glass options
**why:** Widgets are hard to read over busy slideshow images
**who:** Users with widget overlays on their display
]]]
Unticketed (GitHub or no settings):
[[[
**what:** Refactor drag gesture to use named coordinate space
**why:** Fixes Retina scale mismatch on macOS
**who:** macOS users dragging widgets
]]]
Step 6: Create the PR
The PR body must include the [[[...]]] block and a screenshot placeholder.
gh pr create --draft --title "<type>: <TICKET> <short description>" --body "$(cat <<'EOF'
<[[[...]]] block from Step 5>
---
### Screenshot(s):
_No visual changes_
EOF
)"
Title format: Use conventional commit style with the ticket reference after the colon — this is critical because release notes are generated from PR titles. Check for a pr-title-conventions skill in the project's .cursor/skills/ directory for repo-specific title rules.
Default format: <type>(optional-scope): TICKET-123 <short description>
Jira examples:
feat: RETIRE-456 add portfolio rebalance alertsfix: RNDCORE-12337 handle null dynamic type in C++ bridgechore(deps): RNDCORE-6547 bump bundler and rubygemsfix: RETIRE-1884 RETIRE-1885 handle nil account in balance calculation(multiple tickets, not encouraged)
GitHub issue examples:
feat: #5 add widget background style settingfix: #12 handle nil placement on resize
No ticket (use placeholder or NO-TICKET):
chore: RETIRE-1908 add basic auth and documentation(placeholder ticket)fix: NO-TICKET correct typo in login screen(last resort)
Type prefixes:
feat:for new featuresfix:for bug fixesrefactor:for code restructuringchore:for maintenance
Step 7: Report Success
Get the PR URL and format it as a clickable markdown link:
PR_URL=$(gh pr view --json url --jq '.url')
Then output a message with the URL as a clickable markdown link:
Draft PR created successfully! 🎉
[View Draft PR #<number>]($PR_URL)
Example output: "Draft PR created successfully! 🎉\n\nView Draft PR #2640"
Step 8: Attach Screenshots (Optional)
After reporting the PR URL, ALWAYS use the AskQuestion tool:
- Title: "Add Screenshots?"
- Question: "Do you want to attach screenshots to the PR?"
- Options:
- id: "upload", label: "Yes, I have screenshots to attach"
- id: "no-visual", label: "No visual changes"
- id: "later", label: "I'll add them manually later"
If "upload":
- Ask the user for the image file path(s) (one or more).
- For each image, run the upload script bundled with this skill:
~/.cursor/skills/dev-workflow-create-pr/scripts/upload-screenshot.sh "<image-path>" "<alt-text>"
The script uploads the image as a GitHub release asset under a _pr-assets tag and outputs a markdown image reference like:

- Collect all the markdown image references from the script output.
- Update the PR body to replace the screenshot placeholder with the actual images:
# Get current PR body
BODY=$(gh pr view --json body --jq '.body')
# Replace the placeholder with actual screenshots
# The placeholder is: _No visual changes_
NEW_BODY=$(echo "$BODY" | sed 's/_No visual changes_/<collected markdown image references>/')
# Update the PR
gh pr edit --body "$NEW_BODY"
If "no-visual" or "later": Continue to Step 9.
Step 9: Offer to Start Review
After reporting the clickable PR URL, ALWAYS use the AskQuestion tool:
- Title: "Start PR Review?"
- Question: "Would you like me to review the PR for code quality, security, and best practices?"
- Options:
- id: "review", label: "Yes, review it"
- id: "done", label: "No, I'm done"
Based on the response:
- "review" → Use the
dev-workflow-review-prskill to perform a comprehensive code review - "done" → End the workflow
Checklist
PR Creation Progress:
- [ ] Verified no existing PR
- [ ] Confirmed changes are pushed
- [ ] Resolved project settings (Jira vs GitHub vs none)
- [ ] Determined correct base branch (may not be main)
- [ ] Analyzed diff from base branch
- [ ] Generated PR description with [[[...]]] block
- [ ] Created draft PR with gh CLI
- [ ] Reported PR URL as clickable markdown link
- [ ] Offered to attach screenshots (uploaded via upload-screenshot.sh)
- [ ] Offered to start PR review
Edge Cases
No .project-settings.md found
Default to github target. Use the current repo from git remote get-url origin. Do NOT prompt to create project settings during PR creation — just use the default and move on.
Branch has no ticket/issue
For Jira: use N/A or ask the user for the ticket ID.
For GitHub: omit the issue line and proceed without it.
Branch created from another feature branch (not main)
When a branch is created from another feature branch:
- Run
git log --oneline --decorate HEADand look for branch names in parentheses - If you see
(PARENT-BRANCH-NAME)on a commit that isn't HEAD, that's the parent branch - Diff against that branch name directly
Example:
# Git log shows:
# cd9c4c18 (HEAD -> RNDCORE-12097-suspense) refactor: migrate queries
# 8e6b394a (RNDCORE-12097) fix: update test
#
# The parent branch is RNDCORE-12097
git diff RNDCORE-12097..HEAD --stat # Shows only this branch's changes
git log RNDCORE-12097..HEAD --oneline # Shows only this branch's commits
This ensures the PR description only reflects changes in THIS branch, not inherited changes from the parent branch.
Large diff (>1000 lines)
Focus summary on high-level changes. Group by feature area or file type.
No commits ahead of main
STOP - nothing to create a PR for. Inform the user.
Branch is stale (main has diverged significantly)
The diff against main may include many unrelated changes. Identify the actual fork point:
git merge-base main HEAD
And consider if the branch needs to be rebased before creating the PR.
Notes
- Always push changes before creating PR
- Review the generated description for accuracy before the PR is created
- For visual changes, use
upload-screenshot.shto attach images directly from the CLI
微信扫一扫