1. Vibe-coding的诱惑与失控:为什么你需要Spec-kit
先说个真实的场景。我接触Vibe-coding最早是从一个side project开始的,当时的需求很简单:做一个内部用的数据看板,把几个业务表的指标汇总成图表。我打开AI编程工具,用自然语言描述了页面布局、图表类型、刷新频率,AI大概花了二十分钟就把整个项目的骨架推了出来,前后端接口、图表组件、样式文件一应俱全。那一刻的感觉确实很爽,就像有人替你写完了作业,你只需要验收。
但这种爽感持续了大概两天。第三天需求变了:客户要求加一个新的筛选维度,并且要把某个图表的聚合逻辑从"按天"改成"按小时"。我打开那个由AI生成的代码仓库,试图找到负责聚合的那段逻辑,结果发现整个项目里散落着六七个版本的相似函数,有的写死在某一个组件内部,有的是一个通用工具函数,有的是在接口层直接处理。我根本不敢直接改,因为根本不知道哪个在真正生效。
这就是Vibe-coding最典型的困境。它把"写代码"这个动作的成本压到了极低,但把"理解代码、维护代码、修改代码"的成本推到了一个离谱的高度。你用自然语言描述了一个"感觉",AI给你生成了一大堆"实现",但你和AI之间从来没有一个关于"到底要做什么"的精确协议。感觉对上了,代码就对了;感觉没对上,你就得在AI生成的一大堆代码里猜谜。
于是我开始寻找一种方法,让Vibe-coding不只是"让AI写代码",而是"让AI按规格写代码"。这就是Spec-kit进入我视野的原因。
Spec-kit这个工具的出现,本质上是在解决Vibe-coding流程里最要命的一个问题:需求从模糊到精确的沉淀问题。它要求你在让AI动手之前,先写一份规格说明,也就是spec。你不是直接告诉AI"给我做一个看板页面",而是先定义清楚这个页面有哪些模块、每个模块包含哪些指标、指标的口径从哪里来、刷新的频率是多少、展示的顺序是什么、异常情况下怎么兜底。把这些东西全部落到一份结构化的文档里,再让AI基于这份文档去生成代码。
用一句话概括Spec-kit的核心思想:用规格的确定性,约束AI生成的不确定性。
它做的最重要的一件事,是把"人和AI之间的关系"从一个松散的混沌状态,变成了一个工程化的协作流程。人负责定义规格和验收,AI负责生成实现。而Vibe-coding原本的灵感体验也并没有丢失——你依然可以用自然语言去描述需求,只不过这些描述变得更结构化、更精确了。相当于你从一个"约等于"的表达方式,升级到了"严格等于"的工程语言。
这篇文章里,我会从Vibe-coding的痛点讲起,然后把Spec-kit的完整使用流程拆开揉碎,结合我实际跑过的两个项目(一个数据看板,一个内部审批小应用),把从写第一份spec到用AI生成代码再到迭代维护的完整链路记录下来。如果你想用Vibe-coding做正经项目,而不是只做一个demo,这篇文章应该能帮你少踩不少坑。
2. Spec-kit的设计逻辑:为什么"先写规格再写代码"能救Vibe-coding
2.1 一份好spec到底长什么样
我在第一次接触Spec-kit时,最大的困惑就是:spec这个东西,和PRD、技术方案、接口文档到底有什么区别?如果只是把PRD丢给AI,那为什么还需要Spec-kit?
后来我用了一个类比才彻底想明白。Vibe-coding就像你请了一个极其聪明、但极其缺乏常识的实习生。你跟他说"帮我把桌子收拾一下",他会真的去收拾,但可能把你的咖啡杯扔进垃圾桶,因为在他的理解里"收拾"意味着"清空桌面"。你需要的不是反复纠正他每一次的误操作,而是给他一本非常详细的《办公室整理手册》:什么东西放在哪个位置、哪些东西属于保留品、哪些属于垃圾、桌面的最终状态应该符合什么标准。
Spec-kit提供的正是这样一本手册。它定义了一套spec的结构,让机器能够理解和解析你的需求描述,然后通过结构化的方式把这条需求链完整地透传给AI。
我在实际使用中,一份合格spec通常包含这么几个层次:
目标层:这个功能要解决什么问题。不是描述具体怎么实现,而是描述最终用户的使用场景和预期结果。比如"运营人员每天上班第一件事是查看昨日核心指标,如果指标异常能在5分钟内定位到异常原因"。
范围层:哪些功能属于本次开发的边界,哪些明确不做。比如"本次只做看板页面的前端展示,不涉及告警推送"。
逻辑层:核心业务逻辑的定义。比如指标的计算口径、筛选条件的交互逻辑、权限的判断规则。这是spec里最重要的部分,也是AI最容易在代码里埋雷的部分。
界面层:页面布局、交互反馈、状态变化。不用太详细到像素级别,但要描述清楚每种状态下的界面表现。
验收层:定义"怎么样才算做完"。验收标准要可验证、可测量。比如"当筛选条件选择'过去7天'时,图表数据源请求参数中的start_time和end_time分别对应7天前的零点与当前时间"。
把这几层写清楚,你手里就有一份AI可以遵循的规格说明书了。Spec-kit会解析这份文档,把它转换成AI更容易理解和遵循的指令。
2.2 Spec-kit的流转机制:从spec到代码的完整链路
了解了spec的结构之后,有一个很关键的问题:Spec-kit是怎么把一份规格说明变成实际代码的?它和直接在对话窗口里写prompt的区别在哪里?
我理解下来,区别主要在三个环节。
环节一:规格的版本化沉淀。在传统的Vibe-coding里,你的需求藏在对话记录里。昨天你说了"A模块要做X",今天你又说了"A模块要做Y",AI会把这两段对话放在整个上下文中理解,最后很可能生成一个既有X又有Y的混合逻辑。而Spec-kit让spec成为独立于对话的版本化文件。你改的不是对话,你改的是这份规格文件本身。每次迭代,你都能清晰地看到规格版本的演变,AI的上下文也不会被历史对话的噪声污染。
环节二:上下文管理。大语言模型是窗口式的,它的上下文窗口有限,当对话越来越长,它就越容易遗忘早期的需求细节。Spec-kit把spec作为结构化的上下文输入,让AI在每轮生成时都聚焦在当前的规格内容上,而不是靠"记得我们前天聊过什么"来工作。这在项目一变大之后极其重要——我那个数据看板项目大概有三十多个组件文件,如果不依赖spec,AI根本不知道你当前要改的是哪一个组件的逻辑。
环节三:验收标准可执行化。你在spec里写的验收标准,不只是给人看的。Spec-kit可以配合自动化测试、lint规则等工具,把验收标准转换成可执行的检查项。代码生成之后,不是靠你肉眼去检查,而是靠工具去自动验证。这一步把"AI写的代码能不能用"从一种主观感受变成了客观质量门禁。
这三个环节解决了Vibe-coding体验里最让人胃疼的问题:对话即遗忘,感觉即偏差,验收靠猜。
3. 从0到1实操:用Spec-kit跑通一个数据看板项目
3.1 项目初始化:spec驱动的起点
我用一个具体案例来演示完整流程。假设我们要做一个"运营数据看板"的小项目,技术栈选的是前端React + 后端Node.js,这个选择本身就可以是Spec的一部分——你既然用Spec-kit定义需求,干脆把技术栈选型也写进spec里,这样AI生成时会严格遵循。
首先是项目的初始化。我用Spec-kit的标准流程创建了两个目录:一个是/specs,存放全项目的规格文件;一个是/src,存放AI生成的代码。规格文件按模块拆分,比如dashboard.md、api.md、>## 技术栈约束 - 前端框架:React 18,使用函数组件和Hooks,禁止使用类组件 - 样式方案:Tailwind CSS,禁止引入外部UI组件库 - 后端框架:Node.js + Express,禁止使用其他框架 - 数据存储:本阶段使用JSON文件模拟数据库,不引入数据库依赖 - API规范:RESTful风格,响应格式统一为 { code, data, message }
这些约束看着琐碎,但作用很大。它们定义了AI的生成边界,避免它自作主张引入一个UI组件库或者换掉整个技术栈。很多Vibe-coding项目最后变成不可维护的代码屎山,很大原因就是AI自由发挥太多。
3.2 编写第一份spec:从需求到验收标准
spec是整个流程的灵魂。我在初学Spec-kit时犯过一个错误:把spec写成了PRD语言,大段大段散文式的描述,AI有的地方读不明白,有的地方过于笼统,最终生成的代码和我的预期差距很大。
后来我总结出一套比较稳定的spec写法,以看板模块为例:
### 模块:运营数据看板 ### 目标 运营人员打开看板后,可以在一屏内查看到昨日核心业务指标和趋势变化。 ### 范围 - 包含:访问量统计、销售额统计、订单量统计、各渠道趋势图 - 不包含:用户画像模块、告警通知模块、报表导出功能 ### 功能逻辑 1. 指标卡 - 展示昨日PV、UV、销售额、订单量 - 数据来源:调用 GET /api/metrics/summary - 展示格式:数字需要千分位分隔,销售额保留两位小数并显示货币符号 - 刷新方式:页面加载时请求一次,手动点击刷新按钮可重新请求 2. 渠道趋势图 - 展示最近14天各渠道订单量的趋势变化 - 数据来源:调用 GET /api/metrics/channel-trend - 展示顺序:按渠道名称首字母排序 - 图表类型:折线图,各渠道使用不同颜色 - 空值处理:某一天某渠道无数据时,在折线上断开并标记为null ### 异常状态 - 接口请求失败时,在页面顶部展示错误提示条,并提供重试按钮 - 加载状态:首次进入页面时显示骨架屏,禁止使用加载转圈动画 ### 验收标准 1. 启动应用后,访问首页可以看到4个指标卡和1个折线图区域 2. 指标卡的数值与后端接口返回的数据一致,数值超过9999时显示为1.2万 3. 切换筛选时段,折线图数据相应刷新,且无页面刷新 4. 在后端接口停止的情况下,页面展示错误提示,不出现白屏 5. 所有组件文件命名遵循 kebab-case,如 metrics-card.tsx这里有几个容易踩坑的细节我必须多说两句。
第一,验收标准里的每一条都要可验证。比如"数值超过9999时显示为1.2万"这就是一条明确可测的规则。但如果你写"数据展示美观大方",AI就完全不知道你要什么。
第二,异常状态一定要写。很多Vibe-coding生成的代码在一切顺利时跑得很欢,一遇到接口报错就白屏或无限loading。Spec里把异常状态作为一等公民定义好,AI才能把它写进代码里。
第三,"禁止使用加载转圈动画"这种负面约束很重要。AI非常偏爱加载转圈动画,几乎所有现代前端工具的默认实现里都有这个东西。你如果不明确禁止,它一定会给你加一个Spinner。
3.3 让AI按spec生成代码:核心技巧
spec文件准备好之后,进入真正的生成环节。Spec-kit的用法有两种:一种是在它的编辑器界面里操作,另一种是把spec文件直接丢给支持上下文管理的AI编程工具,配合它的提示词工程来生成。
我个人的习惯是混合使用。遇到需要精确控制逻辑的模块,比如数据聚合逻辑、权限判断逻辑,我会把spec文件作为唯一上下文喂给AI;而遇到一些纯粹的UI实现,比如列表、卡片布局,我会在spec基础上额外给一些更感性的描述,比如"这几个卡片之间要有呼吸感,不要挤在一起"。
这里有一个非常实用的技巧:分步生成,而不是一次性生成整个项目。我第一次做的时候,直接把整份spec丢给AI让它一次性生成全部代码,结果AI在生成到第三个模块的时候就开始混乱了——它会在新建组件时把第一个模块的设计模式拿来套用,分不清各模块的边界。
后来我改变了策略:每次只让AI生成一个模块,生成完后立即人工review这个模块的代码,确认没问题后再进入下一个模块。这个过程叫"小步快跑",虽然看起来比一次性生成多花了一些时间,但从长期维护的角度来看,这点时间投入完全是值得的。
另外,在让AI生成每个模块时,我会在提示词里把对应模块的spec原文复制进去,并且要求它逐条对照:
请严格按照以下spec实现"渠道趋势图"模块。在开始编码之前,先列出你对这条spec的理解和可能的疑问点。编码完成后,请逐条对照spec中的验收标准做自我检查,并把检查结果输出。让AI"先复述再干活"这一点极其有用。很多时候AI自以为理解了需求,其实理解偏了。让它先说出"它对这条需求的理解",你可以及时纠正偏差。我第一次用这个技巧时,AI复述出来的理解里就漏掉了"空值断开"这个关键逻辑,赶紧修正,省得生成后返工。
4. Spec-kit实战中的常见问题与排查技巧
4.1 spec写得不够"机器可读",AI理解出现偏差怎么办
这是上手Spec-kit最常遇到的问题。你以为自己写得够清楚了,但AI还是理解得不对。比如我写"按天聚合",AI可能理解成了"按日期字符串排序",这两者在处理跨年数据时行为完全不一样。
一个可靠的解决方法是:在spec里尽量使用结构化的表达方式,而不是叙事性的描述。比如"按天聚合"这种表述本身是有歧义的,你应该写成:
聚合法则:以 yyyy-mm-dd 格式的日期字符串作为分组键,所有业务数据按照该分组键求和,日期升序排列。再比如,凡是涉及规则类的需求,尽量用"如果...那么..."的条件句式。它能直接把模糊的语义转成AI可以执行的逻辑结构。我在写spec时,但凡有规则,都会强制自己写成条件句,时间久了这几乎成了肌肉记忆。
另一个角度是逆向验证。如果AI生成的代码不符合预期,你要先检查是不是spec本身有歧义,而不是急着改代码。我统计过,在我实际项目中,AI理解偏差的case有80%都能追溯到spec文本的模糊表述。改spec比改代码高效得多,因为spec是根,代码是叶。
4.2 迭代过程中的spec漂移:怎么防止AI越写越偏
项目进入迭代期之后,一个新的问题会出现:spec漂移。当需求发生变化时,你往往只更新了某个模块的spec,但其他模块的spec可能已经是几周前写的,与当前需求不一致。如果这时候让AI生成代码,它可能把新旧不一致的逻辑混合在一起。
我遇到过的一个真实案例是:看板模块增加了一个"渠道对比"功能,但渠道趋势图的spec没有同步更新对比的前提条件,导致趋势图和对比图里的数据口径完全不一致,同一时间段的订单量数值对不上号。
解决spec漂移问题的办法是:迭代时强制走一遍"spec影响分析"流程。在修改spec之前,先检查哪些模块可能受影响——这个环节在大型项目里尤其重要,直接影响后续的代码生成质量。流程包括:
- 列出需求变更点,确定变更所属的功能模块
- 找出该模块的依赖方和关联模块,比如"趋势图数据源变更了,那么指标卡的总量统计是否也有影响"
- 逐一更新受影响的spec文件,而不是只改一个
- 在spec变更记录摘要里标注清楚本次改动的逻辑差异,方便以后追溯
这里我有一个具体执行方式:用Spec-kit的spec文件头部维护一个"变更日志"区块,格式很简单:
## 变更记录 - v1.0(2025-01-15):初始版本 - v1.1(2025-01-18):修改渠道趋势图的数据源,从 /api/metrics/channel-trend 变更为 /api/metrics/channel-trend-v2,新增渠道对比功能 - v1.2(2025-01-20):修复空值处理逻辑,断开的折线改为连接虚线有了这个变更记录,每次生成代码前AI都能看到清晰的演进轨迹,不会把已经废弃的旧逻辑又捡回来。
4.3 多人协作时,spec管理怎么避免冲突
Vibe-coding最常见的使用场景是单人作战,但如果你想把它引入一个小团队,spec管理就不可避免。一个项目的多个模块会由不同人去和AI交互,每个人都带着自己的spec和偏好,最后很容易产出风格不一致的代码。
我的建议是:spec文件的规划/同步/归档这三件事必须由一个人统一牵头管理,其他人只提交"需求变更申请",不在实际文件里直接改。我们把这种模式叫作"锚点统一、分支自由"。
锚点统一,指的是项目总纲、技术栈约束、公共模块规范、命名规范这些全局性spec,必须是一致的版本,不能各改各的。
分支自由,指的是各功能模块的详细spec,允许各模块负责人自行细化。你可以用"规格目录 + 模块负责人"的二维划分来管理,比如:
/specs/core——全局共享规格,由项目负责人维护/specs/modules/dashboard——看板模块规格,由A维护/specs/modules/approval——审批模块规格,由B维护
分工清楚之后,最大的好处是每个人的AI提示词上下文不会互相污染。A在生成看板代码时,只需要加载全局规格和看板模块规格,完全不需要看到审批模块的内容。
另外,多人协作时一定要约定代码生成的风格基准。同一个团队里,一个人让AI生成组件时偏好把样式写在单独的CSS文件里,另一个人偏好用CSS-in-JS,最后合并代码时冲突不断。在全局spec里直接用一份"代码风格检查清单"做统一约束,给AI生成时作为必读附加项,你就不用在review阶段一遍遍口头强调这些规约了。
5. 几个小技巧:让Spec-kit用起来更顺手
5.1 善用"例外追加"机制
再好的预判也不可能覆盖所有需求。实际开发中总有一些细节需求是你写spec时想不到的。我在做审批小应用时就遇到过这种场景:spec里只定义了审批表单的字段和流转逻辑,但没定义"审批备注超过30个字时,输入框要自动增高"这种交互细节。这种小细节如果在生成代码之后去改,又得回到对话里去描述一堆上下文。
我的处理方式是在spec文件末尾增加一个"例外追加"区块,专门用来记录那些在生成过程中发现、但规格里没有覆盖到的细节需求。追加时一句话即可,不需要更新整个spec的正式条款。到了下一次生成迭代时,这些追加需求会自动被加载,AI就会遵守了。
5.2 把验收标准的"自动化检查"做实在
我前文提到验收标准要可执行,实操上最好的方法就是把它拆成lint规则和单元测试。Spec-kit本身结合测试框架把部分验收标准自动化为断言,可以大幅减少人工check的疲劳感。
比如我之前做看板时,有一条验收标准是"接口失败时提示错误条且提供重试按钮"。我把它拆成了三条断言:渲染错误提示条、点击重试后重新发起请求、请求成功后错误条消失。这三条写在测试文件里,每次AI生成完代码,跑一下测试,这条标准是否满足就一目了然了。这让我不太需要一条条人工检查,既省力又精准。
能自动化的验收项一定要自动化,这个原则落实得越早,项目后期你从"疯狂人工review"里解放出来的时间就越多。
5.3 spec的颗粒度别走极端
最后说一个很实际的体会:spec不是越详细越好。我一开始追求每个模块都写超大篇幅,事无巨细全部定义,结果AI生成出来的代码嵌套了很多无意义的中间变量——因为它把你写的每一句话都当成需要显式处理的逻辑,反而生成了结构性冗余。AI的过度服从与不服从同样糟糕。
经过好几轮调试,我最后找到了一个相对合适的平衡点:spec只定义例外、规则和边界,不定义通用的实现方式。通用方案只需要在全局spec里声明一次,比如"UI采用网格布局",模块级spec里就不用再说一次"采用网格布局"。这样每一份spec的篇幅都控制在必要信息以内,AI的准确率和生成效率都大幅提高。
我把这种程度的spec戏称为"轻量规格"——它更像一个给AI的地图,而不是一个给AI的填空题答案。地图标记出哪里有山、哪里有河、哪里禁止通行,但具体怎么走,让AI自己找路。我最终用这个思路做了三个项目,整体体验都相当稳定:前期写规格文档的时间从最初的三小时缩短到四十分钟,后期返工率却至少下降了一半。
如果你计划用Vibe-coding做正经的项目,我强烈建议你从一份轻量级的spec开始,让AI第一次生成时就踩在规格画的边界内,然后持续维护这份spec。它不是把你和AI之间的对话记录完整保存,而是把你真实想要的那个系统描述得足够清楚,让AI的每一次进展都不跑偏。这套工作流我用了很久,真心觉得它值得一试。