ScriptsMay 8, 2026·3 min read

Linear SDK — TypeScript Client for Linear Agents

Linear SDK is the official TypeScript client. GraphQL-typed methods cover every Linear API surface. Drop into Inngest or Trigger.dev for issue automation.

Agent ready

Safe staging for this asset

This asset is staged first. The copied prompt tells the agent to inspect the staged files and ask before activating scripts, MCP config, or global config.

Stage only · 17/100Policy: stage
Agent surface
Any MCP/CLI agent
Kind
CLI Tool
Install
Stage only
Trust
Trust: Community
Entrypoint
Asset
Safe staging command
npx -y tokrepo@latest install ade6b301-4446-4383-aa18-352b7330f90c --target codex

Stages files first; activation requires review of the staged README and plan.

Intro

The Linear SDK is the official TypeScript client wrapping Linear's GraphQL API. Every method is fully typed (Issue, Project, Cycle, Team, User), with built-in pagination and rate-limit handling. Best for: agents and bots that automate Linear beyond what MCP covers — bulk imports, complex queries, scheduled triage. Works with: Node 18+, Bun, Deno. Setup time: 2 minutes.


Hello, Linear

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

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

// Get my issues
const me = await linear.viewer;
const issues = await me.assignedIssues({ first: 50 });

for (const issue of issues.nodes) {
  console.log(`${issue.identifier}${issue.title} (${(await issue.state).name})`);
}

Create an issue with all the trimmings

const team = await linear.team("ENG");

const issue = await linear.createIssue({
  teamId: team.id,
  title: "Auth flow drops state on redirect",
  description: "**Steps to reproduce:**\n1. Login\n2. Click external link\n3. Click back\n\nState lost.",
  priority: 1,  // Urgent
  assigneeId: (await linear.viewer).id,
  labelIds: [
    (await team.labels()).nodes.find(l => l.name === "bug")?.id!,
  ],
  projectId: "your-project-id",
});

console.log(`Created ${issue.issue?.identifier}`);

Bulk triage with rate-limit awareness

import pLimit from "p-limit";

const limit = pLimit(5);  // 5 concurrent calls; SDK auto-retries on 429

const stale = await linear.issues({
  filter: {
    state: { type: { eq: "started" } },
    updatedAt: { lt: new Date(Date.now() - 14 * 86400_000) },
  },
});

await Promise.all(
  stale.nodes.map(issue =>
    limit(() =>
      issue.update({
        labelIds: [...issue.labelIds, STALE_LABEL_ID],
      }),
    ),
  ),
);

Webhook payloads (in tandem with SDK)

// Express handler
app.post("/webhooks/linear", async (req, res) => {
  if (req.body.action === "create" && req.body.type === "Issue") {
    const issue = await linear.issue(req.body.data.id);
    if ((await issue.priority) === 1) {
      await notifySlack(`🔥 Urgent issue: ${issue.title}`);
    }
  }
  res.sendStatus(200);
});

FAQ

Q: SDK vs MCP — when to use which? A: MCP for interactive agents (Claude Code asks Linear questions during a session). SDK for scheduled or webhook-driven automation (Inngest jobs, GitHub Actions, server-side bots). Many teams use both.

Q: Is the SDK rate-limit-aware? A: Yes — built-in retry with exponential backoff on 429s. For high-throughput jobs, combine with p-limit (concurrency cap) and persist progress so you can resume.

Q: Does it support Linear's GraphQL directly? A: Yes — every typed SDK method is just a wrapper over GraphQL. For queries the SDK doesn't expose, use linear.client.rawRequest(query, variables) to send arbitrary GraphQL.


Quick Use

  1. npm install @linear/sdk
  2. Generate a personal API key in Linear → Settings → API
  3. const linear = new LinearClient({ apiKey }), then call typed methods like linear.issues({ filter: ... })

Intro

The Linear SDK is the official TypeScript client wrapping Linear's GraphQL API. Every method is fully typed (Issue, Project, Cycle, Team, User), with built-in pagination and rate-limit handling. Best for: agents and bots that automate Linear beyond what MCP covers — bulk imports, complex queries, scheduled triage. Works with: Node 18+, Bun, Deno. Setup time: 2 minutes.


Hello, Linear

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

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

// Get my issues
const me = await linear.viewer;
const issues = await me.assignedIssues({ first: 50 });

for (const issue of issues.nodes) {
  console.log(`${issue.identifier}${issue.title} (${(await issue.state).name})`);
}

Create an issue with all the trimmings

const team = await linear.team("ENG");

const issue = await linear.createIssue({
  teamId: team.id,
  title: "Auth flow drops state on redirect",
  description: "**Steps to reproduce:**\n1. Login\n2. Click external link\n3. Click back\n\nState lost.",
  priority: 1,  // Urgent
  assigneeId: (await linear.viewer).id,
  labelIds: [
    (await team.labels()).nodes.find(l => l.name === "bug")?.id!,
  ],
  projectId: "your-project-id",
});

console.log(`Created ${issue.issue?.identifier}`);

Bulk triage with rate-limit awareness

import pLimit from "p-limit";

const limit = pLimit(5);  // 5 concurrent calls; SDK auto-retries on 429

const stale = await linear.issues({
  filter: {
    state: { type: { eq: "started" } },
    updatedAt: { lt: new Date(Date.now() - 14 * 86400_000) },
  },
});

await Promise.all(
  stale.nodes.map(issue =>
    limit(() =>
      issue.update({
        labelIds: [...issue.labelIds, STALE_LABEL_ID],
      }),
    ),
  ),
);

Webhook payloads (in tandem with SDK)

// Express handler
app.post("/webhooks/linear", async (req, res) => {
  if (req.body.action === "create" && req.body.type === "Issue") {
    const issue = await linear.issue(req.body.data.id);
    if ((await issue.priority) === 1) {
      await notifySlack(`🔥 Urgent issue: ${issue.title}`);
    }
  }
  res.sendStatus(200);
});

FAQ

Q: SDK vs MCP — when to use which? A: MCP for interactive agents (Claude Code asks Linear questions during a session). SDK for scheduled or webhook-driven automation (Inngest jobs, GitHub Actions, server-side bots). Many teams use both.

Q: Is the SDK rate-limit-aware? A: Yes — built-in retry with exponential backoff on 429s. For high-throughput jobs, combine with p-limit (concurrency cap) and persist progress so you can resume.

Q: Does it support Linear's GraphQL directly? A: Yes — every typed SDK method is just a wrapper over GraphQL. For queries the SDK doesn't expose, use linear.client.rawRequest(query, variables) to send arbitrary GraphQL.


Source & Thanks

Built by Linear. MIT-licensed.

linear/linear-sdk — ⭐ Active

🙏

Source & Thanks

Built by Linear. MIT-licensed.

linear/linear-sdk — ⭐ Active

Discussion

Sign in to join the discussion.
No comments yet. Be the first to share your thoughts.

Related Assets