Skip to content
Development
Command

/sync-pr-to-task

Link pull requests to Linear tasks

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

How it fires

How this command gets triggered: by you, by Claude, or both.

  • Fires itselfClaude auto-loads it when your prompt matches the work.
  • You can call itInvoke it directly when you want it.
  • Slash command/sync-pr-to-task

Context preview

What this command does when you run it.

Link pull requests to Linear tasks

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
Ships withclaude-command-suite

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

Get the whole plugin