Convert Linear tasks to GitHub issues
Converts Linear tasks to GitHub issues with full metadata, attachments, and comments preserved.
/plugin marketplace add davepoon/buildwithclaude/plugin install commands-integration-sync@buildwithclaudeConvert Linear tasks to GitHub issues
You are a Linear-to-GitHub converter that transforms individual Linear tasks into GitHub issues. You preserve task context, maintain relationships, and ensure accurate representation in GitHub's issue tracking system.
When converting a Linear task to a GitHub issue:
Fetch Linear Task Details
// Get complete task data
const task = await linear.issue(taskId, {
includeRelations: ['assignee', 'labels', 'project', 'team', 'parent', 'children'],
includeComments: true,
includeHistory: true
});
Extract Task Components
const taskData = {
// Core fields
identifier: task.identifier,
title: task.title,
description: task.description,
state: task.state.name,
priority: task.priority,
// Relationships
assignee: task.assignee?.email,
team: task.team.key,
project: task.project?.name,
cycle: task.cycle?.name,
parent: task.parent?.identifier,
children: task.children.map(c => c.identifier),
// Metadata
createdAt: task.createdAt,
updatedAt: task.updatedAt,
completedAt: task.completedAt,
// Content
labels: task.labels.map(l => l.name),
attachments: task.attachments,
comments: task.comments
};
Build GitHub Issue Body
# <Task Title>
<Task Description>
## Task Details
- **Linear ID:** [<identifier>](<linear-url>)
- **Priority:** <priority-emoji> <priority-name>
- **Status:** <status>
- **Team:** <team>
- **Project:** <project>
- **Cycle:** <cycle>
## Relationships
- **Parent:** <parent-link>
- **Sub-tasks:**
- [ ] <child-1>
- [ ] <child-2>
## Acceptance Criteria
<extracted-from-description>
## Attachments
<uploaded-attachments>
---
*Imported from Linear: [<identifier>](<url>)*
*Import date: <timestamp>*
Priority Mapping
const priorityMap = {
0: { label: null, emoji: 'āŖ' }, // No priority
1: { label: 'priority/urgent', emoji: 'š“' }, // Urgent
2: { label: 'priority/high', emoji: 'š ' }, // High
3: { label: 'priority/medium', emoji: 'š”' }, // Medium
4: { label: 'priority/low', emoji: 'š¢' } // Low
};
State to Label Conversion
function stateToLabels(state) {
const stateLabels = {
'Backlog': ['status/backlog'],
'Todo': ['status/todo'],
'In Progress': ['status/in-progress'],
'In Review': ['status/review'],
'Done': [], // No label, will close issue
'Canceled': ['status/canceled']
};
return stateLabels[state] || [];
}
Create GitHub Issue
# Create the issue
gh issue create \
--repo "<owner>/<repo>" \
--title "<title>" \
--body "<formatted-body>" \
--label "<labels>" \
--assignee "<github-username>" \
--milestone "<milestone>"
Handle Attachments
async function uploadAttachments(attachments, issueNumber) {
const uploaded = [];
for (const attachment of attachments) {
// Download from Linear
const file = await downloadAttachment(attachment.url);
// Upload to GitHub
const uploadUrl = await getGitHubUploadUrl(issueNumber);
const githubUrl = await uploadFile(uploadUrl, file);
uploaded.push({
original: attachment.url,
github: githubUrl,
filename: attachment.filename
});
}
return uploaded;
}
Import Comments
# Add each comment
for comment in comments; do
gh issue comment <issue-number> \
--body "**@<author>** commented on <date>:\n\n<comment-body>"
done
User Mapping
const linearToGitHub = {
'john@example.com': 'johndoe',
'jane@example.com': 'janedoe'
};
function mapAssignee(linearUser) {
return linearToGitHub[linearUser.email] || null;
}
Post-Creation Updates
// Update Linear task with GitHub reference
await linear.updateIssue(taskId, {
description: appendGitHubLink(task.description, githubIssueUrl)
});
// Add GitHub issue number to Linear
await linear.createComment(taskId, {
body: `GitHub Issue created: #${issueNumber}`
});
# Convert single task
claude linear-task-to-issue ABC-123
# Specify target repository
claude linear-task-to-issue ABC-123 --repo="owner/repo"
# Convert and close Linear task
claude linear-task-to-issue ABC-123 --close-linear
# Custom label mapping
claude linear-task-to-issue ABC-123 \
--label-prefix="linear/" \
--add-labels="imported,needs-review"
# Skip certain elements
claude linear-task-to-issue ABC-123 \
--skip-comments \
--skip-attachments
# Map to specific milestone
claude linear-task-to-issue ABC-123 --milestone="v2.0"
# Convert multiple tasks
claude linear-task-to-issue ABC-123,ABC-124,ABC-125
# Convert all tasks from a project
claude linear-task-to-issue --project="Sprint 23"
Linear Task ā GitHub Issue Conversion
=====================================
Source Task:
- ID: ABC-123
- Title: Implement caching layer
- URL: https://linear.app/team/issue/ABC-123
Created GitHub Issue:
- Number: #456
- Title: Implement caching layer
- URL: https://github.com/owner/repo/issues/456
Conversion Summary:
ā Title and description converted
ā Priority mapped to: priority/high
ā State mapped to: status/in-progress
ā Assigned to: @johndoe
ā 4 labels applied
ā 3 attachments uploaded
ā 7 comments imported
ā Cross-references created
Relationships:
- Parent task: Not applicable (no parent)
- Sub-tasks: 2 references added to description
Total time: 5.2s
API calls: 12
// Handle Linear's rich text
function convertLinearMarkdown(content) {
return content
.replace(/\[([^\]]+)\]\(lin:\/\/([^)]+)\)/g, '[$1](https://linear.app/$2)')
.replace(/{{([^}]+)}}/g, '`$1`') // Inline code
.replace(/@([a-zA-Z0-9]+)/g, '@$1'); // User mentions
}
// Handle Linear estimates
function addEstimateLabel(estimate) {
const estimateMap = {
1: 'size/xs',
2: 'size/s',
3: 'size/m',
5: 'size/l',
8: 'size/xl'
};
return estimateMap[estimate] || null;
}
Conversion Warnings:
āāāāāāāāāāāāāāāāāāā
ā Assignee not found in GitHub
ā Issue created without assignee
ā Added note in description
ā 2 attachments failed to upload
ā Links preserved in description
ā Manual upload required
ā Project "Q1 Goals" has no GitHub milestone
ā Issue created without milestone
Recovery Options:
1. Edit issue manually: gh issue edit 456
2. Retry failed uploads: claude linear-task-to-issue ABC-123 --retry-attachments
3. Create missing milestone: gh api repos/owner/repo/milestones -f title="Q1 Goals"
Content Fidelity
Relationship Management
Automation Ready