作者展示在真实项目中使用 Claude Code 的完整工作流:如何真正委托任务、如何处理失败场景,以及 AI Agent 与编辑器自动补全的本质区别。
关于它是什么,不带营销话术
Claude Code 是一个运行在你终端里、跑在你仓库中的 agent。它读取你的文件、运行你的命令、编辑你的代码、帮你做 commit。它不是编辑器自动补全,也不是一个独立的聊天窗口让你来回粘贴代码片段。
这个区别比听起来重要得多。一个只看到单个文件的助手,帮你写一个函数。而一个能看到整个仓库、运行测试并读取输出的 agent,可以把一项完整任务从你手里接过去。这是「请教建议」和「委托工作」的区别。
这个网站的仓库:一个用 Vite 的 React 前端,Sanity 作为 CMS,外加一小部分 Vercel Functions 的后端。
项目里有一个 .claude/ 文件夹,存放本地配置和权限。
还有一个 docs/plans/ 文件夹,所有设计和方案都放在这里。这是关键的一点,我稍后会解释原因。
用 Git worktree 来处理那些值得与当前工作树隔离的大型任务。
以及我自己的一条规则——它真正改变了我做事的结果:任何大事,在写代码之前必须先写一份书面方案。
工作流:设计、方案、执行
用 agent 时很容易陷入的诱惑是——打开终端就说「给我加一个管理后台」。有时候这样能成。但更多时候产出的东西能跑,却不是你想要的,等你发现时六百行代码已经躺在磁盘上了。
所以我把它分成三个阶段,而且不允许它们重叠。
第一阶段:设计。在动手写代码之前,先对话。我们要解决什么问题,两到三个方案及其各自的缺点,我们选哪个、为什么。产出是一份放在 docs/plans/ 里的设计文档。简短,但落笔了。
第二阶段:方案。设计变成一份按任务拆解的计划。每个任务涉及哪些文件,先写哪个测试,用什么命令验证,在哪里做 commit。我的方案文件夹里有类似 2026-04-28-slice-2-vercel-migration.md 和 2026-04-29-portfolio-audit-implementation.md 这样的文件。每一个都是被逐任务执行过的方案。
第三阶段:执行。现在开始写代码。有了方案在手,session 就不会跑偏。如果有什么不对劲,立刻就会显现,因为有一份文档说清楚了应该发生什么。
这听起来像官僚主义,我一开始也这么觉得。但不是。书面方案把「agent 做了件怪事」变成了「agent 在第 4 步跑偏了」,这是完全不同的问题,而且容易修复得多。
我实际委托出去的三项任务
我让它以"这个网站属于一个客户"的方式做审计。读取每个公开组件,在移动端和桌面端遍历路由,测量构建产物 chunk 大小,统计 Sanity 里真实的文章数量。
它返回了四个方向共 20 条发现,每条都有优先级和工作量估算。其中包括:一张未优化的 993 KB 插图、一个只包含零篇已发布文章(实际有九篇)的 sitemap,以及一个永远挂死在「Loading post...」的 404 页面。
我在另一篇文章里详细写了其中一个的排查过程,但这里关键的是分工:机器负责发现,我负责排优先级。文档返回时只包含发现、没有修复——这是故意的,因为我要决定哪些要动、哪些不动。20 条里有 3 条我直接废弃了。
把 Express 迁移到 Vercel Functions
我在 Railway 上有一个小型的 Express 服务器,用来封装 Google Analytics API。它能跑,但每个月都要花钱,24/7 地躺在那里服务一个几乎没人看的仪表盘。
迁移到 serverless function 是教科书级别的任务:把辅助函数拉到 api/_utils/ 里,把路由转成 handler,搬环境变量,验证外部契约没变。前端完全没感知到变化。账单变成了零。
这正是委托出去收益最大的任务类型:机械、定义清晰、有客观的成功标准。不需要判断力,需要的是不把二十个细节连续搞错。机器在晚上十一点做这件事比我强。
从 Sanity 生成的 sitemap
我的 sitemap 是一个静态文件,每次发布都得手动改。说白了就是:从来没改过。
现在是脚本在 prebuild 时运行,用 GROQ 查询 Sanity,写出一个包含每篇文章及其真实日期的文件。八十行 Node 代码,没有新增依赖。
小的任务,正因为小,所以恰恰是它在清单上躺了几个月的原因。这是我注意到最多的模式:真正帮我节省最多时间的不是那些大任务,而是那些本来已经在清单上躺了半年、因为永远不够紧急而一直没做的四十分钟任务。
这里才是大多数这类文章变得模糊的地方。直入主题。
它太快接受你的前提了。如果你说「修这个 CSS bug」,它会去找 CSS bug。如果真正的问题是路由顺序,你可能得到一个掩盖了症状的 CSS 修复。现在我做法是:描述行为,而不是我的诊断。最终结果的差异是巨大的。
它对你的想法过于顺从。如果你提了一个糟糕的方案,默认反应往往是帮你把它做好。我会明确要求在拍板之前给出两到三个选项及其缺点,因为如果不主动要求,选项就不会出现。
上下文在长 session 中会退化。几个小时 session 里,前半小时的决定会变得模糊。所以方案要放到文件里而不是留在对话中:文件不会忘记。
它不知道丑是什么样。它可以写出一个正确、可访问、通过测试、但看起来很丑的组件。视觉判断仍然是你自己的。在这个网站上,我手动重做了不少 CSS,那些在技术层面其实没问题。
以及一个大的问题:你仍然要为合并进去的代码负责。我读每一处 diff。不是因为我觉得它比人类同事更不值得信任,而恰恰和我检查人类同事的程度一样。一条带有我名字的 commit 是我的,不管是谁敲的。
当成本高于收益时:十分钟以内我已经知道怎么做的任务,单行修改,以及任何解释上下文比做事本身还费时的任务。为一个微小的改动写一个好的 prompt 是净负工作。
明天怎么开始
如果你想试试这个而不被坑:
从一个无聊的、定义清晰的任务开始。迁移一种格式、为已有代码写测试、更新依赖项。不要拿你产品的核心功能开刀。
在写代码之前先要方案。即使任务很小。读方案三十秒就能告诉你有没有被理解,和修复一个方案相比修复一个实现,成本可以忽略不计。
在分支或 worktree 上工作。这样如果搞砸了,可以毫无顾虑地全部扔掉。
读所有的 diff。如果你不打算读,就不要委托。
把上下文留在仓库里、写成文字。只存在于对话中的决定会被遗忘。而放在 docs/plans/ 里的那些,三个月后你找不到当初为什么选那个方案时,它们还在那里。
真正改变了什么
我没有写代码更快。我是在那些无聊的部分减少了摩擦,而那些部分恰恰是大部分工作所在。
那些曾经因为惯性躺在清单上的任务现在会被做完,因为启动它们的成本降到了足够低。sitemap 悬了几个月。审计更久。都不难;都是繁琐,而繁琐恰恰是我积压最多的东西。
没有改变的是:我仍然决定要做什么,仍然审查进入代码库的每一行,仍然是线上出问题时的负责人。
我觉得这样是对的。这是我喜欢的那部分工作。
我在 codewithgabo.com 记录那些我搞砸又修好的东西。