Skip to content
OpenSmartRoute
Skillv1.0.0

linear-core-workflow-a

Issue lifecycle management with Linear: create, update, transition, relate, comment, and organize issues through the SDK and GraphQL API. Trigger: "linear issue workflow", "linear issue lifecycle", "c

by jeremylongshore(0) 0 installs
Free
Sign in to install

Free account. Installing gives you the manifest plus copy-paste snippets.

See reviews

About

Imported from jeremylongshore/tons-of-skills-marketplace (plugins/saas-packs/linear-pack/skills/linear-core-workflow-a/SKILL.md). Install upstream with npx skills add jeremylongshore/tons-of-skills-marketplace --skill linear-core-workflow-a. Copyright stays with the author (MIT).

Linear Core Workflow A: Issue Lifecycle

Overview

Master issue lifecycle management: creating, updating, transitioning states, building parent/sub-issue hierarchies, managing labels, and commenting. Linear issues flow through typed workflow states (triage -> backlog -> unstarted -> started -> completed | canceled), belong to a team, and support priorities 0-4, estimates, due dates, labels, and cycle/project assignment.

Prerequisites

  • @linear/sdk installed with API key or OAuth token configured
  • Access to target team(s)
  • Understanding of your team's workflow states

Instructions

Step 1: Create Issues

import { LinearClient } from "@linear/sdk";

const client = new LinearClient({ apiKey: process.env.LINEAR_API_KEY! });

// Get team
const teams = await client.teams();
const team = teams.nodes.find(t => t.key === "ENG") ?? teams.nodes[0];

// Basic issue
const result = await client.createIssue({
  teamId: team.id,
  title: "Implement user authentication",
  description: "Add OAuth 2.0 login flow with Google and GitHub providers.",
  priority: 2, // 0=None, 1=Urgent, 2=High, 3=Medium, 4=Low
});

if (result.success) {
  const issue = await result.issue;
  console.log(`Created: ${issue?.identifier} — ${issue?.title}`);
  console.log(`URL: ${issue?.url}`);
}

// Issue with full metadata
const labelResult = await client.issueLabels({ filter: { name: { eq: "Bug" } } });
const bugLabel = labelResult.nodes[0];
const states = await team.states();
const todoState = states.nodes.find(s => s.type === "unstarted")!;

await client.createIssue({
  teamId: team.id,
  title: "Fix login redirect loop on Safari",
  description: "Users get stuck in infinite redirect after SSO callback.",
  priority: 1,
  stateId: todoState.id,
  assigneeId: "user-uuid",
  labelIds: bugLabel ? [bugLabel.id] : [],
  estimate: 3,
  dueDate: "2026-04-15",
});

Step 2: Update Issues

// Update by issue ID
await client.updateIssue("issue-uuid", {
  title: "Updated title",
  priority: 1,
  estimate: 5,
  dueDate: "2026-04-30",
});

// Find issue by team key + number, then update
const issues = await client.issues({
  filter: { number: { eq: 123 }, team: { key: { eq: "ENG" } } },
});
const issue = issues.nodes[0];
if (issue) {
  await issue.update({
    priority: 2,
    description: "Updated description with more details.",
  });
}

// Add/remove labels
const featureLabel = (await client.issueLabels({
  filter: { name: { eq: "Feature" } },
})).nodes[0];

if (featureLabel) {
  await client.updateIssue(issue.id, {
    labelIds: [...(issue.labelIds ?? []), featureLabel.id],
  });
}

Step 3: State Transitions

// List all workflow states for a team
const teamStates = await team.states();
for (const state of teamStates.nodes) {
  console.log(`${state.name} (type: ${state.type}, position: ${state.position})`);
}
// Output example:
// Triage (type: triage, position: 0)
// Backlog (type: backlog, position: 1)
// Todo (type: unstarted, position: 2)
// In Progress (type: started, position: 3)
// In Review (type: started, position: 4)
// Done (type: completed, position: 5)
// Canceled (type: canceled, position: 6)

// Move to "In Progress"
const inProgress = teamStates.nodes.find(s => s.name === "In Progress");
if (inProgress) {
  await client.updateIssue(issue.id, { stateId: inProgress.id });
}

// Complete an issue
const done = teamStates.nodes.find(s => s.type === "completed");
if (done) {
  await issue.update({ stateId: done.id });
}

Step 4: Parent/Sub-Issue Hierarchy

// Create parent issue
const parentResult = await client.createIssue({
  teamId: team.id,
  title: "Auth system overhaul",
  description: "Epic: modernize authentication infrastructure.",
});
const parent = await parentResult.issue;

// Create sub-issues under parent
await client.createIssue({
  teamId: team.id,
  title: "Implement JWT token refresh",
  parentId: parent!.id,
  priority: 2,
});

await client.createIssue({
  teamId: team.id,
  title: "Add MFA support",
  parentId: parent!.id,
  priority: 3,
});

// List sub-issues
const children = await parent!.children();
for (const child of children.nodes) {
  console.log(`  Sub: ${child.identifier} — ${child.title}`);
}

Step 5: Issue Relations

// Relation types: "blocks", "duplicate", "related"
await client.createIssueRelation({
  issueId: "blocked-issue-id",
  relatedIssueId: "blocking-issue-id",
  type: "blocks",
});

// Mark as duplicate
await client.createIssueRelation({
  issueId: "duplicate-issue-id",
  relatedIssueId: "original-issue-id",
  type: "duplicate",
});

// List relations on an issue
const relations = await issue.relations();
for (const rel of relations.nodes) {
  const related = await rel.relatedIssue;
  console.log(`${rel.type}: ${related?.identifier}`);
}

Step 6: Comments

// Add a comment (supports Markdown)
await client.createComment({
  issueId: issue.id,
  body: "Deployed fix to staging.\n\n```bash\nnpm run test:e2e -- --filter auth\n```\n\nAll 47 tests passing.",
});

// List comments on an issue
const comments = await issue.comments();
for (const comment of comments.nodes) {
  const user = await comment.user;
  console.log(`${user?.name}: ${comment.body.substring(0, 80)}...`);
}

Step 7: Attachments

// Create a link attachment on an issue
await client.createAttachment({
  issueId: issue.id,
  title: "Figma Design",
  url: "https://figma.com/file/xxx",
  subtitle: "Login page redesign",
});

Error Handling

Error Cause Solution
Entity not found Invalid issue ID or deleted Verify with client.issue(id) first
State not found Wrong team's state ID List states for correct team: team.states()
Validation error on create Missing required field teamId + title required; priority must be 0-4
Circular dependency Issue blocks itself transitively Validate relation graph before creating
Forbidden No write access to team Check team membership and API key scope

Examples

Bulk Create from CSV

import { parse } from "csv-parse/sync";
import fs from "fs";

const rows = parse(fs.readFileSync("issues.csv"), { columns: true });
for (const row of rows) {
  const result = await client.createIssue({
    teamId: team.id,
    title: row.title,
    description: row.description,
    priority: parseInt(row.priority) || 3,
  });
  const issue = await result.issue;
  console.log(`Created: ${issue?.identifier}`);
}

Close Stale Issues

const stale = await client.issues({
  filter: {
    state: { type: { in: ["unstarted", "started"] } },
    updatedAt: { lt: new Date(Date.now() - 90 * 24 * 60 * 60 * 1000).toISOString() },
  },
  first: 50,
});

const canceled = (await team.states()).nodes.find(s => s.type === "canceled")!;
for (const issue of stale.nodes) {
  await issue.update({ stateId: canceled.id });
  await client.createComment({
    issueId: issue.id,
    body: "Auto-closed: no activity for 90 days.",
  });
  console.log(`Closed: ${issue.identifier} (last updated ${issue.updatedAt})`);
}

Resources

Use it

Copy one of these into your project. Installing also returns the manifest and these snippets.

yaml
targets:
  - https://api.opensmartroute.ai/api/v1/registry/jeremylongshore-tons-of-skills-marketplace-linear-core-w-8439e1/manifest   # or paste the manifest below

Manifest

An Open Capability Manifest: the router reads it to know what this does, what it costs and when to pick it.

jeremylongshore-tons-of-skills-marketplace-linear-core-w-8439e1.ocm.jsonjson
{
  "ocm": "1",
  "id": "jeremylongshore-tons-of-skills-marketplace-linear-core-w-8439e1",
  "kind": "skill",
  "name": "linear-core-workflow-a",
  "description": "Issue lifecycle management with Linear: create, update, transition, relate, comment, and organize issues through the SDK and GraphQL API. Trigger: \"linear issue workflow\", \"linear issue lifecycle\", \"create linear issues\", \"update linear issue\", \"linear state transition\", \"linear sub-issues\", \"linear comments\".",
  "publisher": "jeremylongshore",
  "version": "1.0.0",
  "capabilities": {
    "domains": [
      "coding"
    ],
    "tags": [
      "skill-md",
      "saas",
      "linear",
      "workflow",
      "skills-sh"
    ],
    "languages": [
      "en"
    ]
  },
  "quality_prior": 0.6,
  "examples": [
    "Issue lifecycle management with Linear: create, update, transition, relate, comment, and organize issues through the SDK and GraphQL API. Trigger: \"linear issue workflow\", \"linear issue lifecycle\", \"create linear issues\", \"update linear issue\", \"linear state transition\", \"linear sub-issues\", \"linear comments\"."
  ],
  "primary": false,
  "metadata": {
    "source": {
      "provider": "skills.sh",
      "repository": "https://github.com/jeremylongshore/tons-of-skills-marketplace",
      "path": "plugins/saas-packs/linear-pack/skills/linear-core-workflow-a/SKILL.md",
      "ref": "HEAD",
      "url": "https://github.com/jeremylongshore/tons-of-skills-marketplace/blob/HEAD/plugins/saas-packs/linear-pack/skills/linear-core-workflow-a/SKILL.md",
      "key": "jeremylongshore/tons-of-skills-marketplace/plugins/saas-packs/linear-pack/skills/linear-core-workflow-a/SKILL.md"
    },
    "compatibility": "Designed for Claude Code",
    "allowed_tools": [
      "Read,",
      "Write,",
      "Edit,",
      "Grep"
    ],
    "license": "MIT"
  },
  "instructions": "# Linear Core Workflow A: Issue Lifecycle\n\n## Overview\n\nMaster issue lifecycle management: creating, updating, transitioning states, building parent/sub-issue hierarchies, managing labels, and commenting. Linear issues flow through typed workflow states (`triage` -> `backlog` -> `unstarted` -> `started` -> `completed` | `canceled`), belong to a team, and support priorities 0-4, estimates, due dates, labels, and cycle/project assignment.\n\n## Prerequisites\n\n- `@linear/sdk` installed with API key or OAuth token configured\n- Access to target team(s)\n- Understanding of your team's workflow states\n\n",
  "cost": {
    "context_tokens": 1874
  }
}

Fetch it by URL: GET /api/v1/registry/jeremylongshore-tons-of-skills-marketplace-linear-core-w-8439e1/manifest?version=1.0.0

Reviews

Star ratings from people who tried it. One review per account; edit yours any time.

No reviews yet. Install it, try it, and be the first to rate it.