brainstorming
Structured design dialogue that validates ideas before implementation begins.
extended
This skill should be used when the user asks to "create Linear document", "write doc in Linear", "add milestone to project", "update Linear document", "delete milestone", or "set milestone target date". Provides write operations for Linear documents and milestones via GraphQL API (extending read-...
Full skill instructions
This skill extends Linear MCP capabilities by adding write operations for Documents and ProjectMilestones. While Linear MCP provides read-only access to documents and no milestone support, this skill enables full CRUD operations via direct GraphQL API calls.
What this skill adds:
Prerequisites:
export LINEAR_API_KEY="lin_api_xxxxx"jq for JSON formattingBasic example:
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d '{
"query": "mutation DocumentCreate($input: DocumentCreateInput!) { documentCreate(input: $input) { success document { id title url slugId createdAt creator { name } } } }",
"variables": {
"input": {
"title": "API Design Document"
}
}
}'
With content and project:
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d '{
"query": "mutation DocumentCreate($input: DocumentCreateInput!) { documentCreate(input: $input) { success document { id title url slugId } } }",
"variables": {
"input": {
"title": "Q4 Roadmap",
"content": "# Q4 Goals\n\n- Launch feature X\n- Improve performance by 30%",
"projectId": "PROJECT_ID_HERE",
"color": "#FF6B6B"
}
}
}'
Available parameters:
title (required): Document titlecontent: Markdown contentprojectId: Attach to projectinitiativeId: Attach to initiativeissueId: Attach to issuecolor: Icon color (hex format)icon: Icon emoji or name (optional, some emojis may not be valid - omit if validation fails)sortOrder: Display order (float)Update title and content:
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d '{
"query": "mutation DocumentUpdate($id: String!, $input: DocumentUpdateInput!) { documentUpdate(id: $id, input: $input) { success document { id title updatedAt updatedBy { name } } } }",
"variables": {
"id": "DOCUMENT_ID_OR_SLUG",
"input": {
"title": "Updated Title",
"content": "# Updated Content\n\nNew information here."
}
}
}'
Move to trash:
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d '{
"query": "mutation DocumentUpdate($id: String!, $input: DocumentUpdateInput!) { documentUpdate(id: $id, input: $input) { success } }",
"variables": {
"id": "DOCUMENT_ID",
"input": {
"trashed": true
}
}
}'
Available update parameters:
title: New titlecontent: New markdown contentcolor: New icon coloricon: New icontrashed: Move to trash (true) or restore (false)projectId: Move to different projectsortOrder: Update display orderPermanently delete (archive):
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d '{
"query": "mutation DocumentDelete($id: String!) { documentDelete(id: $id) { success } }",
"variables": {
"id": "DOCUMENT_ID"
}
}'
Restore archived document:
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d '{
"query": "mutation DocumentUnarchive($id: String!) { documentUnarchive(id: $id) { success entity { id title } } }",
"variables": {
"id": "DOCUMENT_ID"
}
}'
Basic milestone:
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d '{
"query": "mutation ProjectMilestoneCreate($input: ProjectMilestoneCreateInput!) { projectMilestoneCreate(input: $input) { success projectMilestone { id name status progress targetDate project { id name } } } }",
"variables": {
"input": {
"projectId": "PROJECT_ID_HERE",
"name": "Beta Release"
}
}
}'
With description and target date:
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d '{
"query": "mutation ProjectMilestoneCreate($input: ProjectMilestoneCreateInput!) { projectMilestoneCreate(input: $input) { success projectMilestone { id name status progress targetDate } } }",
"variables": {
"input": {
"projectId": "PROJECT_ID_HERE",
"name": "MVP Launch",
"description": "# MVP Goals\n\n- Core features complete\n- 10 beta users onboarded",
"targetDate": "2025-06-30"
}
}
}'
Interactive approach (using AskUserQuestion):
When user doesn't specify a target date, use AskUserQuestion to ask:
// Step 1: Ask user for target date
AskUserQuestion({
questions: [{
question: "What is the target date for this milestone?",
header: "Target Date",
multiSelect: false,
options: [
{
label: "End of this month",
description: "Set target date to the last day of current month"
},
{
label: "End of next month",
description: "Set target date to the last day of next month"
},
{
label: "Custom date",
description: "I'll specify a custom date in YYYY-MM-DD format"
},
{
label: "No target date",
description: "Create milestone without a specific target date"
}
]
}]
})
// Step 2: Based on user's answer, construct the mutation
// If custom date selected, prompt for YYYY-MM-DD format
// If no target date, omit targetDate from input
Available parameters:
projectId (required): Parent project IDname (required): Milestone namedescription: Markdown descriptiontargetDate: Target date (YYYY-MM-DD format)sortOrder: Display order (float)Status values (auto-calculated):
unstarted: No progress yetnext: Next milestone to work onoverdue: Past target datedone: All issues completedUpdate name and target date:
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d '{
"query": "mutation ProjectMilestoneUpdate($id: String!, $input: ProjectMilestoneUpdateInput!) { projectMilestoneUpdate(id: $id, input: $input) { success projectMilestone { id name status targetDate } } }",
"variables": {
"id": "MILESTONE_ID",
"input": {
"name": "MVP Launch - Extended",
"targetDate": "2025-07-15"
}
}
}'
Available update parameters:
name: New namedescription: New markdown descriptiontargetDate: New target date (YYYY-MM-DD)sortOrder: New display orderList all milestones:
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d '{
"query": "query ProjectMilestones($first: Int) { projectMilestones(first: $first) { nodes { id name status progress targetDate project { id name } issues { nodes { id title } } } } }",
"variables": {
"first": 50
}
}'
List milestones for specific project:
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d '{
"query": "query Project($id: String!) { project(id: $id) { id name projectMilestones { nodes { id name status progress targetDate } } } }",
"variables": {
"id": "PROJECT_ID"
}
}'
Detailed milestone info:
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d '{
"query": "query ProjectMilestone($id: String!) { projectMilestone(id: $id) { id name description status progress progressHistory currentProgress targetDate createdAt updatedAt project { id name state } issues { nodes { id title state { name type } assignee { name } } } } }",
"variables": {
"id": "MILESTONE_ID"
}
}'
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d '{
"query": "mutation ProjectMilestoneDelete($id: String!) { projectMilestoneDelete(id: $id) { success } }",
"variables": {
"id": "MILESTONE_ID"
}
}'
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d '{
"query": "mutation ProjectMilestoneMove($id: String!, $input: ProjectMilestoneMoveInput!) { projectMilestoneMove(id: $id, input: $input) { success projectMilestone { id name project { id name } } } }",
"variables": {
"id": "MILESTONE_ID",
"input": {
"projectId": "NEW_PROJECT_ID"
}
}
}'
Document operations:
Milestone operations:
IMPORTANT for Milestones:
Always check for LINEAR_API_KEY:
if [ -z "$LINEAR_API_KEY" ]; then
echo "Error: LINEAR_API_KEY not set. Get key from https://linear.app/settings/api"
exit 1
fi
Get IDs first:
list_projects to get project IDslist_issues to get issue IDslist_documents to get document IDs/slugsFor milestone operations, use AskUserQuestion:
Handle JSON carefully:
\n\"Check responses:
success: true in mutation responsessuccess: false, check the errors arrayHandle icon field carefully:
icon field is optional for documentsFormat output for user:
jq to pretty-print JSONid, url, statusAuthentication errors:
{
"errors": [
{
"message": "Authentication required",
"extensions": { "code": "UNAUTHENTICATED" }
}
]
}
→ Check if LINEAR_API_KEY is set and valid
Not found errors:
{
"errors": [
{
"message": "Resource not found",
"extensions": { "code": "NOT_FOUND" }
}
]
}
→ Verify the ID exists using list operations first
Validation errors:
{
"data": {
"documentCreate": {
"success": false
}
},
"errors": [
{
"message": "Title is required",
"path": ["documentCreate", "input", "title"]
}
]
}
→ Check required fields are provided
Rate limiting:
{
"errors": [
{
"message": "Rate limit exceeded",
"extensions": { "code": "RATE_LIMITED" }
}
]
}
→ Wait and retry after a few seconds
Icon validation errors:
{
"errors": [
{
"message": "Argument Validation Error",
"extensions": {
"code": "INVALID_INPUT",
"validationErrors": [
{
"property": "icon",
"constraints": {
"customValidation": "icon is not a valid icon"
}
}
]
}
}
]
}
→ Omit the icon field or try a different emoji/icon name. Linear API only accepts certain emojis.
This skill works best alongside the official Linear MCP server:
Linear MCP provides (read operations):
list_documents - Get existing documentsget_document - Read document contentlist_projects - Get project IDslist_issues - Get issue IDslist_teams - Get team infoThis skill adds (write operations):
documentCreate - Create new documentsdocumentUpdate - Update documentsdocumentDelete - Delete documentsprojectMilestoneCreate - Create milestonesprojectMilestoneUpdate - Update milestonesprojectMilestoneDelete - Delete milestonesprojectMilestones query - List milestones (not in MCP)Typical workflow:
Extract just the document URL:
curl -X POST ... | jq -r '.data.documentCreate.document.url'
Format milestone list as table:
curl -X POST ... | jq -r '.data.projectMilestones.nodes[] | [.name, .status, (.progress * 100 | tostring + "%")] | @tsv'
CONTENT=$(cat <<'EOF'
# Architecture Design
## Overview
System architecture overview here.
## Components
- API Gateway
- Service Mesh
- Data Layer
EOF
)
# Create temp file with Python for proper JSON encoding
TEMP_FILE=$(mktemp)
python3 << PEOF > "$TEMP_FILE"
import json
data = {
"query": """mutation DocumentCreate(\$input: DocumentCreateInput!) {
documentCreate(input: \$input) {
success
document { id url }
}
}""",
"variables": {
"input": {
"title": "Architecture Design",
"content": """$CONTENT"""
}
}
}
print(json.dumps(data, ensure_ascii=False))
PEOF
curl -X POST https://api.linear.app/graphql \
-H "Content-Type: application/json" \
-H "Authorization: $LINEAR_API_KEY" \
-d @"$TEMP_FILE" | jq '.'
rm "$TEMP_FILE"
For detailed schema information:
grep "DocumentCreateInput\|DocumentUpdateInput\|icon\|color" references/document-schema.mdgrep "ProjectMilestoneCreateInput\|ProjectMilestoneUpdateInput\|targetDate" references/milestone-schema.mdgrep "Example\|mutation\|query" references/examples.mdFor the original GraphQL schema:
Structured design dialogue that validates ideas before implementation begins.
Comprehensive design intelligence for web and mobile UI/UX across 10 technology stacks.
Comprehensive implementation plans for multi-step tasks, breaking down specs into bite-sized, testable steps.
Introduction to the obra skills system with mandatory skill invocation rules and best practices.
Execute a written implementation plan with critical review and task checkpoints.
Delegate independent tasks to specialized agents working concurrently with isolated context.
Isolated git worktrees with smart directory selection and safety verification.
Toolkit for interacting with and testing local web applications using Playwright. Supports verifying frontend functionality, debugging UI behavior, capturing browser screenshots, and viewing browser logs.
Plan searchable and shareable content that drives traffic, builds authority, and generates leads.
README-first repository scanner that extracts commands and classifies reproduction candidates without executing them.
Brainstorm and prioritize marketing strategies tailored to your SaaS stage, budget, and goals.
Plan and optimize your website's page hierarchy, navigation, URL structure, and internal linking.
The world's fastest calendar for remote work
Capture, organize, and utilize your knowledge effortlessly.
Instant Summaries of Audio & Video Interviews with AnySummary
Transform PDFs into engaging mind maps.
Chat with any PDF instantly
Create an optimal daily plan using your voice
A productivity platform to centralize organizational knowledge and workflows with contextual AI assistance.
AskYourPDF Pricing Plans: Tailored to Your Needs