{/* Trang này được tạo tự động từ SKILL.md của kỹ năng bởi website/scripts/generate-skill-docs.py. Chỉnh sửa nguồn SKILL.md, không phải trang này. */}
Tuyến tính
Tuyến tính: quản lý các vấn đề, dự án, nhóm thông qua GraphQL + Curl.
Siêu dữ liệu kỹ năng
| Nguồn | Đi kèm (được cài đặt theo mặc định) |
| Đường dẫn |
skills/productivity/linear ` | | Phiên bản |
1.0.0 ` | | Tác giả | Đại lý Hermes | | Giấy phép | MIT | | Nền tảng | Linux, macOS, Windows | | Thẻ |
Linear
, `Project Management
, `Issues
, `GraphQL
, `API
,
Productivity |
Tham khảo: đầy đủ SKILL.md
Sau đây là định nghĩa kỹ năng đầy đủ mà Hermes tải khi kỹ năng này được kích hoạt. Đây là những gì tác nhân coi là hướng dẫn khi kỹ năng được kích hoạt.
Tuyến tính — Quản lý vấn đề & dự án
Quản lý trực tiếp các vấn đề, dự án và nhóm tuyến tính thông qua API GraphQL bằng `curl
. Không có máy chủ MCP, không có luồng OAuth, không có phần phụ thuộc bổ sung.
Thiết lập
- Nhận khóa API cá nhân từ Cài đặt tuyến tính > Tài khoản > Bảo mật & quyền truy cập > Khóa API cá nhân (URL: https://Linear.app/settings/account/security). Lưu ý: trang Cài đặt > API cấp tổ chức chỉ hiển thị các ứng dụng OAuth và khóa thành viên không gian làm việc chứ không hiển thị khóa cá nhân.
- Đặt
LINEAR_API_KEYtrong môi trường của bạn (thông quaHermes setuphoặc cấu hình env của bạn)
API cơ bản
-
Điểm cuối:
https://API.linear.app/graphql(POST) -
Tiêu đề xác thực:
Authorization: $LINEAR_API_KEY(không có tiền tố "Bearer" cho khóa API) -
Tất cả các yêu cầu đều được POST với `Content-Type: application/JSON
-
Cả UUID và số nhận dạng ngắn (ví dụ: `ENG-123
) đều hoạt động cho `issue(id:) ``Kiểu uốn cong cơ bản:
`
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ viewer { id name } }"}' | Python3 -m JSON.tool
`
## Tập lệnh trợ giúp Python (thay thế tiện dụng)
Để viết một dòng nhanh hơn mà không cần GraphQL viết tay, kỹ năng này sẽ cung cấp một stdlib Python CLI tại
`scripts/linear_API.py
. Không phụ thuộc. Cùng một xác thực (đọc
`LINEAR_API_KEY
).
``` bash
SCRIPT=$(dirname "$(find ~/.Hermes -path '*skills/productivity/linear/scripts/linear_API.py' 2>/dev/null | head -1)")/linear_API.py
Python3 "$SCRIPT" whoami
Python3 "$SCRIPT" list-teams
Python3 "$SCRIPT" get-issue ENG-42
Python3 "$SCRIPT" get-document 38359beef67c # fetch a doc by slugId from the URL
Python3 "$SCRIPT" raw 'query { viewer { name } }'
`
``Tất cả các lệnh phụ:
`whoami
,
`list-teams
,
`list-projects
,
`list-states
,
`list-issues
,
`get-issue
,
`search-issues
,
`create-issue
,
`update-issue
,
`update-status
,
`add-comment
,
`list-documents
,
`get-document
,
`search-documents
,
`raw
. Chạy với
`
--help
` cho cờ.
Sử dụng tập lệnh khi: bạn muốn có câu trả lời nhanh mà không cần tạo GraphQL. Sử dụng tính năng cuộn tròn khi: bạn cần một truy vấn mà tập lệnh không gói gọn hoặc bạn muốn soạn các bộ lọc nội tuyến.
## Trạng thái quy trình làm việc
Tuyến tính sử dụng các đối tượng
`WorkflowState
` với trường
`type
. **6 loại trạng thái:**
| Loại | Mô tả |
|------|-------------|
|
`triage
` | Các vấn đề sắp tới cần xem xét |
|
`backlog
` | Đã ghi nhận nhưng chưa có kế hoạch |
|
`unstarted
` | Đã lên kế hoạch/sẵn sàng nhưng chưa bắt đầu |
|
`started
` | Đang tích cực làm việc |
|
`completed
` | Xong |
|
`canceled
` | Sẽ không làm |
Mỗi đội có các trạng thái được đặt tên riêng (ví dụ: "Đang tiến hành" là loại
`started
). Để thay đổi trạng thái của sự cố, trước tiên bạn cần có
`stateId
` (UUID) của trạng thái mục tiêu - trạng thái quy trình làm việc truy vấn trước tiên.
**Giá trị ưu tiên:** 0 = Không, 1 = Khẩn cấp, 2 = Cao, 3 = Trung bình, 4 = Thấp
## Truy vấn phổ biến
### Nhận người dùng hiện tại
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ viewer { id name email } }"}' | Python3 -m JSON.tool
`
### Liệt kê các đội
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ teams { nodes { id name key } } }"}' | Python3 -m JSON.tool
`
### Liệt kê trạng thái quy trình làm việc của một nhóm
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ workflowStates(filter: { team: { key: { eq: \"ENG\" } } }) { nodes { id name type } } }"}' | Python3 -m JSON.tool
`
### Danh sách các vấn đề (20 đầu tiên)
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ issues(first: 20) { nodes { identifier title priority state { name type } assignee { name } team { key } url } pageInfo { hasNextPage endCursor } } }"}' | Python3 -m JSON.tool
`
### Liệt kê các vấn đề được giao của tôi
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ viewer { assignedIssues(first: 25) { nodes { identifier title state { name type } priority url } } } }"}' | Python3 -m JSON.tool
`
### Nhận một vấn đề duy nhất (theo mã định danh như ENG-123)
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ issue(id: \"ENG-123\") { id identifier title description priority state { id name type } assignee { id name } team { key } project { name } labels { nodes { name } } comments { nodes { body user { name } createdAt } } url } }"}' | Python3 -m JSON.tool
`
### Tìm kiếm vấn đề bằng văn bản
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ issueSearch(query: \"bug login\", first: 10) { nodes { identifier title state { name } assignee { name } url } } }"}' | Python3 -m JSON.tool
`
### Lọc các vấn đề theo loại trạng thái
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ issues(filter: { state: { type: { in: [\"started\"] } } }, first: 20) { nodes { identifier title state { name } assignee { name } } } }"}' | Python3 -m JSON.tool
`
### Lọc theo nhóm và người được giao
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ issues(filter: { team: { key: { eq: \"ENG\" } }, assignee: { email: { eq: \"user@example.com\" } } }, first: 20) { nodes { identifier title state { name } priority } } }"}' | Python3 -m JSON.tool
`
### Liệt kê các dự án
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ projects(first: 20) { nodes { id name description progress lead { name } teams { nodes { key } } url } } }"}' | Python3 -m JSON.tool
`
### Liệt kê các thành viên trong nhóm
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ users { nodes { id name email active } } }"}' | Python3 -m JSON.tool
`
### Liệt kê nhãn
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ issueLabels { nodes { id name color } } }"}' | Python3 -m JSON.tool
`
## Đột biến phổ biến
### Tạo sự cố
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '{
"query": "mutation($input: IssueCreateInput!) { issueCreate(input: $input) { success issue { id identifier title url } } }",
"variables": {
"input": {
"teamId": "TEAM_UUID",
"title": "Fix login bug",
"description": "Users cannot login with SSO",
"priority": 2
}
}
}' | Python3 -m JSON.tool
`
### Cập nhật trạng thái sự cố
Trước tiên, hãy lấy UUID trạng thái mục tiêu từ truy vấn trạng thái quy trình làm việc ở trên, sau đó:
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "mutation { issueUpdate(id: \"ENG-123\", input: { stateId: \"STATE_UUID\" }) { success issue { identifier state { name type } } } }"}' | Python3 -m JSON.tool
`
### Gán một vấn đề
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "mutation { issueUpdate(id: \"ENG-123\", input: { assigneeId: \"USER_UUID\" }) { success issue { identifier assignee { name } } } }"}' | Python3 -m JSON.tool
`
### Đặt mức độ ưu tiên
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "mutation { issueUpdate(id: \"ENG-123\", input: { priority: 1 }) { success issue { identifier priority } } }"}' | Python3 -m JSON.tool
`
``###Thêm bình luận
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "mutation { commentCreate(input: { issueId: \"ISSUE_UUID\", body: \"Investigated. Root cause is X.\" }) { success comment { id body } } }"}' | Python3 -m JSON.tool
`
### Đặt ngày đến hạn
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "mutation { issueUpdate(id: \"ENG-123\", input: { dueDate: \"2026-04-01\" }) { success issue { identifier dueDate } } }"}' | Python3 -m JSON.tool
`
### Thêm nhãn cho một vấn đề
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "mutation { issueUpdate(id: \"ENG-123\", input: { labelIds: [\"LABEL_UUID_1\", \"LABEL_UUID_2\"] }) { success issue { identifier labels { nodes { name } } } } }"}' | Python3 -m JSON.tool
`
### Thêm vấn đề vào dự án
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "mutation { issueUpdate(id: \"ENG-123\", input: { projectId: \"PROJECT_UUID\" }) { success issue { identifier project { name } } } }"}' | Python3 -m JSON.tool
`
### Tạo dự án
`
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '{
"query": "mutation($input: ProjectCreateInput!) { projectCreate(input: $input) { success project { id name url } } }",
"variables": {
"input": {
"name": "Q2 Auth Overhaul",
"description": "Replace legacy auth with OAuth2 and PKCE",
"teamIds": ["TEAM_UUID"]
}
}
}' | Python3 -m JSON.tool
`
## Tài liệuTuyến tính **Tài liệu** là tài liệu văn xuôi (RFC, thông số kỹ thuật, ghi chú) được lưu trữ cùng với các vấn đề. Họ có truy vấn gốc
`documents
` và tìm nạp đơn
`document(id:)
.
### URL tài liệu và
`slugId
``URL tài liệu trông giống như:
`
https://linear.app/<workspace/document/<slug-<hexSlugId
`
``Đoạn hex ở cuối là
`slugId
. Ví dụ:
`https://linear.app/NousResearch/document/rfc-Hermes-permission-gateway-Discord-38359beef67c
` →
`slugId
` là
`38359beef67c
.
**Chi tiết lược đồ quan trọng:** phần nội dung Markdown nằm trong trường
`content
. JSON ProseMirror nằm trong
`contentState
` (không phải
`contentData
- trường đó không tồn tại và API trả về 400).
### Tìm nạp tài liệu bằng slugId``document(id:)
` chỉ chấp nhận UUID. Để tìm nạp theo sên hex của URL, hãy lọc bộ sưu tập:
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "query($s: String!) { documents(filter: { slugId: { eq: $s } }, first: 1) { nodes { id title content contentState slugId url creator { name } project { name } updatedAt } } }", "variables": \{"s": "38359beef67c"}}' \
| Python3 -m JSON.tool
`
``Hoặc thông qua trình trợ giúp Python:
`
``` bash
Python3 scripts/linear_API.py get-document 38359beef67c
`
### Tìm nạp tài liệu bằng UUID
`bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ document(id: \"11700cff-b514-4db3-afcc-3ed1afacba1c\") { title content url } }"}' \
| Python3 -m JSON.tool
`
### Liệt kê các tài liệu gần đây
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ documents(first: 25, orderBy: updatedAt) { nodes { id title slugId url updatedAt project { name } } } }"}' \
| Python3 -m JSON.tool
`
### Tìm kiếm tài liệu theo tiêu đề
Lược đồ tuyến tính không có gốc
`searchDocuments
. Thay vào đó, hãy sử dụng bộ lọc chuỗi con tiêu đề:
``` bash
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ documents(filter: { title: { containsIgnoreCase: \"RFC\" } }, first: 25) { nodes { title slugId url } } }"}' \
| Python3 -m JSON.tool
`
## Phân trang
Tuyến tính sử dụng phân trang con trỏ kiểu Rơle:
``` bash
# First page
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ issues(first: 20) { nodes { identifier title } pageInfo { hasNextPage endCursor } } }"}' | Python3 -m JSON.tool
# Next page — use endCursor from previous response
curl -s -X POST https://API.linear.app/graphql \
-H "Authorization: $LINEAR_API_KEY" \
-H "Content-Type: application/JSON" \
-d '\{"query": "{ issues(first: 20, after: \"Cursor_FROM_PREVIOUS\") { nodes { identifier title } pageInfo { hasNextPage endCursor } } }"}' | Python3 -m JSON.tool
`
``Kích thước trang mặc định: 50. Tối đa: 250. Luôn sử dụng
`first: N
` để giới hạn kết quả.
## Tham chiếu lọc
Bộ so sánh:
`eq
,
`neq
,
`in
,
`nin
,
`lt
,
`lte
,
`gt
,
`gte
,
`contains
,
`startsWith
,
`containsIgnoreCase
``Kết hợp các bộ lọc với
`or: [...]
` cho logic OR (mặc định là AND trong đối tượng bộ lọc).
## Quy trình làm việc điển hình
1. **Nhóm truy vấn** để lấy ID và khóa của nhóm
2. **Truy vấn trạng thái quy trình làm việc** để nhóm mục tiêu nhận UUID trạng thái
3. **Liệt kê hoặc tìm kiếm vấn đề** để tìm ra vấn đề cần giải quyết
4. **Tạo sự cố** với ID nhóm, tiêu đề, mô tả, mức độ ưu tiên
5. **Cập nhật trạng thái** bằng cách đặt
`stateId
` về trạng thái quy trình làm việc mục tiêu
6. **Thêm nhận xét** để theo dõi tiến độ
7. **Đánh dấu hoàn thành** bằng cách đặt
`stateId
` ở trạng thái loại "đã hoàn thành" của nhóm
## Giới hạn tỷ lệ
- 5.000 yêu cầu/giờ cho mỗi khóa API
- 3.000.000 điểm phức tạp/giờ
- Sử dụng
`first: N
` để hạn chế kết quả và giảm chi phí phức tạp
- Giám sát tiêu đề phản hồi
`X-RateLimit-Requests-Remaining
## Lưu ý quan trọng
- Luôn sử dụng công cụ
`terminal
` với
`curl
` cho lệnh gọi API — KHÔNG sử dụng
`web_extract
` hoặc
`browser
- Luôn kiểm tra mảng
`errors
` trong phản hồi GraphQL — HTTP 200 vẫn có thể chứa lỗi
- Nếu
`stateId
` bị bỏ qua khi tạo sự cố, Tuyến tính sẽ mặc định ở trạng thái tồn đọng đầu tiên
- Trường
`description
` hỗ trợ Markdown
- Sử dụng
`Python3 -m JSON.tool
` hoặc
`jq
` để định dạng phản hồi JSON cho dễ đọc