Claude Code 最佳实践与避坑指南
本文汇总四个阶段中最容易踩的坑、最有价值的实践,以及快速自检清单。 建议每次遇到问题时先翻一翻这里。
一、最常见的 10 个坑
坑 1:改完就说"完成了",没有验证
症状:Claude 说"修改已完成",你就关掉窗口,结果第二天发现代码跑不起来。
正确做法:
修复 bug 或实现功能后,必须执行验证命令:
前端:pnpm type-check && pnpm lint && pnpm test
后端:mvn test 或 gradle test
通用:git diff 确认改动范围符合预期
在 CLAUDE.md 中强制这个行为:
## 禁止行为
- 禁止未运行以下命令就宣布任务完成:
- 前端:`pnpm type-check`
- 后端:`mvn test -pl 模块名`
坑 2:让 Claude 读整个目录或大文件
症状:问 Claude "帮我分析这个项目的结构",结果 Claude 读了几千行代码,token 耗尽,分析质量还差。
错误做法:
> @src/ 分析这个项目的架构
> @src/services/OrderService.java 这个文件有什么问题?(文件 800 行)
正确做法:
# 先用 Grep 定位,再精确读取
> 先列出 src/ 下的目录结构,然后找出核心 Service 类在哪里
# 读大文件时指定范围
> 读一下 OrderService.java 中 processOrder 方法的实现,
先用 Grep 找到方法的行号
节省 token 的量化效果:
直接读 800 行文件 → 3200 tokens
Grep(20行) + 精确读(60行) → 320 tokens
节省 90%
坑 3:对话超长不 compact,导致 Claude "失忆"
症状:对话进行到第 30 轮,Claude 开始忘记之前确认过的设计决策,给出和前面矛盾的方案。
判断标准:
超过 20 轮 → 执行 /compact
超过 40 轮 → 考虑 /clear 重开,把关键结论带入新会话
超过 60 轮 → 任务应该被拆分为多个独立会话
带关键结论重开会话的方法:
执行 /clear 前,先让 Claude 总结关键信息:
> 在我们 /clear 之前,列出这次会话的关键结论:
1. 已确认的技术方案
2. 已完成的文件改动
3. 还未完成的任务
然后 /clear,重新开始时把这些结论粘贴进去。
坑 4:CLAUDE.md 写了但不生效
症状:在 CLAUDE.md 里写了某条规范,但 Claude 还是不遵守。
排查步骤:
# 1. 确认文件位置是否正确(必须在当前工作目录或其父目录)
ls ./CLAUDE.md
ls ~/.claude/CLAUDE.md
# 2. 确认文件没有语法问题(@ 引用路径是否正确)
cat ~/.claude/CLAUDE.md | grep "@"
# 3. 验证 Claude 是否读取了配置
claude
> 你知道这个项目禁止使用哪些依赖吗?
常见原因:
- CLAUDE.md 放错了目录(不在项目根目录)
@引用的路径不存在或有拼写错误- 配置内容太多,被截断了(超过 150 行建议拆分)
坑 5:一次让 Claude 改太多文件,失去控制
症状:Claude 一次改了 10 个文件,你不知道每个改动是否正确,出了问题也不知道回滚哪里。
正确做法:
# CLAUDE.md 中设置门控
## 禁止行为
- 禁止在未出方案并等待用户确认的情况下修改 3 个以上的文件
# 执行时主动分批
> 先只修改 UserService.java,改完我确认后再改其他文件
大改动的分批策略:
方案 A:按文件批次(每批 2-3 个文件)
方案 B:按功能层次(先改数据层,确认后改业务层,再改展示层)
方案 C:先写测试(TDD:先改测试文件,确认测试意图后再改实现)
每批改动后立即验证:不要等所有文件都改完再验证,每批改完立刻运行验证命令,确认没有破坏已有功能,再进行下一批。
坑 5.5:Claude 改错了,不知道怎么回滚
症状:Claude 修改了代码,但结果不对,想恢复到修改前的状态。
决策树:选哪种恢复方式
改动还没有 git commit?
├── 只改了 1-2 个文件,知道哪里错了
│ → 直接告诉 Claude:
│ > 你刚才改的第 45-60 行不对,请还原到修改前的逻辑
│
├── 改了多个文件,想全部撤销
│ → git checkout . 或 git restore .
│ (撤销所有未暂存的修改)
│
└── 部分改动是对的,只想撤销某一个文件
→ git checkout -- src/services/OrderService.ts
(只还原这一个文件)
改动已经 git commit?
├── 只想撤销最后一次 commit,保留文件改动
│ → git reset HEAD~1
│ (commit 消失,但文件改动保留,可以重新检查)
│
├── 想完全回到 commit 之前的状态
│ → git reset --hard HEAD~1
│ ⚠️ 危险:文件改动也会丢失,确认后再执行
│
└── 改动已经 push 到远端
→ git revert HEAD(生成一个新的撤销 commit,更安全)
最佳预防策略:在 Claude 大批量修改之前,先建立一个检查点:
# Claude 动手前,先记录当前状态
git stash # 或 git commit -m "wip: checkpoint before Claude changes"
# Claude 改完,确认没问题
git stash drop # 或继续正常提交
# 如果改错了
git stash pop # 或 git reset --hard 到 checkpoint commit
坑 6:Hook 配置了但没有执行
症状:配置了 SessionStart Hook,但每次启动 Claude 都没看到 Hook 的输出。
排查步骤:
# 1. 确认 settings.json 格式正确(JSON 不能有注释、尾逗号)
cat ~/.claude/settings.json | python3 -m json.tool
# 2. 手动测试 Hook 命令
bash -c "你的 hook 命令"
# 3. 检查脚本权限
ls -la ~/scripts/your-hook.sh
chmod +x ~/scripts/your-hook.sh
最小化可用 Hook 配置(先用这个验证机制是否工作):
{
"hooks": {
"SessionStart": [
{
"type": "command",
"command": "echo 'Hook 测试成功'"
}
]
}
}
坑 7:MCP 连接了但 Claude 没有使用
症状:配置了 IDE MCP,但让 Claude 找函数定义时,它还是在用 Grep。
原因:Claude 不会自动偏好 MCP 工具,需要你明确要求。
正确的提问方式:
# 不明确(Claude 可能用 Grep)
> 找一下 UserService 的 createUser 方法在哪里
# 明确要求用 IDE 工具
> 用 ide_find_definition 找到 UserService.createUser 方法的定义
> 用 ide_find_references 分析 validateToken 有多少个引用
什么时候值得明确要求用 IDE 工具:
- 需要语义级查找(不是文本匹配):定义、引用、实现类、调用链
- 需要全局重命名(比 Grep+替换 更安全)
- 想要 IDE 的实时诊断(类型错误、快速修复)
简单的文本搜索(关键词、注释、日志)直接用 Grep 就够,不必每次都用 IDE 工具。
坑 8:/compact 后 Claude 忘了重要信息
症状:/compact 之后,Claude 不记得之前已经确认的技术方案。
预防方法:/compact 前明确告诉 Claude 什么是重要的:
> 我要执行 /compact,请在压缩前确保保留以下关键信息:
1. 我们决定使用 Redis 而不是本地缓存
2. validateToken 的 bug 根因是并发竞态
3. 还未完成:修改 TokenService.java 第 45 行
坑 9:permissions 配置没有生效
症状:deny 了某个命令但 Claude 还是执行了。
排查:
# 检查 settings.json 是否被正确读取
claude --debug 2>&1 | grep "settings"
# 确认 deny 规则语法
# 正确:
"deny": ["Bash(rm -rf *)"]
# 错误(缺少括号内的内容):
"deny": ["Bash"] # 这会禁止所有 Bash,不是只禁止特定命令
权限规则的优先级:deny 优先于 allow。同一命令既在 allow 又在 deny 里,以 deny 为准。
坑 10:经验没有被有效沉淀
症状:每次解决问题后什么都不记录,下次遇到同类问题还是要从头摸索。
有价值 vs 无价值的知识对比:
❌ 无价值(流水账):
"完成了用户登录功能的开发"
✅ 有价值(可复用):
## token 刷新竞态问题(通用模式)
现象:高并发下偶发 401 错误
根因:多个请求同时触发 token 刷新,第一个成功后其他请求拿到的旧 token 已失效
解法:前端用请求队列串行化刷新,后端 refresh 接口加锁防重复执行
适用范围:任何有 token 自动刷新逻辑的前后端项目
一个好的知识条目应该能让另一个人(或未来的自己)在 1 分钟内理解"什么情况下会触发、怎么解决"。
判断知识是否值得记录的三个问题:
- 这个经验下次遇到类似问题能直接用吗?
- 这是一个不直觉的发现(反常识/踩坑)吗?
- 其他人会因为不知道这个而重复踩坑吗?
三个问题有 2 个"是",就值得记录到 learnings/ 目录。
二、坏习惯 vs 好习惯对比表
| 场景 | ❌ 坏习惯 | ✅ 好习惯 |
|---|---|---|
| 分析文件 | @src/ 分析整个目录 | 先 Grep 定位,再精确读取 |
| 修改代码 | 要求 Claude 一次改完所有文件 | 分批改动,每批确认 |
| 对话管理 | 对话 50 轮从不 compact | 每 20 轮执行 /compact |
| 完成确认 | Claude 说"完成了"就信了 | 运行验证命令确认 |
| 写 CLAUDE.md | 只写正面规范 | 同时写"禁止行为" |
| 使用 Skills | 跳过门控点,让 Claude 直接执行 | 认真审阅每个门控点 |
| 经验积累 | 任务完成就关掉会话 | 记录有价值的发现到知识库 |
| 遇到错误 | 让 Claude 重试同样方案 | 让 Claude 换完全不同方向 |
| 搜索代码 | @大文件 让 Claude 找函数 | Grep "函数名" 直接定位 |
| Hook 失效 | 猜测原因 | 先用 echo 测试 最小化验证 |
三、高价值配置检查清单
必备配置(每个项目都应该有)
✅ 项目 CLAUDE.md
□ 技术栈声明(框架、版本、主要依赖)
□ 禁止引入的依赖列表
□ 代码风格约定(命名、分层)
□ 验证命令(类型检查、测试、lint)
□ 禁止行为列表(至少 3 条,用"禁止"开头,不用"应该")
□ 目录结构说明
✅ 全局 ~/.claude/settings.json
□ 危险命令的 deny 规则(rm -rf, git push --force 等)
□ 模型设置(可选)
□ 环境变量(API Key 等)
✅ Hooks(强烈推荐)
□ SessionStart:同步团队配置或打印环境信息
□ Stop:提示记录本次会话的新发现
推荐配置(提升效率)
🔵 MCP 服务器
□ chrome-devtools(前端项目必装,用于 UI 验证)
□ IDE 插件 MCP(代码导航,用 ide_find_definition 等)
🔵 团队配置
□ 团队共享 CLAUDE.md(通过 @引用 加载)
□ SessionStart Hook 自动同步共享配置
四、CLAUDE.md 反模式(不要这样写)
反模式 1:过于宽泛,没有约束力
❌ 不好的写法:
## 注意事项
- 请写好代码
- 注意代码质量
- 遵守规范
✅ 好的写法:
## 禁止行为
- 禁止使用 any 类型,使用 unknown 代替
- 禁止 console.log,必须使用 src/utils/logger.ts 的 logger
- 禁止修改 3+ 文件不先出方案
反模式 2:太长,导致每次 token 消耗巨大
原则:CLAUDE.md 控制在 150 行以内
超出部分使用 @引用 外部文件,按需加载
反模式 3:只有正面规范,没有禁止行为
大量实践证明:明确的"禁止"比模糊的"应该"更有效。
# 效果差(Claude 会灵活解释"最好")
## 规范
最好使用组件库而不是自己写 UI
# 效果好(没有歧义空间)
## 禁止行为
- 禁止自己编写 UI 组件,必须优先使用项目已有的 UI 库
- 如果组件库没有所需组件,在引入前先咨询用户
五、任务开始前的快速检查(30 秒自检)
开始一个新任务前,问自己:
□ 这个任务预计改动多少文件?
→ 3+ 文件:先出方案,等确认再动手
□ 需要探索多少代码?
→ 3+ 文件:考虑委派子 Agent(Sonnet)探索
□ 对话已经多少轮了?
→ 20+ 轮:先 /compact
□ 项目文档或 README 里有没有相关信息?
→ 先查文档,再读代码
□ 这个任务完成后有可复用的经验吗?
→ 任务结束后记录到 learnings/
六、当 Claude 给出错误结果时
诊断流程
第 1 步:确认问题是"理解错误"还是"执行错误"
- 理解错误:Claude 做了你没有要求的事
- 执行错误:Claude 理解正确,但代码有 bug
第 2 步:针对性处理
- 理解错误 → 用更明确的语言重新描述要求
(检查 CLAUDE.md 是否有相关规范)
- 执行错误 → 提供错误信息,让 Claude 重新分析
第 3 步:如果同一类错误出现 3 次
→ 停止尝试同类方案
→ 寻求完全不同的方向
→ 或者咨询同事/查文档
第 4 步:解决后
→ 这个错误是否是个"坑"?
→ 如果是,加到 CLAUDE.md 的禁止行为里
→ 记录根因到 learnings/
七、新手最常见的提问误区(及正确写法)
误区 1:问题太宽泛
❌ > 帮我优化代码
❌ > 这段代码有什么问题?
❌ > 帮我看看项目
✅ > 帮我优化 src/payment/calculator.ts 中 calculateTotal 函数的性能,
现在它在列表渲染时被调用了 1000 次,感觉很慢
✅ > @src/auth/middleware.ts 第 45-80 行有没有并发安全问题?
特别关注 token 验证的部分
✅ > 帮我理解 src/order/ 模块的架构,
重点关注订单状态流转的逻辑
误区 2:没有提供错误信息
❌ > 代码报错了,帮我看看
✅ > 代码报错了,错误信息如下:
TypeError: Cannot read property 'id' of undefined
at OrderService.createOrder (src/services/order.ts:89:23)
相关代码在 src/services/order.ts 第 85-95 行
误区 3:要求 Claude 一次改太多
❌ > 把整个订单模块重构成最佳实践
✅ > 先分析 src/order/ 模块的问题,
给我一个重构方案(不要直接动手),
等我确认方案后再分步骤实施
误区 4:不说清楚约束条件
❌ > 帮我实现分页功能
✅ > 帮我实现分页功能,要求:
- 复用 src/components/Pagination 已有组件
- 分页参数格式参考 src/api/order.ts 里的 getOrderList 接口
- 不要引入新的依赖库
- 改动只限于 src/pages/ProductList.tsx 文件
误区 5:Claude 说完成后不验证
❌ 看到"修改完成"就关掉会话
✅ 每次改完代码必须执行:
git diff → 确认改了什么
pnpm type-check → 确认类型没问题
pnpm test → 确认没破坏已有功能