用 PIL 逐帧绘制并校验,生成符合 Slack 尺寸与体积限制的动图 GIF。
集成
项目管理API
试用通过托管的 OAuth GraphQL 接口查询与管理 Linear 的 issue、项目、团队、周期、标签和评论。
它能做什么
通过 Maton 托管的 OAuth 端点接入 Linear,使用 GraphQL 读写 issue、项目、团队、周期、标签、工作流状态、用户和评论。文档给出了 CLI、Python 和 JavaScript 三种调用方式,覆盖 Maton API Key 认证、多 Linear 连接管理,以及列表、搜索、创建、更新等常见操作。CLI 自动处理基于游标的分页;类似 ABC-123 的标识符可直接替代 UUID 使用。所有写操作都需要先获得用户明确确认;部分变更操作可能依赖额外的 OAuth 权限,遇到权限错误需联系 Maton 申请扩展。
什么时候用它
- 按团队列出并筛选 Linear issue
- 按关键词全文搜索 issue
- 创建或更新 issue,并添加评论
- 管理多个 Linear OAuth 连接以对接不同工作区
技能文档
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:
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
- 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-123can be used in place of UUIDs for theidparameter - 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
| Status | Meaning |
|---|---|
| 400 | Missing Linear connection or GraphQL validation error |
| 401 | Invalid or missing Maton API key |
| 403 | Insufficient OAuth scope for the operation |
| 429 | Rate limited |
| 4xx/5xx | Passthrough 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:
- Check your auth state:
maton whoami
- Verify the API key is valid by listing connections:
maton connection list
Manual:
- Check that the
MATON_API_KEYenvironment variable is set:
echo $MATON_API_KEY
- 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
- Ensure your URL path starts with
linear. For example:
- Correct:
https://api.maton.ai/linear/graphql - Incorrect:
https://api.maton.ai/graphql
Resources
常见问题
- 这个技能会调用 Linear 的 REST 接口吗?
- 不会。Linear 只提供 GraphQL API,技能通过 https://api.maton.ai/linear/graphql 发送带 JSON 查询体的 POST 请求,再由 Maton 转发到 api.linear.app。
- 认证流程是怎样的?
- 需要将 Maton API Key 设置为 MATON_API_KEY 环境变量。Linear 的 OAuth 令牌由 Maton 自动托管;当存在多个连接时,可通过 Maton-Connection 请求头或 CLI 的 --connection 参数指定目标连接。
- 能否创建或修改 issue?
- 可以。文档涵盖了 issueCreate、issueUpdate 以及 commentCreate 等变更操作。所有写操作在执行前都需要用户明确确认;部分变更可能依赖未默认授予的额外 OAuth 权限。
相关技能
Guide for creating effective skills. This skill should be used when users want to create a new skill (or update an existing skill) that extends Codex's capabilities with specialized knowledge, workflo
yeet
官方Use only when the user explicitly asks to stage, commit, push, and open a GitHub pull request in one flow using the GitHub CLI (`gh`).
Migrate supported instruction files, skills, agents, and MCP config into Codex project and global files.
linear
官方Manage issues, projects & team workflows in Linear. Use when the user wants to read, create or updates tickets in Linear.
Install Codex skills into $CODEX_HOME/skills from a curated list or a GitHub repo path. Use when a user asks to list installable skills, install a curated skill, or install a skill from another repo (
byungkyu 的更多技能
浏览全部技能按提示词自动选用合适的 dlazy CLI 音频模型,完成语音、音乐、音效与声音克隆。
类型化知识图谱引擎,将知识表示为可验证的实体-关系图谱。每个实体拥有类型、属性和关系, 所有变更在提交前根据类型约束进行验证。核心能力涵盖类型化实体创建与验证、关系图谱与基数约束、 Schema约束系统、无环验证、追加式变更日志、图谱遍历查询、跨技能契约声明、计划即图谱变换。 支持 Person、Organiza...
创建、检查和编辑Microsoft PowerPoint演示文稿和PPTX文件,确保布局可靠,支持中文交互和自动化操作。
按意图把图像、视频、音频请求分发到合适的 dlazy CLI 模型。
自动化审查代码安全漏洞、认证流和依赖合规,提供结构化报告支持多语言,无需复杂配置,适用开发者与企业团队。
模拟任意角色与经验级别的面试,支持技术、管理等多职能的求职面试演练与定制化练习。