Spec Kit 如何编写自定义 Bundle:从 bundle.yml 到 validate 与 build 产出安装制品
如果你已经用 Spec Kit 的扩展、预设、工作流和步骤搭好了某个团队或角色的组件栈,接下来要做的就是把它们打成一个可版本化、可安装的 bundle:写一份 bundle.yml 清单,用 specify bundle validate 检查清单是否合法、组件引用能否解析,再用 specify bundle build 产出单个 .zip 安装制品。本文以 developer 示例 bundle 为参照,完整走一遍"写清单 → 校验 → 打包"这条路径,并给出文档中有依据的验证方式和常见校验报错。
Bundle 是什么:一份清单加一组可安装引用
按 Bundles 参考文档 的说法,bundle 把既有的 Spec Kit 组件——extensions、presets、workflows、steps——组合成一个单一、带版本、可安装的单元。它本身不引入新的运行时行为,只是分发放置层:安装时按清单中固定的版本解析各组件,幂等地逐个安装,并记录来源以便后续移除或刷新。
一个 bundle 目录的最低要求由打包逻辑定义:目录下必须有 bundle.yml,且必须有一个面向使用者的 README.md,否则 build 会直接拒绝并提示 No README.md found ... Every bundle must ship a README.md describing it.。清单的完整字段可对照 developer 示例:
schema_version: "1.0"
bundle:
id: "developer"
name: "Developer"
version: "1.0.0"
role: "developer"
description: "Spec-Driven Development setup for developers: implementation planning, task breakdown, and code review."
author: "spec-kit-examples"
license: "MIT"
requires:
speckit_version: ">=0.9.0"
tools: []
mcp: []
provides:
extensions:
- id: "agent-context"
version: "1.0.0"
presets:
- id: "implementation-planning"
version: "1.0.0"
priority: 10
strategy: "append"
steps:
- id: "plan-implementation"
- id: "break-down-tasks"
workflows:
- id: "spec-to-implementation"
version: "1.0.0"
tags: ["development", "implementation", "code-review"]
写清单时需要遵守的约束如下,全部来自清单校验逻辑与契约测试(test_manifest_schema.py):
bundle下id、name、version、role、description、author、license均为必填;字段值为空(YAML 里写成author:这种显式 null)会被按缺失报错。requires.speckit_version也是必填,且必须是合法的版本约束。schema_version只接受当前支持的值(示例用的是"1.0"),写其他值会被拒绝。bundle.version必须是 semver,如1.0.0;id必须是可以当作路径片段的 slug(如team-a.bundle_1合法,../evil会被结构性校验标记)。provides中 extensions、presets、workflows 的每个组件都必须用version固定版本,唯独 steps 可以省略版本。- presets 额外要求两个字段:
priority(必须是整数,写"high"这类字符串会直接抛出priority must be an integer)和strategy(示例中是"append",填"merge"这类未定义值会被拒绝)。 requires.tools、requires.mcp、tags都必须是字符串列表,写成单个字符串(如tags: "security")会被拒绝,而不是按字符拆分。- 清单可选地声明
integration(必须是一个 mapping,不能是裸字符串)。声明后 bundle 就不再是 integration-agnostic 的:它绑定特定集成,而示例中的 agnostic bundle 则继承项目当前活跃的 integration。如果 bundle 目标集成与已初始化项目的活跃集成不同,安装会直接中止且不产生任何改动。
用 validate 检查清单与组件引用
清单写好后,在 bundle 所在目录或任意位置都可以显式指定路径运行校验:
specify bundle validate --path examples/bundles/developer
--path 接受 bundle 目录或 bundle.yml 文件路径,缺省为当前目录;--offline 表示只对照 bundled/已安装组件校验引用。校验做两件事:
- 结构性检查:上面列出的必填字段、semver、slug、pin、priority/strategy 等规则,不合法项会逐条以字段名报错,例如缺 license 时报
bundle.license。 - 引用解析检查:清单里每个组件引用会依次对照 bundled 组件、项目已安装组件,以及在线时的活跃 catalog。只有当某个可达的 catalog 明确确认组件不存在时,校验才以 error 失败;离线校验、或 catalog 不可达导致"无法确认"的引用会降级为 warning,让编写流程可以继续。
所以判断标准是:输出中没有 error 即通过;warning 不阻塞,但如果你依赖非默认 catalog 的组件,需要确认用户侧已添加对应 catalog 源,否则安装时这些引用可能解析不到。
用 build 产出 .zip 安装制品
校验通过后执行构建:
specify bundle build --path examples/bundles/developer --output dist/
--path 指定 bundle 目录(缺省为当前目录),--output 指定制品输出目录。构建行为在 packager 实现 中定义,几个直接影响产物的点:
- 产物命名为
<bundle id>-<version>.zip,例如developer-1.0.0.zip,输出到--output目录(未指定则输出到 bundle 目录本身)。 - 构建前会先做清单校验,manifest 非法时拒绝构建,并提示"Run 'specify bundle validate' and fix",同时列出具体错误。
- 打包内容限于 bundle 目录内的文件;
.git、__pycache__、.DS_Store以及符号链接一律排除,目录内之前构建过的同 bundle 的*.zip制品不会被打进新制品。 - 构建是可复现的:相同输入得到逐字节一致的制品(固定的 zip 时间戳与归一化权限)。
验证制品可安装
制品产出后的验证路径与安装命令同源:specify bundle install 的参数既可以是 catalog 里的 bundle id,也可以是本地路径——构建好的 .zip 制品、bundle 目录、或 bundle.yml 文件都可以直接作为本地源安装,且本地源安装不查询 catalog 栈:
# 用构建出的制品安装(在目标项目目录内)
specify bundle install dist/developer-1.0.0.zip
如果当前目录还不是 Spec Kit 项目,install 会先初始化项目再安装,所以在一个干净目录里执行这条命令就是对 bundle 的端到端验证。安装是幂等的(已存在的组件会被跳过);失败时不写来源记录,并会尽力回滚本次运行安装的组件。
安装后可以用 specify bundle list 查看项目中已安装的 bundle、版本、组件数与安装时间;specify bundle info <bundle_id> 则展示"完全展开后的组件集合"——每个 extension、preset、step、workflow 及其固定版本,这个预览就是 install 实际应用的计划,可用来核对制品内容与预期一致。
常见校验报错怎么读
契约测试覆盖了 validate 的多数拒绝路径,遇到报错时可以这样对照:
- 报
bundle.<字段名>:对应必填字段缺失或为 null,按字段名补齐。 - 报
semver:bundle.version不是合法的语义化版本号。 - 报
priority/strategy:preset 条目缺字段或strategy取值不受支持;priority must be an integer表示 priority 写了非整数值。 - 报
must be pinned:extensions/presets/workflows 下的某个组件漏了version。 - 报
Unresolved reference ...:某个组件引用在所有可检查的来源里都不存在——检查组件 id 拼写,或确认用户环境是否已添加该组件所在的 catalog。 - 报
'tags' must be a list of strings/'provides' must be a mapping when present这类类型错误:对应字段写成了标量或非 mapping 值。
发布前的收尾
如果 bundle 要交给其他人使用,参考文档给出的路径是:先在本地完成 validate 与 build,然后自行托管生成的制品与 catalog 元数据(catalog 条目指向 bundle 制品,但 bundle.yml 内声明的组件在用户安装时仍然要走 bundled 组件、已安装组件或活跃的 extension/preset/workflow/step catalog 解析)。如果引用了非默认 catalog 的组件,需要把 catalog 地址写进文档,并在添加了这些 catalog 的干净项目里实测安装路径。社区 bundle 的提交要求见 Community Bundles 文档,其中明确要求提交包含由 specify bundle build 产出的版本化制品、说明用途/组件/依赖 catalog 的文档,以及干净项目的测试证据。
对仓库内四个示例 bundle(developer、product-manager、business-analyst、security-researcher)做同样的校验与构建,可以直接沿用 developer 示例 README 给出的命令形式,替换 --path 指向对应目录即可。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0631
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
video-shotcraftAI宣传片skill,使用 Remotion 制作电影级产品视频:提供106 张镜头配方卡和可复用的视频魔板。适用于 Claude Code 与 Codex以及所有其他智能体Markdown00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python09
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00