关于 linear-sdk-scripting
linear-sdk-scripting 是一项通过官方 TypeScript SDK 和 Node.js 脚本操作 Linear 的技能。它涵盖常见的议题、团队、项目和周期操作,并提供认证与 SDK 使用指南。
主要功能
- 01使用 @linear/sdk 执行 Linear 操作
- 02读取和创建议题
- 03发表评论并更改议题状态
- 04查询团队、项目和周期
- 05提供分页与修改操作范例
适用场景
- 01读取或筛选 Linear 议题
- 02创建议题并添加评论
- 03更改议题的工作流状态
- 04查找团队、项目或周期
MCP 相关
该技能被描述为 Linear MCP 服务的替代方案:它通过调用 Linear SDK 方法执行相应任务,而非使用 MCP。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ cline/ skills --skill linear-sdk-scripting安装后在 Claude Code 中输入/linear-sdk-scripting确认已加载。
附带文件references/docs-index.mdreferences/recipes.md
详细介绍
Linear SDK 脚本编写
通过编写一次性 Node 脚本并执行,使用官方 TypeScript SDK(@linear/sdk)操作 Linear。此方式可替代 Linear MCP 服务:MCP 能做的任何事(读取 issue、创建 issue、发表评论、更改状态、查询团队/项目/周期),都可以在这里通过调用 SDK 方法完成。
相比手写 GraphQL,SDK 更值得优先使用,因为它会规范化分页、关系遍历和 mutation 负载,而且方法名和输入名称都很容易预测。如果需要某个不熟悉的字段或筛选条件,请查阅 references/docs-index.md 中的文档索引,并获取对应的具体页面,而不要猜测。
工作流程一览
采取响应式方式:先尝试运行脚本,遇到身份验证失败时再恢复,只有万不得已时才创建密钥。不要因为当前 shell 中未设置 $LINEAR_API_KEY 就停止操作;即使已有有效密钥并已持久化,这里的变量也几乎总是空的(参见“设置”)。
- 确保工作目录中已安装 SDK。参见“设置”。
- 在工作目录中编写一个小型
.mjs脚本,导入LinearClient并完成任务。 - 先加载 shell 配置文件,再使用
node运行脚本,以便读取已持久化的密钥(参见“执行模式”)。 - 如果因 401/
AuthenticationLinearError而失败,请加载 shell 配置文件并重试一次。只有重试仍然失败时,才说明密钥确实缺失或无效:与用户一起运行 API 密钥设置流程。
设置
1. 个人 API 密钥
SDK 会从 LINEAR_API_KEY 环境变量中读取 Linear 个人 API 密钥进行身份验证。
不要在操作前通过检查环境变量来判断是否存在密钥。这里的脚本运行在非交互式、非登录 shell 中,不会加载 ~/.zshrc、~/.zshenv、~/.bashrc 等文件,因此即使其中某个文件已持久化有效密钥,读取 $LINEAR_API_KEY 也会得到空值。此 shell 中变量为空,并不代表尚未配置密钥。
应先让脚本尝试执行任务(“执行模式”会先加载配置文件),只有在此之后身份验证仍然失败时,才将密钥视为缺失。参见“处理身份验证失败”。
只有在确实缺少密钥时,才引导用户创建密钥:
-
在“个人 API 密钥”下创建新密钥并复制(密钥以
lin_api_开头)。 -
请用户粘贴密钥,然后将其载入当前会话,这样无需打开新终端即可立即使用:
export LINEAR_API_KEY="lin_api_REPLACE_ME" -
持久化前先询问。密钥属于机密,持久化操作会写入用户拥有的文件,因此不要自行操作。务必先明确询问,例如:“你希望我将此密钥持久化到 shell 配置文件(
~/.zshrc),以便在今后的会话中使用吗?”等待用户明确同意。只有在用户确认后,才能使用适用于其 shell 的命令自行写入:
- zsh:
echo 'export LINEAR_API_KEY="lin_api_REPLACE_ME"' >> ~/.zshrc - bash(或 macOS 登录 shell 中的
~/.bash_profile):echo 'export LINEAR_API_KEY="lin_api_REPLACE_ME"' >> ~/.bashrc - fish:
echo 'set -gx LINEAR_API_KEY "lin_api_REPLACE_ME"' >> ~/.config/fish/config.fish
这种在对话中明确征得同意的做法,才能确保此写入是用户请求的操作,而不是 Agent 主动发起的操作。如果用户拒绝或未回复,不要持久化密钥;下次会话时只需重新设置即可。
- zsh:
切勿在对话记录中再次输出密钥值,也不要将其提交到任何地方。请将其视为机密。
2. 在工作目录中安装 SDK
请使用一个有独立 node_modules 的专用工作目录。在其中运行脚本,即可直接使用顶层 await 的 import,无需通过 NODE_PATH 变通。需要 Node 18 或更高版本。
LINEAR_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/linear-sdk-scripting"
mkdir -p "$LINEAR_DIR"
cd "$LINEAR_DIR"
[ -f package.json ] || npm init -y >/dev/null
npm ls @linear/sdk >/dev/null 2>&1 || npm install @linear/sdk
此设置只需执行一次;之后重复使用该目录即可。
执行模式(规范方式)
对于每项任务,都在工作目录中编写一个脚本并运行。使用环境变量;不要将密钥直接写入脚本。
调用 node 前,先加载通用 Shell 配置文件,以便将已持久化的密钥载入环境(此 Shell 不会自动加载这些文件)。即使没有持久化密钥,这段前置命令也不会造成影响,因此请将其作为运行每个脚本的标准方式:
LINEAR_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/linear-sdk-scripting"
cat > "$LINEAR_DIR/task.mjs" <<'EOF'
import { LinearClient } from "@linear/sdk"
const linear = new LinearClient({ apiKey: process.env.LINEAR_API_KEY })
const me = await linear.viewer
const myIssues = await me.assignedIssues({ first: 20 })
for (const issue of myIssues.nodes) {
console.log(`${issue.identifier} ${issue.title}`)
}
EOF
for f in ~/.zshenv ~/.zshrc ~/.zprofile ~/.profile ~/.bashrc ~/.bash_profile; do
[ -f "$f" ] && source "$f"
done
node "$LINEAR_DIR/task.mjs"
说明:
- 脚本文件位于工作目录中,因此
import "@linear/sdk"会从该目录的node_modules中解析。 .mjs支持顶层await,因此无需使用异步包装器。- 如果需要在后续步骤中解析结果,请输出机器可读的数据(
console.log(JSON.stringify(...)))。
处理身份验证失败
密钥缺失或无效时,会报出 AuthenticationLinearError,其 status 为 401。检测到此错误后,转到密钥设置流程:
try {
const me = await linear.viewer
console.log(me.displayName)
} catch (e) {
if (e?.status === 401 || e?.constructor?.name === "AuthenticationLinearError") {
console.error("AUTH_FAILED: set up LINEAR_API_KEY")
process.exit(2)
}
throw e
}
如果看到 AUTH_FAILED(或脚本在返回任何数据前就崩溃),请按以下顺序恢复,不要直接跳到创建密钥:
-
加载 Shell 配置文件并重试一次。密钥可能已持久化在此 Shell 从未加载过的配置文件中。载入密钥后,重新运行同一脚本:
for f in ~/.zshenv ~/.zshrc ~/.zprofile ~/.profile ~/.bashrc ~/.bash_profile; do [ -f "$f" ] && source "$f" done node "$LINEAR_DIR/task.mjs"(如果你已经使用规范执行模式中的前置命令运行过,配置文件就已加载;因此,只有在未使用该前置命令时,重试才会有帮助。)
-
只有在仍然无法通过身份验证时,才说明密钥确实缺失或无效。此时与用户一起设置 Personal API key(创建并持久化新密钥),然后重新运行。
常见操作
下方提供简明示例。更完整的示例(筛选、分页循环、通过工作流状态关闭问题、批量操作)见 references/recipes.md。文档索引见 references/docs-index.md。
读取:
// Current user
const me = await linear.viewer
// List issues (newest first), with a filter
const issues = await linear.issues({
first: 25,
filter: { state: { type: { eq: "started" } } },
})
// A single issue by UUID
const issue = await linear.issue("UUID")
// Teams, users, projects
const teams = await linear.teams()
const users = await linear.users()
const projects = await linear.projects({ first: 50 })
写入(变更操作会返回包含 success 和实体的载荷,通常以 Promise 形式返回):
// Create
const created = await linear.createIssue({
teamId: "TEAM_UUID",
title: "Title",
description: "Markdown body",
})
const newIssue = await created.issue
// Update (e.g. retitle, reassign)
await linear.updateIssue("ISSUE_UUID", { title: "New title", assigneeId: "USER_UUID" })
// Comment
await linear.createComment({ issueId: "ISSUE_UUID", body: "Comment text" })
如果要将用户输入解析为 ID(如团队密钥 ENG、工作流状态名称 Done、指派对象的电子邮件),请先查询。有关先查询再变更的操作模式(包括如何查找团队的已完成工作流状态以关闭问题),请参阅 references/recipes.md。
需要处理本文未涵盖的内容时
Linear 的 schema 很庞大。不要猜测字段名或筛选器名称:
- 打开
references/docs-index.md,选择相关页面。 - 获取该页面(筛选、分页、SDK 数据获取与修改,或 GraphQL schema 参考),并使用其中的准确名称。
注意事项
- 请从工作目录运行脚本(或指定其中的脚本),以便解析
@linear/sdk。NODE_PATH无法为 ESMimport解析包;它只对 CommonJSrequire有效。 - 许多 SDK 属性和嵌套关联都是异步的,会返回 Promise 或连接对象。请对其使用
await(await issue.state、await issue.assignee)。 - 连接对象支持分页。请使用
connection.pageInfo.hasNextPage和await connection.fetchNext(),或使用迭代方式。参阅references/recipes.md。 - 变更结果会公开
success和已变更实体;实体访问器通常是一个 Promise(await payload.issue)。