From linear-pack
Upgrade Linear SDK versions and handle breaking changes safely. Use when updating to a new SDK version, handling deprecations, or migrating between API versions. Trigger: "upgrade linear SDK", "linear SDK migration", "update linear", "linear breaking changes", "linear deprecation".
npx claudepluginhub flight505/skill-forge --plugin linear-packThis skill is limited to using the following tools:
Safely upgrade `@linear/sdk` versions with zero downtime. The SDK is auto-generated from Linear's GraphQL schema -- major versions can rename fields, change return types, add required parameters, or remove deprecated methods. This skill covers version checking, upgrade procedure, compatibility layers, and rollback.
Guides Next.js Cache Components and Partial Prerendering (PPR): 'use cache' directives, cacheLife(), cacheTag(), revalidateTag() for caching, invalidation, static/dynamic optimization. Auto-activates on cacheComponents: true.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Share bugs, ideas, or general feedback.
Safely upgrade @linear/sdk versions with zero downtime. The SDK is auto-generated from Linear's GraphQL schema -- major versions can rename fields, change return types, add required parameters, or remove deprecated methods. This skill covers version checking, upgrade procedure, compatibility layers, and rollback.
set -euo pipefail
# Current installed version
npm list @linear/sdk 2>/dev/null || echo "Not installed"
# Latest available
npm view @linear/sdk version
# All recent versions
npm view @linear/sdk versions --json | jq '.[-10:]'
set -euo pipefail
# View SDK changelog on GitHub
npm view @linear/sdk repository.url
# Then check: https://github.com/linear/linear/blob/master/packages/sdk/CHANGELOG.md
# Also review Linear's API changelog:
# https://linear.app/changelog (filter for API/developer updates)
Common breaking changes between major versions:
issue.state property vs lazy relationset -euo pipefail
git checkout -b upgrade/linear-sdk-$(npm view @linear/sdk version)
npm install @linear/sdk@latest
# Immediately check for type errors
npx tsc --noEmit 2>&1 | head -50
// src/linear-compat.ts
// Bridge pattern for gradual migration across SDK versions
import { LinearClient } from "@linear/sdk";
/**
* Normalize issue state access across SDK versions.
* SDK v2: issue.state was a direct string property
* SDK v3+: issue.state is a lazy-loaded WorkflowState relation
*/
export async function getIssueStateName(issue: any): Promise<string> {
if (typeof issue.state === "string") return issue.state;
const state = await issue.state;
return state?.name ?? "unknown";
}
export async function getIssueStateType(issue: any): Promise<string> {
if (typeof issue.stateType === "string") return issue.stateType;
const state = await issue.state;
return state?.type ?? "unknown";
}
/**
* Normalize team access — some versions changed from direct to paginated.
*/
export async function getTeamByKey(client: LinearClient, key: string) {
const teams = await client.teams({ filter: { key: { eq: key } } });
return teams.nodes[0];
}
/**
* Normalize issue creation return — handle both success shapes.
*/
export async function createIssue(
client: LinearClient,
input: { teamId: string; title: string; [key: string]: any }
) {
const result = await client.createIssue(input);
// Some versions return { success, issue } others return directly
if ("success" in result) {
return { success: result.success, issue: await result.issue };
}
return { success: true, issue: result };
}
set -euo pipefail
# Type-check
npx tsc --noEmit
# Run unit tests
npm test
# Run integration tests (if API key available)
npm run test:integration 2>&1 || true
# Lint
npm run lint 2>&1 || true
Common fixes:
// Fix: Property 'x' does not exist
// Old: issue.statusName
// New: (await issue.state)?.name
// Fix: Type 'X' is not assignable to type 'Y'
// Old: const states: string[] = team.states
// New: const states = await team.states()
// Fix: Expected 2 arguments but got 1
// Check if mutation added required parameter
// Old: client.updateIssue(id, { title: "new" })
// New: client.updateIssue(id, { title: "new" }) // usually same
set -euo pipefail
# Deploy to staging
npm run build
npm run deploy:staging
# Run integration tests against staging
LINEAR_API_KEY=$STAGING_LINEAR_API_KEY npm run test:integration
# Check health endpoint
curl -s https://staging.yourapp.com/health/linear | jq .
set -euo pipefail
# Commit upgrade
git add package.json package-lock.json src/linear-compat.ts
git commit -m "chore: upgrade @linear/sdk to $(npm list @linear/sdk --json | jq -r '.dependencies["@linear/sdk"].version')"
git push origin upgrade/linear-sdk-*
# If something breaks in production:
git revert HEAD
npm install # Restores previous version
npm run deploy
| SDK Range | Node.js | TypeScript | Notable Changes |
|---|---|---|---|
| 1.x | 14+ | 4.5+ | Initial release, callback-style |
| 2.x-16.x | 16+ | 4.7+ | ESM support, typed models |
| 17.x-28.x | 18+ | 5.0+ | Strict types, new entity models |
| Latest | 18+ | 5.0+ | Refresh tokens, initiatives, agents |
| Error | Cause | Solution |
|---|---|---|
Property does not exist | Renamed field | Check changelog, update field name |
Type is not assignable | Changed return type | Update type annotations |
Module not found | ESM/CJS mismatch | Update import syntax or tsconfig |
Cannot find name | Removed export | Replace with new API equivalent |
| Tests pass, prod fails | SDK version mismatch in lockfile | Delete node_modules, npm ci |
// scripts/audit-linear-usage.ts
// Run before upgrading to find all SDK touchpoints
import { readFileSync } from "fs";
import { globSync } from "glob";
const files = globSync("src/**/*.ts");
const patterns = [
/LinearClient/g,
/client\.issues/g,
/client\.createIssue/g,
/client\.updateIssue/g,
/\.state\b/g,
/\.assignee\b/g,
/rawRequest/g,
];
for (const file of files) {
const content = readFileSync(file, "utf-8");
for (const pattern of patterns) {
const matches = content.match(pattern);
if (matches) {
console.log(`${file}: ${pattern.source} (${matches.length} occurrences)`);
}
}
}