Claude-code-plugins-plus-skills linear-hello-world
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/linear-pack/skills/linear-hello-world" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-skills-linear-hello-world && rm -rf "$T"
manifest:
plugins/saas-packs/linear-pack/skills/linear-hello-world/SKILL.mdsource content
Linear Hello World
Overview
Create your first issue, query teams, and explore the Linear data model using the
@linear/sdk. Linear's API is GraphQL-based -- the SDK wraps it with typed models, lazy-loaded relations, and pagination helpers.
Prerequisites
installed (@linear/sdk
)npm install @linear/sdk
environment variable set (starts withLINEAR_API_KEY
)lin_api_- Access to at least one Linear team
Instructions
Step 1: Connect and Identify
import { LinearClient } from "@linear/sdk"; const client = new LinearClient({ apiKey: process.env.LINEAR_API_KEY! }); // Get current authenticated user const me = await client.viewer; console.log(`Hello, ${me.name}! (${me.email})`); // Get your organization const org = await me.organization; console.log(`Workspace: ${org.name}`);
Step 2: List Teams
Every issue in Linear belongs to a team. Teams have a short key (e.g., "ENG") used in identifiers like
ENG-123.
const teams = await client.teams(); console.log("Your teams:"); for (const team of teams.nodes) { console.log(` ${team.key} — ${team.name} (${team.id})`); }
Step 3: Create Your First Issue
const team = teams.nodes[0]; const result = await client.createIssue({ teamId: team.id, title: "Hello from Linear SDK!", description: "This issue was created using the `@linear/sdk` TypeScript SDK.", priority: 3, // 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}`); }
Step 4: Query Issues
// Get recent issues from a team const issues = await client.issues({ filter: { team: { key: { eq: team.key } }, state: { type: { nin: ["completed", "canceled"] } }, }, first: 10, }); console.log(`\nOpen issues in ${team.key}:`); for (const issue of issues.nodes) { const state = await issue.state; console.log(` ${issue.identifier}: ${issue.title} [${state?.name}]`); }
Step 5: Explore Workflow States
Each team has customizable workflow states organized by type:
triage, backlog, unstarted, started, completed, canceled.
const states = await team.states(); console.log(`\nWorkflow states for ${team.key}:`); for (const state of states.nodes) { console.log(` ${state.name} (type: ${state.type}, position: ${state.position})`); }
Step 6: Fetch a Single Issue by Identifier
// Search for a specific issue by its human-readable identifier const searchResults = await client.issueSearch("ENG-1"); const found = searchResults.nodes[0]; if (found) { console.log(`\nFound: ${found.identifier}`); console.log(` Title: ${found.title}`); console.log(` Priority: ${found.priority}`); console.log(` Created: ${found.createdAt}`); const assignee = await found.assignee; console.log(` Assignee: ${assignee?.name ?? "Unassigned"}`); }
Step 7: Raw GraphQL Query
The SDK exposes the underlying GraphQL client for custom queries.
const response = await client.client.rawRequest(` query TeamDashboard($teamKey: String!) { teams(filter: { key: { eq: $teamKey } }) { nodes { name key issues(first: 5, orderBy: updatedAt) { nodes { identifier title priority state { name type } assignee { name } } } } } } `, { teamKey: "ENG" }); console.log(JSON.stringify(response.data, null, 2));
Error Handling
| Error | Cause | Solution |
|---|---|---|
| Invalid API key | Regenerate at Settings > Account > API |
| Invalid ID or no access | Use first to get valid IDs |
| Missing required field | and are required for |
| Accessing nullable relation | Use optional chaining: |
Examples
Complete Hello World Script
import { LinearClient } from "@linear/sdk"; async function main() { const client = new LinearClient({ apiKey: process.env.LINEAR_API_KEY! }); const me = await client.viewer; console.log(`Connected as ${me.name}\n`); const teams = await client.teams(); const team = teams.nodes[0]; // Create issue const result = await client.createIssue({ teamId: team.id, title: "Hello from Linear SDK!", description: "Testing the API integration.", priority: 3, }); if (result.success) { const issue = await result.issue; console.log(`Created: ${issue?.identifier} — ${issue?.url}`); // Read it back const fetched = await client.issue(issue!.id); console.log(`Verified: ${fetched.title}`); // Clean up await fetched.delete(); console.log("Deleted test issue."); } } main().catch(console.error);