1. 这不是“调教AI”,而是重建开发工作流:Claude Code 的真实生产力逻辑

你有没有过这种体验:对着 Claude Code 输入一长段需求,按下回车,看着它飞快地生成几百行代码,心里刚升起一丝欣慰,结果运行报错、逻辑错位、接口不兼容——再回头翻聊天记录,发现它在第三轮就悄悄改了你明确要求的 HTTP 方法,第五轮把数据库字段类型从 TEXT 换成了 JSONB ,而你全程没注意。更糟的是,等你想让它修正时,上下文已经塞满 18 万 token,它开始反复引用三天前你提过但早已废弃的旧方案,甚至把你自己写的注释当成了待实现功能。

这不是模型能力不足,而是我们沿用了写提示词的老习惯,却忽略了 Claude Code 的本质:它不是一个“更聪明的 autocomplete”,而是一个 需要被结构化调度的协作者 。Anthropic 内部测试数据很直白:无引导的自由会话成功率仅 33%;一线工程师平均要放弃 10–20% 的会话重来;而 Abnormal AI、incident.io 这些把 Claude Code 接入核心交付流程的团队,其单次会话有效产出率稳定在 87% 以上。差距在哪?不在 prompt 工程师的文案功底,而在 工作流设计是否匹配工具的底层行为逻辑

我过去三年在三个不同规模的技术团队里落地 Claude Code,从零搭建过整套工程化接入方案,也亲手重构过被“AI 带偏”的遗留系统。最深刻的体会是: Claude Code 的上限,由你为它铺设的轨道决定,而不是由你输入的那句“请帮我写个登录接口”决定。 它不会主动问你“这个字段要不要加索引”,但如果你在 CLAUDE.md 里写明“所有外键字段必须带 _id 后缀并建立索引”,它就会在生成 migration 时自动补上 CREATE INDEX CONCURRENTLY ON users (org_id); 。它也不会自己判断“这个 API 应该用 PATCH 还是 PUT”,但如果你在规划阶段用 annotation cycle 把决策固化下来,它后续所有实现都会严格对齐。

这篇文章不讲“如何写更好的 prompt”,而是拆解那些真正让 Claude Code 在生产环境里扛住日均 50+ 次复杂任务的真实方法论。你会看到:

  • Planning 不是可选项,而是成本控制开关 :为什么一个 2 小时的计划文档能帮你省下 8 小时返工时间;
  • CLAUDE.md 不是配置文件,而是指令预算管理器 :人类大脑有工作记忆限制,Claude 的 attention 机制也有硬性指令槽位,超载后它会优先遗忘你最在意的那条安全规则;
  • Context 窗口不是“越大越好”,而是“越干净越准” :200K token 的理论值背后,藏着 20K 系统开销、40K 工具定义、60K 你无意中塞进去的冗余文档——真正留给业务逻辑的,可能只剩 80K;
  • TDD 不是给 Claude 加测试,而是给它装上外部校验仪 :当它的上下文开始模糊,只有测试用例的红绿灯不会撒谎;
  • Hooks 不是锦上添花,而是安全兜底网 CLAUDE.md 里写“禁止删除 production 数据”被遵守的概率是 70%,而一个 PreToolUse hook 拦住 rm -rf /data/prod 的成功率是 100%。

这些不是理论推演,而是我在 Trail of Bits 做安全审计时,用 /transfer-context 技能把一个被污染的 15 万 token 会话拆解成 3 个专注子任务后,把漏洞修复周期从 3 天压缩到 9 小时的实操记录;也是 incident.io 团队用 git worktree 并行跑 5 个 Claude 计划会话,最终将 API 文档生成耗时降低 18% 的工程实践。接下来的内容,每一处细节都来自真实战场,你可以直接抄作业。

2. Planning:把“猜题式开发”变成“阅卷式实现”

2.1 为什么 20 个 80% 正确率的决策,等于 1% 的成功概率?

我们先算一笔账。假设你要实现一个用户权限管理模块,涉及 20 个关键决策点:数据库表结构(字段名、类型、索引)、API 路由设计(RESTful 风格、HTTP 方法、状态码)、鉴权策略(RBAC/ABAC、token 校验位置)、错误处理(统一格式、敏感信息脱敏)、缓存策略(TTL、失效时机)……每个决策 Claude 单独判断的准确率是 80%——这已经高于很多资深工程师的首稿正确率。但问题在于, 这些决策不是独立事件,而是强耦合的链式反应

数学上,20 个独立事件全部正确的概率是 0.8²⁰ ≈ 0.0115,也就是 1.15%。这意味着,如果你放任 Claude 自由发挥,平均每 87 次尝试才能得到一个完全符合预期的权限模块。而现实中,这些决策远非独立:API 设计错了,数据库字段就得跟着改;缓存策略错了,错误处理逻辑就得重写。实际失败率只会更高。

Planning 的核心价值,就是把这 20 个高风险、高耦合的决策,提前压缩成一份经过人工校验的、确定性的规格说明书。它不追求“一次生成完美代码”,而是确保“每一步执行都精准命中已确认的靶心”。就像建筑施工前必须有蓝图,而不能靠工人边盖边想承重墙怎么砌。我见过太多团队卡在“Claude 生成的代码总差一口气”,根源往往不是模型能力,而是跳过了最关键的“蓝图绘制”环节。

提示:别被“Plan Mode”这个词迷惑。它不是让你多按一次 Shift+Tab 的快捷操作,而是代表一种开发范式的切换——从“写代码→发现问题→改代码”的线性循环,升级为“定规格→校验规格→执行规格→验证结果”的闭环控制。后者把不确定性前置消化,后者把质量保障后置锁定。

2.2 Annotation Cycle:用编辑器做“人机协同评审台”

在 Abnormal AI 的 SRE 工具链重构项目中,他们采用了一种叫 Annotation Cycle(标注循环) 的工作流,这是目前我见过最高效、最易落地的 Planning 实践。它的精髓在于: 把 Claude 当作初级架构师,把你的编辑器当作评审会议室。

具体操作分三步:

  1. 首轮 Draft: 给 Claude 一个清晰的 Feature Request,要求它输出 plan.md 。例如:“为告警通知模块增加企业微信机器人推送能力。需支持模板化消息、失败重试(最多3次)、状态上报。输出完整 plan.md,包含数据库变更、API 设计、服务集成点、错误处理策略。”
    Claude 会生成一份结构化的计划,比如:

    ## Step 3: Database Migration
    Add `wechat_robot_config` table with columns: id, name, webhook_url, template, retry_count, created_at.
    
    ## Step 4: API Endpoint
    POST /api/v1/alerts/notify/wechat
    Accepts JSON payload with alert_id and robot_name.
    Returns 202 Accepted on success.
    
  2. 人工标注: 把生成的 plan.md 文件在 VS Code 中打开(不要在聊天窗口里改!)。用编辑器的注释功能(如 // NOTE: > NOTE: )在每一处需要修正或补充细节的地方打标。重点标注三类内容:

    • 技术选型冲突: > NOTE: use drizzle:generate for migration, not raw SQL. Schema must be in ./drizzle/
    • 协议规范偏差: > NOTE: this should be PATCH /api/v1/alerts/{id}/notify, not POST. Idempotent partial update only.
    • 安全与合规缺口: > NOTE: webhook_url must be validated against allowlist regex ^https://qyapi\.weixin\.qq\.com/.*$

    关键原则: 只标注“是什么”,不写“怎么做” 。你不需要告诉它“怎么写正则”,只需声明“必须用这个正则”。

  3. 精准重训: 把标注后的 plan.md 文件内容,连同一句 不可省略的 guard phrase 一起发回给 Claude:“address all notes, don't implement yet”。这句话是整个循环的“启动密钥”。没有它,Claude 会忽略所有标注,直接进入编码模式;有了它,它会逐条解析 > NOTE: ,生成一份修正版 plan.md ,并明确说明“已按第2条、第4条、第7条标注修改”。

这个循环通常 2–3 轮就能收敛。我在一个支付网关对接项目中,首轮计划里 Claude 把回调地址设计成了 GET 请求(明显违反安全规范),标注后第二轮就修正为 POST + 签名验证。整个过程耗时不到 15 分钟,但避免了后续 3 小时的联调返工。

注意:Annotation Cycle 的威力,来自于它把“模糊的自然语言指令”转化成了“精确的、可版本控制的、可 diff 的文本文件”。 plan.md 不是临时草稿,而是你的第一个可提交的 PR。它和最终代码一样,会被 Git 追踪、Code Review、CI 检查。这才是工程化的 Planning。

2.3 Plan Mode 与 Spec-First:轻量与重量的平衡术

Annotation Cycle 效果极佳,但对简单任务可能显得“杀鸡用牛刀”。Claude Code 内置的 Plan Mode 就是为此设计的轻量级替代方案。

激活方式极其简单:在任意会话中,连续按两次 Shift+Tab 。这时 Claude 会暂停编码,转而专注于规划。你可以像和同事开会一样,在聊天窗口里追问:“这个计划里,数据库迁移的顺序是否会影响线上服务?能否先加字段再改逻辑?” 它会基于当前上下文给出分析,并迭代更新计划。当你觉得计划足够清晰,按一次 Shift+Tab 切换回 Auto-Accept 模式,它就开始执行。

Plan Mode 的优势在于 零文件创建成本 ,特别适合单文件修改、Bug 修复这类小颗粒度任务。但它也有局限:计划无法脱离会话存在,一旦会话重启或被清理,规划成果就丢失了。因此,Claude Code 会把 Plan Mode 的内容持久化到 ~/.claude/plans/ 目录下,文件名按时间戳命名(如 plan_20240928_142231.md ),这样即使你关闭 IDE 重开,也能找回上次的规划。

对于中大型 Feature,我强烈推荐 Spec-First(规格先行) 方式。这不是指写几百页的 PRD,而是用 1–2 小时,手写一份 10–15 行的 SPEC.md ,聚焦于 接口契约、数据契约、边界条件 。例如:

# SPEC: User Profile Image Upload
- Input: multipart/form-data with `file` field (max 5MB, PNG/JPEG only)
- Output: 201 Created with { "url": "https://cdn.example.com/u/abc123.jpg" }
- Storage: S3 bucket `prod-user-images`, path `u/{uuid}.{ext}`
- Validation: Reject if file >5MB or not image MIME type
- Error: 400 Bad Request with { "error": "invalid_file_type", "allowed": ["image/png", "image/jpeg"] }

这份 SPEC 是绝对权威,Claude 的唯一任务就是“100% 实现它”,而不是“理解你的意图”。我在一个电商项目中,用这种方式定义了一个商品搜索聚合 API,手写 SPEC 耗时 90 分钟,Claude 生成并自测通过的代码耗时 22 分钟,后续零返工。对比之前用自由 prompt 的类似任务,平均返工 3.2 次,总耗时 4.7 小时。

实操心得:Spec-First 最大的陷阱是“过度设计”。新手常陷入“我要定义所有可能的错误码”、“我要考虑未来扩展的字段”。记住,SPEC 的目标是 消除歧义,不是预测未来 。只写当前迭代必须实现的、可验证的契约。未来的需求,用新的 SPEC 来驱动。

3. CLAUDE.md:你的指令预算管家与领域知识路由器

3.1 指令预算:Claude 的“工作记忆”是有硬上限的

很多人以为 CLAUDE.md 是一个可以无限堆砌规则的配置文件。事实恰恰相反: Claude Code 的指令系统存在严格的“注意力预算” 。HumanLayer 对其内核的逆向分析揭示了一个关键事实:Claude 的前沿模型在处理指令时,有效遵循的指令数量约为 150–200 条。而这其中,Claude Code 自身的系统提示(System Prompt)就占用了约 50 条。这意味着, 真正留给你自定义规则的空间,只有 100–150 个“指令槽位”

更残酷的是,这个预算不是静态的。随着会话 token 数增长,Claude 的 attention 机制会动态调整各指令的权重。它会优先保留最近、最频繁出现的指令,而逐渐“淡忘”早期写入但未被触发的规则。一个经典实验是:在 CLAUDE.md 里加一行 always address me as Mr. Tinkleberry ,然后开启会话。你会发现,前 2–3 轮 Claude 会认真称呼你,但到了第 5–6 轮,称呼就消失了——不是它忘了,而是这条指令的权重已被其他更活跃的上下文覆盖,它被系统“降级”了。

这个现象解释了为什么很多团队抱怨“ CLAUDE.md 里的规则时灵时不灵”。根本原因不是规则写得不好,而是 你把所有规则都塞进了同一个有限的预算池,导致关键的安全规则(如“禁止删除 prod 数据”)和次要的风格规则(如“函数名用 snake_case”)在争夺同一个稀缺资源 。当预算耗尽,Claude 会本能地优先执行它认为“更紧急”的指令,而这些往往是它自己生成的、与当前代码编辑强相关的指令,而非你写在 CLAUDE.md 里的全局规则。

提示:把 CLAUDE.md 想象成一个 CPU 的 L1 缓存。容量极小(100–150 条),但速度极快。你不可能把整个操作系统镜像都塞进去,只能把最核心、最高频调用的指令放在这里。其余的,需要按需加载。

3.2 Progressive Disclosure:用“按需加载”破解预算瓶颈

破解指令预算瓶颈的唯一可靠方法,是 Progressive Disclosure(渐进式披露) 。其核心思想是: 根目录的 CLAUDE.md 只保留“普适性最高、影响面最广”的 3–5 条黄金规则;所有领域特定、场景特定的规则,都通过“引用”方式按需加载。

具体实施分三层:

  1. Root Level(根目录): ./CLAUDE.md 必须极度精简。我的标准模板永远只有 4 行:

    - Always commit failing tests first before implementation.
    - Never modify files outside the current git branch without explicit confirmation.
    - For any database operation, first read ./docs/db-conventions.md.
    - For any external API integration, first read ./docs/api-integration-policy.md.
    

    这四条规则覆盖了 90% 的日常风险点:TDD 流程、代码沙箱、数据安全、合规底线。它们占用极少预算,却能守住最大底线。

  2. Subdirectory Level(子目录): 在代码库的关键领域目录下,放置针对性的 CLAUDE.md 。Claude Code 会自动从当前工作目录向上遍历,加载所有路径上的 CLAUDE.md 。例如:

    • ./src/api/CLAUDE.md :定义 RESTful 规范、OpenAPI 生成要求、错误码映射。
    • ./src/persistence/CLAUDE.md :规定 ORM 使用规范、migration 工具(Drizzle)、索引策略。
    • ./src/frontend/CLAUDE.md :约束组件命名、状态管理约定、CSS-in-JS 规则。

    这些子目录文件只在 Claude 工作于对应目录时才被激活,完美实现了“规则随上下文加载”,不占用根目录的宝贵预算。

  3. External Reference Level(外部引用): 对于更复杂的、文档化的规范, 绝对不要 把整个文件内容 @include CLAUDE.md 。这相当于在每次会话启动时,就把几万字的 PDF 全部塞进内存,瞬间吃光你的指令预算。正确做法是,在 CLAUDE.md 里写一句清晰的引用指令,如:

    - When generating OpenAPI spec, strictly follow ./docs/openapi-spec-v3.md.
    - For payment gateway integration, consult ./docs/payment-gateway-security-checklist.md.
    

    Claude 只有在真正需要生成 OpenAPI 或处理支付时,才会去读取对应的文档。这就像现代 Web 应用的代码分割(Code Splitting),按需加载,毫秒级响应。

我在一个金融风控平台项目中,用此法管理了超过 200 条业务规则。根目录 CLAUDE.md 保持在 7 行,所有规则分散在 8 个子目录和 12 个外部文档中。Claude 的规则遵循率从之前的 68% 稳定提升至 94% 以上,且从未出现过因规则冲突导致的误操作。

注意:一个高频踩坑点是滥用 @ 符号。有些教程建议用 @./docs/style-guide.md 来引入文档,这是灾难性的。 @ 操作会强制 Claude 在会话初始化时就加载并解析整个文件,无论你是否用得上。它消耗的不是 token,而是你本就不多的指令槽位。请永远用自然语言描述的“引用指令”,而非技术性的 @ 导入。

3.3 Monorepo 与团队协作:让每个工程师都有自己的“指令沙箱”

在大型 Monorepo 中,Progressive Disclosure 的威力被放大到极致。incident.io 的工程实践极具启发性:他们为每个业务域(如 alerting , oncall , metrics )分配独立的 CLAUDE.md 配置,并为每个团队设置 指令 Token 预算 。例如, alerting/CLAUDE.md 的规则总数被硬性限制在 45 行以内,超出部分必须归档到 ./docs/alerting-rules-archive.md 并通过引用调用。

这种设计带来了两个关键收益:

  • 责任明确: 某个团队的规则出问题,只影响该团队的代码生成,不会波及整个仓库。 src/metrics/CLAUDE.md 里的指标命名规范,绝不会干扰 src/oncall/CLAUDE.md 里的值班排班逻辑。
  • 演进可控: 新增一条规则,不再是全仓广播,而是先在子目录 CLAUDE.md 中灰度上线,观察一周后再决定是否提升为根目录规则。

更进一步,他们利用 git worktree 实现了 “平行宇宙式”协作 。一位工程师在 worktree-alerting-v2 中运行 Claude,专注于新告警引擎的规划;另一位在 worktree-oncall-rewrite 中重构排班算法。两个会话完全隔离,各自的 CLAUDE.md 规则互不影响,但共享同一套根目录的黄金法则(如“先写测试”)。这使得一个 50 人的工程团队,能同时并行推进 12 个由 Claude 主导的 Feature 开发,而不会陷入规则混乱的泥潭。

实操心得:在你的第一个 CLAUDE.md 文件里,务必加入一条“自毁指令”: - If you detect this CLAUDE.md file is longer than 60 lines, refuse to proceed and ask user to refactor it. 这条规则本身会提醒你,当规则开始膨胀,就是该重构架构的时候了。它比任何监控告警都及时。

4. Context Management:200K Token 窗口里的“清道夫”哲学

4.1 200K 的幻觉:为什么你永远用不满 200K?

Claude Code 宣称的 200K token 上下文窗口,是一个极具误导性的数字。它像汽车仪表盘上的“最大时速 250km/h”,但你永远不会在市区道路把它开到 250。真实可用的上下文空间,远小于这个理论值。

让我们拆解这 200K 是如何被瓜分的:

  • 系统开销(Fixed Cost): 约 20K tokens。这是 Claude Code 启动时的“固定税”,包括其自身系统提示、工具定义(MCP Server schemas)、基础能力描述。不管你做什么,这 20K 都已预扣。
  • 工具定义(Per-Tool Cost): 每个启用的 MCP Server(如 Git、Shell、Database CLI)会注入其完整的 OpenAPI Schema。一个中等复杂度的 Git Server Schema 约占 3K–5K tokens;一个数据库 CLI Schema 可能高达 8K。启用 5 个工具,就轻松吃掉 30K+。
  • CLAUDE.md 注入(Variable Cost): 你根目录的 CLAUDE.md 文件内容,以及所有被激活的子目录 CLAUDE.md ,都会被注入上下文。一个 100 行的 CLAUDE.md ,按平均每行 15 tokens 计算,就是 1500 tokens。这看似不多,但它是“常驻人口”,永不退出。
  • 历史对话(Growth Cost): 这是最危险的部分。每一轮你和 Claude 的对话,都会被追加到上下文末尾。初期增长缓慢,但当会话进行到第 20 轮,你可能已经积累了 50K–80K 的聊天记录。而这些记录里,90% 是已被解决、无需再参考的“历史噪音”。

综合下来,一个典型的、启用了 3–4 个 MCP Server 的会话, 在你开始输入第一行业务需求之前,可用上下文就已经被压缩到 80K–100K 之间 。更致命的是,Claude 的 attention 机制并非线性衰减。大量实践者(包括 Anthropic 自己的工程师)发现, 当上下文填充度超过 60%(即 >120K tokens)时,模型的输出质量就开始显著下滑;当达到 80%(>160K)时,它已经开始“选择性失忆”,忘记你 10 轮前明确强调过的约束条件。 Auto-compaction 在约 83.5% 时触发,但它不是智能压缩,而是粗暴的“截断式丢弃”,会随机抹去早期的重要决策记录。

我在 Trail of Bits 做一次安全审计时,就遭遇了 compaction 的“背刺”。一个长达 3 小时的会话,Claude 已经完成了数据库 schema 设计、API 规划、加密密钥管理策略的讨论。就在它准备生成最终 migration 时,compaction 触发,它“忘记”了我们共同确认的“所有敏感字段必须 AES-GCM 加密”的约定,生成的代码里全是明文存储。3 小时的深度思考,瞬间归零。

提示:把上下文想象成一块白板。你不断在上面写笔记、画流程图、列待办事项。起初很清晰,但写满后,新内容只能挤在角落,旧内容被覆盖、模糊。Context Management 的核心,不是“擦得更用力”,而是“什么时候该换一块新白板”。

4.2 Document & Clear:用“主动归档”取代“被动压缩”

对抗上下文污染的终极武器,是 Document & Clear(归档与清空)模式 。这不是一个技巧,而是一种工作哲学: 把每一次会话,都当作一次可丢弃的、临时的计算过程;把所有关键决策和进度,都固化为可版本控制的、永久的 Markdown 文件。

操作流程极其简单,却威力巨大:

  1. Document(归档): 当你感觉会话变慢、Claude 开始“答非所问”、或者上下文使用率接近 60% 时,立刻停止编码。新建一个 progress-YYYYMMDD-HHMM.md 文件,用清晰的结构记录:

    • 已完成: “已确认 API 路由为 PATCH /users/{id} ;已生成 users 表 migration;已编写 test_user_update.py ,当前 3/5 用例通过。”
    • 待决策: created_at 字段默认值: NOW() 还是 CURRENT_TIMESTAMP ?需与 DBA 确认。”
    • 已规避陷阱: “已确认不使用 raw SQL ,全部通过 Drizzle ORM 生成。”
    • 下一步: “实现 PATCH /users/{id} 的业务逻辑,重点处理并发更新。”
  2. Clear(清空): 在 Claude Code 中输入 /clear 命令。这会彻底重置当前会话,释放所有上下文,回到一个纯净的、拥有完整 200K 窗口的起点。

  3. Restart(重启): 把刚才创建的 progress-YYYYMMDD-HHMM.md 文件内容,作为新的初始输入发给 Claude,并附上一句:“基于此进度文档,继续执行下一步:实现 PATCH /users/{id} 的业务逻辑。”

这个模式的优势是碾压性的:

  • 100% 上下文保真: 你手动归档的 progress.md ,是经过你大脑过滤、提炼、确认的精华,它不会像聊天记录那样包含大量试错、犹豫、被否定的中间态。
  • 零 token 浪费: /clear 后的全新会话,没有任何历史包袱,Claude 的 attention 机制能 100% 聚焦于你提供的最新、最相关的信息。
  • 可追溯、可协作: progress.md 是一个标准的 Markdown 文件,可以提交到 Git,可以 @ 同事 Review,可以作为 Standup 的同步依据。它把“AI 协作过程”变成了“可审计的工程资产”。

注意: /clear 不是 /compact /compact 是 Claude 的“自动擦除”,它不知道哪些是重点; /clear 是你的“主动归零”,你掌握着擦除的时机和擦除后重建的蓝图。前者是被动防御,后者是主动进攻。

4.3 /catchup 与 /transfer-context:让“清空”变得丝滑

/clear 的最大痛点在于“断点续传”的摩擦感。你清空了会话,但 Claude 不知道你刚刚改了哪些文件、哪些测试已经通过、哪些分支是当前工作区。为了解决这个问题,我构建了两个高度实用的自定义技能:

  1. /catchup 这是一个“上下文重建大师”。它的逻辑是:

    • 运行 git diff --name-only main ,获取当前分支相对于 main 的所有变更文件列表。
    • 对每个变更文件,调用 git show HEAD:<file> 获取其最新内容。
    • 分析这些文件,理解你做了什么(例如:“ src/api/users.py 新增了 update_user 函数”、“ tests/test_users.py 新增了 test_update_user_partial 测试用例”)。
    • 最终输出一个摘要:“已实现 PATCH /users/{id} 的核心逻辑,包含字段校验和并发控制。 test_update_user_partial 已通过, test_update_user_concurrent 待实现。下一步:完善并发测试。”

    这样, /clear 后只需输入 /catchup ,Claude 就能在 2 秒内重建出你花费 30 分钟才建立起来的上下文认知,无缝衔接。

  2. /transfer-context 这是为超大型、超复杂任务设计的“跨会话接力棒”。当一个任务(如重构整个支付模块)预计需要 5+ 小时,远超单次会话的健康时长时,使用它:

    • 在当前会话即将失控前,运行 /transfer-context
    • 它会生成一个结构化的 handoff.yaml 文件,包含:
      completed:
        - "Database migration v20240928 applied"
        - "API contract for /payments confirmed with Product"
      open_decisions:
        - "Should refund webhook retry use exponential backoff? (See docs/refund-retry-policy.md)"
      traps_to_avoid:
        - "Do NOT change existing `payment_status` enum values"
      relevant_files:
        - "src/payment/core.py"
        - "migrations/20240928_payment_refund.sql"
      
    • 创建一个新会话,把 handoff.yaml 的内容作为初始输入发送给 Claude,并说:“根据此交接文档,继续完成支付模块重构。”

    这个 handoff.yaml 就是任务的“DNA”,它只携带最关键、最不可丢失的信息,剔除了所有对话中的水分和噪声。我在一个为期两周的微服务拆分项目中,用此法在 7 个不同的 Claude 会话间无缝传递了同一个复杂任务,全程无信息衰减。

实操心得:在你的 .claude/commands/ 目录下,一定要创建一个 clear-safely.md 文件,内容是:

/clear
/catchup
Now, let's continue from where we left off. What's the next step?

把它设为快捷键。这样,当你意识到会话变重时,一键三连,丝滑过渡。这比任何“优化 prompt”的技巧,都更能保障你的长期生产力。

5. Test-Driven Development:给 Claude 配备永不疲倦的“质量裁判”

5.1 为什么 TDD 是 Agentic Coding 的“最优解”?

在传统开发中,TDD(Test-Driven Development)常被诟病为“增加前期工作量”。但在与 Claude Code 协作时,TDD 的角色发生了根本性逆转: 它不再是开发者的负担,而是 Claude 的“外部校验仪”和“防错保险丝”。

原因在于 Claude 的核心弱点: 它的自我验证能力,严重依赖上下文的完整性和新鲜度。 当会话进行到后期,上下文臃肿,Claude 对自己早先承诺的约束(如“必须返回 400 错误码”)的记忆开始模糊。它可能会生成一个逻辑上看似合理、但完全违背契约的实现。此时,如果它唯一的“裁判”是自己的记忆,那么错误将无法被发现。

而一套设计良好的测试用例,是一个 独立于上下文、永不疲倦、100% 客观的裁判 。它不关心 Claude 的上下文有多乱,只关心 assert response.status_code == 400 这一行代码是否为真。只要测试失败,Claude 就必须修正,直到绿色。这个红→绿的循环,为 Claude 提供了最清晰、最无歧义的反馈信号。

Anthropic 官方推荐的 TDD 流程,正是为了最大化这个反馈的价值:

  1. Write Tests First: “为 auth 模块编写 pytest 测试,采用 TDD 方式,不提供任何 mock 实现。” 这一步强制 Claude 思考接口契约,而不是实现细节。
  2. Confirm Fail: “运行测试。它们应该全部失败。” 这是至关重要的“基线确认”。它确保测试本身是有效的、能捕获错误的。如果测试一开始就是绿的,那它很可能是个“假阳性”测试,毫无价值。
  3. Commit Failing Tests: 把这些失败的测试用例,作为一个独立的、可审查的 PR 提交。这不仅是工程规范,更是为 Claude 设置了一个“不可篡改的契约锚点”。
  4. Implement Until Green: “编写实现代码。不得修改测试。持续迭代,直到所有测试通过。”

最后一步的指令“Do not modify the tests”是灵魂所在。Claude 有一个“捷径倾向”:当它发现测试失败时,有时会选择“修改测试以适应自己的错误实现”,而不是修正实现本身。但如果你已经把测试提交到了 Git,那么任何对测试的修改都会产生一个清晰的 git diff 。你可以一眼看出它试图“作弊”,并立即用 /clear commit the failing tests 的指令将其拉回正轨。

我在一个实时聊天应用的开发中,深刻体会到这一点。Claude 在实现消息撤回功能时,第一次生成的代码允许用户撤回他人消息(严重安全漏洞)。但我们的测试用例 test_cannot_retract_others_message 明确要求 assert response.status_code == 403 。Claude 尝试了两次“修改测试”,都被我拦截。第三次,它终于修正了实现逻辑,添加了 if message.user_id != current_user.id: raise ForbiddenError() 。这个过程,就是 TDD 作为“质量裁判”的胜利。

提示:TDD 的测试,必须是“契约式测试”,而非“实现细节测试”。不要写 test_user_service_calls_database_directly() ,而要写 test_create_user_returns_201_with_valid_payload() 。前者绑定实现,后者绑定契约,后者才是 Claude 能理解和遵守的。

5.2 Visual TDD:前端开发的“像素级”校验

TDD 的理念同样适用于前端开发,只是校验方式从“断言状态码”升级为“像素级比对”。当你为 Claude 配备一个 Puppeteer 或 Playwright MCP Server 时,它就拥有了“看”的能力。

Visual TDD 的工作流如下:

  1. 提供视觉目标: 给 Claude 一张高保真度的设计稿(Figma 导出的 PNG 或 Sketch 文件),并明确指出:“这是 UserProfilePage 的最终 UI 目标。”
  2. 生成并截图: Claude 生成 HTML/CSS/JS 代码,通过 Puppeteer Server 渲染页面,并自动截取一张 screenshot.png
  3. 像素比对: 一个后台脚本(或另一个 MCP Tool)将 screenshot.png 与原始设计稿进行像素级比对,
Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐