Claude-skill-registry linear-subagent-guide
Guides optimal Linear operations usage with caching, performance patterns, and error handling. Auto-activates when implementing CCPM commands that interact with Linear. Prevents usage of non-existent Linear MCP tools.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/linear-subagent-guide" ~/.claude/skills/majiayu000-claude-skill-registry-linear-subagent-guide && rm -rf "$T"
skills/data/linear-subagent-guide/SKILL.mdLinear Subagent Guide
⛔ EXACT LINEAR MCP PARAMETERS (VERIFIED)
These are the EXACT parameter names from
. Copy exactly.get_server_tools
Most Common Operations
// GET ISSUE - uses "id" mcp__agent-mcp-gateway__execute_tool({ server: "linear", tool: "get_issue", args: { id: "WORK-26" } // ✅ CORRECT - "id" not "issueId" }) // UPDATE ISSUE - uses "id" mcp__agent-mcp-gateway__execute_tool({ server: "linear", tool: "update_issue", args: { id: "WORK-26", // ✅ CORRECT - "id" not "issueId" description: "...", state: "In Progress" } }) // CREATE COMMENT - uses "issueId" mcp__agent-mcp-gateway__execute_tool({ server: "linear", tool: "create_comment", args: { issueId: "WORK-26", // ✅ CORRECT - "issueId" for comments body: "Comment text" } }) // LIST COMMENTS - uses "issueId" mcp__agent-mcp-gateway__execute_tool({ server: "linear", tool: "list_comments", args: { issueId: "WORK-26" } // ✅ CORRECT })
Parameter Reference Table
| Tool | Required Parameter | Example Args |
|---|---|---|
| | |
| | |
| , | |
| | |
| , | |
| | |
| | |
| | |
Overview
The Linear subagent (
ccpm:linear-operations) is a dedicated MCP handler that optimizes all Linear API operations in CCPM. Rather than making direct Linear MCP calls, commands should delegate to this subagent, which provides:
- 50-60% token reduction (15k-25k → 8k-12k per workflow)
- Session-level caching with 85-95% hit rates
- Performance: <50ms for cached operations (vs 400-600ms direct)
- Structured error handling with actionable suggestions
- Centralized logic for Linear operations consistency
When to Use the Linear Subagent
Use the subagent for:
- Reading issues, projects, teams, statuses
- Creating or updating issues, projects
- Managing labels and comments
- Fetching documents and cycles
- Searching Linear documentation
Never use the subagent for:
- Local file operations
- Git commands
- External API calls (except Linear)
⚠️ CRITICAL: Parameter Name Gotcha
Different Linear MCP tools use different parameter names for issue IDs:
| Tool | Parameter | WRONG | CORRECT |
|---|---|---|---|
| | ❌ | ✅ |
| | ❌ | ✅ |
| | ❌ | ✅ |
| | ❌ | ✅ |
First-call failures are often caused by using
issueId instead of id for get_issue/update_issue.
Available Linear MCP Tools (Complete Reference)
Linear MCP provides 23 tools for interacting with Linear. This is the complete, validated list.
1. Comments (2 tools)
list_comments
list_commentsList comments for a specific Linear issue.
Parameters:
(string, required) - The issue IDissueId
Example:
mcp__linear__list_comments({ issueId: "PSN-41" })
create_comment
create_commentCreate a comment on a specific Linear issue.
Parameters:
(string, required) - The issue IDissueId
(string, required) - The content of the comment as Markdownbody
(string, optional) - A parent comment ID to reply toparentId
Linear's Native Collapsible Syntax: Use
+++ to create collapsible sections (starts collapsed, native Linear feature):
+++ Section Title Content here (multi-line markdown supported) +++
Example (simple):
mcp__linear__create_comment({ issueId: "PSN-41", body: "## Progress Update\n\nCompleted first phase." })
Example (with collapsible section):
mcp__linear__create_comment({ issueId: "PSN-41", body: `🔄 **Progress Update** Completed first phase, all tests passing +++ 📋 Detailed Context **Changed Files:** - src/auth.ts - src/tests/auth.test.ts **Next Steps:** - Implement phase 2 - Update documentation +++` })
2. Cycles (1 tool)
list_cycles
list_cyclesRetrieve cycles for a specific Linear team.
Parameters:
(string, required) - The team IDteamId
(string, optional) - "current", "previous", or "next"type
Example:
mcp__linear__list_cycles({ teamId: "team-123", type: "current" })
3. Documents (2 tools)
get_document
get_documentRetrieve a Linear document by ID or slug.
Parameters:
(string, required) - The document ID or slugid
Example:
mcp__linear__get_document({ id: "doc-abc-123" })
list_documents
list_documentsList documents in the user's Linear workspace.
Parameters:
(number, optional, max 250, default 50)limit
(string, optional) - An ID to end atbefore
(string, optional) - An ID to start fromafter
(string, optional) - "createdAt" or "updatedAt" (default: "updatedAt")orderBy
(string, optional) - Search queryquery
(string, optional) - Filter by project IDprojectId
(string, optional) - Filter by initiative IDinitiativeId
(string, optional) - Filter by creator IDcreatorId
(string, optional) - ISO-8601 date-time or duration (e.g., "-P1D")createdAt
(string, optional) - ISO-8601 date-time or durationupdatedAt
(boolean, optional, default false)includeArchived
Example:
mcp__linear__list_documents({ projectId: "proj-123", limit: 20 })
4. Issues (4 tools)
get_issue
get_issueRetrieve detailed information about an issue by ID.
Parameters:
(string, required) - The issue ID (e.g., "PSN-41")id
Example:
mcp__linear__get_issue({ id: "PSN-41" })
list_issues
list_issuesList issues in the user's Linear workspace. Use "me" for assignee to get your issues.
Parameters:
(number, optional, max 250, default 50)limit
(string, optional)before
(string, optional)after
(string, optional) - "createdAt" or "updatedAt"orderBy
(string, optional) - Search title or descriptionquery
(string, optional) - Team name or IDteam
(string, optional) - State name or IDstate
(string, optional) - Cycle name or IDcycle
(string, optional) - Label name or IDlabel
(string, optional) - User ID, name, email, or "me"assignee
(string, optional) - Agent name or IDdelegate
(string, optional) - Project name or IDproject
(string, optional) - Parent issue IDparentId
(string, optional) - ISO-8601 date-time or durationcreatedAt
(string, optional) - ISO-8601 date-time or durationupdatedAt
(boolean, optional, default true)includeArchived
Example:
mcp__linear__list_issues({ assignee: "me", state: "In Progress" })
create_issue
create_issueCreate a new Linear issue.
Parameters:
(string, required)title
(string, required) - Team name or IDteam
(string, optional) - Markdown descriptiondescription
(string, optional) - Cycle name, number, or IDcycle
(number, optional) - 0=None, 1=Urgent, 2=High, 3=Normal, 4=Lowpriority
(string, optional) - Project name or IDproject
(string, optional) - State type, name, or IDstate
(string, optional) - User ID, name, email, or "me"assignee
(string, optional) - Agent name, displayName, or IDdelegate
(array of strings, optional) - Label names or IDslabels
(string, optional) - ISO format datedueDate
(string, optional) - Parent issue ID for sub-issuesparentId
(array of objects, optional) - Each object needslinks
andurltitle
Example:
mcp__linear__create_issue({ title: "Fix authentication bug", team: "Engineering", description: "## Problem\n\nUsers cannot login", state: "Todo", labels: ["bug", "critical"], assignee: "me" })
update_issue
update_issueUpdate an existing Linear issue.
Parameters:
(string, required) - The issue IDid
(string, optional)title
(string, optional) - Markdowndescription
(number, optional) - 0-4priority
(string, optional) - Project name or IDproject
(string, optional) - State type, name, or IDstate
(string, optional) - Cycle name, number, or IDcycle
(string, optional) - User ID, name, email, or "me"assignee
(string, optional) - Agent name, displayName, or IDdelegate
(array of strings, optional) - Label names or IDs (replaces existing)labels
(string, optional)parentId
(string, optional) - ISO formatdueDate
(number, optional) - Numerical estimate valueestimate
(array of objects, optional)links
Example:
mcp__linear__update_issue({ id: "PSN-41", state: "In Progress", labels: ["planning", "implementation"] })
5. Issue Statuses (2 tools)
list_issue_statuses
list_issue_statusesList available issue statuses in a Linear team.
Parameters:
(string, required) - Team name or IDteam
Example:
mcp__linear__list_issue_statuses({ team: "Engineering" })
get_issue_status
get_issue_statusRetrieve detailed information about an issue status by name or ID.
Parameters:
(string, required) - Status IDid
(string, required) - Status namename
(string, required) - Team name or IDteam
Example:
mcp__linear__get_issue_status({ name: "In Progress", team: "Engineering" })
6. Labels (3 tools)
list_issue_labels
list_issue_labelsList available issue labels in a workspace or team.
Parameters:
(number, optional, max 250, default 50)limit
(string, optional)before
(string, optional)after
(string, optional) - "createdAt" or "updatedAt"orderBy
(string, optional) - Filter by label namename
(string, optional) - Team name or IDteam
Example:
mcp__linear__list_issue_labels({ team: "Engineering" })
create_issue_label
create_issue_labelCreate a new Linear issue label.
Parameters:
(string, required)name
(string, optional)description
(string, optional) - Hex color codecolor
(string, optional) - Team UUID (workspace label if omitted)teamId
(string, optional) - Parent label UUID for groupsparentId
(boolean, optional, default false) - Whether this is a label groupisGroup
Example:
mcp__linear__create_issue_label({ name: "feature-request", color: "#bb87fc", teamId: "team-123" })
list_project_labels
list_project_labelsList available project labels in the Linear workspace.
Parameters:
(number, optional, max 250, default 50)limit
(string, optional)before
(string, optional)after
(string, optional)orderBy
(string, optional)name
Example:
mcp__linear__list_project_labels({ limit: 100 })
7. Projects (4 tools)
list_projects
list_projectsList projects in the user's Linear workspace.
Parameters:
(number, optional, max 250, default 50)limit
(string, optional)before
(string, optional)after
(string, optional)orderBy
(string, optional) - Search project namequery
(string, optional) - State name or IDstate
(string, optional) - Initiative name or IDinitiative
(string, optional) - Team name or IDteam
(string, optional) - User ID, name, email, or "me"member
(string, optional)createdAt
(string, optional)updatedAt
(boolean, optional, default false)includeArchived
Example:
mcp__linear__list_projects({ team: "Engineering", state: "started" })
get_project
get_projectRetrieve details of a specific project.
Parameters:
(string, required) - Project ID or namequery
Example:
mcp__linear__get_project({ query: "CCPM" })
create_project
create_projectCreate a new project in Linear.
Parameters:
(string, required)name
(string, required) - Team name or IDteam
(string, optional) - Max 255 charssummary
(string, optional) - Markdowndescription
(string, optional)state
(string, optional) - ISO formatstartDate
(string, optional) - ISO formattargetDate
(integer, optional) - 0-4priority
(array of strings, optional)labels
(string, optional) - User ID, name, email, or "me"lead
Example:
mcp__linear__create_project({ name: "Q1 Authentication", team: "Engineering", description: "## Goals\n\n- OAuth integration\n- SSO support", lead: "me" })
update_project
update_projectUpdate an existing Linear project.
Parameters:
(string, required)id
(string, optional)name
(string, optional)summary
(string, optional)description
(string, optional)state
(string, optional)startDate
(string, optional)targetDate
(integer, optional) - 0-4priority
(array of strings, optional)labels
(string, optional)lead
Example:
mcp__linear__update_project({ id: "proj-123", state: "completed" })
8. Teams (2 tools)
list_teams
list_teamsList teams in the user's Linear workspace.
Parameters:
(number, optional, max 250, default 50)limit
(string, optional)before
(string, optional)after
(string, optional)orderBy
(string, optional) - Search queryquery
(boolean, optional, default false)includeArchived
(string, optional)createdAt
(string, optional)updatedAt
Example:
mcp__linear__list_teams({ includeArchived: false })
get_team
get_teamRetrieve details of a specific Linear team.
Parameters:
(string, required) - Team UUID, key, or namequery
Example:
mcp__linear__get_team({ query: "Engineering" })
9. Users (2 tools)
list_users
list_usersRetrieve users in the Linear workspace.
Parameters:
(string, optional) - Filter by name or emailquery
Example:
mcp__linear__list_users({ query: "john" })
get_user
get_userRetrieve details of a specific Linear user.
Parameters:
(string, required) - User ID, name, email, or "me"query
Example:
mcp__linear__get_user({ query: "me" })
10. Documentation (1 tool)
search_documentation
search_documentationSearch Linear's documentation to learn about features and usage.
Parameters:
(string, required) - Search queryquery
(number, optional, default 0) - Page numberpage
Example:
mcp__linear__search_documentation({ query: "issue statuses", page: 0 })
Summary: All 23 Tools
- List comments on issuelist_comments
- Add comment to issuecreate_comment
- Get team cycleslist_cycles
- Fetch Linear documentget_document
- List documentslist_documents
- Fetch single issueget_issue
- Search/list issueslist_issues
- Create new issuecreate_issue
- Update existing issueupdate_issue
- List workflow stateslist_issue_statuses
- Get specific statusget_issue_status
- List labelslist_issue_labels
- Create new labelcreate_issue_label
- List project labelslist_project_labels
- List projectslist_projects
- Get specific projectget_project
- Create new projectcreate_project
- Update existing projectupdate_project
- List all teamslist_teams
- Get specific teamget_team
- List workspace userslist_users
- Get specific userget_user
- Search Linear docssearch_documentation
Tool Validation: Critical Rules
Only Use Validated Tools
RULE: Every Linear operation MUST use a tool from the validated list above.
Examples of INVALID tool names that will fail:
- ❌
(correct:get_issues
)list_issues - ❌
(correct: create new comment instead)update_comment - ❌
(not supported)delete_issue - ❌
(correct tool, but check args)list_issue_statuses
Before Using a Tool
- Check the validated list above
- Verify the exact tool name matches
- If unsure, use
variants which are widely availablelist_* - Never assume tool names—verify first
Error Prevention Strategy
// ✅ CORRECT: Use only validated tools Task(ccpm:linear-operations): ` operation: get_issue params: issueId: PSN-29 context: cache: true ` // ❌ INCORRECT: Non-existent tool Task(ccpm:linear-operations): ` operation: fetch_issue // This tool doesn't exist! params: issueId: PSN-29 ` // ❌ INCORRECT: Assuming delete exists Task(ccpm:linear-operations): ` operation: delete_issue // Linear MCP doesn't support deletion params: issueId: PSN-29 `
Using the Linear Subagent
⚠️ IMPORTANT: Command File Invocation Format
When writing CCPM command files (files in
commands/), you MUST use explicit execution instructions, NOT the YAML template format shown in the examples below.
Command files must use this format:
**Use the Task tool to fetch the issue from Linear:** Invoke the `ccpm:linear-operations` subagent: - **Tool**: Task - **Subagent**: ccpm:linear-operations - **Prompt**:
operation: get_issue params: issueId: "{the issue ID from previous step}" context: cache: true command: "work"
Why? Claude Code interprets command markdown files as executable prompts, not documentation. YAML template syntax appears as an example rather than an instruction to execute. Explicit instructions (e.g., "Use the Task tool to...") are unambiguous execution directives that ensure Claude invokes the subagent correctly.
Basic Syntax (For Documentation/Examples Only)
The examples below use YAML template format for readability. Do NOT use this format in command files—use the explicit format shown above instead.
Task(ccpm:linear-operations): ` operation: <tool_name> params: <param1>: <value1> <param2>: <value2> context: cache: true command: "planning:plan" `
Enabling Caching (Recommended)
For read operations, always enable caching to achieve 85-95% hit rates:
Task(ccpm:linear-operations): ` operation: get_issue params: issueId: PSN-123 context: cache: true # Enable session-level caching command: "planning:plan" `
Providing Context for Better Errors
Include context to improve error messages and debugging:
Task(ccpm:linear-operations): ` operation: update_issue params: issueId: PSN-29 state: "In Progress" context: cache: false # Skip cache for writes command: "implementation:start" # Which command triggered this purpose: "Marking task as started" # Why we're doing this `
Shared Helpers
The
_shared-linear-helpers.md file provides convenience functions that delegate to the subagent. Use these for common operations:
getOrCreateLabel(teamId, labelName)
Smart label management with automatic creation if missing:
// Use this instead of manual list + create const label = await getOrCreateLabel(teamId, "feature-request");
Benefits:
- Deduplicates label creation logic
- Handles caching automatically
- Returns label ID or creates new one
getValidStateId(teamId, stateNameOrId)
Fuzzy state matching with suggestions on errors:
// Handles "In Progress" → actual state ID const stateId = await getValidStateId(teamId, "In Progress");
Benefits:
- Case-insensitive matching
- Fuzzy matching for typos
- Suggests available states on error
ensureLabelsExist(teamId, labelNames)
Batch create labels if missing:
// Create multiple labels in one call const labels = await ensureLabelsExist(teamId, [ "planning", "implementation", "review" ]);
Performance Optimization
Caching Strategy
Read Operations: Always enable caching
,get_issue
,list_issueslist_projects- Cache hits: 85-95%
- Performance: <50ms
Write Operations: Disable caching
,create_issue
,update_issuecreate_comment- Always fetch fresh data
// READ: Cache enabled Task(ccpm:linear-operations): ` operation: get_issue params: issueId: PSN-29 context: cache: true # ✅ Cached reads ` // WRITE: Cache disabled Task(ccpm:linear-operations): ` operation: update_issue params: issueId: PSN-29 state: "Done" context: cache: false # ❌ Never cache writes `
Batching Operations
When possible, batch related operations:
// ✅ GOOD: Get all needed data in one context Task(ccpm:linear-operations): ` operation: get_issue params: issueId: PSN-29 context: cache: true batchId: "planning-workflow" ` // Then use Team, Project, Status in sequence // Subsequent calls reuse cached Team/Project data
Token Reduction Comparison
| Operation | Direct MCP | Via Subagent | Savings |
|---|---|---|---|
| Get issue | 400ms, 2.5k tokens | <50ms, 0.8k tokens | 68% |
| Update issue | 600ms, 3.2k tokens | <50ms, 1.2k tokens | 62% |
| Create comment | 500ms, 2.8k tokens | <50ms, 1.0k tokens | 64% |
| Workflow average | 500ms, 15k tokens | <50ms, 8k tokens | -47% |
Error Handling
The Linear subagent provides structured errors with actionable suggestions.
Common Error Scenarios
STATE_NOT_FOUND
When updating an issue to a non-existent status:
error: code: STATE_NOT_FOUND message: "State 'In Review' not found in team" params: requestedState: "In Review" teamId: "psn123" suggestions: - "Use 'In Progress' (exact match required)" - "Available states: Backlog, Todo, In Progress, Done, Blocked" - "Check team configuration in Linear"
Fix: Use exact state name or
getValidStateId() helper
LABEL_NOT_FOUND
When assigning a non-existent label:
error: code: LABEL_NOT_FOUND message: "Label 'feature' not found" params: requestedLabel: "feature" teamId: "psn123" suggestions: - "Label will be created automatically" - "Use 'ensureLabelsExist()' to batch create" - "Available labels: bug, feature-request, documentation"
Fix: Use
getOrCreateLabel() or ensureLabelsExist() helpers
ISSUE_NOT_FOUND
When accessing a non-existent issue:
error: code: ISSUE_NOT_FOUND message: "Issue PSN-9999 not found" params: issueId: "PSN-9999" suggestions: - "Verify issue ID is correct (use Linear UI)" - "Check team/project context" - "Issue may have been archived"
Fix: Validate issue ID before using
Examples
Example 1: Get Issue with Caching
Task(ccpm:linear-operations): ` operation: get_issue params: issueId: PSN-29 context: cache: true command: "planning:plan" purpose: "Fetch task details for planning" `
Performance: <50ms (cached) Token cost: ~0.8k Result: Issue object with title, description, status, labels, assignee
Example 2: Update Issue Status and Labels
Task(ccpm:linear-operations): ` operation: update_issue params: issueId: PSN-29 state: "In Progress" labels: ["planning", "implementation"] context: cache: false command: "implementation:start" purpose: "Mark task as started with relevant labels" `
Performance: 100-200ms (no cache) Token cost: ~1.2k Result: Updated issue with new status and labels
Example 3: Create Comment with Context
Task(ccpm:linear-operations): ` operation: create_comment params: issueId: PSN-29 body: | Progress update: - Implemented JWT authentication - 2 unit tests passing - Need to fix Redis integration Blockers: - Redis library compatibility context: cache: false command: "implementation:sync" purpose: "Log implementation progress" `
Performance: 150-300ms Token cost: ~1.5k Result: Comment added to issue with timestamp
Example 4: Using Shared Helpers
// Get or create label (delegates to subagent with caching) const label = await getOrCreateLabel(teamId, "feature-request"); // Get valid state ID (fuzzy matching with suggestions) const stateId = await getValidStateId(teamId, "In Progress"); // Ensure multiple labels exist const labels = await ensureLabelsExist(teamId, [ "planning", "implementation", "blocked" ]); // Now use the results Task(ccpm:linear-operations): ` operation: update_issue params: issueId: PSN-29 state: ${stateId} labels: ${labels.map(l => l.id)} context: cache: false purpose: "Apply validated status and labels" `
Performance: <100ms total (mostly cached lookups) Token cost: ~1.8k Result: Reliable label/status application with error prevention
Example 5: Error Handling
// PATTERN: Try operation, handle structured errors Task(ccpm:linear-operations): ` operation: update_issue params: issueId: PSN-29 state: "Review" // Might not exist context: cache: false command: "implementation:sync" ` // If error: // { // code: "STATE_NOT_FOUND", // suggestions: ["Available states: Backlog, Todo, In Progress, Done"] // } // RECOVERY: Use helper or ask user const stateId = await getValidStateId(teamId, "Review"); // Or ask user: "Which status should I use?"
Pattern: Structured errors guide user or helper selection
Migration from Direct MCP
Before: Direct MCP Call (Inefficient)
// Direct call - no caching, higher token cost Task(linear-operations): ` List issues in PSN project where status = "Todo" ` // Result: ~2.5k tokens, 400ms, no future cache hits
After: Via Subagent (Optimized)
// Via subagent - automatic caching Task(ccpm:linear-operations): ` operation: list_issues params: projectId: "PSN" filter: {status: "Todo"} context: cache: true command: "planning:plan" ` // Result: ~0.9k tokens, <50ms, 85-95% cache hits next time
Common Pitfalls to Avoid
// ❌ DON'T: Forget caching Task(ccpm:linear-operations): ` operation: get_issue params: issueId: PSN-29 // Missing: context: cache: true ` // ❌ DON'T: Use non-existent tools Task(ccpm:linear-operations): ` operation: fetch_issue_details // This doesn't exist params: issueId: PSN-29 ` // ❌ DON'T: Cache writes Task(ccpm:linear-operations): ` operation: update_issue params: issueId: PSN-29 context: cache: true // WRONG! Never cache writes ` // ✅ DO: Follow patterns Task(ccpm:linear-operations): ` operation: get_issue params: issueId: PSN-29 context: cache: true // ✅ Cache reads command: "planning:plan" `
Best Practices Summary
| Practice | Reason |
|---|---|
| Always use subagent for Linear ops | 50-60% token reduction |
| Enable caching on reads | 85-95% hit rate, <50ms performance |
| Disable caching on writes | Avoid stale data |
| Use shared helpers | Reduces duplication, better error handling |
| Validate tools against list | Prevent failures with non-existent tools |
| Provide context object | Better error messages and debugging |
| Handle structured errors | Graceful degradation and user guidance |
References
- Subagent Location:
agents/linear-operations.md - Shared Helpers:
agents/_shared-linear-helpers.md - Architecture Guide:
docs/architecture/linear-subagent-architecture.md - Linear MCP Docs: Available via
toolsearch_documentation