linear-sync
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineselinear-sync
linear-sync
Move the Linear issues linked to the current branch through their workflow
states. This skill is the single source of truth for how issues are
transitioned: resolving the live state IDs, extracting issue IDs from a branch
name, and the per-state transition rules. Callers decide when and whether
to fire it; the mechanics live here once so the rules don't drift across the
ship flow, branch cleanup, and the start-of-work transition.
将当前分支关联的Linear issues在其工作流状态间进行转换。本skill是issue状态转换方式的唯一权威来源:包括解析实时状态ID、从分支名称提取issue ID,以及各状态的转换规则。调用方决定何时以及是否触发它;转换机制统一在此实现,确保规则在发布流程、分支清理和工作启动转换等场景中保持一致。
Configuration
配置
Two knobs live in beside this file. Read it at the
start of a run and use its values throughout. Edit your copied to
match the consuming repo:
config.jsonconfig.json| Key | Meaning | Default |
|---|---|---|
| Linear team name used to resolve the live state IDs. Use the name, not the key — the key is renamed over time but the name is stable. | |
| Team-key prefixes that may appear in branch names. The issue-ID regex is built from these. | |
A neutral ships alongside it as a
template — copy it over and fill in your values, or edit
directly.
config.example.jsonconfig.jsonconfig.json本文件旁的 中有两个配置项。运行开始时读取该文件,并在整个流程中使用其值。请编辑你复制的以匹配当前仓库的需求:
config.jsonconfig.json| 键名 | 含义 | 默认值 |
|---|---|---|
| 用于解析实时状态ID的Linear团队名称。请使用名称而非key——key会随重命名而失效,但名称保持稳定。 | |
| 可能出现在分支名称中的团队key前缀。issue ID的正则表达式将基于这些前缀构建。 | |
随工具附带的中立模板 可作为参考——将其复制并重命名为后填写你的值,或直接编辑。
config.example.jsonconfig.jsonconfig.jsonUsage modes
使用模式
--dry-run$ARGUMENTS--dry-runNormal — resolve state IDs, extract the branch's issue IDs, apply the
transition, and report what moved:
bash
linear-syncDry run — resolve state IDs and each issue's current state, report the
intended transition (or skip reason) per issue, and exit without any
call:
save_issuebash
linear-sync --dry-runUnder the resolve + read steps still run (they are read-only), so the
preview is accurate; only the write in the transition step is
skipped. End the report with
--dry-runsave_issueDRY RUN — no issues were changed.--dry-run$ARGUMENTS--dry-run正常模式——解析状态ID,提取分支的issue ID,执行状态转换,并报告哪些issue发生了状态变更:
bash
linear-syncDry Run模式——解析状态ID和每个issue的当前状态,报告每个issue的预期转换(或跳过原因),然后退出不执行任何调用:
save_issuebash
linear-sync --dry-run在模式下,解析和读取步骤仍会执行(这些是只读操作),因此预览结果准确;仅会跳过转换步骤中的写入操作。报告末尾会显示
--dry-runsave_issueDRY RUN — no issues were changed.Resolving the target state (do this once per run)
解析目标状态(每次运行仅执行一次)
Call with
once to fetch the team's live workflow states. Each carries a stable
( / / / / / ), a
display , an , and a .
mcp__linear-server__list_issue_statusesteam: <linearTeamName>typetriagebacklogunstartedstartedcompletedcancelednameidpositionResolve the target by , not by display name. Display names are
customisable — a consumer may rename → or →
— so matching the literal name silently fails to find the state (the
biggest correctness gap for adopters). Map each transition to a concrete state:
typeIn ProgressDoingIn ReviewCode Review- In Progress → the state named "In Progress" (case-insensitive); else the earliest
startedbystarted.position - In Review → the state whose name matches "In Review" / "Review"; else, when there are ≥2
startedstates, the lateststartedbystarted; else the In Progress state.position - Done → the state named "Done"; else the earliest
completedbycompleted.position
startedpositionstartedidsave_issuePass the team name, not the key. Linear state IDs are per-team, and a
workspace's team can be renamed over its lifetime (e.g. CAT → WTF → AKW → ASW),
so a hardcoded key goes stale. The team name () does not move.
This is the canonical gotcha for adopters — resolve by name, every run.
linearTeamName调用 并传入 ,仅调用一次即可获取团队的实时工作流状态。每个状态包含一个稳定的( / / / / / )、显示名称、ID和位置。
mcp__linear-server__list_issue_statusesteam: <linearTeamName>typetriagebacklogunstartedstartedcompletedcancelednameidposition通过而非显示名称解析目标状态。显示名称可自定义——使用者可能会将重命名为,或把改为,因此匹配字面名称会导致无法找到状态(这是使用者最常遇到的正确性问题)。将每个转换映射到具体状态:
typeIn ProgressDoingIn ReviewCode Review- In Progress → 类型为且名称为"In Progress"的状态(不区分大小写);若不存在,则选择
started最早的position状态。started - In Review → 类型为且名称匹配"In Review" / "Review"的状态;若不存在,且有≥2个
started状态,则选择started最晚的position状态;否则选择In Progress状态。started - Done → 类型为且名称为"Done"的状态;若不存在,则选择
completed最早的position状态。completed
startedpositionstartedsave_issueid传入团队名称而非key。Linear状态ID是按团队划分的,且工作区中的团队可能会多次重命名(例如CAT → WTF → AKW → ASW),因此硬编码的key会失效。团队名称()是固定不变的。这是使用者最容易犯的错误——每次运行都要通过名称解析。
linearTeamNameExtracting issue IDs from the branch
从分支中提取issue ID
Build the issue-ID regex deterministically — mirror the canonical, tested
in the repo-root ,
which copies into each consuming bundle (ADR-0004) and which
exists for exactly this job:
buildIssueRelib/issue-keys.mjspnpm vendor:sync- Escape regex metacharacters in each key (a configured key such as would otherwise throw or silently widen the match).
C++ - Group the alternation. Wrap the keys in whenever there is more than one, so the
(?:…)binds to the whole alternation:-\d+. The naive join\b(?:A|B)-\d+\bis wrong — it parses as\bA|B-\d+\bor\bA, matching a bareB-\d+\band missingA. A single key needs no wrapper:A-7.\bA-\d+\b - Guard the empty case. With no configured keys, match nothing — never build
an empty alternation (it would match the empty string before every and inject bogus IDs like
-<digits>).-2
Match the result (with the flag) against the upper-cased branch name —
branches like carry the key in lower case, and a flow such as
produces upper-case branch names like . Keeping the
legacy keys means leftover branches from before a team-key rename are still
recognised. Deduplicate the matches. Bogus or malformed IDs simply error on lookup
and are skipped with a warning — no separate validation pass.
gasw-7-as-acquired--issue=A-7A-7-as-acquiredWhen a caller already has an list to hand (e.g. a changelog step emits
one), use that instead of re-extracting.
issues确定性地构建issue ID正则表达式——镜像仓库根目录 中经过测试的标准函数,该函数会通过复制到每个消费包中(ADR-0004),专门用于完成此任务:
lib/issue-keys.mjsbuildIssueRepnpm vendor:sync- 转义正则元字符——对每个key中的正则元字符进行转义(例如配置的key为时,若不转义会导致错误或匹配范围意外扩大)。
C++ - 分组备选分支——当有多个key时,将它们包裹在中,确保
(?:…)绑定到整个备选分支:-\d+。直接拼接的\b(?:A|B)-\d+\b是错误的——它会解析为\bA|B-\d+\b或\bA,匹配单独的B-\d+\b且无法匹配A。单个key无需包裹:A-7。\bA-\d+\b - 处理空配置情况——若未配置任何key,则不匹配任何内容——绝不要构建空的备选分支(否则会匹配每个前的空字符串,生成
-<数字>这类无效ID)。-2
将构建好的正则表达式(带标志)与大写的分支名称进行匹配——分支名称如中的key为小写,而这类流程会生成这类大写分支名称。保留旧key意味着团队key重命名前遗留的分支仍能被识别。对匹配结果进行去重。无效或格式错误的ID在查找时会直接报错,并被跳过同时给出警告——无需单独的验证步骤。
gasw-7-as-acquired--issue=A-7A-7-as-acquired若调用方已持有列表(例如变更日志步骤生成的列表),则直接使用该列表,无需重新提取。
issuesTransition rules
转换规则
For each issue ID, call to read its current state
(use its , not its display name). Decide using the progression order of
state types:
mcp__linear-server__get_issuetypetext
triage < backlog < unstarted < started < completedcanceledDuplicatestartedpositioncompletedcanceled- In Progress (fired when starting work on an issue) — apply from /
triage/backlog; skip from anyunstarted,started, orcompleted.canceled - In Review (fired on PR open/update inside a ship flow) — apply from /
triage/backlog, or from aunstartedstate earlier bystartedthan the resolved In Review (e.g. In Progress); skip once at or past In Review, orposition/completed.canceled - Done (fired on branch cleanup) — apply from /
triage/backlog/unstarted; skip fromstarted/completed.canceled
Apply a transition with using the resolved state
— it is unambiguous across renames. The display-name form
works only when the consumer kept Linear's default state names.
mcp__linear-server__save_issueidstate: "<target>"Under , skip this call. Still read each issue's
current state with and decide whether it would transition, but
report the intended move (e.g. /
) instead of writing it.
--dry-runsave_issueget_issueA-7: Todo → In Progress (would apply)A-9: In Review (would skip — already at/past target)is the Linear API's own US spelling — keep it as-is when referenced in code or config.Canceled
对每个issue ID,调用读取其当前状态(使用而非显示名称)。根据状态类型的递进顺序做出判断:
mcp__linear-server__get_issuetypetext
triage < backlog < unstarted < started < completedcanceledDuplicatestartedpositioncompletedcanceled- In Progress(开始处理issue时触发)——适用于/
triage/backlog状态;若处于任何unstarted、started或completed状态则跳过。canceled - In Review(发布流程中PR创建/更新时触发)——适用于/
triage/backlog状态,或处于unstarted类型中position早于解析出的In Review状态的情况(例如In Progress);若处于或超过In Review状态,或started/completed状态则跳过。canceled - Done(分支清理时触发)——适用于/
triage/backlog/unstarted状态;若处于started/completed状态则跳过。canceled
使用**解析得到的状态**调用执行转换——该ID在重命名后仍保持明确。使用显示名称形式仅在使用者保留Linear默认状态名称时有效。
idmcp__linear-server__save_issuestate: "<target>"在模式下,跳过调用。仍会调用读取每个issue的当前状态,并判断是否会执行转换,但仅报告预期的变更(例如 / ),而非实际执行写入操作。
--dry-runsave_issueget_issueA-7: Todo → In Progress (would apply)A-9: In Review (would skip — already at/past target)是Linear API自身使用的美式拼写——在代码或配置中引用时请保持原样。Canceled
Caller responsibilities (when / whether to fire)
调用方职责(何时/是否触发)
The skill owns the mechanics; each caller owns the policy:
- Start of work — transition to when work begins on an issue (unless already In Progress or further along). Run automatically; no prompt.
In Progress - Ship flow (PR open/update) — transition linked issues to automatically after the PR is created or updated. No prompt.
In Review - Branch cleanup — transition orphaned issues to only after explicit confirmation, default no. Linear's GitHub integration normally handles the
Donetransition on PR merge, so this prompt exists only for the rare case where the integration didn't fire (e.g. the issue ID was added after merge).Done
本skill负责转换机制;每个调用方负责触发策略:
- 工作启动时——开始处理issue时将其转换为状态(若已处于In Progress或更后续状态则跳过)。自动运行;无需提示。
In Progress - 发布流程(PR创建/更新)——PR创建或更新后自动将关联的issue转换为状态。无需提示。
In Review - 分支清理时——仅在**明确确认(默认不确认)**后,将孤立的issue转换为状态。Linear的GitHub集成通常会在PR合并时自动处理
Done转换,因此该提示仅用于集成未触发的罕见情况(例如issue ID是在合并后添加的)。Done
Standalone vs inside a caller
独立运行 vs 被调用方调用
- Standalone — resolve the target state, extract the branch's issue IDs, apply the transition, and report which issues moved and which were skipped. The default target is In Progress (the start-of-work transition that has no other home).
- Inside a caller — the caller supplies the target (and often the list) and decides whether to prompt; the mechanics above are unchanged.
issues
- 独立运行——解析目标状态,提取分支的issue ID,执行转换,并报告哪些issue发生了变更、哪些被跳过。默认目标状态为In Progress(这是工作启动时的转换,无其他适用场景)。
- 被调用方调用——调用方提供目标状态(通常还会提供列表)并决定是否提示;上述转换机制保持不变。
issues
Implementation
实现
No supporting scripts — the skill drives the Linear MCP tools directly
(, , ). The only repo-specific inputs
are the team name and the issue-ID prefixes, both read from .
list_issue_statusesget_issuesave_issueconfig.json无需辅助脚本——本skill直接调用Linear MCP工具(、、)。唯一的仓库特定输入是团队名称和issue ID前缀,两者均从读取。
list_issue_statusesget_issuesave_issueconfig.json