mcpField
L
linear-sdk-scripting

linear-sdk-scripting

github.com/cline生产力401.2k 次安装15 周前更新
代码仓库

关于 linear-sdk-scripting

linear-sdk-scripting 是一项通过官方 TypeScript SDK 和 Node.js 脚本操作 Linear 的技能。它涵盖常见的议题、团队、项目和周期操作,并提供认证与 SDK 使用指南。

主要功能

  1. 01使用 @linear/sdk 执行 Linear 操作
  2. 02读取和创建议题
  3. 03发表评论并更改议题状态
  4. 04查询团队、项目和周期
  5. 05提供分页与修改操作范例

适用场景

  1. 01读取或筛选 Linear 议题
  2. 02创建议题并添加评论
  3. 03更改议题的工作流状态
  4. 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 就停止操作;即使已有有效密钥并已持久化,这里的变量也几乎总是空的(参见“设置”)。

  1. 确保工作目录中已安装 SDK。参见“设置”。
  2. 在工作目录中编写一个小型 .mjs 脚本,导入 LinearClient 并完成任务。
  3. 先加载 shell 配置文件,再使用 node 运行脚本,以便读取已持久化的密钥(参见“执行模式”)。
  4. 如果因 401/AuthenticationLinearError 而失败,请加载 shell 配置文件并重试一次。只有重试仍然失败时,才说明密钥确实缺失或无效:与用户一起运行 API 密钥设置流程。

设置

1. 个人 API 密钥

SDK 会从 LINEAR_API_KEY 环境变量中读取 Linear 个人 API 密钥进行身份验证。

不要在操作前通过检查环境变量来判断是否存在密钥。这里的脚本运行在非交互式、非登录 shell 中,不会加载 ~/.zshrc、~/.zshenv、~/.bashrc 等文件,因此即使其中某个文件已持久化有效密钥,读取 $LINEAR_API_KEY 也会得到空值。此 shell 中变量为空,并不代表尚未配置密钥。

应先让脚本尝试执行任务(“执行模式”会先加载配置文件),只有在此之后身份验证仍然失败时,才将密钥视为缺失。参见“处理身份验证失败”。

只有在确实缺少密钥时,才引导用户创建密钥:

  1. 打开安全与访问设置:https://linear.app/settings/account/security

  2. 在“个人 API 密钥”下创建新密钥并复制(密钥以 lin_api_ 开头)。

  3. 请用户粘贴密钥,然后将其载入当前会话,这样无需打开新终端即可立即使用:

    export LINEAR_API_KEY="lin_api_REPLACE_ME"
    
  4. 持久化前先询问。密钥属于机密,持久化操作会写入用户拥有的文件,因此不要自行操作。务必先明确询问,例如:“你希望我将此密钥持久化到 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 主动发起的操作。如果用户拒绝或未回复,不要持久化密钥;下次会话时只需重新设置即可。

切勿在对话记录中再次输出密钥值,也不要将其提交到任何地方。请将其视为机密。

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(或脚本在返回任何数据前就崩溃),请按以下顺序恢复,不要直接跳到创建密钥:

  1. 加载 Shell 配置文件并重试一次。密钥可能已持久化在此 Shell 从未加载过的配置文件中。载入密钥后,重新运行同一脚本:

    for f in ~/.zshenv ~/.zshrc ~/.zprofile ~/.profile ~/.bashrc ~/.bash_profile; do
      [ -f "$f" ] && source "$f"
    done
    node "$LINEAR_DIR/task.mjs"
    

    (如果你已经使用规范执行模式中的前置命令运行过,配置文件就已加载;因此,只有在未使用该前置命令时,重试才会有帮助。)

  2. 只有在仍然无法通过身份验证时,才说明密钥确实缺失或无效。此时与用户一起设置 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 很庞大。不要猜测字段名或筛选器名称:

  1. 打开 references/docs-index.md,选择相关页面。
  2. 获取该页面(筛选、分页、SDK 数据获取与修改,或 GraphQL schema 参考),并使用其中的准确名称。

注意事项

  • 请从工作目录运行脚本(或指定其中的脚本),以便解析 @linear/sdk。NODE_PATH 无法为 ESM import 解析包;它只对 CommonJS require 有效。
  • 许多 SDK 属性和嵌套关联都是异步的,会返回 Promise 或连接对象。请对其使用 await(await issue.state、await issue.assignee)。
  • 连接对象支持分页。请使用 connection.pageInfo.hasNextPage 和 await connection.fetchNext(),或使用迭代方式。参阅 references/recipes.md。
  • 变更结果会公开 success 和已变更实体;实体访问器通常是一个 Promise(await payload.issue)。

评论

支持 Markdown