在项目中设置 Zuke
Zuke 将构建定义为一个在 Deno 上运行的 TypeScript 类。每个目标都是一个类字段;目标之间通过 this.<field>(而不是字符串)相互引用。包从 JSR (jsr:@zuke/...) 导入,而非 npm。
快速路径:zuke setup
@zuke/cli 工具可以自动搭建所有内容。全局安装一次,然后在目标项目中运行 setup:
deno install -A -g -n zuke jsr:@zuke/cli # 全局安装一次
zuke setup # 在项目根目录中运行
./zuke # 运行构建
不想全局安装?可以直接运行相同的向导:
deno run -A jsr:@zuke/cli setup
setup 标志:--dir <path>,--name <ClassName>,--force(覆盖现有文件),--yes(非交互式),--launcher-name <name>(当 zuke/ 目录已被占用时,以不同的名称写入启动器——现在目录冲突会失败并显示可操作错误,而不是静默跳过启动器)。
要读取 @zuke/* 包的 API,而不受 Node 仓库 @types/node 的干扰,请运行 zuke doc <package>(例如 zuke doc core)——它会在一个隔离目录中运行 deno doc。
迁移现有项目:zuke import
如果项目已经有 package.json 脚本或 Makefile,优先使用 zuke import 而不是 setup——它会读取这些文件并生成一个 zuke.ts,为每个任务创建一个目标,这是一个可用的起点,而不是一个空白的构建:
zuke import # 自动检测 package.json,然后是 Makefile
zuke import --from makefile # 或指定来源 (package.json | makefile)
每个脚本/目标都会成为一个 target();一个命令映射到 CmdTasks.exec(...)——这是一个占位符,而不是最终目标:在验收之前,请检查包目录(llms.txt 的 ## Packages 列表,或 zuke-write-build 的速查表 中的表格),查找与该命令匹配的 @zuke/<tool> 包装器,并用它替换占位符——对于有类型包装器的工具,将 CmdTasks.exec 保留在原位是一个错误,而不是捷径。&& 链变成顺序步骤,run/前置条件委托变成 .dependsOn(...),任何过于特定于 shell 而无法翻译的内容(管道、重定向、环境变量赋值)都被保留在 // TODO 后面,以便文件仍然可以编译。它像 setup 一样搭建启动器和 deno.json,并接受相同的 --dir、--name、--force、--yes 标志。之后,使用 zuke-write-build 技能来完成替换任何剩余生成的 CmdTasks.exec 调用,改用类型化的 *Tasks 包装器。
zuke setup 写入的内容
zuke.ts—— 一个入门构建类,包含一个示例目标和一个default。./zuke+./zuke.ps1—— 用于定位项目并使用PATH上的 Deno 运行zuke.ts的启动器。如果缺少 Deno,它们会指向官方安装文档并退出,而不是将安装脚本通过管道输入到 shell 中(那将下载并执行未经验证的代码)。一旦deno.lock存在,它们会传递--frozen,这样第一次运行会写入锁文件,之后的每次运行都会验证它。deno.json—— 合并以添加zuke任务,如果不存在则添加fmt/lint/test。合并是全有或全无:如果已经声明了zuke任务,则完全保留文件原样;无法解析的文件会跳过并显示一条通知。zuke.json——{ "name": "..." },标记仓库根目录。.gitignore—— 创建或追加,以便忽略.zuke/(缓存和持久运行状态存储在那里);如果已包含则保持原样。
运行构建
./zuke # 运行默认目标 (Windows: .\zuke.ps1)
./zuke <target> # 运行特定目标
./zuke --list # 列出所有目标
./zuke --list --json # 将整个构建表面(命令、标志、目标)输出为 JSON
./zuke <target> --dry-run # 打印计划但不执行
CLI 是自描述的:./zuke --help 打印使用语法以及构建的实时目标和参数,因此代理可以发现真实的命令表面而不是进行猜测。对于希望通过类型化调用来操作构建的 AI 客户端,zuke mcp 会运行一个模型上下文协议服务器(使用 claude mcp add zuke -- deno run -A zuke.ts mcp 注册;添加 --allow-run 可让代理执行目标,而不仅仅是检查它们)。
如果已经安装了 Deno,也可以使用 deno task zuke <target> 或 deno run -A zuke.ts <target>。-A 标志授予权限,因为目标通常运行进程并接触文件。这些与启动器并不完全等同:搭建的 zuke 任务故意省略了 --frozen,因此它可以修复过时的锁文件,而 ./zuke 则会因该锁文件而失败。
手动设置(无 CLI)
在项目根目录创建 zuke.ts,扩展 Build,使用 target() 声明目标,并在底部调用 await run(MyBuild):
import { Build, run, target } from "jsr:@zuke/core";
import { DenoTasks } from "jsr:@zuke/deno";
class CI extends Build {
lint = target().executes(() => DenoTasks.lint());
test = target().dependsOn(this.lint)
.executes(() => DenoTasks.test((s) => s.allowAll()));
default = target().dependsOn(this.test).executes(() => {});
}
await run(CI);
使用 deno run -A zuke.ts test 运行。(要获得 ./zuke 启动器的体验,请优先使用 zuke setup,它会为您放入启动器脚本。)
查找确切的 API——永远不要猜测
每个外部工具都有一个类型化的 *Tasks 包装器;不要回退到 Deno.Command 或手写的 shell。 首先确认是否存在包装器——llms.txt 的 ## Packages 目录或 zuke-write-build 的速查表 中的表格是回答这个问题的唯一方法;逐包的 deno doc 需要一个名称作为目标,因此它无法揭示包装器的存在。一旦知道了包名,获取其确切签名:
- 在命令行中指定单个包:
deno doc jsr:@zuke/<package>。在消费者仓库中优先使用此方法——它会解析项目实际安装的版本,因此不会描述该版本缺少的 API。 - 每个包的完整类型化表面都在
llms-full.txt中(由llms.txt索引)——位于 Zuke 仓库本身的根目录,或来自消费者仓库 https://raw.githubusercontent.com/zuke-build/zuke/master/llms-full.txt(索引:https://raw.githubusercontent.com/zuke-build/zuke/master/llms.txt)。两者都追踪master分支,因此它们可能记录了已合并但尚未发布的符号;使用它们来查找存在的内容,然后使用deno doc确认签名。
项目搭建完成后,使用 zuke-write-build 技能来添加和编辑目标。