linear-install-auth
Set up authentication for the Linear SDK using personal API keys or OAuth 2.0.
Install
mkdir -p .claude/skills/linear-install-auth && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/5480" && unzip -o skill.zip -d .claude/skills/linear-install-auth && rm skill.zipInstalls to .claude/skills/linear-install-auth
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Install and configure Linear SDK/CLI authentication.Key capabilities
- →Install Linear TypeScript SDK
- →Configure personal API key authentication
- →Implement OAuth 2.0 authorization code flow
- →Handle OAuth token refresh
- →Validate API key format on startup
How it works
The skill configures the LinearClient using either a personal API key for server-side scripts or an OAuth 2.0 flow with PKCE for user-facing applications.
Inputs & outputs
When to use linear-install-auth
- →Initialize LinearClient in a project
- →Configure personal API keys for server scripts
- →Set up OAuth 2.0 authentication for apps
About this skill
Linear Install & Auth
Overview
Install the @linear/sdk TypeScript SDK and configure authentication for the Linear GraphQL API at https://api.linear.app/graphql. Supports personal API keys for scripts and OAuth 2.0 (with PKCE) for user-facing apps.
Prerequisites
- Node.js 18+ (SDK is TypeScript-first, works in any JS environment)
- Package manager (npm, pnpm, or yarn)
- Linear account with workspace access
- For API key: Settings > Account > API > Personal API keys
- For OAuth: Create app at Settings > Account > API > OAuth applications
Instructions
Step 1: Install the SDK
set -euo pipefail
npm install @linear/sdk
# or: pnpm add @linear/sdk
# or: yarn add @linear/sdk
The SDK exposes LinearClient, typed models for every entity (Issue, Project, Cycle, Team), and error classes (LinearError, InvalidInputLinearError).
Step 2: API Key Authentication (Scripts & Server-Side)
Generate a Personal API key at Linear Settings > Account > API > Personal API keys. Keys start with lin_api_ and are shown only once.
import { LinearClient } from "@linear/sdk";
// Environment variable (recommended)
const client = new LinearClient({
apiKey: process.env.LINEAR_API_KEY,
});
// Verify connection
const me = await client.viewer;
console.log(`Authenticated as: ${me.name} (${me.email})`);
Environment setup:
# .env (never commit)
LINEAR_API_KEY=lin_api_xxxxxxxxxxxxxxxxxxxxxxxxxxxx
# .gitignore
echo '.env' >> .gitignore
Step 3: OAuth 2.0 Authentication (User-Facing Apps)
Linear supports the standard Authorization Code flow with optional PKCE. As of October 2025, newly created OAuth apps issue refresh tokens by default.
import crypto from "crypto";
// 1. Build authorization URL
const SCOPES = ["read", "write", "issues:create"];
const state = crypto.randomBytes(16).toString("hex");
const authUrl = new URL("https://linear.app/oauth/authorize");
authUrl.searchParams.set("client_id", process.env.LINEAR_CLIENT_ID!);
authUrl.searchParams.set("redirect_uri", process.env.LINEAR_REDIRECT_URI!);
authUrl.searchParams.set("response_type", "code");
authUrl.searchParams.set("scope", SCOPES.join(","));
authUrl.searchParams.set("state", state);
// Optional PKCE:
// authUrl.searchParams.set("code_challenge", challenge);
// authUrl.searchParams.set("code_challenge_method", "S256");
// 2. Exchange authorization code for tokens
const tokenResponse = await fetch("https://api.linear.app/oauth/token", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "authorization_code",
code: authorizationCode,
client_id: process.env.LINEAR_CLIENT_ID!,
client_secret: process.env.LINEAR_CLIENT_SECRET!,
redirect_uri: process.env.LINEAR_REDIRECT_URI!,
}),
});
const { access_token, refresh_token, expires_in } = await tokenResponse.json();
// 3. Create client with OAuth token
const client = new LinearClient({ accessToken: access_token });
Available OAuth scopes: read, write, issues:create, admin, initiative:read, initiative:write, customer:read, customer:write.
Step 4: Token Refresh (OAuth)
async function refreshAccessToken(refreshToken: string): Promise<string> {
const response = await fetch("https://api.linear.app/oauth/token", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "refresh_token",
refresh_token: refreshToken,
client_id: process.env.LINEAR_CLIENT_ID!,
client_secret: process.env.LINEAR_CLIENT_SECRET!,
}),
});
if (!response.ok) {
throw new Error(`Token refresh failed: ${response.status}`);
}
const tokens = await response.json();
// Store new refresh_token — Linear rotates it on each refresh
await saveTokens(tokens.access_token, tokens.refresh_token);
return tokens.access_token;
}
Step 5: Validate Configuration on Startup
function validateLinearConfig(): void {
const key = process.env.LINEAR_API_KEY;
if (!key) throw new Error("LINEAR_API_KEY environment variable is required");
if (!key.startsWith("lin_api_")) throw new Error("LINEAR_API_KEY must start with lin_api_");
if (key.length < 30) throw new Error("LINEAR_API_KEY appears truncated");
}
// Call before creating client
validateLinearConfig();
Error Handling
| Error | Cause | Solution |
|---|---|---|
Authentication required | Invalid, expired, or missing API key | Regenerate at Settings > Account > API |
Invalid API key format | Key doesn't start with lin_api_ | Copy full key from Linear (shown once) |
Forbidden | Token lacks required OAuth scope | Re-authorize with correct scopes |
invalid_grant on token exchange | Code expired or PKCE verifier mismatch | Restart OAuth flow; codes expire quickly |
Module not found: @linear/sdk | SDK not installed | Run npm install @linear/sdk |
ENOTFOUND api.linear.app | DNS/firewall issue | Ensure outbound HTTPS to api.linear.app |
Examples
Raw GraphQL Without SDK
const response = await fetch("https://api.linear.app/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": process.env.LINEAR_API_KEY!,
},
body: JSON.stringify({
query: `{ viewer { id name email } }`,
}),
});
const { data, errors } = await response.json();
if (errors) console.error("GraphQL errors:", errors);
else console.log("Viewer:", data.viewer);
Server-to-Server (Client Credentials)
// For apps without user interaction — uses client_credentials grant
const response = await fetch("https://api.linear.app/oauth/token", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: new URLSearchParams({
grant_type: "client_credentials",
client_id: process.env.LINEAR_CLIENT_ID!,
client_secret: process.env.LINEAR_CLIENT_SECRET!,
scope: "read,write",
}),
});
const { access_token } = await response.json();
const client = new LinearClient({ accessToken: access_token });
Resources
When not to use it
- →When using non-Node.js environments
- →When bypassing standard authentication flows
Prerequisites
Limitations
- →API keys must start with lin_api_
- →OAuth refresh tokens rotate on each refresh
How it compares
This workflow automates the setup of typed client instances and provides specific validation logic for API keys compared to manual configuration.
Compared to similar skills
linear-install-auth side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| linear-install-auth (this skill) | 1 | 27d | Review | Intermediate |
| supabase-developer | 95 | 7mo | Review | Intermediate |
| better-auth-best-practices | 18 | 6mo | No flags | Intermediate |
| cloudbase-auth | 1 | 8mo | No flags | Intermediate |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by jeremylongshore
View all by jeremylongshore →You might also like
supabase-developer
daffy0208
Build full-stack applications with Supabase (PostgreSQL, Auth, Storage, Real-time, Edge Functions). Use when implementing authentication, database design with RLS, file storage, real-time features, or serverless functions.
better-auth-best-practices
novuhq
Skill for integrating Better Auth - the comprehensive TypeScript authentication framework.
cloudbase-auth
TencentCloudBase
A single skill that helps design and implement CloudBase Auth v2 using Web SDK, Node SDK, and HTTP APIs, including login methods, tokens, and best practices.
firebase-vertex-ai
jeremylongshore
Execute firebase platform expert with Vertex AI Gemini integration for Authentication, Firestore, Storage, Functions, Hosting, and AI-powered features. Use when asked to "setup firebase", "deploy to firebase", or "integrate vertex ai with firebase". Trigger with relevant phrases based on skill purpose.
jwt-auth
dadbodgeoff
Implement secure JWT authentication with refresh token rotation, secure storage, and automatic renewal. Use when building authentication for SPAs, mobile apps, or APIs that need stateless auth with refresh capabilities.
documenso-install-auth
jeremylongshore
Install and configure Documenso SDK/API authentication. Use when setting up a new Documenso integration, configuring API keys, or initializing Documenso in your project. Trigger with phrases like "install documenso", "setup documenso", "documenso auth", "configure documenso API key".