| name | linear-workflow |
| description | Manage Linear project management: create and update issues, cycle management, GitHub integration, status updates via GraphQL API. Trigger: when creating Linear issues, updating Linear status, Linear cycles, Linear project management, Linear GraphQL API, Linear workflow |
| version | 1 |
| argument-hint | [create-issue|update-status|list-issues|cycles|teams] |
| allowed-tools | ["bash","read","write","grep","glob"] |
Linear Project Management
You are now operating in Linear workflow management mode.
Authentication
export LINEAR_API_KEY="lin_api_your_key_here"
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"query":"{ viewer { id name email } }"}' | jq '.data.viewer'
GraphQL API Basics
All Linear operations use the GraphQL API at https://api.linear.app/graphql.
linear_query() {
local query="$1"
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{\"query\": ${query}}"
}
Teams and Projects
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"query":"{ teams { nodes { id name key } } }"}' \
| jq '.data.teams.nodes'
TEAM_ID="your-team-id"
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{\"query\":\"{ team(id: \\\"${TEAM_ID}\\\") { projects { nodes { id name } } } }\"}" \
| jq '.data.team.projects.nodes'
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{\"query\":\"{ team(id: \\\"${TEAM_ID}\\\") { states { nodes { id name type } } } }\"}" \
| jq '.data.team.states.nodes'
Issue Management
Create an Issue
TEAM_ID="your-team-id"
TITLE="Fix authentication timeout bug"
DESCRIPTION="Users are being logged out unexpectedly after 5 minutes. Expected session length is 24 hours."
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{
\"query\": \"mutation CreateIssue(\$input: IssueCreateInput!) { issueCreate(input: \$input) { success issue { id identifier title url } } }\",
\"variables\": {
\"input\": {
\"teamId\": \"${TEAM_ID}\",
\"title\": \"${TITLE}\",
\"description\": \"${DESCRIPTION}\",
\"priority\": 2
}
}
}" | jq '.data.issueCreate.issue'
Priority values: 0 = No priority, 1 = Urgent, 2 = High, 3 = Medium, 4 = Low.
Create an Issue with Labels and Assignee
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{\"query\":\"{ team(id: \\\"${TEAM_ID}\\\") { labels { nodes { id name } } } }\"}" \
| jq '.data.team.labels.nodes'
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{\"query\":\"{ team(id: \\\"${TEAM_ID}\\\") { members { nodes { id name } } } }\"}" \
| jq '.data.team.members.nodes'
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{
\"query\": \"mutation CreateIssue(\$input: IssueCreateInput!) { issueCreate(input: \$input) { success issue { id identifier title url } } }\",
\"variables\": {
\"input\": {
\"teamId\": \"${TEAM_ID}\",
\"title\": \"Add rate limiting to /api/login\",
\"description\": \"Implement IP-based rate limiting (10 req/min) on the login endpoint.\",
\"priority\": 1,
\"labelIds\": [\"label-id-1\", \"label-id-2\"],
\"assigneeId\": \"user-id\"
}
}
}" | jq '.data.issueCreate.issue'
List Issues
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{
\"query\": \"{ team(id: \\\"${TEAM_ID}\\\") { issues(first: 20, orderBy: updatedAt) { nodes { id identifier title state { name } assignee { name } priority createdAt } } } }\"
}" | jq '.data.team.issues.nodes'
STATE_ID="your-state-id"
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{
\"query\": \"{ issues(filter: { team: { id: { eq: \\\"${TEAM_ID}\\\" } }, state: { id: { eq: \\\"${STATE_ID}\\\" } } }) { nodes { id identifier title assignee { name } } } }\"
}" | jq '.data.issues.nodes'
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"query": "{ issueSearch(query: \"authentication timeout\") { nodes { id identifier title state { name } } } }"
}' | jq '.data.issueSearch.nodes'
Update an Issue
ISSUE_ID="issue-uuid"
NEW_STATE_ID="in-progress-state-uuid"
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{
\"query\": \"mutation UpdateIssue(\$id: String!, \$input: IssueUpdateInput!) { issueUpdate(id: \$id, input: \$input) { success issue { id identifier title state { name } } } }\",
\"variables\": {
\"id\": \"${ISSUE_ID}\",
\"input\": {
\"stateId\": \"${NEW_STATE_ID}\"
}
}
}" | jq '.data.issueUpdate.issue'
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{
\"query\": \"mutation CreateComment(\$input: CommentCreateInput!) { commentCreate(input: \$input) { success comment { id body } } }\",
\"variables\": {
\"input\": {
\"issueId\": \"${ISSUE_ID}\",
\"body\": \"Fixed in commit abc1234. Deployed to staging for verification.\"
}
}
}" | jq '.data.commentCreate.comment'
Cycle Management
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{\"query\":\"{ team(id: \\\"${TEAM_ID}\\\") { cycles { nodes { id number name startsAt endsAt completedAt } } } }\"}" \
| jq '.data.team.cycles.nodes'
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{
\"query\": \"{ team(id: \\\"${TEAM_ID}\\\") { activeCycle { id number startsAt endsAt issues(first: 50) { nodes { id identifier title state { name } assignee { name } } } } } }\"
}" | jq '.data.team.activeCycle'
CYCLE_ID="cycle-uuid"
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{
\"query\": \"mutation AddIssueToCycle(\$issueId: String!, \$cycleId: String!) { cycleCreate(input: { issueId: \$issueId, cycleId: \$cycleId }) { success } }\",
\"variables\": {
\"issueId\": \"${ISSUE_ID}\",
\"cycleId\": \"${CYCLE_ID}\"
}
}" | jq '.'
GitHub Integration
Linear can link GitHub PRs and commits to issues automatically.
git commit -m "fix: resolve authentication timeout issue
Fixes LIN-123. Increased session TTL from 5m to 24h.
See https://linear.app/your-org/issue/LIN-123"
GitHub Actions Integration
name: Update Linear Issue Status
on:
pull_request:
types: [closed]
jobs:
update-linear:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: Extract Linear Issue ID from PR title
id: linear
run: |
ISSUE=$(echo "${{ github.event.pull_request.title }}" | grep -oP 'LIN-\d+' | head -1)
echo "issue=${ISSUE}" >> $GITHUB_OUTPUT
- name: Mark issue as Done
if: steps.linear.outputs.issue != ''
run: |
# Get Done state ID for your team
DONE_STATE_ID="${{ secrets.LINEAR_DONE_STATE_ID }}"
ISSUE_IDENTIFIER="${{ steps.linear.outputs.issue }}"
curl -s https://api.linear.app/graphql \
-H "Authorization: ${{ secrets.LINEAR_API_KEY }}" \
-H "Content-Type: application/json" \
-d "{
\"query\": \"mutation { issueUpdate(id: \\\"${ISSUE_IDENTIFIER}\\\", input: { stateId: \\\"${DONE_STATE_ID}\\\" }) { success } }\"
}"
Workflow Automation Patterns
create_ci_failure_issue() {
local job_name="$1"
local run_url="$2"
curl -s https://api.linear.app/graphql \
-H "Authorization: ${LINEAR_API_KEY}" \
-H "Content-Type: application/json" \
-d "{
\"query\": \"mutation CreateIssue(\$input: IssueCreateInput!) { issueCreate(input: \$input) { success issue { identifier url } } }\",
\"variables\": {
\"input\": {
\"teamId\": \"${LINEAR_TEAM_ID}\",
\"title\": \"CI Failure: ${job_name}\",
\"description\": \"Automated issue from failed CI run: ${run_url}\",
\"priority\": 2,
\"labelIds\": [\"${CI_LABEL_ID}\"]
}
}
}" | jq '.data.issueCreate.issue'
}
Best Practices
- Store
LINEAR_API_KEY in CI secrets — never commit it to source code.
- Include the Linear issue identifier (e.g.,
LIN-123) in commit messages and PR titles for automatic linking.
- Use priority
1 (Urgent) sparingly; reserve it for production incidents and security issues.
- Create issues at the point of discovery, not just before starting work — this captures the full backlog.
- Use labels consistently across the team to enable filtering (e.g.,
bug, feature, tech-debt).
- Automate status transitions via GitHub integration to keep Linear in sync with code state without manual updates.
- Use cycles for sprint planning; keep cycle scope realistic (do not add more than team capacity).