前言在实际使用 Claude Code 等 AI 编程工具的过程中开发者普遍遇到一个痛点描述了功能需求代码能跑但完全不符合项目的实际约束。本文从问题根源出发结合 Spec Kit 方法论和 Claude Code 原生的 CLAUDE.md 机制系统介绍规范驱动开发的思路与落地方式。一、AI 编程的「需求漂移」从何而来先看几个典型场景你说「做一个用户登录功能」它给你写了 JWT bcrypt 的完整方案但项目用的是 session-based auth。你说「优化一下这个查询」它直接重构了整个数据层。你说「加个分页」它顺手把 REST API 改成了 GraphQL。这不是 Claude Code 的 bug而是大模型的结构性工作方式决定的。1.1 根本原因语义缺口的默认填充大模型生成代码时依赖的是训练数据里的「概率最优解」。prompt 越模糊模型越倾向于输出统计意义上最常见的实现方式。链路如下模糊的 prompt → 模型填补语义缺口 → 用通用最佳实践替代未说清的约束 → 输出结果偏离实际项目约束具体来看这个例子❌ 模糊 prompt 帮我写一个文件上传功能 ✅ AI 的「合理」推断 - 用 multer 处理 multipart/form-data - 文件存到 /uploads 目录 - 返回文件 URL - 加上文件大小限制 ❌ 但项目实际约束 - 已有 AWS S3 封装好的 upload util - 文件路径有特定格式规则 - 需要与现有 audit log 系统集成 - 有自己的 error handling 约定四个约束一个没出现在 prompt 里AI 全部用默认方案替代。代码能跑但接入系统需要大量改造。1.2 为什么多轮纠正不解决问题很多开发者的第一反应是「多轮对话逐步纠正」。这条路走得通但有两个隐藏陷阱上下文消耗每次纠正都在消耗上下文窗口后续任务不保证记住之前确立的约束。会话隔离新开一个对话之前所有纠正全部清零需要重新建立 context。在 vibe coding 场景下问题更突出跟着 AI 节奏走一边生成一边微调等回过头来代码架构已经和最初设想相差甚远。二、Spec Kit把约束写成文档GitHub Spec Kit 11 万 Stars解决的正是这个问题。核心思路很直接与其每次重新解释约束不如把约束写成文档让 AI 每次工作前先读它。Spec Kit 的核心是一个spec.md文件示例结构如下# 项目规范 ## 技术栈约束 - Runtime: Node.js 18, TypeScript 5.x - 数据库: PostgreSQL via Prisma ORM禁止直接写 SQL - 认证: 使用 /lib/auth 的 session 封装不引入新的 JWT 库 - 文件存储: 统一使用 /lib/storage 的 S3 封装 ## 代码风格 - 错误处理: 统一 throw AppError 类不使用 console.error - API 响应格式: { data, error, meta } 结构 - 文件命名: kebab-case组件用 PascalCase ## 禁止事项 - 不修改 /lib 目录下的基础设施代码 - 不引入 spec 里未列出的新依赖 - 不修改数据库 schema只读操作 ## 当前任务 [在这里描述具体任务]AI 读完这份规范再开始写代码语义缺口被规范填充漂移空间大幅压缩。三、CLAUDE.mdClaude Code 的原生规范方案如果使用的是 Claude Code有一个更原生的方式CLAUDE.md 配置文件。这是 Claude Code 使用技巧里最容易被忽视的功能之一。3.1 工作机制在项目根目录创建CLAUDE.mdClaude Code 会自动读取它作为每次会话的系统上下文无需在每次对话里手动粘贴约束说明。3.2 CLAUDE.md 模板# CLAUDE.md ## 项目背景 这是一个 SaaS 产品的后端服务使用 Express TypeScript PostgreSQL。 ## 核心约束 1. 所有数据库操作通过 src/db/ 里的 repository 层不直接调用 Prisma 2. 认证逻辑在 src/middleware/auth.ts不要重复实现 3. 日志统一用 src/lib/logger基于 pino ## 代码生成规则 - 新增 API endpoint 必须在 src/routes/ 对应文件里注册 - 数据验证用 zodschema 放在 src/schemas/ - 错误处理继承 AppError定义在 src/errors/ ## 测试约定 - 单元测试用 vitest - 测试文件和源文件同目录命名 *.test.ts ## 当前上下文 Sprint 目标完成用户权限模块本周不做性能优化3.3 团队协作价值将CLAUDE.md提交到 Git 仓库团队里所有人使用 Claude Code 时都会自动加载这份上下文。这相当于把 AI 的 onboarding 文档版本化管理新成员和 AI 都能从同一份规范出发。四、两种方案的核心逻辑Spec Kit 和 CLAUDE.md 解决的是同一个问题让 AI 在你的约束空间里工作而不是在统计意义上的最优解空间里工作。维度传统 prompt 工程规范驱动开发约束表达散落在每次 prompt 里集中在规范文档里会话持久性新对话重置通过文件持久化团队一致性依赖个人习惯版本化、可共享维护成本每次重复描述一次写入持续生效漂移风险高低用一个类比来理解你不会跟新入职的工程师说「写个登录功能」然后等交付。你会先给他项目文档、代码规范、架构说明再分配具体任务。AI 需要同样的 onboarding只是它每次「入职」都要重新来一遍——除非你把这个文档固化下来。五、实操5 分钟搭起规范体系Step 1列出「AI 最容易搞错的地方」通常包括以下几类自定义工具库和封装已有的 util、helper特殊的目录结构约定团队代码风格要求命名、注释、错误处理不能动的遗留代码区域禁止引入的依赖或技术栈Step 2创建 CLAUDE.mdtouchCLAUDE.md按模板填充重点放在两类内容禁止做什么明确列出不允许的操作比「请遵循最佳实践」更有效。必须用哪些现有封装列出路径避免 AI 重新实现已有功能。Step 3迭代完善每次 Claude Code 跑偏问自己这条约束CLAUDE.md 里有没有写没有就补进去。一两个 sprint 之后你会有一份相当完善的规范文件。进阶用法任务级 spec 文件对于复杂功能模块可以在 CLAUDE.md 基础上再加一个任务级的 spec 文件# 目录结构建议.claude/ specs/ payment-module.md user-permissions.md notification-system.md在 Claude Code 对话里显式引用请先读 .claude/specs/payment-module.md然后实现支付回调处理这种方式特别适合需要多次对话才能完成的大型功能模块每次对话都从同一份 spec 出发保证实现方向一致。六、常见问题QCLAUDE.md 写多长合适没有固定标准但有个原则只写「AI 容易用错误方式实现的约束」不要把所有项目文档都塞进去。过长的 CLAUDE.md 会稀释关键约束的权重。建议控制在 100 行以内核心约束用列表格式清晰表达。QCLAUDE.md 和 prompt 里的约束冲突怎么办CLAUDE.md 作为系统上下文加载优先级高于单次 prompt。如果某个任务需要临时突破某条约束在 prompt 里明确说明「本次任务例外」即可。Q非 Claude Code 工具也能用这套方法吗可以。Spec Kit 的spec.md方案与工具无关手动在对话开始时粘贴规范内容同样有效。CLAUDE.md 是 Claude Code 的原生机制其他工具需要查看各自的系统 prompt 或上下文配置方式。总结AI 编程的需求漂移本质上是信息缺口问题不是 AI 不够聪明。把隐式约束显式化让 AI 在有边界的空间里工作漂移问题基本可以得到解决。核心建议把 CLAUDE.md 列为每个新项目 checklist 的第一项重点写「禁止事项」和「必须使用的现有封装」每次跑偏后反手补充到规范文档里形成迭代闭环复杂模块使用任务级 spec 文件进一步约束前期 20 分钟建立规范体系节省的是后期几十次纠错往返的时间成本。参考资源GitHub Spec KitClaude Code 官方文档Claude Code CLAUDE.md 配置说明如果需要使用 Claude Code可以私我。也欢迎有需求的企业进行深度合作。