老胡茶室
老胡茶室

钱都花了,为何你们吹爆的 Cursor、Claude Code 和 Codex 仍然没有输出我想要的结果?

胡键

面对这个提问式标题,一些见多识广的读者可能会脱口而出:

  • 不就是上下文工程的问题吗?
    • 老胡批注:废话,跟没说一样!
  • 好马配好鞍,上工具,比如:playwright 和 context7 之类的。
    • 老胡批注:有帮助,但它们只能起到辅助治疗的效果。
  • 试试最新的 Spec 驱动开发。
    • 老胡批注:能说出这个词的,肯定是与时俱进的朋友,但同上:治标不治本。

老实讲,因为本月杂事较多,本没打算再写这类务虚类的文章,但两件小事让我有了写写的冲动。

第一件事依旧来自于开发的日常:在每日例会时,发现小伙伴们仍未达到我的预期(很正常,coding agent 带来效率提升的同时,让我的预期也同步提高了,😄)。在经过一系列对话和观察之后,我初步有了一个结论。

第二件则是来自一则关于 Claude Code 的推文,见下图:

Claude Code Tweet

这条推文跟我之前写过的一系列关于 Claude Code 的文章倒有些呼应:

  • 非必要不加 MCP。(到现在为止,我也就只加了 playwright 的 mcp server,那还是出于懒得来回复制 error 信息和截图给 Claude Code 的目的。)
  • Claude Code 类的模板工具其时没什么用,除了看看它们的花式 prompt 写法。

这些文章都散布于我的公众号中,感兴趣的读者可自行搜索。

就这样,两件事一合力,促使我决定写点东西,算是记录思考过程,也方便团队成员参考和未来的回顾。

闲话说完,言归正传,来让我试着回答标题中的问题。

你可能依旧只是将 Coding Agent 只是视为工具对待而非合作伙伴

将 LLM 视为“人”而非工具,这一观点我在之前的文章中曾多次提及,同时在团队中也反复强调。但转变却并不容易。

或许有人对此并不以为然,觉得这无关痛痒,但我认为它却是能否用好 Coding Agent 的关键!

为何这么说?主要有两点原因。

第一,你对“人”和工具的要求是不同的,因为你自己就会有不同的预期和心态。比如,你很少会要求一个工具去深入思考,也不会去跟一个工具去倾诉的烦恼。但对人则会。

其次,我也曾反复说过,用 coding agent 来写代码,本质上是一个技术管理过程,相当于你在带一个小团队。而这却恰恰是很多技术人不愿意做或不擅长的。受各类编程英雄传记(本质上类似新形态的武侠小说,而且其中内容亦真亦假)的影响,不少技术人都推崇写得一手好代码的个人英雄主义,而忽视了团队协作和管理的重要性。如此潜意识下,自然不会有好的 prompt 和 context 给 coding agent。

说到这里,你是否还依旧觉得该如何对待这些 Coding Agent 是无关痛痒的事情吗?

如果将其视为“人”或你的技术小弟,你自然会:

  • 跟它讨论技术,而非简单的“搜索 - 再搜索”
  • 让它出多个备选方案,同时提供论据,你来决定
  • ……

让它干任何你会派给人干的事。也就是说,换一个角度对待它,你会自然而然地打开思路,尝试更多的使用方式。这本身也是一个自我心理暗示的过程。

你可能是个“好人”

拿到“好人卡”对于各类恋爱养成类游戏或影视作品来说,并非好事,这意味着你基本已经处于失败者的行列。

从 GPT 类应用横空出世不久,在网上就开始流传着 PUA LLM 会得到更好结果的“都市传说”。 不过对于我这种技术出身且粗通 ML 的“伪专家”来讲,此等说法只能是茶余饭后的谈资,绝不会当真。

我当然也会骂人并且爆过 F 字头的粗口,但有个前提:言之有物。言之无物的 PUA 只能换来廉价的道歉和浪费时间和金钱的修正,而且这类修正往往是换汤不换药。

根据上一条的心智,面对 Coding Agent 小弟,为了进一步的激活其思考的深度,按照我目前的经验,需要适当的严格要求,把每次对话都当作一次同行评审来对待。这其中最关键的就是:用批判的眼光去看待它的输出,有意识地去挑战它,制造冲突。

这一点非常关键!

在现实中,我们应该也有体会,在经过激烈的讨论后,往往能碰撞出更好的想法和结果。因为这些言辞激烈的词汇相当于激活大脑思考的信号,促使其跳出舒适区,去思考更深层次的东西。而基于人类数据训练出来的 LLM 自然也会有这样类似的反应(有篇论文提到这一点,但我忘了名字!)。

因此,不要当好好先生,适当的“毒舌”会让你得到更好的结果。

至于那些老生常谈的:先讨论、再计划、再执行、再测试、再重复前面第 x 步骤,等等,这里就不必再赘述了。好的 coding agent 很可能已经内置了这些流程。

之所以有这样的结论,也是基于我不完整的观察:达不到我预期的(使用 coding agent 的)成员,往往在现实生活中也是温和的“好人”。

如果你觉得还是难以掌握,这里说一个诀窍:把 coding agent 当作自己的小孩,拿出你望子成龙的心态去要求它,哈哈。

但也要注意:言之有物,提供必要的上下文和背景,无论你是通过提供工具让它自行搜集,还是你手动给提供给它。

你或许正在面对一个 unknown unknown

本来,这一条我是想写:你或许对自己要求太低的。但转念一想,这并不公平。因为有可能,你根本就不知道自己想要什么!

面对这类状况,只能依赖两点:直觉和知识面,这两者在 coding agent 大行其道的今天尤为重要。

就现阶段而言,这类 llm 依旧相当于一个无状态的纯函数,其输出完全依赖于外部输入。即便其功能再强大,若没有输入,依然是“巧妇难为无米之炊”。如果你自己都不清楚自己要什么,自然也就不能指望别人能帮你什么。

因此要解决这类 unknown unknown,你得先 know unknown,这里的第一步则来自于直觉。正如不知哪里看到的一段文字说的:那么多人都被苹果砸过脑袋,但只有牛顿发现了万有引力,若非直觉驱使,不会有后来的发现。

直觉和知识面相辅相成,难以借助工具来提升,只能不断尝试和积累。但依旧有几个技巧可以分享。

技巧 1:直接跟 coding agent 讨论直觉

讨论的过程本质上是一个整理思维的过程,

比如:当你在看到一个 astro 工程中有大量 react 组件的时候,老炮儿们应该会直观觉得:不对路,若是这样,还不如直接用 react 系列的框架。

此时,你当即就可以写一个 prompt,要 Claude Code 以一个 astro 专家的身份,批判一下当下的设计,并给出改进建议。由此开头,后面的改进也就自然展开了。

技巧 2:无脑让 coding agent 先批判

这个过程相当于让它先帮你打开思路,给你一些灵感和想法,但此时需要小心它给你华而不实的建议。跟上一条区别在于:前者有一个模糊的直觉,后者则是不管三七二十一先打一枪再说。

技巧 3:让它帮你做调研

当你清楚问题,但不清楚解决方案时,此技巧就非常有用。比如,在我们的 astro 模板工程开源前的大改造中,有不少废旧代码,如果手动清除自然费时费力还容易遗漏。于是,小伙伴借助 Codex 去调研了一下:

... (精简输出) ...

## 首选:Knip(项目级死代码/未用导出/未用文件)

Knip 能一次性扫出未被使用的导出、没被引用的文件、以及 `package.json` 里没用到/漏写的依赖,而且对 `Next.js` 有内置插件,在 monorepo / pnpm workspaces 里也能跑,误报相对少。
它还支持 `--fix` 自动移除未用导出(建议先看 `diff` 再提交)。
...

## 补充 1:ts-prune(专抓未用导出,简单快)

`ts-prune` 专注 TypeScript 未使用的导出,零配置,执行很快,是清理导出的“快刀”。
...

## 补充 2:unimported(找“孤儿文件”+ 依赖核对)

...

## 补充 3:Madge(依赖图 & 找 “orphans”)

...

之后,在人工调研之后,选定 Knip 顺利完成项目大扫除。

在这样的过程中,你同样会获得经验和增加知识面。

总的来讲就是:遇事不决 GPT

结语

以上三点,最重要的还是第一点,一旦你能将 coding agent 视为“人”或“技术小弟”,那么你自然会打开思路,尝试更多的使用方式。

祝各位:happy coding!

精品内容