2026/10/12 20:21:55

Claude Code用不好?问题不在工具,而在两个关键误区

Claude Code用不好?问题不在工具,而在两个关键误区 一开始接触 Claude Code 的那两周我几乎在每一个深夜都对着终端怀疑人生让它重构一个类它把同文件里另一段业务逻辑一并“顺带优化”了让它补测试它在测试用例里自作主张改掉了被测试函数的返回值让它跑一次构建它甚至会在提交信息里替我写下“修复多个潜在问题”这种我根本不敢直面的表述。直到后来我请一位擅长结对编程的同事帮忙诊断同一个需求对方看完我的操作之后只问了三个问题改哪个文件边界在哪哪些东西碰都不能碰那一刻我才反应过来——问题根本不在 Claude Code而在我把它当成了一个“能读懂我心思的自动程序员”而不是一个“需要你用工程化方式去协作的结对搭档”。这篇文章不会有让人眼前一亮的魔法技巧但如果你也正在被 Claude Code 的“不听话”折磨或者刚打开它没几天就想卸载我建议你先花十分钟看完这两个最常见的理解误区应该能省下好几个晚上的折腾时间。1. 误区一你把它当“命令执行器”只发指令不给上下文很多人会用得很痛苦是因为把 Claude Code 当成了 IDE 里的终端插件指令越短越好“把登录逻辑改一下”“这个报错处理一下”“把这个页面优化一下”。短指令在传统工具面前没问题但 Claude Code 是对话式编码代理它根据你的上下文、工作区文件和模型自身对任务的推演来生成改动。你给它一个含糊的指令它只能去猜——而它猜的方向往往和你的心智模型不一样。1.1 你以为的“对话式编程”本质是“结对编程”把 Claude Code 理解成“下面这个命令行里住着一位远程协作者”会更准确。真正的结对程序员不会在你只说一句“你把登录改一下”的时候就直接动手他一定想搞清楚几个问题是改前端登录页、后端登录接口还是改鉴权中间件是修 bug还是做需求变更旧行为是必须保留的还是可以替换的哪些相关联的模块也在影响范围内Claude Code 也一样。它不是全知全能的它每次能确认的信息主要来自三块当前会话里你说了什么、工作区里索引到的文件内容、以及模型自身训练时对通用代码的理解。你给它越精确的“任务边界”它越不容易跑偏。我有一个实操习惯任何一条任务指令至少包含“文件路径 目标行为 禁止改动项”三要素。比如在 src/services/AuthService.ts 中修改 login 方法的逻辑 1. 保留原有 validatePassword 的调用顺序不变 2. 在 token 过期时返回 { needRefresh: true } 3. 不要动 AuthService 里的 refreshToken 方法 4. 不要动同目录下的 userRepository.ts这种写法看起来啰嗦但实际执行效率和准确度都高得多。因为“不要让工具猜”这件事本身就是工程素养的一部分就像你给团队新人派活一样。1.2 缺失上下文导致的一连串“翻车现场”我见过最典型的崩溃现场是这样某次我让它“给订单列表页加一个筛选状态”它很开心地把订单查询接口的参数改了顺手把状态枚举也改了还在类型定义里加了两个无关字段。原因很简单我只描述了页面效果没有说清“筛选状态是前端本地过滤还是后端查询参数”也没有说明“订单状态枚举在枚举文件里其他地方引用很多不能改”。它的补全逻辑只是基于“当前对话 文件索引”做最合理的猜测而它猜测的“合理”在你眼里可能就是灾难。这类问题在真实项目里会被放大因为项目越大关联文件越多它越容易从你觉得无关的地方“助攻”一下。所以现在只要涉及跨文件改动我都会在任务里明确写出影响范围偶尔还会加一条“如果发现需要在 X 之外修改其他文件请先停下来问我”。这是成本极低但收益极高的一条约束。1.3 把“帮我看一下”这种模糊请求变成可执行确认单大多数新人爱说“帮我看一下这个报错”然后贴一段日志。Claude Code 确实能读日志但“看一下”本身不构成任务。我习惯把这类请求拆成“问题描述 我尝试过的排查 要求它输出的内容”三段式报错信息构建时 Module not found: Cant resolve ./config 所在文件src/App.tsx 第 3 行引入 我确认过src/config 目录存在且 index.ts 已导出配置对象 请帮我 1. 检查 import 路径是否与实际文件路径大小写不一致 2. 检查 tsconfig 中 paths 别名配置是否有缓存或路径错误 3. 输出问题原因 最小改动方案不要直接改代码先给我方案注意这里最后一条“先给我方案”很关键这相当于把一个自动执行的工具切换成了“先对齐、再动手”的协作模式。你把它当成需要确认清单的同事它回馈给你的就是可预期的行为。2. 误区二你完全跳过了“上下文工程”把它当成零门槛的 AI 程序员第二个更大的误区是以为 Claude Code 开箱就能“懂你的项目”。这是被通用聊天助手惯出来的直觉跟聊天助手说话它天然会写代码那跟 Claude Code 说话它不是应该更懂代码吗单次对话它确实懂代码但对“你的业务为什么要这么写”“你的项目有哪些不能动的历史包袱”毫无概念。同一个getUserInfo在你的项目里可能是返回加密后的脱敏数据在另一个开源项目里可能就是直接查表。它默认按照通用最佳实践去猜猜错了你还觉得它笨。2.1 从来不建项目词典却指望它理解业务规则Claude Code 支持在工作目录里放CLAUDE.md这本质上就是一份给代理看的“项目工作手册”。它不是给你写文档用的而是为了让你在对话里只描述增量需求把项目共识、编码规范、禁忌清单一次性固化进去。我之前不愿意维护这份文件理由是“多一层东西要同步”。直到连续两个新会话里它都把同一个常量改错了我才真正花半小时把项目里最重要的约定写了进去。一份真正有用的CLAUDE.md不需要长篇大论它更像一份给临时工看的上岗须知# 项目约定 ## 后端 - 所有接口返回格式统一为 { code, message, data }禁止在业务里直接返回裸对象 - 数据库操作一律走 storage/ 目录下的 Repository 层禁止在 service 里直接写 SQL - 不要修改 migrations/ 目录下任何已提交的文件如需变更 schema必须新增迁移文件 ## 前端 - 页面组件放 pages/通用组件放 components/ - 状态管理禁止直接修改 state一律通过 actions 提交 mutation - 常量命名使用全大写下划线所有魔法数字必须提取到 constants/ ## 禁止事项 - 禁止在代码中引入新的全局样式 - 禁止把测试文件里的 mock 数据直接用于生产环境 - 禁止为了通过 lint 而关闭规则写完之后新会话里的行为稳定性提升非常明显改错字段的次数少了跨层写 SQL 的情况几乎绝迹它甚至会主动在动手前引用CLAUDE.md里的约定来说明为什么不做某件事。2.2 会话讲不清的“历史包袱”每次都要重新喂很多人忽略的一个重要现实Claude Code 的每一次新会话都像刚入职的第一天它什么都不记得。你在上一个会话里反复强调过的“我们项目的 id 字段叫 uuid 不叫 id”新会话里它照样会用id。所以凡是“每个任务都需要知道”的信息都应该固化到CLAUDE.md或者工作区内的约定文件里而不是靠每次对话灌输。灌输能解决单次任务固化才能解决长期一致的协作问题。我见过一个比较极端的例子某开发者为了让代理正确理解“订单状态机的迁移必须经过 audit 日志”每次都在对话开头贴一段说明。结果有一次赶上机器人短路它直接改坏了状态迁移逻辑。后来他把这段约束写进CLAUDE.md问题彻底消失。这背后其实是一个简单工程道理代理的“记忆质量”取决于你有多少知识沉淀在工作区文件里而不是它的上下文窗口有多大。2.3 把长上下文当免死金牌只会让“假理解”更加严重现在的模型上下文窗口越做越大很多人下意识觉得“反正它都能记住我一次性把所有背景都塞进去不就行了”。但注意上下文窗口大意味着它能“容纳”的信息多却不代表它能正确“区分”哪些信息对当前任务真正重要。当你在一个会话里塞入整个项目说明、五十个文件的内容、三天的讨论记录时Claude Code 会把注意力分散在不同权重上很容易优先采纳离当前编辑位置最近的相似代码风格而不是你藏在第 37 条里的“禁止事项”。长上下文的正确用法是靠CLAUDE.md和项目内文档来做“信息抽屉”它需要时去翻翻不到才来问你。而不是你一次性把整个图书馆推到它面前。3. 纠正理解之后我的日常工作流变了如果你看完上面两个误区决定换个方式和 Claude Code 协作那接下来的工作流是我目前在真实项目里一直用的可以直接抄作业。3.1 开工前先花 10 分钟“办入职”每次开始一个有一定复杂度的功能之前我不会直接说“开始做”而是先执行一个固定动作把任务相关背景写成一个简短的TASK.md或直接在对话里贴一段“入职说明”。这段说明一般包括四块内容项目结构当前模块在哪个目录依赖哪些相邻模块关键文件清单优先读哪些文件不要碰哪些文件业务规则这个功能必须满足的约束条件验收标准代码写成什么样算完成。举个例子我要做一个“批量导出订单 Excel”的功能我不会只说“帮我加个导出功能”而是说任务在 admin/src/pages/orders 下新增批量导出功能。 背景订单数据来自 src/api/order.ts 的 fetchOrders 接口支持分页参数。 约束条件 - 导出格式使用 xlsx上限 5000 条 - 导出文件列头必须与页面表格一致 - 不新增后端接口前端直接复用 fetchOrders - 不要改动 order.ts 现有函数签名 验收点击导出按钮后调用导出工具生成文件并自动下载页面不卡死。这个过程看起来很费时间实际上比我之前边聊边改要快得多因为它大幅减少了来回修正的轮次。总体上花 10 分钟“办入职”至少能省掉三十分钟的返工。3.2 小步走一次只让它动一个文件给完就检查我之前犯过的最严重错误是让它一口气“把所有相关文件都优化一遍”。听起来很高效结果它同时动了接口、页面、样式、测试、配置五个维度出问题之后根本分不清哪些是预期改动哪些是它自由发挥。现在的做法是“一次一个改动单元”明确唯一目标比如“把 utils/date.ts 里的 formatDate 方法改成支持传入 Date 对象和字符串两种入参”让它先给修改方案不许直接动手方案确认后限制“只允许改 utils/date.ts 这一个文件”改完立刻git diff检查有意外改动就在下一个任务里要求回滚。这个流程牺牲了一点“自动化感”换回来的是每一步都可控、可回滚、可验收。3.3 我负责决策它负责执行和反馈修正确实理解之后我对 Claude Code 的定位其实变成了三个角色缺一不可快速打字员帮我生成大量重复性代码、模板代码、类型定义代码检索器在我记不清某些调用链时直接在项目里帮我翻出引用关系初稿生成器把复杂需求先写出一版可运行的粗糙实现再由我做架构把关和边界修正。这听起来好像很保守但恰恰是这种定位才让它在日常开发里成为真正省时间的工具。你不需要它替你思考整个系统的未来你只需要它在明确的边界内快速执行并且把所有它认为的“隐患点”反馈给你。4. 真正踩过坑之后才理解的几条实战细节这一节想聊一些官方文档不会告诉你、只有你真实跑过一段时间才能体会到的细节算是个人踩坑笔记吧。4.1 一次改太多文件会出现“连锁塌方”Claude Code 在拿到一个多文件任务时倾向于按照它自己理解的顺序依次修改但修改 A 文件时产生的假设可能到修改 B 文件时已经变了。比如它先改了接口返回结构然后又根据旧的类型声明去改前端调用最后两者对不上整个构建直接崩掉。所以要严格限制改动范围。我自己常用的句式是只允许修改 src/order 目录下的 .ts 文件其他目录下的文件如果有改动需要先列出来给我确认。如果它中途提出“发现 src/shared/button.tsx 也需要改”那就停下来先确认再继续。把这个习惯建立起来之后崩溃概率直线下降。4.2 让它“别碰什么”往往比“做什么”更重要有一次我让它优化某个文件的性能它非常勤快地把里面一个被三处引用的公共函数改成了新的实现结果另外两处调用直接行为不一致。原因就是我只说了“优化”没有说“这个公共函数还被别人用着”。从此之后我的任务描述里会专门加一个“禁止事项区”。这一区甚至可以比正向描述更重要。你越清楚项目的雷区在哪里就越要用文字明确标出来。毕竟工具不会像老员工一样知道“这块代码当年为什么这么烂别动它”。4.3 养成 diff 洁癖每次改动都要过一遍“变更审查”我见过很多人对 AI 改代码极度信任让它改完就直接提交了。这是灾难的根源。我现在设置了三个动作属于铁律谁来了都不破git diff --stat # 看它到底动了哪些文件有没有越界 git diff # 逐行看关键文件的具体变更确认没有夹带私货 git log -1 --oneline # 提交信息是否出自你真实意图如果要用 Claude Code 帮我写提交记录我也只会让它“基于我指定的改动范围来写”而不是让它看着所有 diff 自由发挥。4.4 会话太长会“失忆”该断则断Claude Code 在很长的会话里注意力更容易偏向最近的内容早期提到的关键约束可能会在后面被稀释。如果你发现同一个需求来回改了四五轮它还在反复提出同一类问题那就别再硬撑着续这段对话了。正确做法是新开一个会话把必要背景浓缩成一小段“入职说明”接着做。不要觉得这是浪费Session 是用来聚焦的不是用来拼续航的。聚焦越强它的表现越稳定。5. 回归本质它是一块“动力十足的引擎”但方向盘始终在你手里聊到这里再回头看标题里的“理解错了”四个字我想你大概也认同Claude Code 确实不是不好用而是很多人一开始就对它抱了错误的期待误以为 AI 编程工具应该代替人做判断结果自己放弃了上下文控制权还把翻车归因于工具太蠢。我个人的体会是把它当“一个能力很强但完全不了解项目背景的试用期同事”来对待是收益最稳的方式。你要给它清晰的工作手册设定明确改动边界在它动手前先让它给方案在它动手后认真做 diff 审查。它负责把力气用在对的地方你负责告诉它哪些地方是雷区。如果你此刻正被它改得头皮发麻不妨先停下操作检查一下自己的任务描述是否写清了“文件路径、目标行为、禁止改动项”三要素再检查一下项目根目录有没有CLAUDE.md。大部分所谓“不听话”归根到底都是这两件事没做到位而已。