skills/create-pr/SKILL.md
Skill for pushing branch and creating pull requests with proper target branch detection and draft support. Use when user asks to "create PR", "push and create PR", "open a pull request", or says "/create-pr". Also invoked by /resolve workflow finalization phase. Do NOT use for reviewing PRs (use review-pr skill instead).
npx skillsauth add nicolas-codemate/claudecodeconfig create-prInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill handles the finalization phase of ticket resolution: pushing the branch and creating a pull request.
--wait-for-ci) - monitor PR checks, fix failures, retry (bounded)Priority order for determining the PR target branch:
--base main
Read from .claude-work/{ticket-id}/status.json:
{
"options": {
"base_branch": "develop"
}
}
This can be set when creating a worktree, preserving the original base branch.
Some tickets specify target branch:
Check in ticket.md or analysis.md for:
Target Branch: develop
Fix Version: release/2.0
Detect from current branch name:
hotfix/* → main (or master)
release/* → main
feature/* → develop (if exists) or main
fix/* → develop (if exists) or main
From .claude/ticket-config.json:
{
"pr": {
"default_target": "main"
}
}
git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/origin/@@'
Try in order: main, master, develop
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)
From branch prefix:
feat/ → featfix/ → fixrefactor/ → refactordocs/ → docschore/ → choreBefore generating the body, check if the project has a PR template. Search in order:
.github/pull_request_template.md
.github/PULL_REQUEST_TEMPLATE.md
PULL_REQUEST_TEMPLATE.md
docs/pull_request_template.md
If a template is found:
If no template is found, fall back to the built-in template below.
## Summary
{Brief description from ticket or plan}
## Ticket
- **ID**: {ticket_id}
- **Source**: {YouTrack|GitHub}
- **Link**: {ticket_url}
From config (overrides both project template and built-in):
{
"pr": {
"body_template": "custom template with {{ticket_id}} placeholders",
"include_ticket_link": true
}
}
Check if repository supports draft PRs:
# GitHub - always supports drafts
gh pr create --draft ...
# GitLab - check version
# Bitbucket - check settings
{
"pr": {
"draft_by_default": true
}
}
| Mode | draft_by_default | Result | |------|------------------|--------| | Auto | true | Create as draft | | Auto | false | Create as ready | | Interactive | - | Ask user |
# 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 1
# Push with upstream tracking
git push -u origin "$CURRENT_BRANCH"
If push fails:
git pull --rebase if behind# 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
fi
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
}
Search for a PR template in the repository root:
# Check standard locations (first match wins)
for TPL in \
".github/pull_request_template.md" \
".github/PULL_REQUEST_TEMPLATE.md" \
"PULL_REQUEST_TEMPLATE.md" \
"docs/pull_request_template.md"; do
if [[ -f "$TPL" ]]; then
PR_TEMPLATE="$TPL"
break
fi
done
FEATURE_DIR=".claude-work/$TICKET_ID"
TICKET_FILE="$FEATURE_DIR/ticket.md"
PLAN_FILE="$FEATURE_DIR/plan.md"
Extract:
PR_TEMPLATE found: read the template, fill in sections with extracted databody_template set in config: use config template instead (highest priority)# 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_FLAG
Update .claude-work/{ticket-id}/status.json:
{
"phases": {
"finalize": "completed"
},
"pr": {
"number": 123,
"url": "https://github.com/owner/repo/pull/123",
"draft": true,
"target": "main"
}
}
--wait-for-ci)Skip this step entirely if --wait-for-ci was not passed. Otherwise, parse the optional retry count:
--wait-for-ci → MAX_RETRIES = 3 (default)
--wait-for-ci 5 → MAX_RETRIES = 5
Set a completion goal using the /goal command. This delegates the loop to Claude Code's goal-tracking machinery, with a live overlay showing elapsed time, turns, and tokens. The user can interrupt at any moment with Ctrl+C.
Invoke:
/goal All checks on PR #{PR_NUMBER} are passing (gh pr checks #{PR_NUMBER} reports SUCCESS for every check), OR I have already pushed {MAX_RETRIES} fix attempts for CI failures on this PR.
While /goal is active, repeat:
Poll PR check status
gh pr checks {PR_NUMBER} --json name,state,conclusion
States to handle:
SUCCESS → goal met, stop loop, report successIN_PROGRESS / QUEUED / PENDING → wait, do not act. Re-poll after a short delay (use Bash sleep 30 or wait between turns)FAILURE / STARTUP_FAILURE / TIMED_OUT / CANCELLED AND retry counter < MAX_RETRIES → enter fix mode (step 3)Wait scope: watch ALL checks reported by gh pr checks, including optional ones. Do not filter to required-only.
Fix mode (per failing check): a. Identify the failing run ID:
gh pr checks {PR_NUMBER} --json name,state,conclusion,link,workflow
b. Fetch the failure logs:
gh run view <run_id> --log-failed
If logs are huge, also try gh run view <run_id> --log-failed | tail -200 to focus on the tail.
c. Identify the root cause from the logs. Common categories:
git add -A
git commit -m "fix(ci): {one-line description}"
git push
f. Increment the local retry counter. Mention the counter in your next turn so /goal can track it. g. Wait for the new CI run to start (CI typically picks up the push within 1-2 min), then resume polling.
When /goal exits, produce one of three outcomes in the response:
| Outcome | Trigger | Report |
|---------|---------|--------|
| CI_GREEN | All checks SUCCESS | "PR #{N} CI: tous les checks verts (après {retry_count} fix(es))" |
| CI_RED_EXHAUSTED | Retries exhausted | "PR #{N} CI: {retry_count}/{MAX} tentatives épuisées. Jobs encore en échec: {list}. Investigation manuelle requise." |
| INTERRUPTED | User Ctrl+C | "Watch CI interrompu par l'utilisateur (après {retry_count} fix(es))" |
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"
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"
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"
--wait-for-ci not already set)AskUserQuestion:
question: "Surveiller la CI et tenter de fixer les echecs automatiquement ?"
header: "Watch CI"
options:
- label: "Non (Recommended)"
description: "Fin du flow apres creation PR. Tu reprends la main sur la CI."
- label: "Oui, max 3 fix-pushes"
description: "Lance /goal: surveille gh pr checks, tente un fix sur echec, push, retry max 3 fois."
- label: "Oui, max 5 fix-pushes"
description: "Pareil avec 5 tentatives. Pour les PRs ou plusieurs checks peuvent casser independamment."
Erreur: Authentification echouee
Solutions:
1. Verifiez vos credentials git
2. Pour HTTPS: gh auth login
3. Pour SSH: ssh-add ~/.ssh/id_rsa
Erreur: Push refuse par protection de branche
La branche '{branch}' a des regles de protection.
Verifiez les settings du repository.
Erreur: Impossible de creer la PR
Verifiez que vous avez les droits sur le repository.
Tentez: gh auth refresh
Erreur: Branche cible '{branch}' introuvable
Branches disponibles:
- main
- develop
- release/2.0
Utilisez --base pour specifier la cible.
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,
"wait_for_ci": {
"enabled": false,
"max_retries": 3
}
}
}
| 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 |
| wait_for_ci.enabled | false | Auto-enable Step 8 (CI watch with fix) without passing --wait-for-ci |
| wait_for_ci.max_retries | 3 | Max fix-push cycles before giving up |
## 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 done
## PR Already Exists
- **PR**: #456
- **URL**: https://github.com/owner/repo/pull/456
- **Status**: Open
No action needed.
This skill is invoked at the end of the /resolve workflow:
/resolve PROJ-123
│
├─► ... existing phases ...
├─► Implementation
│
└─► Finalize (this skill)
├─► Push branch
├─► Create PR
└─► (optional) Wait for CI with auto-fix
draft_by_default settingpr.wait_for_ci.enabled = true in config, or --wait-for-ci was passed to /resolveUser-facing messages in French. Git commands and PR content in English.
tools
--- name: deep-review description: Performs deep code review via an isolated fresh agent (triple perspective, anti-bias). Use when the user asks for an in-depth review of current branch changes, or when invoked by /resolve step 08. Do NOT use for reviewing PRs from GitHub (use review-pr skill instead) or for a quick correctness scan with effort levels (use bundled /code-review instead). argument-hint: [--ticket <id>] [--base <branch>] [--fix] [--severity <level>] allowed-tools: Read, Glob, Grep,
tools
Resolve git rebase conflicts methodically. Classifies each conflict (imports/namespace cleanup vs real logic clash), analyzes the commit introducing the change against the current ticket context, auto-fixes only trivial cases with a per-file summary, and asks the user when ambiguous. Verifies static analysis tools pass at the end and optionally runs functional tests. Use after `git rebase` triggers conflicts, or when the user asks to "resolve conflicts", "fix rebase", "j'ai des conflits", "aide-moi sur ce rebase".
development
Synchronize the markdown test plan in docs/qa/ with the current state of the codebase. Use after adding or modifying features to keep the plan up to date, or to bootstrap a test plan for the first time. Do NOT use to execute tests (use /qa-run instead) and do NOT use to design product specs (use /express-need instead).
tools
Execute the markdown test plan in docs/qa/ via Playwright MCP and create a ticket on each failing scenario. Use after /qa-sync, before a release, or to validate a feature end-to-end. Do NOT use to design or update scenarios (use /qa-sync instead) and do NOT use for visual regression (use visual-verify agent instead).