关于 preflight
preflight 是面向代码仓库的变更范围 lint 技能,只检查分支改动相关的类别与路径,并区分新增和已有问题。适合希望在提交或发布流程中运行针对性检查的开发团队。
主要功能
- 01按分支改动范围运行 lint
- 02区分新增与已有违规
- 03支持 ESLint、markdownlint 和 actionlint
- 04提供范围内 lint 修复脚本
- 05按退出码驱动检查循环
适用场景
- 01提交前检查当前分支的 lint
- 02发布流程中设置 lint 门禁
- 03区分新问题与仓库存量问题
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rheged-studio/ agent-skills --skill preflight安装后在 Claude Code 中输入/preflight确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
config.example.jsonpackage.jsonREADME.mdscripts/classify-lint.mjslint-fix.mjspreflight.mjsscripts/lib/diff-lines.mjspaths.mjsscope.mjsscripts/lib/vendor/base-branch.mjs详细介绍
preflight
按变更门控、限定分支范围的 lint 预检。它只会针对 origin/<base>...HEAD 中相关的类别执行 lint,且仅检查变更路径——不会运行全仓库的 pnpm lint——然后将每项违规归类为新增(位于此分支新增或修改的行)或既有(本来就存在,只是恰好位于此分支触及的文件中)。
此技能是预检循环的唯一事实来源。它有两种调用方式:
- 独立运行(
/preflight)——快速检查“我的分支能否通过限定范围的 lint?”,修复会保留在工作树中。 - 在发布流程中运行(例如
/send-it)——在提交之后、变更日志和推送步骤之前运行的 lint 门禁。
所有捆绑脚本仅使用 Node 内置模块——无需 npm install,也无需构建步骤。它们操作的是使用方仓库的根目录(请在仓库根目录运行,以便 git 能解析分支差异)。
运行
- 确保基准分支是最新的:
git fetch origin <base>(基准分支会自动检测——请参阅“配置”)。 - 运行预检:
node skills/preflight/scripts/preflight.mjs(附加--dry-run可报告类别和限定范围的文件列表,但不对违规进行分类)。--dry-run是真正的预览——每个 linter 都会报告would-run,不会写入任何内容,包括.preflight-summary.json。脚本会先检查当前 Node 主版本是否与仓库指定版本一致——优先使用精确的engines.node版本指定(24.x、24.18.0),否则使用.nvmrc中的主版本;如果不匹配,则退出码为 1 并提示切换版本(nvm use/fnm use/mise use),以避免 ESLint 在错误的 Node 版本下运行。>=/^/~范围不算版本指定;两者都没有的仓库不会进行检查。 - 查看
.preflight-summary.json,了解运行的类别和违规计数(passed、deferred、blocking)。仅实际运行时才会写入,--dry-run时不会写入。这是临时草稿产物,绝不会提交——使用方仓库会将其加入 gitignore(rheged-skills-setup技能会在协调仓库时添加相应条目)。
脚本的退出码决定后续流程:
- 退出码 0 — 通过。 没有新增违规,且所有 linter 均运行成功。 继续。
- 退出码 1 — 存在新增违规(阻塞)。 在分支限定范围内的路径上运行
node skills/preflight/scripts/lint-fix.mjs,然后重新运行预检。重复此步骤,直到清除新增违规或用户中止。(在发布流程中,提交修复;独立运行时,将修复保留在工作树中,供用户审核并提交。)默认情况下,只有新增的_错误_会阻塞——新增的 ESLint 警告会作为非阻塞通知报告,不会导致门禁失败,与pnpm lint/ CI 一致(出现警告时退出码为 0)。设置blockOnWarnings: true可让警告也触发门禁(请参阅“配置”)。 - 退出码 2 — 仅存在既有违规。 显示列表并请用户选择:
- 立即修复——应用修复,(发布时)提交修复,然后重新运行预检。
- 延期处理——在 Linear 中创建债务事项(请参阅下文的创建债务事项)。 创建(或拒绝创建)后,决定是继续还是中止。
退出码 1 也可能表示某个 linter 运行失败(退出码非零,且没有可解析的违规)——请检查其 stderr;这同样会阻塞——或者表示 Node 主版本不匹配(请参阅步骤 2):切换 Node 版本并重新运行,不要将其视为 lint 失败。
类别
每个类别的运行条件取决于分支中的变更(与 CI 路径触发条件一致,范围更窄):
| 类别 | 运行条件 | 跳过条件 |
|---|---|---|
| ESLint | 分支差异包含可 lint 的代码,或 eslint/tsconfig 配置路径 | 仅修改 Markdown,或修改不可 lint 的内容 |
| markdownlint | 分支差异包含 .md / .mdx(遵循仓库忽略规则) | 没有 Markdown 变更;若缺少 markdownlint-cli2 二进制文件,则发出警告并跳过 |
| actionlint | 分支差异包含 .github/workflows/*.yml 或 .github/actionlint.yaml | 没有工作流变更;仅修改配置时会 lint 所有已跟踪的工作流;若缺少 actionlint 二进制文件,则发出警告并跳过 |
ESLint 按工作区运行(通过 pnpm --filter),另加一个根目录/脚本目录分组。
类型检查、测试和框架检查(例如 astro check)不属于预检范围——这些仍由 CI 负责。
独立运行与在发布流程中运行
- 独立运行(
/preflight)会执行 lint 预检和退出码循环,然后报告结果。发现新引入的违规项时,它可能会运行node skills/preflight/scripts/lint-fix.mjs并重新运行,但修复会留在工作区中——它不会提交、编写变更日志、推送或创建 PR。 - 在
/send-it中运行时,同一循环会作为 lint 门禁运行(提交后、变更日志处理前);修复会被提交,以便在编写变更日志前保持分支干净。变更日志及其验证是发布流程负责的独立门禁——不属于此技能。
配置
两个特定于仓库的输入会自动检测——通常情况下,使用此工具的仓库无需编辑任何内容:
- Lint 工作区根据
pnpm-workspace.yaml和各软件包的package.json推导得出:只有声明了lint脚本的工作区才会被纳入。这样无需手动维护列表,就能自动排除有意不进行 lint 的工作区和非软件包目录。 - 基础分支从
origin/HEAD检测(例如main、master、develop);若该符号引用不存在,则回退到main。
如需覆盖其中任一项,请在使用此工具的仓库根目录添加 preflight.config.json
(此文件旁附带 config.example.json 作为模板):
{
"baseBranch": "main",
"blockOnWarnings": false,
"workspaces": {
"web": { "filter": "@acme/web", "prefix": "apps/web/" }
},
"linearTeamName": "",
"debtProject": ""
}
可单独提供任意键;其他项仍会自动检测或使用默认值。对于非 pnpm 仓库、有意排除的项目,或检测器无法展开的嵌套工作区 glob,请使用覆盖配置。
blockOnWarnings(默认false)——是否让新引入的 ESLint 警告级别问题阻断门禁。默认关闭时,预检只会因新引入的错误(以及无法运行的 linter)而阻断;新引入的警告会作为非阻断项显示,这与pnpm lint/ CI 的语义一致。对于希望将分支新引入的警告级问题也纳入门禁的仓库,请设为true。 markdownlint/actionlint 的问题始终会阻断——警告/错误级别的区分仅适用于 ESLint。linearTeamName/debtProject——面向 Agent 的键,用于退出码 2 的延期路径(lint 脚本会忽略这两个键)。创建债务问题时,两者都必须为非空;请参阅创建债务问题。留空会禁用债务问题创建(告知用户设置这些键,或选择立即修复)——绝不在没有项目的情况下创建问题。
债务问题创建
当用户在 Exit 2 中选择 Defer 时,仅当仓库根目录的
preflight.config.json 中设置了 linearTeamName 和 debtProject,才创建 Linear 债务问题
(读取该文件;键缺失或值为空表示已禁用债务问题创建)。默认失败关闭:
- 如果任一键为空,或 Linear MCP 服务器不可用 → 不要
调用
save_issue。告知用户设置linearTeamName+debtProject(或 选择 Fix now)。仅当 MCP 不可用且用户仍想在不进行跟踪的情况下继续时,才静默跳过。 - 按名称解析团队(
linearTeamName),并通过list_projects解析项目 (debtProject可为名称、ID 或 slug)。未找到时 → 不要调用save_issue; 明确报错并指出未解析的值。 - 找到后 → 调用
save_issue,并传入team、project(始终传入)、涵盖 预先存在的违规项的标题/描述、被分配人为维护者,以及指向分支/PR 上下文的链接。绝不可省略project。
实现
捆绑脚本与此文件位于同一目录下的
scripts/ 中,并通过 node 直接调用——不使用 pnpm 别名,
也不执行 npm install:
scripts/preflight.mjs— 变更门控预检和退出码约定。scripts/lint-fix.mjs— 对分支中变更的路径执行限定范围的eslint --fix/markdownlint-cli2 --fix。scripts/classify-lint.mjs— 解析并将违规项分类为新引入或预先存在。scripts/lib/{scope,diff-lines,paths}.mjs— 共用辅助工具(工作区/基分支检测、差异行映射、路径规范化)。
这些脚本没有外部 npm 依赖(仅使用 Node 内置模块)。
参数
$ARGUMENTS