Integrations

项目管理API

Try it

Query and manage Linear issues, projects, teams, cycles, labels, and comments through a managed OAuth GraphQL endpoint.

What it does

Connect to Linear through the Maton-managed OAuth endpoint and send GraphQL queries to read or write issues, projects, teams, cycles, labels, workflow states, users, and comments. The CLI, Python, and JavaScript examples show how to authenticate with a Maton API key, manage multiple Linear connections, and run common operations like listing, searching, creating, and updating issues. Cursor-based pagination is handled automatically by the CLI, and identifiers like ABC-123 can be used in place of UUIDs. All write operations require explicit user approval, and some mutations may need additional OAuth scopes.

When to use it

  • Listing and filtering team issues in Linear
  • Full-text searching issues by keyword
  • Creating or updating issues and adding comments
  • Managing multiple Linear OAuth connections for different workspaces

The skill document

Linear

Access the Linear API with managed OAuth authentication. Query and manage issues, projects, teams, cycles, labels, and comments using GraphQL.

Quick Start

CLI:

maton linear issue list -c ABC -L 10
maton api '/linear/graphql'

Python:

python <<'EOF'
import urllib.request, os, json
data = json.dumps({'query': '{ viewer { id name email } }'}).encode()
req = urllib.request.Request('https://api.maton.ai/linear/graphql', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Base URL

https://api.maton.ai/linear/graphql

All requests use POST to the GraphQL endpoint. Maton proxies requests to api.linear.app and automatically injects your OAuth token.

Installation

NPM:

npm install -g @maton/cli

Homebrew:

brew install maton-ai/cli/maton

Authentication

CLI:

maton login                          # Opens browser for API key
maton login --interactive            # Skip browser, paste API key directly
maton whoami                         # Show current auth state

Manual:

  1. Sign in or create an account at maton.ai
  2. Go to maton.ai/settings
  3. Copy your API key
  4. Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"

Connection Management

Manage your Linear OAuth connections at https://api.maton.ai.

List Connections

CLI:

maton connection list linear --status ACTIVE
maton api -X GET /connections -f app=linear -f status=ACTIVE

Python:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=linear&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Create Connection

CLI:

maton connection create linear
maton api /connections -f app=linear

Python:

python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'linear'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Get Connection

CLI:

maton connection view {connection_id}
maton api /connections/{connection_id}

Python:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Response:

{
  "connection": {
    "connection_id": "{connection_id}",
    "status": "ACTIVE",
    "creation_time": "2026-02-04T23:03:22.676001Z",
    "last_updated_time": "2026-02-04T23:03:51.239577Z",
    "url": "https://connect.maton.ai/?session_token=...",
    "app": "linear",
    "metadata": {}
  }
}

Open the returned url in a browser to complete OAuth authorization.

Delete Connection

CLI:

maton connection delete {connection_id}
maton api -X DELETE /connections/{connection_id}

Python:

python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Specifying Connection

If you have multiple Linear connections, specify which one to use:

CLI:

maton linear issue list -c ABC --connection {connection_id}
maton api /linear/graphql --connection {connection_id}

Python:

python <<'EOF'
import urllib.request, os, json
data = json.dumps({'query': '{ viewer { id name } }'}).encode()
req = urllib.request.Request('https://api.maton.ai/linear/graphql', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

If you have multiple connections, always specify the connection to ensure requests go to the intended account.

Security & Permissions

  • Access is scoped to issues, projects, teams, cycles, and comments within the connected Linear account.
  • All write operations require explicit user approval. Before executing any create, update, or delete call, confirm the target resource and intended effect with the user.

API Reference

Linear uses a GraphQL API. All operations are sent as POST requests with a JSON body containing the query field.

Viewer (Current User)

POST /linear/graphql
Content-Type: application/json

{"query": "{ viewer { id name email } }"}

Example:

maton linear whoami

Organization

POST /linear/graphql
Content-Type: application/json

{"query": "{ organization { id name urlKey } }"}

Example:

maton linear org view

Teams

List Teams

POST /linear/graphql
Content-Type: application/json

{"query": "{ teams { nodes { id name key } } }"}

Example:

maton linear team list

Get Team

POST /linear/graphql
Content-Type: application/json

{"query": "{ team(id: \"ABC\") { id name key issues { nodes { id identifier title } } } }"}

Example:

maton linear team view ABC

Issues

List Issues

POST /linear/graphql
Content-Type: application/json

{"query": "{ issues(first: 10, filter: { team: { key: { eq: \"ABC\" } } }) { nodes { id identifier title state { name } priority createdAt } pageInfo { hasNextPage endCursor } } }"}

Example:

maton linear issue list -c ABC -L 10

Get Issue by ID or Identifier

POST /linear/graphql
Content-Type: application/json

{"query": "{ issue(id: \"ABC-123\") { id identifier title description state { name } priority assignee { name } team { key name } createdAt updatedAt } }"}

Example:

maton linear issue view ABC-123

Filter Issues

Filter by state type:

POST /linear/graphql
Content-Type: application/json

{"query": "{ issues(first: 10, filter: { state: { type: { eq: \"started\" } } }) { nodes { id identifier title state { name type } } } }"}

Example:

maton linear issue list --state started -L 10

Filter by title:

POST /linear/graphql
Content-Type: application/json

{"query": "{ issues(first: 10, filter: { title: { containsIgnoreCase: \"bug\" } }) { nodes { id identifier title } } }"}

Example:

maton linear issue list --title bug -L 10

Search Issues

POST /linear/graphql
Content-Type: application/json

{"query": "{ searchIssues(first: 10, term: \"shopify\") { nodes { id identifier title } } }"}

Example:

maton linear issue search shopify -L 10

Create Issue

POST /linear/graphql
Content-Type: application/json

{"query": "mutation { issueCreate(input: { teamId: \"TEAM_ID\", title: \"New issue title\" }) { success issue { id identifier title state { name } } } }"}

Example:

maton linear issue create --team-id TEAM_ID -t 'New issue title'

Update Issue

POST /linear/graphql
Content-Type: application/json

{"query": "mutation { issueUpdate(id: \"ABC-123\", input: { title: \"Updated title\", priority: 2 }) { success issue { id identifier title priority } } }"}

Example:

maton linear issue update ABC-123 -t 'Updated title' --priority 2

Projects

List Projects

POST /linear/graphql
Content-Type: application/json

{"query": "{ projects(first: 10) { nodes { id name state createdAt } } }"}

Example:

maton linear project list

Cycles

List Cycles

POST /linear/graphql
Content-Type: application/json

{"query": "{ cycles(first: 10) { nodes { id name number startsAt endsAt } } }"}

Example:

maton linear cycle list

Labels

List Labels

POST /linear/graphql
Content-Type: application/json

{"query": "{ issueLabels(first: 20) { nodes { id name color } } }"}

Example:

maton linear label list

Workflow States

POST /linear/graphql
Content-Type: application/json

{"query": "{ workflowStates(first: 20) { nodes { id name type team { key } } } }"}

Example:

maton linear state list

Users

POST /linear/graphql
Content-Type: application/json

{"query": "{ users(first: 20) { nodes { id name email active } } }"}

Example:

maton linear user list

Comments

List Comments

POST /linear/graphql
Content-Type: application/json

{"query": "{ issue(id: \"ABC-123\") { comments(first: 10) { nodes { id body createdAt user { name } } } } }"}

Example:

maton linear comment list --issue ABC-123 -L 10

Create Comment

POST /linear/graphql
Content-Type: application/json

{"query": "mutation { commentCreate(input: { issueId: \"ABC-123\", body: \"Looking into this\" }) { success comment { id body } } }"}

Example:

maton linear comment create --issue ABC-123 -b 'Looking into this'

Pagination

Linear uses Relay-style cursor-based pagination. The CLI automatically paginates with '--paginate'.

Example:

maton linear issue list -c ABC --paginate

Code Examples

CLI

# List issues for a team
maton linear issue list -c ABC -L 10

# View a specific issue
maton linear issue view ABC-123

# Create a new issue
maton linear issue create --team-id TEAM_ID -t 'Fix login'

# Add a comment
maton linear comment create --issue ABC-123 -b 'Looking into this'

JavaScript

const response = await fetch('https://api.maton.ai/linear/graphql', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${process.env.MATON_API_KEY}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    query: `{ issues(first: 10) { nodes { id identifier title state { name } } } }`
  })
});
const data = await response.json();

Python

import os
import requests

response = requests.post(
    'https://api.maton.ai/linear/graphql',
    headers={
        'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}',
        'Content-Type': 'application/json'
    },
    json={
        'query': '{ issues(first: 10) { nodes { id identifier title state { name } } } }'
    }
)
data = response.json()

Notes

  • Linear uses GraphQL exclusively (no REST API)
  • Issue identifiers like ABC-123 can be used in place of UUIDs for the id parameter
  • Priority values: 0 = No priority, 1 = Urgent, 2 = High, 3 = Medium, 4 = Low
  • Workflow state types: backlog, unstarted, started, completed, canceled
  • The GraphQL schema is introspectable at https://api.linear.app/graphql
  • Use searchIssues(term: "...") for full-text search across issues
  • Some mutations (delete, create labels/projects) may require additional OAuth scopes. If you receive a scope error, contact Maton support at support@maton.ai with the specific operations/APIs you need and your use-case

Error Handling

StatusMeaning
400Missing Linear connection or GraphQL validation error
401Invalid or missing Maton API key
403Insufficient OAuth scope for the operation
429Rate limited
4xx/5xxPassthrough error from Linear API

GraphQL errors are returned in the errors array:

{
  "errors": [
    {
      "message": "Invalid scope: `write` required",
      "extensions": {
        "type": "forbidden",
        "code": "FORBIDDEN",
        "statusCode": 403
      }
    }
  ]
}

Troubleshooting: API Key Issues

CLI:

  1. Check your auth state:
maton whoami
  1. Verify the API key is valid by listing connections:
maton connection list

Manual:

  1. Check that the MATON_API_KEY environment variable is set:
echo $MATON_API_KEY
  1. Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF

Troubleshooting: Invalid App Name

  1. Ensure your URL path starts with linear. For example:
  • Correct: https://api.maton.ai/linear/graphql
  • Incorrect: https://api.maton.ai/graphql

Resources

Questions people ask

Does this skill use Linear's REST API?
No. Linear only exposes a GraphQL API. The skill sends POST requests with a JSON query body to https://api.maton.ai/linear/graphql, which proxies to api.linear.app.
How is authentication handled?
You provide a Maton API key as the MATON_API_KEY environment variable. The Linear OAuth token is managed by Maton, and multiple Linear connections can be selected via the Maton-Connection header or the --connection CLI flag.
Can the skill create or modify issues?
Yes. The docs cover issueCreate, issueUpdate, and commentCreate mutations. All write operations require explicit user approval before execution, and some mutations may require additional OAuth scopes not granted by default.

Related skills

Find why your productivity system keeps failing, then apply the smallest fix — capacity math, bottleneck routing, durable local notes.

by Iván855 installs69 stars

Generate and edit Draw.io, Mermaid, and Excalidraw diagrams from natural language using a structured JSON spec.

by nssa.io1.0k installs47 stars

Join a video meeting as an AI bot with voice, avatar, and screenshare across four operating modes.

by johnpatternai21 installs8 stars

Run Git operations — commits, branches, merges, rebases, conflict resolution, and recovery — with safety rules enforced.

by Iván533 installs31 stars

Stores durable facts in a categorized, plain-markdown vault on disk, alongside your agent's built-in memory.

by Iván556 installs18 stars

More from byungkyu

Browse all skills

Route prompts to the right dlazy CLI audio model for TTS, music, sound effects, and voice cloning.

by dlazy

Build, debug, preview, and publish WeChat Mini Programs using Nightly DevTools, wechatide CLI, and a miniprogram-ci fallback.

by Booker Zhao

Call the Jira Cloud API with managed OAuth to search and manage issues.

by byungkyu

Route image, video, and audio requests to the right dlazy CLI model based on intent.

by dlazy

Access Pipedrive CRM resources through a managed OAuth connection.

by byungkyu

常见办公流程自动化中枢,覆盖文档处理、数据整理、邮件管理、日程协调、报表生成与工作流编排。 聚焦批量操作容错、格式保真、PII 脱敏、模板复用四大痛点,让繁琐办公一键稳妥完成。 核心能力: - 文档批处理:Word/PDF/Excel/PPT 批量生成、转换、合并拆分,含失败隔离与重试 - 数据整理:清洗、转换、...

by thcjp3 installs1 stars