用途
generate-runner 用于为任意技术生态生成定制化的 precommit 运行器(runner)。适用场景包括:非 Node 项目需要运行器、从通用运行器脱离(eject)、为项目定制运行器。
触发关键词:generate runner、create runner、custom runner、eject runner、runner for python、runner for rust、runner for go。
不适用场景:
- 需要运行 precommit 检查时,改用 /precommit 或 /precommit-fast。
- 需要安装已有运行器时,改用 /project-setup(自动安装)。
- 需要配置已发布运行器的 lint globs 时,先确认运行时运行器没有 @generated_at 头,然后编辑 .claude/runner-config.json,并为同一脚本角色设置 lintArgMode,否则 globs 不会生效。
主要能力
生态检测
扫描项目根目录的清单文件:
| 清单文件 | 生态 | 模板 ID |
|---|---|---|
| pnpm-lock.yaml | Node.js (pnpm) | node-pnpm |
| yarn.lock | Node.js (yarn) | node-yarn |
| package-lock.json 或 package.json | Node.js (npm) | node-npm |
| pyproject.toml | Python | python |
| Cargo.toml | Rust | rust |
| go.mod | Go | go |
若检测到多个,优先级为 Node.js > Python > Rust > Go。若均未检测到,则询问用户。
模板选择与定制
从 references/templates.md 加载对应生态的模板。读取项目特定配置:package.json scripts(lint、test、build 命令)、锁文件(包管理器选择)。注意:.claude/runner-config.json 不会为 lint 配置而读取,lintGlobs 和 lintArgMode 都不会作用于生成的运行器,因为模板根本不追加 lint 参数。
写入运行器
写入 .claude/scripts/precommit-runner.js(Node)或 .claude/scripts/precommit-runner.sh(非 Node)。
非 Node 运行器是为手动调用而生成的,不供 /precommit 使用。/precommit、/precommit-fast 和 /verify 只探测 .js 路径并在其存在时执行;它们目前都不检测 .sh 运行器。因此此处生成的 Python、Rust 或 Go 运行器是真实可用的脚本,但这些命令不会运行它——需直接调用,或将生态检查保留在已发布运行器中(它把 pytest/cargo/go 作为一等步骤编排)。
包含 eject 头:
@generated_at <ISO 8601>
@plugin_version <current version>
@template <template-id>
@ecosystem <ecosystem>
冲突处理:若目标文件已存在,通过 AskUserQuestion 提供 diff 预览。
验证
- 文件写入成功
- 脚本可执行(非 Node:chmod +x)
- 语法检查:Node 运行器用 node --check <path>,shell 运行器用 bash -n <path>
使用方式
参数:
| 参数 | 说明 | 默认值 |
|---|---|---|
| --ecosystem <name> | 强制指定生态(跳过检测) | 自动检测 |
| --output <path> | 自定义输出路径 | 依生态而定:Node 为 .claude/scripts/precommit-runner.js,否则为 .claude/scripts/precommit-runner.sh |
| --force | 覆盖已存在文件而不询问 | 关闭 |
输出示例:
## Generated Runner
- Ecosystem: <detected>
- Template: <template-id>
- Output: <path>
- Package manager: <pm>
生成的运行器归用户所有——插件更新不会覆盖它。可自由编辑以定制项目。
验证清单:生态正确检测、模板匹配生态、eject 头存在且元数据正确、运行器脚本有效(无语法错误)、已存在文件冲突已处理(询问或 --force)。
示例:
- 输入 /generate-runner:检测 Node.js (yarn) → 加载 node-yarn 模板 → 定制 → 写入 .claude/scripts/precommit-runner.js
- 输入 /generate-runner --ecosystem python:加载 python 模板 → 定制 → 写入 .claude/scripts/precommit-runner.sh
- 输入 /generate-runner --force:检测生态 → 覆盖已存在运行器而不询问
适用场景
- 非 Node 项目(Python、Rust、Go)需要 precommit 运行器
- 需要从通用运行器脱离并自定义
- 需要为特定项目定制运行器
限制
- 非 Node 运行器仅供手动调用,/precommit、/precommit-fast 和 /verify 不会运行它。
- 生成的运行器不追加 lint 参数,lintGlobs / lintArgMode 对其无效。
- 已发布运行器(scripts/precommit-runner.js 和 scripts/verify-runner.js)的 lint 参数注入为可选开启。lintGlobs 单独无效,需为同一脚本角色设置 lintArgMode。lintArgMode 取值仅接受 "eslint" 和 "none",按脚本角色键控,不能是裸字符串。优先级:.claude/runner-config.json 优先,首个有效值胜出;package.json → sd0x 为回退。不可用值会警告并回退而非锁定。
- 已知限制:在此修复前安装运行器的项目会继续运行旧版本,该版本将仅 ESLint 的标志传入仓库声明的任意 lint 脚本——会重写文件的非 ESLint linter 会将其读作路径并编辑源文件。修复插件源码不会触及该副本。补救:/install-scripts precommit-runner.js verify-runner.js --force,先加 --dry-run 读取写入集。
- 为何可选开启:运行器曾默认注入并根据脚本文本猜测接收方是否为 ESLint。markdownlint-cli2 将每个未识别参数视为文件 glob,因此在 --fix 下将 JavaScript 重写为 Markdown;一次运行损坏了本仓库 71 个文件。四代检测语法各自误分类,因此移除检测而非加深。
参考
各生态模板:references/templates.md