From linear-pack
Provides runbooks for Linear integration incidents: severity classification, curl checks for status/auth/rate limits, TypeScript SDK diagnostics for outages and errors.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin linear-packThis skill is limited to using the following tools:
Step-by-step runbooks for handling production incidents with Linear integrations. Covers API authentication failures, rate limiting, webhook issues, and Linear platform outages.
Provides production readiness checklist for Linear integrations, covering authentication, error handling, rate limits, monitoring, observability, and data handling for deployments.
Troubleshoots Linear MCP integration with fixes for OAuth failures, unauthorized access, token expiration, and setup via /mcp commands.
Triages production incidents by severity (P1-P3), contains blast radius via rollback or strategies, root-causes issues, documents timeline, generates postmortems. Triggers on outages, errors, or 'incident' mentions.
Share bugs, ideas, or general feedback.
Step-by-step runbooks for handling production incidents with Linear integrations. Covers API authentication failures, rate limiting, webhook issues, and Linear platform outages.
| Severity | Impact | Response | Examples |
|---|---|---|---|
| SEV1 | Complete integration outage | < 15 min | Auth broken, API unreachable |
| SEV2 | Major degradation | < 30 min | High error rate, rate limited |
| SEV3 | Minor issues | < 2 hours | Some features affected |
| SEV4 | Low impact | < 24 hours | Warnings, non-critical |
set -euo pipefail
# 1. Check Linear platform status
curl -s https://status.linear.app/api/v2/status.json | jq '.status'
# 2. Test your API key
curl -s -X POST https://api.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "{ viewer { name email } }"}' | jq .
# 3. Check rate limit status
curl -s -I -X POST https://api.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "{ viewer { id } }"}' 2>&1 | grep -i ratelimit
# 4. Check your app health endpoint
curl -s https://yourapp.com/health/linear | jq .
// scripts/incident-diagnostic.ts
import { LinearClient } from "@linear/sdk";
async function diagnose() {
console.log("=== Linear Incident Diagnostic ===\n");
// 1. Auth check
console.log("1. Authentication:");
try {
const client = new LinearClient({ apiKey: process.env.LINEAR_API_KEY! });
const viewer = await client.viewer;
console.log(` OK: ${viewer.name} (${viewer.email})`);
} catch (error: any) {
console.log(` FAILED: ${error.message}`);
}
// 2. Team access
console.log("\n2. Team Access:");
try {
const client = new LinearClient({ apiKey: process.env.LINEAR_API_KEY! });
const teams = await client.teams();
console.log(` OK: ${teams.nodes.length} teams accessible`);
teams.nodes.forEach(t => console.log(` ${t.key}: ${t.name}`));
} catch (error: any) {
console.log(` FAILED: ${error.message}`);
}
// 3. Write test
console.log("\n3. Write Capability:");
try {
const client = new LinearClient({ apiKey: process.env.LINEAR_API_KEY! });
const teams = await client.teams();
const result = await client.createIssue({
teamId: teams.nodes[0].id,
title: "[INCIDENT-DIAG] Safe to delete",
});
if (result.success) {
const issue = await result.issue;
await issue?.delete();
console.log(" OK: Created and deleted test issue");
}
} catch (error: any) {
console.log(` FAILED: ${error.message}`);
}
// 4. Rate limit check
console.log("\n4. Rate Limits:");
try {
const resp = await fetch("https://api.linear.app/graphql", {
method: "POST",
headers: {
Authorization: process.env.LINEAR_API_KEY!,
"Content-Type": "application/json",
},
body: JSON.stringify({ query: "{ viewer { id } }" }),
});
const remaining = resp.headers.get("x-ratelimit-requests-remaining");
const limit = resp.headers.get("x-ratelimit-requests-limit");
console.log(` Requests: ${remaining}/${limit}`);
} catch (error: any) {
console.log(` FAILED: ${error.message}`);
}
console.log("\n=== End Diagnostic ===");
}
diagnose();
Symptoms: All API calls returning 401/403, "Authentication required" errors
Diagnosis:
set -euo pipefail
# Verify API key format
echo $LINEAR_API_KEY | head -c 8
# Should output: lin_api_
# Test directly
curl -s -X POST https://api.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "{ viewer { id } }"}' | jq .errors
Resolution:
[ -n "$LINEAR_API_KEY" ] && echo "Set" || echo "NOT set"git revert HEAD && npm run deploySymptoms: HTTP 429 responses, "Rate limit exceeded", degraded performance
Diagnosis:
set -euo pipefail
curl -s -I -X POST https://api.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "{ viewer { id } }"}' 2>&1 | grep -i ratelimit
Resolution:
const EMERGENCY_DELAY_MS = 5000;
async function emergencyThrottle<T>(fn: () => Promise<T>): Promise<T> {
await new Promise(r => setTimeout(r, EMERGENCY_DELAY_MS));
return fn();
}
Symptoms: Events not received, signature validation errors, processing timeouts
Diagnosis:
set -euo pipefail
# Check endpoint is reachable
curl -s -o /dev/null -w "%{http_code}" https://yourapp.com/webhooks/linear
# Verify secret length
echo -n "$LINEAR_WEBHOOK_SECRET" | wc -c
# Should be > 20 characters
Resolution:
LINEAR_WEBHOOK_SECRET matches webhook config in Linear Settings > API > Webhooksexpress.raw() not express.json()Symptoms: All API calls failing, status.linear.app reports issues
Resolution:
INCIDENT: Linear Integration Issue
Severity: SEVX
Status: Investigating
Impact: [description]
Start: [UTC timestamp]
Investigating issues with Linear integration. Updates to follow.
RESOLVED: Linear Integration Issue
Duration: X hours Y minutes
Root Cause: [brief]
Impact: [what was affected]
Post-mortem within 48 hours.
[ ] All systems verified healthy
[ ] Stuck/queued jobs cleared
[ ] Data consistency validated
[ ] Stakeholders notified of resolution
[ ] Timeline documented
[ ] Root cause identified
[ ] Action items assigned
[ ] Monitoring gaps addressed
| Issue | Cause | Solution |
|---|---|---|
| Auth failure | Expired/rotated key | Regenerate and update secret manager |
| Rate limit | Budget exceeded | Emergency throttle, stop background jobs |
| Webhook failure | Secret mismatch or endpoint down | Verify secret, check endpoint health |
| Platform outage | Linear infrastructure issue | Graceful degradation, serve cached data |