Skill for pushing branch and creating pull requests with proper target branch detection and draft support.
Install
npx skillscat add nicolas-codemate/claudecodeconfig/create-pr Install via the SkillsCat registry.
Create PR Skill
This skill handles the finalization phase of ticket resolution: pushing the branch and creating a pull request.
Capabilities
- Push to remote with upstream tracking
- Detect target branch from multiple sources
- Create PR with auto-generated title and body
- Draft mode support (when available)
- Idempotent - skip if PR already exists
Target Branch Detection
Priority order for determining the PR target branch:
1. Explicit Argument
--base main2. Status File (from worktree creation)
Read from .claude/feature/{ticket-id}/status.json:
{
"options": {
"base_branch": "develop"
}
}This is set by resolve-worktree.sh when creating the worktree, preserving the original base branch.
3. Ticket Metadata
Some tickets specify target branch:
- YouTrack: custom field "Target Branch" or "Fix versions", or parsed from Milestone
- GitHub: base branch in linked PR
Check in ticket.md or analysis.md for:
Target Branch: develop
Fix Version: release/2.04. Branch Pattern Matching
Detect from current branch name:
hotfix/* → main (or master)
release/* → main
feature/* → develop (if exists) or main
fix/* → develop (if exists) or main5. Project Configuration
From .claude/ticket-config.json:
{
"pr": {
"default_target": "main"
}
}6. Git Default Branch
git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@'7. Fallback
Try in order: main, master, develop
PR Title Generation
Format: {type}: {ticket_title} ({ticket_id})
Examples:
feat: Add CSV export for users (PROJ-123)
fix: Null pointer in login flow (PROJ-456)
refactor: Extract validation service (PROJ-789)Type Detection
From branch prefix:
feat/→featfix/→fixrefactor/→refactordocs/→docschore/→chore
PR Body Generation
Template:
## Summary
{Brief description from ticket or plan}
## Ticket
- **ID**: {ticket_id}
- **Source**: {YouTrack|GitHub}
- **Link**: {ticket_url}Customization
From config:
{
"pr": {
"body_template": "custom template with {{ticket_id}} placeholders",
"include_ticket_link": true
}
}Draft Mode
Detection
Check if repository supports draft PRs:
# GitHub - always supports drafts
gh pr create --draft ...
# GitLab - check version
# Bitbucket - check settingsConfiguration
{
"pr": {
"draft_by_default": true
}
}Behavior
| Mode | draft_by_default | Result |
|---|---|---|
| Auto | true | Create as draft |
| Auto | false | Create as ready |
| Interactive | - | Ask user |
Process
Step 1: Pre-flight Checks
# Check if on feature branch (not main/master)
CURRENT_BRANCH=$(git branch --show-current)
if [[ "$CURRENT_BRANCH" =~ ^(main|master|develop)$ ]]; then
echo "Error: Cannot create PR from protected branch"
exit 1
fi
# Check for uncommitted changes
if [[ -n $(git status --porcelain) ]]; then
echo "Warning: Uncommitted changes detected"
# In interactive: ask to commit or stash
# In auto: fail or stash
fi
# Check if remote exists
git remote get-url origin || exit 1Step 2: Push Branch
# Push with upstream tracking
git push -u origin "$CURRENT_BRANCH"If push fails:
- Check authentication
- Check branch protection rules
- Suggest
git pull --rebaseif behind
Step 3: Check Existing PR
# Check if PR already exists for this branch
EXISTING_PR=$(gh pr view "$CURRENT_BRANCH" --json number,url 2>/dev/null)
if [[ -n "$EXISTING_PR" ]]; then
PR_URL=$(echo "$EXISTING_PR" | jq -r '.url')
echo "PR already exists: $PR_URL"
# Option: update existing PR description
exit 0
fiStep 4: Determine Target Branch
Apply detection priority (see above).
# Verify target branch exists
git ls-remote --heads origin "$TARGET_BRANCH" || {
echo "Error: Target branch '$TARGET_BRANCH' not found"
# Suggest alternatives
}Step 5: Generate PR Content
Read from feature directory:
FEATURE_DIR=".claude/feature/$TICKET_ID"
TICKET_FILE="$FEATURE_DIR/ticket.md"
PLAN_FILE="$FEATURE_DIR/plan.md"Extract:
- Title from ticket
- Summary from plan
- Changes from plan phases
- Validation from plan
Step 6: Create PR
# Draft mode
DRAFT_FLAG=""
if [[ "$DRAFT" == "true" ]]; then
DRAFT_FLAG="--draft"
fi
# Create PR
gh pr create \
--title "$PR_TITLE" \
--body "$PR_BODY" \
--base "$TARGET_BRANCH" \
$DRAFT_FLAGStep 7: Update Status
Update .claude/feature/{ticket-id}/status.json:
{
"phases": {
"finalize": "completed"
},
"pr": {
"number": 123,
"url": "https://github.com/owner/repo/pull/123",
"draft": true,
"target": "main"
}
}Interactive Mode Questions
Question 1: Push Confirmation
AskUserQuestion:
question: "Pousser la branche et creer une PR ?"
header: "Finalisation"
options:
- label: "Oui, push + PR"
description: "Pousser la branche et creer la pull request"
- label: "Push seulement"
description: "Pousser sans creer de PR"
- label: "Non, plus tard"
description: "Terminer sans push"Question 2: Draft Mode (if creating PR)
AskUserQuestion:
question: "Creer la PR en mode draft ?"
header: "Draft"
options:
- label: "Oui, draft (Recommended)"
description: "PR en brouillon, a marquer ready apres review"
- label: "Non, ready for review"
description: "PR prete pour review immediate"Question 3: Target Branch (if ambiguous)
AskUserQuestion:
question: "Quelle branche cible pour la PR ?"
header: "Target"
options:
- label: "main (Recommended)"
description: "Branche principale"
- label: "develop"
description: "Branche de developpement"
- label: "{ticket_target}"
description: "Specifie dans le ticket"Error Handling
Push Failed - Authentication
Erreur: Authentification echouee
Solutions:
1. Verifiez vos credentials git
2. Pour HTTPS: gh auth login
3. Pour SSH: ssh-add ~/.ssh/id_rsaPush Failed - Branch Protection
Erreur: Push refuse par protection de branche
La branche '{branch}' a des regles de protection.
Verifiez les settings du repository.PR Creation Failed - No Permission
Erreur: Impossible de creer la PR
Verifiez que vous avez les droits sur le repository.
Tentez: gh auth refreshTarget Branch Not Found
Erreur: Branche cible '{branch}' introuvable
Branches disponibles:
- main
- develop
- release/2.0
Utilisez --base pour specifier la cible.Configuration Reference
Full PR configuration in .claude/ticket-config.json:
{
"pr": {
"draft_by_default": true,
"default_target": "main",
"include_ticket_link": true,
"auto_push": true,
"title_format": "{type}: {title} ({ticket_id})",
"body_template": null
}
}Options
| Option | Default | Description |
|---|---|---|
draft_by_default |
true |
Create PRs as draft |
default_target |
"main" |
Fallback target branch |
include_ticket_link |
true |
Add ticket link in body |
auto_push |
true |
Push before creating PR |
title_format |
"{type}: {title} ({ticket_id})" |
PR title template |
body_template |
null |
Custom body template |
Output Format
Success
## PR Created
- **Branch**: feat/proj-123-add-csv-export
- **Target**: main
- **PR**: #456
- **URL**: https://github.com/owner/repo/pull/456
- **Status**: Draft
### Next Steps
1. Review the changes
2. Request reviews
3. Mark as ready when doneAlready Exists
## PR Already Exists
- **PR**: #456
- **URL**: https://github.com/owner/repo/pull/456
- **Status**: Open
No action needed.Integration with /resolve
This skill is invoked at the end of the /resolve workflow:
/resolve PROJ-123
│
├─► ... existing phases ...
├─► Implementation
│
└─► Finalize (this skill)
├─► Push branch
└─► Create PRAuto Mode
- Always push
- Always create PR (if not exists)
- Use
draft_by_defaultsetting
Interactive Mode
- Ask about push + PR
- Ask about draft mode
- Ask about target branch (if ambiguous)
Language
User-facing messages in French.
Git commands and PR content in English.