| name | linear |
| description | Managing Linear issues, projects, and teams. Use when working with Linear tasks, creating issues, updating status, querying projects, or managing team workflows. |
| allowed-tools | ["mcp__linear","mcp__linear-server","WebFetch(domain:linear.app)","Bash"] |
Linear
Tools and workflows for managing issues, projects, and teams in Linear.
⚠️ Tool Availability (READ FIRST)
This skill supports multiple tool backends. Use whichever is available:
- MCP Tools (
mcp__linear-server__* or mcp__linear__*, depending on the configured server name) - Use if available in your tool set
- Linear CLI (
linear command) - Always available via Bash
- Helper Scripts - For complex operations
If MCP tools are NOT available, use the Linear CLI via Bash:
linear issues view ENG-123
linear issues create --title "Issue title" --description "Description"
linear issues update ENG-123 -s "STATE_ID"
linear issues comment add ENG-123 -m "Comment text"
linear issues list
Do NOT report "MCP tools not available" as a blocker - use CLI instead.
🔐 Security: Varlock Integration
CRITICAL: Never expose API keys in terminal output or Claude's context.
Safe Commands (Always Use)
varlock load 2>&1 | grep LINEAR
varlock run -- npx tsx scripts/query.ts "query { viewer { name } }"
cat .env.schema | grep LINEAR
Unsafe Commands (NEVER Use)
linear config show
echo $LINEAR_API_KEY
printenv | grep LINEAR
cat .env
Setup for New Projects
-
Create .env.schema with @sensitive annotation:
LINEAR_API_KEY=
-
Add LINEAR_API_KEY to .env (never commit this file)
-
Note: the official MCP server authenticates via OAuth and does not read LINEAR_API_KEY — the key is only used by this skill's SDK/GraphQL scripts (scripts/query.ts, scripts/linear-ops.ts)
-
Use varlock load to validate before operations
Quick Start (First-Time Users)
1. Check Your Setup
Run the setup check to verify your configuration:
npx tsx scripts/setup.ts
This will check:
- LINEAR_API_KEY is set and valid
- @linear/sdk is installed
- Linear CLI availability (optional)
- MCP configuration (optional)
2. Get API Key (If Needed)
If setup reports a missing API key:
- Open Linear in your browser
- Go to Settings (gear icon) -> Security & access -> Personal API keys
- Click Create key and copy the key (starts with
lin_api_)
- Add to your environment:
export LINEAR_API_KEY="lin_api_your_key_here"
echo 'LINEAR_API_KEY=lin_api_your_key_here' >> ~/.claude/.env
3. Test Connection
Verify everything works:
npx tsx scripts/query.ts "query { viewer { name } }"
You should see your name from Linear.
4. Common Operations
npx tsx scripts/linear-ops.ts create-issue "Project" "Title" "Description"
npx tsx scripts/linear-ops.ts status Done ENG-123 ENG-124
npx tsx scripts/linear-ops.ts create-sub-issue ENG-100 "Sub-task" "Details"
npx tsx scripts/linear-ops.ts project-status "Phase 1" completed
npx tsx scripts/linear-ops.ts help
See Project Management Commands for full reference.
Project Planning Workflow
Create Issues in the Correct Project from the Start
Best Practice: When planning a new phase or initiative, create the project and its issues together in a single planning session. Avoid creating issues in a catch-all project and moving them later.
Recommended Workflow
-
Create the project first (pass --team in multi-team workspaces — the default is the workspace's first team):
npx tsx scripts/linear-ops.ts create-project "Phase X: Feature Name" "My Initiative" --team ENG
-
Set project state to Planned:
npx tsx scripts/linear-ops.ts project-status "Phase X: Feature Name" planned
-
Create issues directly in the project:
npx tsx scripts/linear-ops.ts create-issue "Phase X: Feature Name" "Parent task" "Description"
npx tsx scripts/linear-ops.ts create-sub-issue ENG-XXX "Sub-task 1" "Description"
npx tsx scripts/linear-ops.ts create-sub-issue ENG-XXX "Sub-task 2" "Description"
-
Update project state when work begins:
npx tsx scripts/linear-ops.ts project-status "Phase X: Feature Name" in-progress
Why This Matters
- Traceability: Issues are linked to their project from creation
- Metrics: Project progress tracking is accurate from day one
- Workflow: No time wasted moving issues between projects
- Organization: Linear views and filters work correctly
Anti-Pattern to Avoid
❌ Creating issues in a "holding" project and moving them later:
create-issue "Phase 6A" "New feature"
Project Management Commands
project-status
Update a project's state in Linear. Accepts user-friendly terminology that maps to Linear's API.
npx tsx scripts/linear-ops.ts project-status <project-name> <state>
Valid States:
| Input | Description | API Value |
|---|
backlog | Not yet started | backlog |
planned | Scheduled for future | planned |
in-progress | Currently active | started |
paused | Temporarily on hold | paused |
completed | Successfully finished | completed |
canceled | Will not be done | canceled |
Examples:
npx tsx scripts/linear-ops.ts project-status "Phase 8: MCP Decision Engine" in-progress
npx tsx scripts/linear-ops.ts project-status "Phase 8" completed
npx tsx scripts/linear-ops.ts project-status "Phase 8" paused
link-initiative
Link an existing project to an initiative.
npx tsx scripts/linear-ops.ts link-initiative <project-name> <initiative-name>
Examples:
npx tsx scripts/linear-ops.ts link-initiative "Phase 8: MCP Decision Engine" "Q1 Goals"
npx tsx scripts/linear-ops.ts link-initiative "Phase 8" "Q1 Goals"
unlink-initiative
Remove a project from an initiative.
npx tsx scripts/linear-ops.ts unlink-initiative <project-name> <initiative-name>
Examples:
npx tsx scripts/linear-ops.ts unlink-initiative "Phase 8" "Linear Skill"
npx tsx scripts/linear-ops.ts unlink-initiative "Test Project" "Q1 Goals"
Error Handling:
- Returns error if project is not linked to the specified initiative
- Returns error if project or initiative not found
Complete Project Lifecycle Example
npx tsx scripts/linear-ops.ts create-project "Phase 11: New Feature" "Q1 Goals"
npx tsx scripts/linear-ops.ts project-status "Phase 11" planned
npx tsx scripts/linear-ops.ts create-issue "Phase 11" "Parent task" "Description"
npx tsx scripts/linear-ops.ts create-sub-issue ENG-XXX "Sub-task 1" "Details"
npx tsx scripts/linear-ops.ts project-status "Phase 11" in-progress
npx tsx scripts/linear-ops.ts status Done ENG-XXX ENG-YYY
npx tsx scripts/linear-ops.ts project-status "Phase 11" completed
npx tsx scripts/linear-ops.ts link-initiative "Phase 11" "Q2 Goals"
Tool Selection
Three tiers, in order. Reach for the lowest tier that fits:
| Tier | Tool | When to Use |
|---|
| 1 | MCP tools (official server) | Interactive, one-off operations in conversation — view/create/update a single issue, quick searches. The interactive default. |
| 2 | SDK scripts (npx tsx + @linear/sdk) | The programmatic default: bulk, scripted, multi-step, conditional, or repeatable work — anything the API supports, fully typed. See sdk.md. |
| 3 | Raw GraphQL via the SDK's client.client.rawRequest | Rare escape hatch only. The SDK is generated from the same GraphQL schema, so "not supported by the SDK" is almost never true. |
The bundled scripts (scripts/linear-ops.ts, scripts/sync.ts, etc.) are Tier-2 SDK scripts — use them, or write your own, for anything beyond a single interactive action. scripts/query.ts is the Tier-3 CLI for ad-hoc raw GraphQL.
MCP Server Configuration
Use the official Linear MCP server at mcp.linear.app over native HTTP transport:
claude mcp add --transport http --scope user linear-server https://mcp.linear.app/mcp
Or in .mcp.json:
{
"mcpServers": {
"linear-server": {
"type": "http",
"url": "https://mcp.linear.app/mcp"
}
}
}
The server authenticates via OAuth — run /mcp, pick the server, and log in through the browser. LINEAR_API_KEY is not used by the MCP connection; it is only needed for this skill's SDK/GraphQL scripts.
WARNING: The old /sse endpoint and the npx mcp-remote https://mcp.linear.app/sse shim are deprecated — OAuth against /sse now fails with "Protected resource https://mcp.linear.app/mcp does not match expected ...". Do NOT use deprecated community servers either. See troubleshooting.md for details.
MCP Reliability (Official Server)
| Operation | Reliability | Notes |
|---|
| Create issue | ✅ High | Full support |
| Update status | ✅ High | Use state: "Done" directly |
| List/Search issues | ✅ High | Supports filters, queries |
| Add comment | ✅ High | Works with issue IDs |
Quick Status Update
save_issue with id="issue-uuid", state="Done"
npx tsx scripts/linear-ops.ts status Done ENG-123 ENG-124
Helper Script Reference
For detailed helper script usage, see troubleshooting.md.
Parallel Agent Execution
For bulk operations or background execution, use the Linear-specialist subagent:
Task({
description: "Update Linear issues",
prompt: "Mark ENG-101, ENG-102, ENG-103 as Done",
subagent_type: "Linear-specialist"
})
When to use Linear-specialist (parallel):
- Bulk status updates (3+ issues)
- Project status changes
- Creating multiple issues
- Sync operations after code changes
When to use direct execution:
- Single issue queries
- Viewing issue details
- Quick status checks
- Operations needing immediate results
See sync.md for parallel execution patterns.
Image Uploads
Step 1: Extract the image from conversation context
Images shared inline in Claude Code are not saved to disk automatically — they live as base64 in the session JSONL. Use the extraction script:
ls -t ~/.claude/projects/<project-path>/*.jsonl | head -1
npx tsx scripts/extract-image.ts <path-to-session.jsonl>
npx tsx scripts/extract-image.ts <path-to-session.jsonl> ~/Desktop
This saves images to /tmp/shared-image-0.png, /tmp/shared-image-1.png, etc.
Always verify the extracted image with the Read tool before uploading.
Step 2: Create the issue
npx tsx scripts/linear-ops.ts create-issue "Project Name" "Issue title" "Description"
Note: create-issue resolves the team from the target project, so it picks the right team automatically. If you still need manual control over the team, use a short SDK call instead of the helper — look up the project's team, then create the issue with an explicit teamId:
import { LinearClient } from '@linear/sdk'
const client = new LinearClient({ apiKey: process.env.LINEAR_API_KEY })
const projects = await client.projects({ filter: { name: { containsIgnoreCase: 'PROJECT NAME' } } })
const project = projects.nodes[0]
const teamId = (await project.teams()).nodes[0].id
await client.createIssue({ teamId, projectId: project.id, title: 'Issue title' })
Step 3: Upload the image and attach to the issue
npx tsx scripts/upload-image.ts /tmp/shared-image-0.png ENG-123 "Optional comment text"
The script will:
- Upload the file to Linear's S3 storage
- Post a comment on the issue with the image embedded as markdown
Supported formats: PNG, JPG/JPEG, GIF, WebP, SVG, PDF
Known pitfalls
| Problem | Cause | Fix |
|---|
create-issue picks wrong team | Need a non-default team in a multi-team workspace | Resolve the team from the project via SDK and pass an explicit teamId (see Step 2) |
upload-image.ts "Issue not found" | Issue was deleted before attaching | Ensure issue exists first |
| Image not found on disk | Shared inline, not as file | Extract from session JSONL (Step 1) |
Critical Requirements
Issues → Projects → Initiatives
Every issue MUST be attached to a project. Every project MUST be linked to an initiative.
| Entity | Must Link To | If Missing |
|---|
| Issue | Project | Not visible in project board |
| Project | Initiative | Not visible in roadmap |
See projects.md for complete project creation checklist.
Conventions
Issue Status
- Assigned to me: Set
state: "Todo"
- Unassigned: Set
state: "Backlog"
Labels
Uses domain-based label taxonomy. See docs/labels.md.
Key rules:
- ONE Type label:
feature, bug, refactor, chore, spike
- 1-2 Domain labels:
security, backend, frontend, etc.
- Scope labels when applicable:
blocked, breaking-change, tech-debt
npx tsx scripts/linear-ops.ts labels validate "feature,security"
npx tsx scripts/linear-ops.ts labels suggest "Fix XSS vulnerability"
SDK Automation Scripts
The right tool for anything programmatic, bulk, or repeatable — use MCP for interactive single operations, and SDK scripts (npx tsx + @linear/sdk) for everything scripted. For loops, mapping, conditionals, or bulk updates, write TypeScript using @linear/sdk. See sdk.md for:
- Complete script patterns and templates
- Common automation examples (bulk updates, filtering, reporting)
- Tool selection criteria
Scripts provide full type hints and are easier to debug than raw GraphQL for multi-step operations.
GraphQL API
Fallback only — and not a separate toolchain. Raw GraphQL is reached through the SDK's client.client.rawRequest escape hatch, not a parallel set of tools. The bundled scripts/query.ts is exactly that: a thin CLI wrapper around rawRequest. Use it only for the rare query the typed SDK doesn't already cover.
See api.md for complete documentation including:
- Authentication and setup
- The
rawRequest escape hatch and example queries/mutations
- Timeout handling patterns
- Shell quoting compatibility
Quick ad-hoc query:
npx tsx scripts/query.ts "query { viewer { name } }"
Projects & Initiatives
For advanced project and initiative management patterns, see projects.md.
Quick reference - common project commands:
npx tsx scripts/linear-ops.ts create-project "Phase X: Name" "My Initiative" --team ENG
npx tsx scripts/linear-ops.ts project-status "Phase X" in-progress
npx tsx scripts/linear-ops.ts project-status "Phase X" completed
npx tsx scripts/linear-ops.ts link-initiative "Phase X" "My Initiative"
npx tsx scripts/linear-ops.ts unlink-initiative "Phase X" "Old Initiative"
Key topics in projects.md:
- Project creation checklist (mandatory steps)
- Content vs Description fields
- Discovery before creation
- Codebase verification before work
- Sub-issue management
- Project status updates
- Project updates (status reports)
Sync Patterns (Bulk Operations)
For bulk synchronization of code changes to Linear, see sync.md.
Quick sync commands:
npx tsx scripts/linear-ops.ts status Done ENG-101 ENG-102 ENG-103
npx tsx scripts/linear-ops.ts project-status "My Project" completed
Reference
External: Linear MCP Documentation