$catMANUAL||~28 min

用了半年 AI 编程工具,这些坑我替你踩了

advertisement

用了半年 AI 编程工具,这些坑我替你踩了

从今年年初开始,我基本上每天都在用 AI 编程工具写代码。Claude Code、Cursor、Copilot、Gemini CLI,能试的都试了。半年下来,效率确实提升了不少,但踩过的坑也够写一篇文章了。

今天把这些坑整理出来,都是真金白银(和时间)换来的教训。如果你刚开始用 AI 编程工具,或者用了一段时间总觉得哪里不对劲,这篇文章可能对你有点用。

说实话,半年前我刚开始用这些工具的时候,心态是"这玩意能帮我写代码,我终于可以躺平了"。结果第一个月就打脸了。AI 写的代码看着挺像样,但 bug 比我自己写的还多。review 代码的时间反而变长了,因为你不信任 AI 写的东西,又不得不一行行看。

后来我慢慢摸索出了一套跟 AI 协作的方法,效率才真正上来。但这个过程中的坑,真的够写一篇文章。

先说结论:AI 编程工具不是银弹

我知道这话听起来像废话,但真的有不少人(包括我自己一开始)觉得装上 AI 编程工具就能起飞了。结果呢?代码写得更快了,但 bug 也更多了。

AI 编程工具本质上是个很强的助手,但它不会替你思考架构,不会替你做技术决策,更不会替你背锅。搞清楚这个定位,后面的事情就好办了。

坑一:盲目信任 AI 生成的代码

这是新手最容易踩的坑,也是最贵的坑。

我有一次让 Claude Code 帮我写一个文件上传功能。它噼里啪啦写了一大堆,代码看起来挺像样的,有错误处理、有进度提示、甚至还加了类型校验。我一看,不错啊,直接提交了。

结果上线第二天就出问题了——大文件上传会把服务器内存撑爆。AI 写的代码只处理了小文件的情况,完全没有考虑流式上传和内存限制。这种问题你在本地测试的时候根本发现不了,只有在生产环境、用户上传一个 500MB 文件的时候才会暴露。

教训是什么?AI 生成的代码,你必须 review。

具体来说,这几个地方最容易出问题:

  • 错误处理:AI 经常写一个 try-catch 包住所有东西,然后 catch 里面就一个 console.log。看起来有错误处理,实际上什么都没处理。
  • 边界条件:空数组、null 值、超长字符串、并发请求,这些 AI 不太会主动考虑。
  • 性能问题:AI 写的代码通常能跑,但不一定高效。N+1 查询、不必要的 re-render、内存泄漏,这些它不太管。
  • 安全漏洞:SQL 注入、XSS、CSRF,AI 不会主动帮你防护。你得自己检查。不是那种走马观花的 review,是真的要理解它在干什么、有什么边界条件没考虑到。尤其是涉及 I/O 操作、并发、内存管理这些容易出问题的地方,AI 经常会给你一个"看起来对但实际有坑"的方案。

后来我养成了一个习惯:AI 写完代码之后,我会问它"这段代码有什么边界情况没考虑到?"。它通常能自己找出几个问题来。虽然不是每次都准,但总比直接提交强。

坑二:上下文管理不当,AI 变笨了

用 Claude Code 和 Cursor 的时候,我发现一个很奇怪的现象:有时候 AI 特别聪明,能一下子理解你的意图;有时候又特别笨,你说得再清楚它也搞不明白。

后来我搞明白了,问题出在上下文(Context)上。

AI 编程工具的能力很大程度上取决于它能看到多少上下文。如果你的项目结构很乱,或者你给它的提示不够具体,它就只能靠猜。猜对了你觉得它聪明,猜错了你觉得它笨。其实都是上下文的锅。

具体来说,有几个常见的上下文问题:

文件太多,AI 看不过来。 Claude Code 的上下文窗口虽然有 1M token,但你的项目如果很大(几十个文件、上万行代码),它不可能全部看进去。这时候你需要主动告诉它哪些文件是相关的。在 Cursor 里可以用 @file 引用特定文件,在 Claude Code 里可以在提示里指定路径。

项目结构不清晰,AI 找不到相关文件。 我有一个项目,目录结构特别深,src/lib/utils/helpers/string/format.ts 这种。Claude Code 经常找不到它要改的文件在哪,因为它不知道你的目录命名逻辑。后来我在 CLAUDE.md 里加了一段目录结构说明,这个问题就解决了。

对话太长,AI 记不住前面说的。 这个在 Claude Code 里特别明显。你跟它聊了 20 轮之后,它可能已经忘了你在第 3 轮说的那些约束条件。解决办法是定期用 /compact 命令压缩上下文,或者干脆开一个新会话。

没有 CLAUDE.md 或 .cursorrules。 这个太重要了。如果你不在项目根目录放一个配置文件告诉 AI 你的项目规范、技术栈、代码风格,它每次都要从头猜。我现在的项目都有一个 CLAUDE.md,里面写了用什么框架、什么代码风格、哪些文件不要动。有了这个文件之后,AI 的输出质量明显提升。

我给你看一个真实的例子。我有一个 Next.js 项目,没写 CLAUDE.md 的时候,Claude Code 总是用 CommonJS 的 require 语法。写上"项目使用 ES Modules,请用 import/export"之后,它就再也没搞错过。

CLAUDE.md 里我一般会写这些内容:

  • 技术栈和版本(Next.js 15、TypeScript 5.x、Tailwind CSS v4)
  • 代码风格偏好(函数式组件、async/await、不要用 any)
  • 项目结构说明(src/ 下面按功能分目录)
  • 不要动的文件(比如 .env、prisma/schema.prisma)
  • 测试要求(用 vitest,测试文件放在 tests 目录)

这些东西你写一次就够了,但能省掉后面无数次的纠正。

坑三:Token 消耗比你想的快得多

这个坑直接跟钱包挂钩。

我用 Claude Code Pro($20/月),一开始觉得挺够用的。结果第一个月用了不到两周就把额度用完了。原因很简单:我让它帮我看一个大项目的代码,每次都是"帮我看看这个文件"、"这个函数是什么意思"、"帮我重构这一段"。每次对话都在消耗 token,而且大文件消耗得特别快。

后来我学乖了,总结了几个省 token 的技巧:

先说一下大致的消耗量,让你有个概念:Claude Code 的 Pro 计划($20/月)大概能让你进行 100-200 次中等复杂度的对话。如果你让它读一个 500 行的文件,一次对话可能就消耗掉 10000+ token。所以不要觉得 $20 很多,用起来是真的快。

先想清楚再问。 不要上来就说"帮我看看这个项目",AI 会把整个项目都读一遍。先想清楚你要解决什么问题,然后精确地告诉它看哪些文件。

善用 /compact 命令。 在 Claude Code 里,/compact 可以把之前的对话压缩,释放上下文空间。长对话的时候定期用一下,能省不少 token。

复杂的任务用 Cursor,简单的用 Copilot。 Claude Code 适合处理复杂的、需要理解整个项目的任务。如果你只是想补全一行代码或者写个小函数,用 Copilot 就够了,不需要启动 Claude Code 这个大杀器。

注意 rate limit。 Anthropic 会限制你的使用频率。如果你跑得太猛,会被临时封号。我有一次连续跑了几个小时,突然就用不了了,等了好几个小时才恢复。后来我学会了:不要让 Claude Code 跑那种需要持续运行很久的任务,分批处理更安全。

还有个省钱的技巧:如果你只是想让 AI 帮你理解一段代码,不需要它改什么,可以用 Gemini CLI。Google 的 Gemini 模型目前是免费的,上下文窗口也够大。我经常用它来快速看代码,把 Claude Code 留给真正需要它改代码的任务。

坑四:Cursor 的 Agent 模式没有你想的那么靠谱

Cursor 的 Agent 模式(之前叫 Composer)是个很诱人的功能:你给它一个任务描述,它自动帮你改多个文件、运行命令、甚至自己修 bug。听起来很爽对吧?

实际用起来,翻车率不低。

我有一次让它帮我把一个 Express.js 项目迁移到 Next.js。它确实改了很多文件,但改完之后项目根本跑不起来。仔细一看,它把一些不该改的文件也改了,有些路由逻辑被它搞乱了,还有几个依赖版本不对。

更气人的是,它改完之后还跟我说"完成了",好像一切都很顺利。我试了半天才发现一堆问题。

后来我总结了使用 Cursor Agent 模式的几个原则:

任务要小、要具体。 不要给它一个大任务(比如"帮我重构整个项目"),而是拆成小任务("帮我把这个文件的 API 路由改成 Next.js 的 Route Handler")。任务越小,出错的概率越低。

每次改完都要 review。 Cursor 会告诉你它改了哪些文件,你必须一个个看。不要只看它说的 summary,要看实际的 diff。

善用 "notepad" 功能。 Cursor 有个 notepad 可以记录项目的约定和你的偏好。每次开新会话的时候先加载 notepad,AI 就不会每次都重新猜你的意图。

不要让它自动运行命令。 我建议关掉 Cursor 的自动命令执行功能。每次它要运行 npm install 或者 git commit 之前,你先看看它要执行什么。有一次它差点帮我跑了一个 rm -rf,幸亏我多看了一眼。

还有个问题是 Cursor Agent 的"幻觉"。它有时候会告诉你它做了某件事,但实际上没做。比如你让它"给所有 API 路由加上错误处理",它会说"已完成,已为 12 个路由添加了错误处理"。但你去检查,可能只有 8 个被改了,另外 4 个它忘了。这种问题很难发现,因为你潜意识里会信任它的报告。

我现在用 Cursor Agent 的流程是:它说完成之后,我会用 git diff --stat 看一下到底改了多少文件。如果数字对不上,就说明它漏了。

对了,Cursor 有个功能我觉得特别好用但很多人不知道:它的 "Apply" 按钮。当你在 Chat 里让 AI 写了一段代码,不要手动复制粘贴,点 "Apply" 按钮它会自动帮你把代码放到正确的位置。这个功能省了我很多时间。

还有一个小技巧:如果你发现 Cursor Agent 模式总是改错文件,可以在 .cursorrules 里加一条"修改文件前先确认文件路径"。虽然不能完全解决问题,但能减少一些低级错误。

坑五:Copilot 的建议看起来对,实际有坑

GitHub Copilot 是我用得最多的工具,因为它直接集成在 VS Code 里,几乎零成本。但它的建议有个特点:看起来非常合理,语法完全正确,但逻辑上可能是错的。

举个例子,我写一个 React 组件,需要从 API 获取数据然后渲染。Copilot 给我补全了一段代码,看起来没问题。但我仔细一看,它没有处理 loading 状态和 error 状态。在开发环境里数据秒返回,所以看起来没问题。上线之后 API 慢了一点,用户就看到了空白页面。

还有一次更离谱。我在写一个数据库查询,Copilot 给我补全了一个看起来很合理的 SQL。我差点就用了,幸好多想了一下——它给的查询没有加索引条件,在大数据量下会全表扫描。如果我直接用了,生产数据库可能就挂了。

Copilot 的问题在于:它是基于模式匹配的。它看到你写了一半的代码,然后根据它见过的类似代码来补全。但"看起来像"和"逻辑对"是两回事。

我的建议:Copilot 适合写样板代码(boilerplate)、测试用例、类型定义这些不太需要创造力的东西。涉及业务逻辑、安全、性能的地方,还是自己写比较靠谱。

另外说一下 Copilot 的 Chat 功能。很多人只用它的行内补全,但其实 Copilot Chat 也挺好用的。你可以选中一段代码然后问它"这段代码有什么问题?",它通常能找出一些你没注意到的细节。不过要注意,它的回答也不一定全对,尤其是涉及业务逻辑的时候。

我还发现一个技巧:写测试的时候先写函数签名和注释描述你要测什么,然后让 Copilot 补全测试体。它生成的测试用例覆盖度通常还不错,虽然你需要再加几个边界条件的 case。

还有个事情得提一下。Copilot 的代码建议有时候会"学坏"。如果你的项目里有一些不好的代码实践(比如到处用 var 而不是 const/let),Copilot 会学着也用 var。它是在模仿你的代码风格,包括坏习惯。所以如果你接手了一个代码质量不高的项目,用 Copilot 的时候要格外小心,它的建议可能会延续项目里已有的坏毛病。

解决办法是:在项目根目录放一个 .github/copilot-instructions.md(或者 VS Code 的 settings.json 里配置),告诉 Copilot 你想要什么风格的代码。这个配置文件的作用类似 CLAUDE.md,但格式不一样。

坑六:不同工具用错场景

用了半年之后,我最大的感悟是:每个 AI 编程工具都有它最适合的场景。用错了场景,效率不升反降。

Claude Code 适合:

  • 大型重构(需要理解整个项目的上下文)
  • 代码审查(让它帮你找潜在问题)
  • 调试复杂 bug(给它错误日志和相关代码)
  • 写文档和注释

Cursor 适合:

  • 日常编码(在 IDE 里直接用,最自然)
  • 多文件编辑(Agent 模式虽然不完美,但确实能省时间)
  • 前端开发(预览功能很好用)
  • 快速原型(几分钟搭个原型出来)

Copilot 适合:

  • 代码补全(这是它最强的地方)
  • 写测试用例
  • 写样板代码
  • 学习新框架(看它的建议能学到不少东西)

Windsurf 适合:

  • 需要跨会话保持上下文(Cascade 记忆功能)
  • 代码研究和探索(理解陌生代码库)
  • 预算有限但需要 IDE 集成(免费额度比 Cursor 多)

Gemini CLI 适合:

  • 免费使用(没有 token 限制)
  • 快速提问(不需要启动 IDE)
  • 代码解释(让它帮你理解一段陌生的代码)
  • 快速原型验证(想个 idea 让它帮你快速实现)

不过 Gemini CLI 也有它的局限。它的代码质量没有 Claude Code 那么稳定,有时候写出来的代码能跑但不够优雅。而且它的工具调用能力(比如读写文件、运行命令)没有 Claude Code 成熟。所以我的建议是:把 Gemini CLI 当成一个免费的"代码问答机",复杂任务还是交给 Claude Code 或 Cursor。

如果你把 Claude Code 当 Copilot 用(只是补全代码),那是大材小用。如果你把 Copilot 当 Claude Code 用(让它理解整个项目),那肯定会失望。

坑七:工具之间的切换成本

很多人(包括我)会同时用好几个 AI 编程工具。但工具之间的切换是有成本的。

每个工具的提示词风格不一样。Claude Code 喜欢你给它详细的上下文和明确的指令;Cursor 的 Agent 模式更喜欢你给它一个高层的任务描述;Copilot 只需要你在代码里写好注释就行。

如果你不注意这些差异,用同一种方式跟所有工具沟通,效果会打折扣。我以前习惯像跟 Claude Code 说话一样跟 Copilot Chat 说话,给了一大堆上下文,结果它反而理解不了,因为 Copilot Chat 的上下文窗口没那么大。

另外,不同工具的配置也要统一。你在 Cursor 里设的 .cursorrules 和在 Claude Code 里设的 CLAUDE.md,内容应该保持一致。不然你在 Cursor 里写的代码是一种风格,切到 Claude Code 里写的又是另一种风格,最后整个项目风格混乱。

我现在维护一个统一的配置模板,每个新项目都复制一份,然后根据项目特点微调。这样不管用哪个工具,输出的代码风格都是统一的。

坑八:安全问题被忽略了

这个坑很多人没注意到,但我觉得很重要。

AI 编程工具需要读取你的代码才能工作。这意味着你的代码会被发送到云端(除非你用本地模型)。对于个人项目可能没什么,但对于公司项目,这就涉及到代码安全和知识产权的问题。

我有个朋友在一家金融公司工作,他们公司明确规定不能用云端 AI 编程工具。原因很简单:代码里有交易算法和客户数据,不能外传。他只能用本地部署的模型,效果差了不少。

即使你是在做个人项目,也要注意几个安全问题:

不要把 API key 和密码写在代码里让 AI 看到。 有些 AI 工具会把你的对话记录保存在云端。如果你在代码里暴露了敏感信息,这些信息可能会被保存下来。

注意 AI 生成的代码的安全性。 AI 可能会给你生成有安全漏洞的代码,比如 SQL 注入、XSS 攻击等。它不会主动帮你做安全审查。

  • *检查 AI 引入的依赖。 有时候 AI 会建议你安装某个 npm 包或者 Python 库。你得确认这个包是真实存在的、是安全的。AI 有时候会"幻觉"出不存在的包名,这种包名如果被恶意注册了,就是一种供应链攻击。

我遇到过一个真实的例子:Claude Code 给我推荐了一个叫 python-utils 的包,说能帮我处理某些数据转换。我去 PyPI 上一搜,确实有这个包,但下载量很少,最近一次更新是两年前。我没敢用,后来发现标准库里就有同样的功能。

还有一个更隐蔽的问题:AI 有时候会在代码里硬编码一些示例值,比如 API endpoint、数据库连接字符串之类的。如果你不仔细看就提交了,这些信息可能会泄露你的基础设施细节。** 有时候 AI 会建议你安装某个 npm 包或者 Python 库。你得确认这个包是真实存在的、是安全的。AI 有时候会"幻觉"出不存在的包名,这种包名如果被恶意注册了,就是一种供应链攻击。

坑九:过度依赖 AI,自己的能力退化

这个坑是最隐蔽的,也是最危险的。

用了几个月 AI 编程工具之后,我发现一个可怕的事实:我的编码能力在下降。不是说我不懂编程了,而是我的"手感"变差了。以前写一个函数,我脑子里自然就有思路了;现在我会习惯性地先问 AI,看看它怎么写,然后在它的基础上改。

这种模式短期内效率很高,但长期来看是有问题的。你会变成一个"代码修改者"而不是"代码创造者"。你不再从零开始思考问题,而是总在 AI 给你的方案上修修补补。

我现在有意识地在做一些调整:

简单的东西自己写。 不是所有代码都需要 AI 帮忙。一些简单的逻辑、常见的模式,自己写反而更快。保持手感很重要。

先想清楚再问 AI。 不要一遇到问题就问 AI。先自己想几分钟,有个大概的思路,然后再让 AI 帮你完善。这样你既有思考的过程,又能利用 AI 的效率。

定期不带 AI 写代码。 我现在每周会有一天完全不用 AI 编程工具,纯手写。虽然效率低一点,但能保持对代码的直觉。

说到这个,我想起一个在 Reddit 上看到的讨论。有人问"停用 Copilot 之后你的生产力有变化吗?",结果不少人回复说没感觉到明显下降。这说明什么?说明 AI 编程工具的很多"效率提升"可能是幻觉。它让你写代码更快了,但如果你花更多时间在 review 和 debug 上,总效率可能并没有提高。

所以我的建议是:把 AI 当成一个很强的实习生,而不是一个 senior engineer。实习生能帮你干活,但你得检查他的工作。你不会让实习生独立负责一个核心模块,对吧?

我还发现一个有趣的现象:用 AI 编程工具久了,你会对某些语言特性越来越陌生。比如我现在写正则表达式,第一反应是让 AI 来写,而不是自己想。以前我正则写得挺溜的,现在如果不让 AI 帮忙,得想半天。这不是什么大问题,但说明你的某些技能确实在退化。

所以我的建议是:把 AI 当成一个很强的实习生,而不是一个 senior engineer。实习生能帮你干活,但你得检查他的工作。你不会让实习生独立负责一个核心模块,对吧?

坑十:忽略版本控制和回滚

这个坑说起来简单,但真的很痛。

用 AI 编程工具的时候,它会帮你改很多文件。如果你没有用 Git 做版本控制,或者没有频繁 commit,一旦 AI 改坏了什么东西,你想回滚都找不到上一个正常的版本。

我现在的工作流是这样的:

  1. 在让 AI 做大改动之前,先 commit 一下当前的代码
  2. AI 改完之后,review diff,确认没问题再 commit
  3. 如果改坏了,直接 git checkout 回到上一个版本

这个流程看起来多此一举,但它救过我好几次。有一次 Cursor Agent 模式把我的路由配置搞乱了,如果我没有提前 commit,可能要花几个小时才能手动修复。

另外,我建议用 Git 的 feature branch 来隔离 AI 的改动。不要直接在 main 分支上让 AI 改代码,开一个新分支,改完测试没问题再合并。

坑十一:没有写好提示词

最后这个坑是最常见的,也是最容易解决的。

很多人用 AI 编程工具的时候,提示词写得太模糊了。比如"帮我优化这段代码"——优化什么?性能?可读性?安全性?AI 不知道你在想什么,只能猜。

我总结了几个写好提示词的原则:

说清楚你要什么。 不要说"帮我写个函数",要说"帮我写一个 Python 函数,接收一个 URL 列表,并发下载所有文件,保存到 /tmp/downloads 目录,每个文件最多重试 3 次"。越具体,AI 的输出越接近你想要的。

提供上下文。 告诉 AI 你在用什么框架、什么版本、这个功能在项目的哪个部分。它不是你肚子里的蛔虫,不知道你的项目背景。

给出约束条件。 如果你有特定的要求(比如"不要用 any 类型"、"必须用 async/await 而不是 .then()"),提前说清楚。不然 AI 会按照它认为"最好"的方式来,可能跟你的想法完全不一样。

分步骤来。 复杂的任务不要一次给 AI,分步骤来。先让它理解项目结构,再让它做第一部分,review 通过之后再做第二部分。这样出错的概率小很多,而且你能在每一步都保持控制。

写在后面

说了这么多坑,但我还是要强调:AI 编程工具确实改变了我的工作方式,而且是往好的方向改变。以前要写一天的功能,现在可能两三个小时就搞定了。以前看不懂的代码,现在让 AI 帮我解释一下就明白了。以前懒得写的测试用例,现在随手就让 AI 生成了。

关键是你要知道它的边界在哪里。它能帮你写代码,但不能帮你做决策。它能帮你提高效率,但不能替你思考。它能帮你处理重复劳动,但不能替你学习和成长。

用了半年,我现在的工作流大概是这样的:Copilot 负责日常的代码补全,Cursor 负责日常的编码和小规模重构,Claude Code 负责大项目和复杂任务。三个工具各司其职,效率最大化。

附:常见报错和解决方法

用了半年 AI 编程工具,遇到过不少报错。这里列几个最常见的,省得你踩同样的坑:

Claude Code 报 "Rate limit exceeded": 你用得太猛了,Anthropic 限制了你的请求频率。等一会儿再试,或者升级到更高额度的计划。我有一次连续跑了两个小时,突然就被限流了。后来我学乖了,每跑 30 分钟就休息一下。

Claude Code 报 "Context window exceeded": 你的对话太长了,上下文窗口装不下了。用 /compact 压缩一下对话,或者开一个新会话。如果你在处理一个大文件,先让 AI 看关键部分,不要把整个文件都丢给它。

Cursor Agent 模式卡住不动了: Agent 在等待某个命令的输出,但命令卡住了。点取消,然后手动运行那个命令看看是什么问题。通常是某个依赖没装好,或者端口被占用了。

Copilot 不给建议了: 可能是网络问题,也可能是 GitHub 那边在维护。先检查网络连接,然后重启 VS Code。如果还不行,看看 GitHub Status 页面有没有什么故障报告。

AI 生成的代码跑不起来: 最常见的原因是版本不匹配。AI 可能用了某个库的新版本 API,但你项目里装的是旧版本。检查一下 package.json 里的版本号,让 AI 按照你实际使用的版本来写。

附:我的日常工作流

说了这么多坑,最后分享一下我现在的日常工作流,供参考:

开始一个新功能之前:

  1. 先自己想清楚方案,在纸上画一下大概的架构
  2. 用 Claude Code 帮我理解相关代码("帮我看看 src/api/users.ts 这个文件的逻辑")
  3. 确认方案可行之后,切到 Cursor 开始写代码

写代码的时候:

  1. Copilot 负责行内补全(基本上是自动的,不需要特别操作)
  2. 遇到复杂的逻辑,用 Cursor Chat 问一下
  3. 需要改多个文件的时候,用 Cursor Agent 模式(但每次只给一个小任务)

写完之后:

  1. 用 Claude Code 做 code review("帮我 review 这个 PR,重点看安全和性能")
  2. 让 AI 帮我补全测试用例
  3. 跑一遍测试,确认没问题再提交

遇到 bug 的时候:

  1. 先自己看错误日志,定位大概位置
  2. 把错误信息和相关代码一起给 Claude Code,让它帮我分析
  3. 如果它给的方案不对,换个方式描述问题再试一次

这个流程不完美,但对我来说是目前效率最高的方式。每个人的项目和习惯不一样,你可以根据自己的情况调整。

后面我打算试试用 AI 来做 code review 和自动化测试,到时候再写一篇分享。有啥问题评论区聊。

advertisement

用了半年 AI 编程工具,这些坑我替你踩了 — AI Hub