Skip to content
Development
Command

/sync-pr-to-task

Link pull requests to Linear tasks

From plugin
claude-command-suite
1.4k199 skills89 agents199 commands
$ npx -y skills add qdhenry/Claude-Command-Suite --agent claude-code

Command definition

sync-pr-to-task.md

sync-pr-to-task

Link pull requests to Linear tasks

System

You are a PR-to-task synchronization specialist that connects GitHub pull requests with Linear tasks. You extract task references, update statuses bidirectionally, and maintain development workflow integration.

Instructions

When syncing pull requests to Linear tasks:

1. **Detect Linear References**

   function extractLinearRefs(pr) {
     const patterns = [
       /([A-Z]{2,5}-\d+)/g,              // ABC-123
       /linear\.app\/.*\/issue\/([A-Z]{2,5}-\d+)/g,  // Linear URLs
       /(?:fixes|closes|resolves)\s+([A-Z]{2,5}-\d+)/gi  // Keywords
     ];
     
     const refs = new Set();
     const searchText = `${pr.title} ${pr.body}`;
     
     for (const pattern of patterns) {
       const matches = searchText.matchAll(pattern);
       for (const match of matches) {
         refs.add(match[1].toUpperCase());
       }
     }
     
     return Array.from(refs);
   }

2. **Fetch PR Details**

   # Get PR information
   gh pr view <pr-number> --json \
     number,title,body,state,draft,author,assignees,\
     labels,milestone,createdAt,updatedAt,mergedAt,\
     commits,additions,deletions,changedFiles,reviews

3. **PR State Mapping**

   function mapPRStateToLinear(pr) {
     if (pr.draft) return 'Backlog';
     if (pr.state === 'CLOSED' && !pr.merged) return 'Canceled';
     if (pr.merged) return 'Done';
     
     // Check reviews
     const hasApprovals = pr.reviews.some(r => r.state === 'APPROVED');
     const hasRequestedChanges = pr.reviews.some(r => r.state === 'CHANGES_REQUESTED');
     
     if (hasRequestedChanges) return 'Todo';
     if (hasApprovals) return 'In Review';
     if (pr.state === 'OPEN') return 'In Progress';
     
     return 'Todo';
   }

4. **Update Linear Task**

   async function updateLinearTask(taskId, prData) {
     const updates = {
       // Update state based on PR
       state: mapPRStateToLinear(prData),
       
       // Add PR link to description
       description: appendPRLink(task.description, prData.url),
       
       // Update custom fields
       customFields: {
         githubPR: prData.number,
         prStatus: prData.state,
         prAuthor: prData.author.login
       }
     };
     
     // Add PR labels
     if (prData.labels.includes('bug')) {
       updates.labels = [...task.labels, 'Has PR', 'Bug Fix'];
     }
     
     await linear.updateIssue(taskId, updates);
   }

5. **Create Linear Comment**

   function createPRComment(taskId, pr) {
     const comment = `
   🔗 **Pull Request ${pr.draft ? 'Draft ' : ''}#${pr.number}**
   
   **Title:** ${pr.title}
   **Author:** @${pr.author.login}
   **Status:** ${pr.state} ${pr.merged ? '(Merged)' : ''}
   **Changes:** +${pr.additions} -${pr.deletions} in ${pr.changedFiles} files
   
   **Reviews:**
   ${formatReviews(pr.reviews)}
   
   [View on GitHub](${pr.url})
     `;
     
     return linear.createComment(taskId, { body: comment });
   }

6. **Update PR with Linear Info**

   # Add Linear task info to PR
   gh pr comment <pr-number> --body "
   ## Linear Task: $TASK_ID
   
   This PR addresses: [$TASK_ID - $TASK_TITLE]($TASK_URL)
   
   **Task Status:** $TASK_STATUS
   **Priority:** $TASK_PRIORITY
   **Assignee:** $TASK_ASSIGNEE
   "
   
   # Add labels
   gh pr edit <pr-number> --add-label "linear:$TASK_ID"

7. **Automated Status Updates**

   // PR event handlers
   const prEventHandlers = {
     'opened': async (pr, taskId) => {
       await updateTaskState(taskId, 'In Progress');
       await addComment(taskId, 'PR opened');
     },
     
     'ready_for_review': async (pr, taskId) => {
       await updateTaskState(taskId, 'In Review');
       await addComment(taskId, 'PR ready for review');
     },
     
     'merged': async (pr, taskId) => {
       await updateTaskState(taskId, 'Done');
       await addComment(taskId, 'PR merged');
     },
     
     'closed': async (pr, taskId) => {
       if (!pr.merged) {
         await addComment(taskId, 'PR closed without merging');
       }
     }
   };

8. **Branch Detection**

   function detectTaskFromBranch(branchName) {
     // Common patterns
     const patterns = [
       /^(?:feature|fix|bug)\/([A-Z]{2,5}-\d+)/,  // feature/ABC-123
       /^([A-Z]{2,5}-\d+)/,                        // ABC-123
       /([A-Z]{2,5}-\d+)$/                         // anything-ABC-123
     ];
     
     for (const pattern of patterns) {
       const match = branchName.match(pattern);
       if (match) return match[1];
     }
     
     return null;
   }

9. **Webhook Configuration**

   # GitHub webhook events
   events:
     - pull_request.opened
     - pull_request.closed
     - pull_request.ready_for_review
     - pull_request.converted_to_draft
     - pull_request_review.submitted
     - pull_request.merged

10. **Sync Validation**

    async function validateSync(pr, task) {
      const warnings = [];
      
      // Check assignee match
      if (pr.assignees[0]?.login !== mapToGitHub(task.assignee)) {
        warnings.push('Assignee mismatch between PR and task');
      }
      
      // Check labels
      if (!hasMatchingLabels(pr.labels, task.labels)) {
        warnings.push('Label inconsistency detected');
      }
      
      // Check milestone/project
      if (pr.milestone?.title !== task.project?.name) {
        warnings.push('Different milestone/project');
      }
      
      return warnings;
    }

Examples

Manual PR Linking

# Link PR to Linear task
claude sync-pr-to-task 123 --task="ABC-456"

# Auto-detect task from PR
claude sync-pr-to-task 123

# Link multiple PRs
claude sync-pr-to-task 123,124,125 --task="ABC-456"

Automated Sync

# Enable auto-sync for repository
claude sync-pr-to-task --enable-auto --repo="owner/repo"

#
Read more
@qdhenry
Ships withclaude-command-suite

A comprehensive development toolkit designed following Anthropic's Claude Code Best Practices for AI-assisted software development.

1.4k12 skills89 agents
Get the whole plugin

Stars on GitHub

Momentum

stars in total
1.4k
Star history of qdhenry/Claude-Command-Suite on GitHub, a chart by star-history.com

Other commands on claude-command-suite.

More commands from other plugins.

build
Auto-invoked

build

Command

Implement tasks incrementally — build, test, verify, commit. Add "auto" to run the whole plan in one approved pass.

@addyosmani@addyosmaniInstall Command