Receber por email
← Voltar para o catálogo

create-pr

Create or update GitHub PR with gh CLI. Auto-extracts ticket ID from branch name, generates title/summary from commits. Auto-detects existing PR and switches to update mode. Default: --dry-run (show command, don't execute). Use when: user asks to open/create/update a PR, says /create-pr, wants to refresh PR description after new commits, or says 'update pr', 'update PR title', 'refresh PR body'.

172estrelas
Atualizado há 5 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add sd0xdev/sd0x-dev-flow

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/create-pr-sd0xdev/svg)](https://www.skillteca.com.br/skills/create-pr-sd0xdev)

Skills relacionadas

Ver todas de Desenvolvimento →

Alerta por categoria

Receba novas skills de Desenvolvimento toda segunda

1 email curto, só com as skills novas de Desenvolvimento. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Create PR

Input

/create-pr [--head <branch>] [--base <branch>] [--title <title>] [--update] [--execute] [--dry-run]

  • --head: Source branch (default: current branch)
  • --base: Target branch (default: {TARGET_BRANCH} or main)
  • --title: Override auto-generated title
  • --update: Force update mode (re-generate title/body for existing PR)
  • --dry-run: Show command without executing (default)
  • --execute: Actually create/update the PR (requires user confirmation)
  • No args: use current branch → default target, dry-run mode. Auto-detects existing PR → update mode

Workflow

1. Gather Info (parallel)

# Current branch
git rev-parse --abbrev-ref HEAD

# Remote repo (owner/repo)
gh repo view --json nameWithOwner --jq '.nameWithOwner'

# Check if head branch is pushed
git ls-remote --heads origin <head-branch>

# Check existing PR
gh pr list --head <head-branch> --base <base-branch> --json number,title,state

# Commits between base..head
git log --oneline <base>..<head>

# Full diff for summary
git diff <base>...<head> --stat

2. Extract Ticket ID

From branch name, extract ticket ID using {TICKET_PATTERN} (default: [A-Z]+-\d+):

| Branch Pattern | Ticket ID | |----------------|-----------| | fix/PROJ-520 | PROJ-520 | | fix/PROJ-520-2 | PROJ-520 | | feat/PROJ-123-some-desc | PROJ-123 | | refactor/PROJ-999 | PROJ-999 |

Regex: first match of {TICKET_PATTERN} — take first match. Strip trailing -N suffixes.

3. Generate Title

Format: <type>: [<TICKET>] <concise summary>

  • <type>: from branch prefix (fix/ → fix, feat/ → feat, docs/ → docs, refactor/ → refactor)
  • <TICKET>: extracted ticket ID (omit if none found)
  • <concise summary>: summarize commits in <60 chars, focus on main changes

4. Generate Body

## Summary

<3-5 bullet points summarizing changes from commits>

## Ticket

[<TICKET>]({ISSUE_TRACKER_URL}<TICKET>)

## Test plan

- [ ] <test items based on what changed>

Rules:

  • No AI-generated tags — enforced by Step 4b sanitization (see below)
  • Keep summary factual, based on actual commits
  • Use imperative mood in bullet points
  • Omit Ticket section if no ticket ID or {ISSUE_TRACKER_URL} not configured

Forbidden patterns (POSIX ERE, case-insensitive — canonical source: scripts/commit-msg-guard.sh:19-23):

| Pattern Category | Regex | |-----------------|-------| | Co-Authored-By AI | Co-Authored-By:.(Claude\|Anthropic\|GPT\|OpenAI\|Copilot\|noreply@anthropic) | | Generated-by tag | Generated (by\|with).(Claude\|Claude Code\|AI\|GPT\|Copilot) | | Emoji robot tag | 🤖.*(Claude\|AI\|GPT) |

Note: \| in the table above is Markdown table escaping. Actual POSIX ERE uses unescaped |.

4b. AI Content Sanitization

After generating title and body (Step 3-4), scan for forbidden patterns and sanitize before any output or execution. Applies to all modes: dry-run/execute, create/update, --title override.

Title sanitization (regenerate/fail):

  1. Scan title for forbidden patterns (grep -Ei)
  2. If match found → regenerate title from commits (1 attempt, without AI attribution)
  3. If regenerated title still matches → HARD FAIL: abort with error message
  4. --title override: same scan-and-fail logic (no regeneration — user-provided text fails immediately if matched)

Body sanitization (line-strip + log):

  1. Scan body line-by-line for forbidden patterns
  2. Remove matching lines
  3. Log each removal: [AI_STRIPPED] <removed line>
  4. If all content lines removed → preserve template structure (Summary / Test plan headers only)

5. Pre-flight Checks + Mode Detection

| Check | Action if fails | |-------|-----------------| | Head branch not pushed | Warn: "branch not pushed to remote, push first" and STOP | | PR already exists | → Enter Update Mode (see section below) | | --update flag + no existing PR | Warn: "no PR found for this branch" and STOP | | No commits between base..head (create mode) | Warn: "no diff between branches" and STOP | | No commits between base..head (update mode) | Continue — PR may need title/body refresh from --title override |

Mode detection logic:

| Condition | Mode | |-----------|------| | --update flag passed | Force update mode (error if no PR exists) | | Existing PR detected (auto) | Update mode (auto-switch) | | No existing PR, no --update | Create mode (original workflow) |

5a. Update Mode

When an existing PR is detected (or --update is passed):

Step 1: Fetch current PR state (use PR number from pre-flight gh pr list result):

gh pr view <PR-number> --json number,title,body,url,baseRefName

Step 2: Re-generate title and body from latest commits (same logic as Steps 2-4 above, using full commit range base..head). Run Step 4b AI Content Sanitization on the re-generated content before proceeding.

Step 3: Smart diff — compare current vs newly generated:

| Field | Current | New | Action | |-------|---------|-----|--------| | Title | same | same | Skip (no change needed) | | Title | differs | differs | Show before/after | | Body | same | same | Skip | | Body | differs | differs | Show before/after |

Step 4: Decision — if both title and body are unchanged → report "PR is already up to date" and STOP.

If changes detected, show the diff and decide what to update:

  • Title changed significantly: update title automatically. Criteria: type prefix changed (fix: → feat:) or ticket ID changed.
  • Title changed trivially: AskUserQuestion — "Title changed slightly. Update?" (show before/after). Criteria: only the summary text after <type>: [<TICKET>] differs.
  • Body changed: always update (body reflects commit history, should stay current)
  • When --title is passed: override title regardless of diff

Step 5: Output (respects --dry-run / --execute):

Dry-run (default) — show the gh pr edit command with only changed fields included:

# Title-only update (use printf for safe escaping):
gh pr edit <number> --title "$(printf '%s' '<new-title>')"

# Body-only update (use --body-file for safe escaping):
gh pr edit <number> --body-file /dev/stdin <<'EOF'
<new-body>
EOF

# Both title + body:
gh pr edit <number> --title "$(printf '%s' '<new-title>')" --body-file /dev/stdin <<'EOF'
<new-body>
EOF

Use --body-file instead of --body to avoid shell escaping issues with quotes and newlines in the body content.

Execute (--execute) — ask user for confirmation via AskUserQuestion, then run gh pr edit. Output:

PR updated: <URL>
Title: <old-title> → <new-title>
Changes: title updated, body updated

6. Output (dry-run, default) — Create Mode

Show the full gh pr create command:

gh pr create \
  --head <head-branch> \
  --base <base-branch> \
  --title "<title>" \
  --body "$(cat <<'EOF'
<generated body>
EOF
)"

User can copy-paste to execute, or re-run with --execute.

7. Execute (--execute flag)

Ask user for confirmation, then run the command. Output:

PR created: <URL>
Title: <title>
Base: <base> ← Head: <head>

7b. Post-creation Verify (execute-only)

After gh pr create or gh pr edit completes in --execute mode, verify the published content for AI attribution leaks.

Step 1: Fetch actual published content:

gh pr view <number> --json title,body --template '{{.title}}{{"\n"}}{{.body}}'

Step 2: Scan for forbidden patterns (same 3 POSIX ERE from Step 4b).

Step 3: If leak detected — auto-remediate (single attempt, using pre-sanitized snapshot from Step 4b):

# Title (safe escaping via printf):
gh pr edit <number> --title "$(printf '%s' "$SANITIZED_TITLE")"

# Body (safe escaping via --body-file + heredoc):
gh pr edit <number> --body-file /dev/stdin <<'EOF'
<pre-sanitized-body-snapshot>
EOF

Step 4: Re-verify via gh pr view. If still leaked → HARD FAIL:

❌ AI attribution leaked
Compartilhar X LinkedIn