---
description: Create a pull request with context-aware content generation
argument-hint: [--draft] [--base=branch]
allowed-tools: Bash, Read, Edit, Write, Glob, mcp__task-master-ai__get_tasks, mcp__task-master-ai__get_task, mcp__github-mcp__create_pull_request, mcp__github-mcp__update_pull_request, mcp__github-mcp__search_pull_requests, mcp__github-mcp__get_me
---

# Create Pull Request: $ARGUMENTS

Create a pull request with intelligent context gathering from PRD files, Task Master tasks, and bug tracking.

## Phase 0: Parse Arguments

Extract optional flags from `$ARGUMENTS`:

- `--draft`: Create PR as draft
- `--base=BRANCH`: Target branch (default: main/master)
- `--auto`: Skip editor review and create immediately

**Default behavior**: Interactive review before PR creation

```bash
# Parse flags
DRAFT_MODE=false
BASE_BRANCH=""
AUTO_MODE=false

for arg in $ARGUMENTS; do
  case "$arg" in
    --draft) DRAFT_MODE=true ;;
    --base=*) BASE_BRANCH="${arg#*=}" ;;
    --auto) AUTO_MODE=true ;;
  esac
done
```

## Phase 1: Gather Context from Multiple Sources

### 1.1 Check for PRD Files

Search repository root for `*.prd.*.md` files:

```bash
# Find PRD files in repo root
find . -maxdepth 1 -name "*.prd.*.md" -type f 2>/dev/null
```

**If PRD files found:**

- Read content from each file
- Extract requirements and context
- Store as `prd_context`

**Example PRD files:**

```text
.prd.phase1.md
.prd.feature-auth.md
feature.prd.user-management.md
```

### 1.2 Query Task Master MCP

Use Task Master MCP to get current task context:

```javascript
// Get tasks with in-progress or recently completed status
const tasksResult = mcp__task_master_ai__get_tasks({
  projectRoot: process.cwd(),
  status: 'in-progress,done',
  withSubtasks: true,
});

// Filter for recent tasks (last 7 days)
const recentTasks = tasksResult.tasks.filter((task) => {
  const updatedDate = new Date(task.updatedAt || task.createdAt);
  const daysSince = (Date.now() - updatedDate) / (1000 * 60 * 60 * 24);
  return daysSince <= 7;
});
```

Store as `task_context`.

### 1.3 Check Bug Tracking File

Read `.bugs.local.md` if it exists:

```bash
test -f .bugs.local.md && cat .bugs.local.md
```

**Parse for in-progress bugs:**

- Extract bugs with status "In Progress" or "Resolved"
- Find bug IDs referenced in current branch name
- Store as `bug_context`

### 1.4 Extract Task Reference from Branch Name

Get current branch and parse for ticket ID:

```bash
# Get current branch
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null)

# Extract ticket ID patterns:
# - feat/PROJECTID123-123-description
# - fix/bug-42-description
# - task/ISSUE-101-description

# Jira-style pattern
TICKET_ID=$(echo "$CURRENT_BRANCH" | grep -oE '[A-Z]+-[0-9]+' | head -1)

# Bug/issue pattern
if [ -z "$TICKET_ID" ]; then
  TICKET_ID=$(echo "$CURRENT_BRANCH" | grep -oE '(bug|issue)-[0-9]+' | head -1)
fi
```

### 1.5 Confirm Context with User

**If multiple context sources found:**

```text
Found multiple context sources:
1. PRD files: .prd.phase1.md, .prd.auth.md
2. Task Master: Task #27 (In Progress)
3. Bug tracking: Bug #42 (Resolved)

Which context should be used for this PR?
- Enter number (1-3) or 'all' to combine
```

**If no context found:**

```text
⚠ No context found from PRD files, Task Master, or bug tracking.

Please provide PR context manually or:
- Create a PRD file (*.prd.*.md)
- Mark tasks as in-progress in Task Master
- Track bugs in .bugs.local.md
```

Prompt user for manual PR description input.

## Phase 2: Locate and Parse PR Template

### 2.1 Search for PR Template

Check common template locations:

```bash
# Check standard locations
if [ -f .github/PULL_REQUEST_TEMPLATE.md ]; then
  TEMPLATE_PATH=".github/PULL_REQUEST_TEMPLATE.md"
elif [ -f .github/pull_request_template.md ]; then
  TEMPLATE_PATH=".github/pull_request_template.md"
elif [ -f docs/PULL_REQUEST_TEMPLATE.md ]; then
  TEMPLATE_PATH="docs/PULL_REQUEST_TEMPLATE.md"
else
  TEMPLATE_PATH=""
fi
```

### 2.2 Parse Template Structure

**If template found:**

- Read template content
- Identify sections (headers starting with `##`)
- Note required vs optional sections
- Preserve template structure exactly

**Template section detection:**

```bash
# Extract section headers
grep '^## ' "$TEMPLATE_PATH"
```

**Common sections:**

- Summary / Overview / Why
- Changes / What
- Outcome / Delivered Functions
- Key Decision Points (optional)
- Validation / Testing (optional)
- Review Checklist

### 2.3 Use Default Template

**If no template found**, use default structure:

```markdown
# [TICKET-ID] Pull Request Title

## Summary

**Why:**
[Business or technical reason for change]

**What:**
[What was implemented]

## Outcome

**Delivered Functions:**

- Function 1
- Function 2

**Value:**

- Business value 1
- Technical improvement 1

## Validation

Report what testing has been completed:

- **Unit Tests:** [Pass rate and coverage]
- **Integration Tests:** [What was validated]
- **Manual Testing:** [Scenarios verified]

## Review Checklist

Areas for feedback:

- Specific area 1
- Specific area 2
```

## Phase 3: Generate PR Content

### 3.1 Generate PR Title

**Format:** `[TICKET-ID] Brief description of change`

**Examples:**

```text
[PROJECTID123-123] Add user authentication with JWT
[Bug-42] Fix markdown linting issues in documentation
[ISSUE-101] Implement pull request automation
```

**Title generation logic:**

```bash
# Extract primary change from context
PRIMARY_CHANGE="[derive from context]"

# Format with ticket ID
if [ -n "$TICKET_ID" ]; then
  PR_TITLE="[$TICKET_ID] $PRIMARY_CHANGE"
else
  PR_TITLE="$PRIMARY_CHANGE"
fi
```

### 3.2 Populate Template Sections

**Summary section:**

**Why:**

- Extract business/technical reason from PRD or task description
- Explain problem being solved
- Note any background context

**What:**

- Summarize planned implementation from context
- Reference specific requirements
- Note scope boundaries

**Outcome section:**

**Delivered Functions:**

- List implemented features/functions
- Use bullet points for clarity
- Focus on what was delivered, not how

**Value:**

- Business impact (user experience, efficiency)
- Technical improvements (performance, maintainability)
- Quality enhancements (test coverage, documentation)

**Validation section:**

Generate testing summary based on project:

```bash
# Detect test framework
if grep -q "bun:test" package.json 2>/dev/null; then
  TEST_FRAMEWORK="bun:test"
  # Run tests and capture results
  TEST_OUTPUT=$(bun test --reporter=json 2>&1 || true)
elif grep -q "jest" package.json 2>/dev/null; then
  TEST_FRAMEWORK="jest"
fi
```

Report actual test results:

```markdown
**Unit Tests:** 45/45 passing (100% coverage on new code)
**Integration Tests:** Validated API endpoints in dev environment
**Manual Testing:** Tested authentication flow with Google OAuth
```

**Review Checklist:**

Generate context-specific review areas:

- Architecture decisions (if significant changes)
- Security implications (if auth/sensitive data)
- Performance impact (if data processing)
- Backward compatibility (if API changes)

### 3.3 Follow Documentation Guidelines

Check for `~/.claude/guides/agents.markdown.md`:

```bash
test -f ~/.claude/guides/agents.markdown.md
```

**If found**, apply guidelines:

- No emojis (unless explicitly allowed)
- Professional tone for reviewers
- Concise, focused content
- Avoid blocked words (comprehensive, detailed, robust, etc.)

### 3.4 Remove Optional Sections

**For trivial changes** (documentation only, typo fixes, formatting):

- Remove "Key Decision Points" section
- Remove "Validation" section
- Keep Summary and Review Checklist minimal

**Detection logic:**

```bash
# Check git diff for file types
CHANGED_FILES=$(git diff --name-only HEAD)

# Check if only docs/markdown changed
if echo "$CHANGED_FILES" | grep -qE '\.(md|txt)$' && \
   ! echo "$CHANGED_FILES" | grep -qvE '\.(md|txt)$'; then
  TRIVIAL_CHANGE=true
fi
```

## Phase 4: Save and Review

### 4.1 Write to .pr.local.md

```bash
# Write PR content to file
cat > .pr.local.md << 'EOF'
[GENERATED PR CONTENT]
EOF
```

**File format:**

- First line: `# [TICKET-ID] PR Title`
- Following lines: PR body content
- No frontmatter or metadata

### 4.2 Open in Editor

```bash
# Open in VSCode
code .pr.local.md

# Alternative editors
# vim .pr.local.md
# nano .pr.local.md
```

### 4.3 Prompt for User Review

**Output to console:**

```text
✓ PR content generated: .pr.local.md

Context sources:
  - PRD files: .prd.phase1.md
  - Task Master: Task #27
  - Branch: feat/PROJECTID123-123-add-pr-command

Review checklist:
  ✓ Title includes ticket ID
  ✓ Template structure followed
  ✓ Testing results included
  ✓ Optional sections removed (trivial change)

Next steps:
  1. Review and edit .pr.local.md
  2. Run: task git:pr:create FILE=.pr.local.md
     (or use --auto flag to skip this step)
```

**If --auto flag enabled:**

Skip editor review and proceed directly to Phase 5.

## Phase 5: Check for Existing Pull Request

### 5.1 Detect Existing PR on Current Branch

**Before creating a new PR**, check if one already exists:

```bash
# Get current branch
CURRENT_BRANCH=$(git branch --show-current 2>/dev/null)

# Get remote URL to parse owner/repo
REMOTE_URL=$(git remote get-url origin 2>/dev/null)
```

**Using GitHub MCP:**

```javascript
// Parse owner/repo from remote URL
const remoteUrl = execSync('git remote get-url origin', { encoding: 'utf-8' }).trim();
const match = remoteUrl.match(/github\.com[:/]([^/]+)\/(.+?)(?:\.git)?$/);
const owner = match[1];
const repo = match[2];

// Get current branch
const currentBranch = execSync('git branch --show-current', { encoding: 'utf-8' }).trim();

// Search for existing PR from this branch
try {
  const searchResult = await mcp__github_mcp__search_pull_requests({
    owner,
    repo,
    query: `head:${currentBranch} is:pr`,
  });

  if (searchResult.total_count > 0) {
    // Found existing PR
    const existingPR = searchResult.items[0];
    EXISTING_PR_NUMBER = existingPR.number;
    EXISTING_PR_URL = existingPR.html_url;
    UPDATE_MODE = true;

    console.log(`Found existing PR #${EXISTING_PR_NUMBER}: ${existingPR.title}`);
    console.log(`  ${EXISTING_PR_URL}`);
    console.log(`  Will update PR instead of creating new one`);
  }
} catch (error) {
  // If MCP fails or not available, try GitHub CLI
  console.log(`GitHub MCP search failed, trying gh CLI...`);
}
```

**Using GitHub CLI (fallback):**

```bash
# Search for PR from current branch
EXISTING_PR=$(gh pr list --head "$CURRENT_BRANCH" --json number,url,title --limit 1 2>/dev/null)

if [ -n "$EXISTING_PR" ] && [ "$EXISTING_PR" != "[]" ]; then
  EXISTING_PR_NUMBER=$(echo "$EXISTING_PR" | jq -r '.[0].number')
  EXISTING_PR_URL=$(echo "$EXISTING_PR" | jq -r '.[0].url')
  UPDATE_MODE=true

  echo "Found existing PR #${EXISTING_PR_NUMBER}"
  echo "  ${EXISTING_PR_URL}"
  echo "  Will update PR instead of creating new one"
fi
```

### 5.2 Prompt User Confirmation

**If existing PR found:**

```text
Found existing pull request for branch: feat/PROJECTID123-123-add-pr-command

  PR #123: [PROJECTID123-123] Add PR command with context generation
  https://github.com/owner/repo/pull/123

  Status: Open
  Base: main
  Draft: No

Do you want to:
  1. Update existing PR (recommended)
  2. Close existing and create new PR
  3. Cancel

Choice [1]:
```

**Default behavior:** Update existing PR (option 1)

**If option 2 selected:**

```javascript
// Close existing PR via MCP
await mcp__github_mcp__update_pull_request({
  owner,
  repo,
  pullNumber: EXISTING_PR_NUMBER,
  state: 'closed',
});

// Proceed to create new PR
UPDATE_MODE = false;
```

## Phase 6: Create or Update Pull Request

### 6.1 Check GitHub MCP Availability

**First, try GitHub MCP server** (preferred method):

```bash
# Check if GitHub MCP is configured
MCP_AVAILABLE=false

# Try to list MCP servers via Claude CLI
if command -v claude &>/dev/null; then
  MCP_LIST=$(claude mcp list 2>/dev/null || echo "")

  if echo "$MCP_LIST" | grep -q "github-mcp"; then
    MCP_AVAILABLE=true
  fi
fi
```

**Benefits of GitHub MCP:**

- Direct API integration (no CLI dependencies)
- Consistent authentication via MCP
- Better error handling
- Works across all AI tools (Claude, Cursor, Codex)

### 6.2 Create or Update PR via GitHub MCP (Preferred)

**If GitHub MCP is available:**

```javascript
// Parse .pr.local.md file
const prContent = readFileSync('.pr.local.md', 'utf-8');
const lines = prContent.split('\n');

// Extract title (first line without #)
const title = lines[0].replace(/^#\s*/, '').trim();

// Extract body (everything after first line)
const body = lines.slice(1).join('\n').trim();

// Get current branch and remote info
const currentBranch = execSync('git branch --show-current', { encoding: 'utf-8' }).trim();
const remoteUrl = execSync('git remote get-url origin', { encoding: 'utf-8' }).trim();

// Parse owner/repo from remote URL
// Examples:
//   - https://github.com/owner/repo.git
//   - git@github.com:owner/repo.git
const match = remoteUrl.match(/github\.com[:/]([^/]+)\/(.+?)(?:\.git)?$/);
const owner = match[1];
const repo = match[2];

// Determine base branch
const baseBranch = BASE_BRANCH || 'main';

try {
  let result;

  if (UPDATE_MODE) {
    // Update existing PR
    console.log(`Updating existing PR #${EXISTING_PR_NUMBER}...`);

    result = await mcp__github_mcp__update_pull_request({
      owner,
      repo,
      pullNumber: EXISTING_PR_NUMBER,
      title,
      body,
      base: baseBranch,
      draft: DRAFT_MODE,
    });

    console.log(`✓ Pull request updated: ${result.html_url}`);
    console.log(`  PR #${result.number}: ${result.title}`);
    console.log(`  Changes: Updated title and description`);
  } else {
    // Create new PR
    console.log(`Creating new pull request...`);

    result = await mcp__github_mcp__create_pull_request({
      owner,
      repo,
      title,
      body,
      head: currentBranch,
      base: baseBranch,
      draft: DRAFT_MODE,
    });

    console.log(`✓ Pull request created: ${result.html_url}`);
    console.log(`  PR #${result.number}: ${result.title}`);
  }

  // Open in browser (optional)
  execSync(`open "${result.html_url}"`, { stdio: 'ignore' });

  // Success - exit with code 0
  process.exit(0);
} catch (error) {
  console.log(`⚠ GitHub MCP failed: ${error.message}`);
  console.log(`  Falling back to GoTask method...`);
  // Fall through to GoTask method
}
```

**Handle MCP-specific errors:**

- **Token expired:** Display instructions to update token
- **Insufficient permissions:** Show required permissions
- **Network errors:** Retry with exponential backoff
- **Branch not pushed:** Detect and prompt user to push

### 6.3 Fallback to GoTask Method

**If GitHub MCP unavailable or failed**, use GoTask:

```bash
# Verify GitHub CLI installed
gh --version 2>/dev/null || echo "❌ GitHub CLI (gh) not found"

# Verify GITHUB_TOKEN available
task op:export 2>/dev/null && [ -n "$GITHUB_TOKEN" ] || echo "❌ GITHUB_TOKEN not available"

# Verify .pr.local.md exists
test -f .pr.local.md || echo "❌ .pr.local.md not found"

# Verify git working tree is clean (or all changes committed)
git diff --quiet || echo "⚠ Uncommitted changes detected"
```

**Execute GoTask command:**

```bash
# For creating new PR
if [ "$UPDATE_MODE" = "false" ]; then
  task git:pr:create FILE=.pr.local.md
else
  # For updating existing PR
  task git:pr:update PR=$EXISTING_PR_NUMBER FILE=.pr.local.md
fi
```

**Expected task behavior (create):**

1. Source GITHUB_TOKEN via `task op:export`
2. Parse title from first line of .pr.local.md
3. Extract body (all content after title)
4. Execute `gh pr create --title "TITLE" --body "BODY" [--draft]`
5. Open PR in browser
6. Output PR URL

**Expected task behavior (update):**

1. Source GITHUB_TOKEN via `task op:export`
2. Parse title from first line of .pr.local.md
3. Extract body (all content after title)
4. Execute `gh pr edit PR_NUMBER --title "TITLE" --body "BODY"`
5. Output confirmation

**Example output (create):**

```text
Creating pull request for feat/PROJECTID123-123-add-pr-command -> main

https://github.com/org/repo/pull/123

✓ Pull request created successfully
✓ Opened in browser
```

**Example output (update):**

```text
Updating pull request #123

https://github.com/org/repo/pull/123

✓ Pull request updated successfully
  - Title updated
  - Description updated
```

### 6.4 Handle Creation/Update Errors

**GitHub MCP errors:**

**Token validation failed:**

```text
❌ GitHub token validation failed

The GitHub token configured in MCP is invalid or expired.

To update:
  1. Create new token: https://github.com/settings/tokens
  2. Update in 1Password or environment variable
  3. Restart Claude Code
  4. Retry: /pr
```

**Insufficient permissions:**

```text
❌ GitHub token missing required permissions

Required permissions:
  - Contents: Read
  - Pull requests: Write

Update token permissions:
  https://github.com/settings/tokens
```

**GoTask errors:**

**GitHub CLI not authenticated:**

```text
❌ GitHub CLI authentication required

Run: gh auth login
```

**Branch not pushed to remote:**

```text
❌ Current branch not found on remote

Run: git push -u origin $(git branch --show-current)
```

**Network/API errors:**

```text
❌ Failed to create pull request: API rate limit exceeded

Try again later or check: gh pr list
```

## Error Handling

### Context Gathering Errors

- **No git repository:** Warn user, skip git-related context
- **Task Master MCP unavailable:** Skip task context, use PRD/bugs only
- **Corrupted .bugs.local.md:** Warn user, skip bug context

### Template Processing Errors

- **Invalid template format:** Warn user, use default template
- **Missing required sections:** Fill with placeholders, flag for user

### File Operation Errors

- **Cannot write .pr.local.md:** Check permissions, suggest alternative path
- **Cannot open editor:** Output file path, suggest manual review

### PR Creation Errors

- **Missing GITHUB_TOKEN:** Provide setup instructions
- **gh CLI missing:** Provide installation instructions
- **Uncommitted changes:** Recommend committing or stashing first

## Exit Codes

- 0: PR content generated successfully (or PR created if --auto)
- 1: Invalid arguments or missing dependencies
- 2: Context gathering failed
- 3: Template processing failed
- 4: File operation failed
- 5: PR creation failed (only with --auto flag)

## Examples

### Basic usage

```bash
/pr
```

Creates PR with automatic context detection, opens editor for review.

### Create draft PR

```bash
/pr --draft
```

Creates PR in draft mode.

### Target specific branch

```bash
/pr --base=develop
```

Creates PR targeting `develop` branch instead of default.

### Auto-create without review

```bash
/pr --auto
```

Generates content and creates PR immediately without editor review.

### Combined flags

```bash
/pr --draft --base=staging --auto
```

Creates draft PR targeting staging branch without manual review.
