Quick Use
npm install @linear/sdk- Generate a personal API key in Linear → Settings → API
const linear = new LinearClient({ apiKey }), then call typed methods likelinear.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