用 Claude Code 写了半年大型项目,这 10 个坑踩完才知道怎么用对

有一件事我直到用了 Claude Code 三个月才搞清楚------

它的上下文窗口是 200K tokens,但这个数字在大型代码库里根本撑不了多久。

粗略换算:一个普通 Java 服务文件大约 200-500 行,按每行 10 个 token 计算,200K tokens 大约能容纳 400-1000 个完整文件。听起来不少,但一次深度调试或功能开发,Claude 会连带读依赖、读测试、读配置------不知不觉上下文就满了,然后开始"失忆",重复犯之前说好不会犯的错。

我们当时接手了一个运行了 4 年的 Spring Cloud 单体拆微服务的项目,代码量 8 万多行,依赖关系错综复杂。最开始用 Claude Code 就是当一个聪明的补全工具------让它改几个文件、写几个测试,能跑就行。但慢慢发现,同样的问题同事用 Claude Code 能 20 分钟搞定,我自己要来回折腾两个小时。

差距不在模型,在使用方式。

把摸索出来的 10 个技巧整理成这篇,每个都是踩过坑之后才真正理解的。

技巧一:CLAUDE.md 不是越详细越好,超过 200 行就是在害自己

大多数人的误用

刚开始用的时候,我把 CLAUDE.md 当成一个什么都往里塞的"说明书"------项目架构、API 文档、代码规范、常用命令、禁止事项......洋洋洒洒写了 500 行,觉得交代得越详细 Claude 表现越好。

结果恰恰相反。Claude 开始忽略文件里后半段的内容,说好不要改的文件照样改,说好用的框架换成了另一个。

为什么会这样

CLAUDE.md 的内容会在每次会话开始时直接注入上下文窗口,按照官方文档的数据,一份典型的项目 CLAUDE.md 大约消耗 1800 tokens。但如果你的文件是 500 行,消耗就到了 5000-8000 tokens。

更关键的问题是:CLAUDE.md 是以"上下文"的方式加载的,不是"配置规则"。Claude 读完它之后,并不会像代码里的 if/else 那样严格执行,而是"知道了这个信息,根据情况判断"。文件越长,重要规则被稀释的概率越高,反而让 Claude 觉得每条规则的权重差不多。

正确做法

官方建议是:CLAUDE.md 保持在 200 行以内,只写 Claude 靠自己读不到的信息。

具体来说,哪些值得写:

markdown 复制代码
# 项目构建
- 运行:mvn clean test -pl user-service(单服务测试)
- 全量构建:./scripts/build-all.sh(大约 3 分钟)

# 不要动的文件
- src/legacy/DataMigration.java(迁移脚本,已废弃但生产依赖)
- .env.production(生产环境变量,只读不改)

# 代码规范差异
- 这个项目用 MyBatis 不用 JPA,不要引入 Hibernate
- 服务间通讯走 OpenFeign,不要用 RestTemplate

# 架构决策
- 每个服务独立数据库,禁止跨服务直接访问 DB

哪些不用写:Java 基本语法、标准 REST 规范、Claude 读代码就能推断出来的东西。

如果确实有很多规则,用 .claude/rules/ 目录做路径隔离------比如只在修改 src/api/**/*.java 时才加载 API 规范文件。这样规则按需加载,不会每次都占满上下文。

json 复制代码
// .claude/rules/api-conventions.md 的 frontmatter
---
paths:
  - "src/api/**/*.java"
---
# API 规范(只在修改 API 层文件时加载)
- 所有接口返回 Result<T> 包装类
- 参数校验用 javax.validation 注解,不要手写 if

判断标准很简单:如果去掉某条规则,Claude 是否会做出不同的决定? 答案是"不会"就删掉。

图:200K tokens 上下文的实际分配------启动自动注入约 7400 tokens,一次典型调试 Session 消耗约 30,400 tokens(15%),探索陌生大模块不用 Subagent 可能耗掉 80%+

技巧二:一个 Session 做太多事是效率杀手

大多数人的误用

打开 Claude Code,开始让它修 Bug,修完顺手让它加个功能,加完让它写测试,写完觉得文档也顺手更新一下......几个小时过去,这个 Session 的上下文里全是各种文件读取记录、失败尝试、修改历史,乱成一锅粥。

然后发现 Claude 开始犯奇怪的错误------明明说好的变量名,它换成了另一个;明明已经修好的问题,重新冒出来了。

为什么会这样

Claude 的 Session 是有状态的,所有的"对话"都累积在上下文里。读了 10 个文件、尝试了 3 种方案、来回改了 2 次------这些全都在消耗上下文空间。当上下文快满的时候,Claude 会触发自动压缩(compaction),把之前的对话总结成摘要。

但压缩是有损的。你在对话里说的临时决定、中途修改的方向、某个特定的约束,在压缩后可能就消失了。CLAUDE.md 里的内容在压缩后会重新注入,所以写进文件里的规则比口头说的更可靠。

正确做法

养成按任务切换 Session 的习惯。用 /clear 在无关任务之间重置上下文。

一个实用的工作流:

bash 复制代码
# 任务 A:修复登录 Bug
claude
# 完成后
/clear

# 任务 B:新增支付功能
claude

如果当前任务涉及大量文件阅读(比如理解一个陌生模块),用 Subagent 来做------让子 Agent 去读文件、做调查,只把结论带回来,不让探索过程污染主 Session 的上下文。

复制代码
用 subagent 去读一下 payment-service 模块,
弄清楚现有的支付流程,然后告诉我需要在哪里加新的支付渠道

子 Agent 在自己独立的上下文里跑,读了 100 个文件也不影响你的主 Session。

图:遇到新任务时的 Session 管理决策树------何时 /clear、何时 /compact、何时用 Subagent、何时开 Worktree

技巧三:Plan 模式是你在大型代码库里最重要的工具

大多数人的误用

让 Claude 直接改代码------特别是在大型代码库里,不知道它会改哪些文件,结果改完一看,动了 15 个文件,其中有几个地方改法明显不对,还不知道该从哪里开始 revert。

为什么会这样

大型代码库里的修改往往有连锁反应。改一个接口,可能涉及 Controller、Service、Mapper、DTO、测试、文档......Claude 知道要改这些,但执行顺序和改法不一定符合你的预期。在代码直接落地之前,你没有机会说"等一下,这个地方不对"。

正确做法

启动 Plan 模式(Shift+Tab 切换,或 --permission-mode plan)。在这个模式下,Claude 读文件、分析代码,给出完整的变更计划,但不执行任何修改

实测下来,这是大型代码库里提升效率最明显的单一操作。典型的工作流:

复制代码
[Plan 模式下]
我要在 user-service 里添加手机号登录功能。
先读一下现有的登录实现,告诉我需要修改哪些文件,
以及每个文件具体的改动方向。

Claude 会给出一份类似这样的计划:

复制代码
计划修改以下文件:
1. UserController.java - 添加 /login/phone 接口
2. UserService.java - 添加 phoneLogin() 方法  
3. SmsService.java - 添加验证码校验逻辑
4. UserMapper.java - 添加按手机号查询用户的 SQL
5. LoginDTO.java - 添加 PhoneLoginRequest 内部类

不需要修改:认证中间件(复用现有 token 逻辑)

你看完计划,觉得没问题了,再切回正常模式让它执行。这样改的是你知情的、你同意的,不会有意外。

进阶用法 :看完计划,按 Ctrl+G 在文本编辑器里直接编辑这份计划,改掉你觉得不对的地方,再让 Claude 按修改后的计划执行。

技巧四:上下文不够用时,多开几个 Session 并行跑

大多数人的误用

一直在同一个 Session 里工作,遇到上下文快满的提示就用 /compact 压缩一次,继续跑。但压缩完 Claude 表现变差了,又不知道是什么原因。

为什么会这样

/compact 会把历史对话压缩成摘要,节省 tokens,但压缩后 Claude 失去了很多具体的上下文细节。之前读过的文件内容、之前探索过的路径------摘要里可能只剩几行概述。

对于大型代码库的复杂任务,一个 Session 根本不够用。

正确做法

Worktrees 开多个并行 Session,每个 Session 处理独立的子任务。

bash 复制代码
# 创建一个新的 worktree,专门处理认证模块重构
claude --worktree auth-refactor

# 另一个终端,另一个 worktree,处理支付模块
claude --worktree payment-feature

每个 Worktree 是独立的 git 分支和独立的文件系统快照,两个 Session 的修改不会相互干扰。用完合并就行。

对于特别大的单体仓库(monorepo),还可以配置 sparsePaths 做稀疏检出,只让 Claude 看它需要的那部分:

json 复制代码
// .claude/settings.json
{
  "worktree": {
    "baseRef": "fresh",
    "symlinkDirectories": ["node_modules", ".cache"],
    "sparsePaths": ["packages/user-service", "shared/common-utils"]
  }
}

这样一个 monorepo 里,Claude 只会看 user-service 和共用工具,不会被其他 50 个服务的代码干扰。

技巧五:给 Claude 能验证自己的工具,效果会好很多

大多数人的误用

让 Claude 改完代码,自己去跑测试看结果,再回来告诉 Claude "有个测试失败了"。

这个来回就是效率损耗。

为什么会这样

Claude 的核心能力是"探索-修改-验证"的循环。如果它每次改完都要等你来告诉它结果,这个循环断了,很多次可以自动修复的小问题变成了需要你手动介入的问题。

而且更重要的是:当 Claude 能自己运行测试、看到输出,它的修复精准度会明显提升。 因为它能看到真实的错误信息,而不是你描述的错误信息。

正确做法

在 prompt 里明确告诉 Claude 验证方法:

复制代码
修改 UserService 的 findByPhone 方法,
让它在手机号格式不对时抛出 InvalidPhoneException。
改完之后运行 mvn test -pl user-service -Dtest=UserServiceTest,
确保测试通过。如果测试失败,看错误信息继续修。

或者用 Hooks 自动化这个过程------每次文件修改后自动跑 lint:

json 复制代码
// .claude/settings.json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "mvn checkstyle:check -pl user-service",
            "timeout": 30
          }
        ]
      }
    ]
  }
}

这样每次 Claude 改完代码,自动跑一次 checkstyle,违规直接反馈给 Claude,它自己修,不需要你盯着。

技巧六:@ 引用文件比让 Claude 自己"找"更高效

大多数人的误用

"帮我修一下登录的 Bug" → Claude 开始 grep 整个项目,读了十几个文件,花了大量上下文 tokens,才找到问题所在。

为什么会这样

如果你不告诉 Claude 去哪里找,它会自己做 codebase 搜索------这很消耗上下文。每一次 grep、每一次 Read 都在占用 token 配额。在 200K 的上下文里,读 5 个 2000 行的文件就花掉了大约 5% 的额度。

正确做法

@ 直接引用你知道相关的文件或目录:

复制代码
@src/api/UserController.java @src/service/UserService.java
登录接口在高并发下出现了 token 不一致的问题,帮我看一下是哪里有并发问题

这样 Claude 直接拿到了你指定的上下文,不用到处搜索。减少了不必要的文件读取,也让 Claude 更聚焦在你认为相关的代码上。

还有一个进阶技巧:对于大型项目,配置自定义的文件建议命令。这样用 @ 触发的自动补全是项目专属的,不是通用的文件系统搜索:

json 复制代码
// ~/.claude/settings.json 或 .claude/settings.json
{
  "fileSuggestion": {
    "type": "command",
    "command": "~/.claude/scripts/project-file-index.sh"
  }
}

这个脚本可以结合你的项目结构(比如 Maven 的 module 划分)返回更精确的文件建议,而不是把整个文件树都列出来。

技巧七:Auto Memory 在悄悄学习,你需要知道它记了什么

大多数人的误用

不知道有 Auto Memory 这个东西。或者知道了,但觉得这是黑盒,不去管它。

为什么会这样

Claude Code 有个功能叫 Auto Memory(自动记忆)。当你纠正 Claude 的行为、告诉它某个项目的特殊规则,它会把这些学到的东西存入 ~/.claude/projects/<项目>/memory/MEMORY.md下次 Session 自动加载

这是个很有用的功能,但也有两个坑:

第一,你可能不知道它"记住"了什么错误的东西。比如你曾经在某个测试场景里让它用了一个临时方案,结果它把这个临时方案记下来了,之后每次都用,让你莫名其妙。

第二,MEMORY.md 的前 200 行会自动加载进每个 Session,如果记了很多乱七八糟的内容,无形中消耗上下文。

正确做法

定期审查 Auto Memory:

bash 复制代码
# 打开当前项目的自动记忆文件
~/.claude/projects/<项目hash>/memory/MEMORY.md

或者在 Session 里直接运行 /memory,查看当前加载的所有记忆文件,该删的删,该修正的修正。

对于一些明确不想让 Claude 自动记忆的内容,可以在 CLAUDE.md 里显式说明------CLAUDE.md 里的规则优先级更高,而且是你主动维护的,比 Auto Memory 更可控。

技巧八:Subagent 不只是"让它自己想",而是上下文隔离的关键手段

大多数人的误用

只知道 Subagent 可以并行处理任务,觉得这是一个"速度"工具。

为什么会这样

Subagent 最重要的作用不是速度,而是上下文隔离。当你让 Claude 探索一个陌生模块时,它会读很多文件,这些读取全都进入你的主 Session 上下文。如果改用 Subagent,这些文件读取发生在子 Agent 的独立上下文里,主 Session 只收到最终结论。

正确做法

凡是"先搞清楚某件事,再告诉我结果"的任务,都适合用 Subagent:

复制代码
用 subagent 去调查一下 order-service 里的库存扣减逻辑,
包括:现在的并发处理方式、已有的测试覆盖范围、有没有已知的并发问题。
调查完告诉我结论,不用给我读文件的过程。

还有一个更高级的用法:Writer/Reviewer 模式。一个 Session 写代码,写完之后用另一个 Session(或 Subagent)来 Review。因为 Reviewer 没有参与写代码的过程,不会带入"我觉得这样写是对的"的偏见,Review 质量更高。

复制代码
用 subagent review 一下 @src/payment/PaymentProcessor.java
这段代码,重点看:事务边界是否正确、异常处理有没有漏洞、
有没有可能出现重复扣款的场景。

技巧九:Hooks 做到"每次自动做",CLAUDE.md 只能做到"大概会做"

大多数人的误用

把很多应该用 Hooks 实现的自动化规则写进了 CLAUDE.md。比如"每次改完代码要运行一遍 lint"。

为什么这样不可靠

CLAUDE.md 里的规则是给 Claude 的"建议",Claude 会尽量遵守,但不能 100% 保证。特别是在上下文接近满的时候,这些规则可能被"遗忘"。

而 Hooks 是程序级别的触发------在特定事件发生时,无论 Claude 愿不愿意,脚本都会执行,结果都会反馈给 Claude。

正确做法

把"每次必须做"的事情写成 Hooks,"应该怎么做"的风格规范写进 CLAUDE.md

几个真正有用的 Hook 场景:

json 复制代码
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/check-dangerous-commands.sh",
            "timeout": 5
          }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "mvn checkstyle:check -q 2>&1 | head -20",
            "timeout": 30
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          {
            "type": "command",
            "command": "~/.claude/hooks/session-summary.sh"
          }
        ]
      }
    ]
  }
}

第一个 Hook 在每次执行 Bash 命令前先检查有没有危险操作(比如 rm -rfDROP TABLE);第二个每次文件修改后自动跑代码风格检查;第三个在 Session 结束时自动记录这次做了什么,方便下次继续。

这些都是"每次必须做"的事情,用 Hook 实现比写进 CLAUDE.md 可靠得多。

图:CLAUDE.md 是"告知型"软性约束,Hooks 是"程序化"确定性执行------两者定位不同,不要混用

技巧十:大型代码库里的权限配置不是障碍,是保障

大多数人的误用

嫌权限确认烦,直接开 --dangerously-skip-permissions 或者在 settings 里把所有权限都 allow。

为什么这是个坑

在小项目里,Claude 改错了无所谓,撤销就行。在 8 万行代码的生产服务里,如果 Claude 在没有任何权限控制的情况下随意执行命令------比如不小心跑了数据库 migration、删了临时文件但那个文件正在被其他进程用------代价可能相当大。

我们曾经遇到过 Claude 误删了一个本地缓存目录,虽然能恢复,但恢复过程花了一个小时,而那个任务本身只要 20 分钟。

正确做法

配置精细化权限,不是全开也不是全关,而是只放行你真正信任的操作

json 复制代码
// .claude/settings.json
{
  "permissions": {
    "allow": [
      "Bash(mvn test *)",
      "Bash(mvn clean compile)",
      "Bash(git status)",
      "Bash(git diff *)",
      "Bash(git add *)",
      "Bash(git commit *)",
      "Read(**)",
      "Edit(src/**)",
      "Write(src/**)"
    ],
    "deny": [
      "Bash(rm *)",
      "Bash(DROP *)",
      "Read(.env*)",
      "Read(**/secrets/**)",
      "Write(**/migrations/**)"
    ]
  }
}

允许读所有文件、改 src 目录下的代码、跑 Maven 命令和 Git 操作;禁止删文件、禁止读取密钥文件、禁止直接写 migration 脚本。

这样配置完之后,大部分正常开发操作 Claude 能直接执行,不会反复问你,但真正危险的操作被拦住了。权限配置的目标不是让你省掉所有确认,而是把需要确认的操作缩减到真正值得你看一眼的那些。

常见问题

Q: Claude Code 的上下文满了之后,用 /compact 好还是 /clear 好?

A: 取决于当前任务的状态。如果还在同一个任务里,正在进行中的修改有价值保留,用 /compact------它会总结关键信息,保留重要的上下文。如果你已经完成了这个任务,准备开始下一个无关的任务,直接 /clear------彻底清理比有损压缩好。一个判断标准:如果你能用一段话清楚地描述当前任务的状态,那就 /clear 重开,把那段描述作为新 Session 的开场白效果更好。

Q: CLAUDE.md 里的规则 Claude 不遵守怎么办?

A: 先检查文件是否太长(/memory 可以查看当前 Session 加载了哪些文件)。CLAUDE.md 超过 200 行的话,精简是第一步。其次,确认规则表达是否够具体------"写好的代码"不如"使用 2 空格缩进,类名用 PascalCase"。如果某条规则是"必须执行"的(比如每次提交前要跑测试),换成 Hook 来保证,不要靠 Claude 自觉。

Q: 在大型代码库里,怎么让 Claude 快速找到相关代码?

A: 两个方法:一是用 @ 直接引用你知道相关的文件,省去 Claude 搜索的过程;二是让 Claude 用 git log --all -S "关键词" 这种 git 命令搜索,比 grep 全文要精准,而且能看到变更历史。如果你的代码库有特殊的模块划分或目录结构,在 CLAUDE.md 里说明,"认证相关代码在 auth-service/src/main",这样 Claude 搜索时有范围。

Q: 多个 Worktree 并行工作时,怎么合并结果?

A: 每个 Worktree 是独立的 git 分支。并行工作完成后,正常走 git merge 或 git rebase 流程。区别是可以在合并前用另一个 Session(新的上下文)来 Review 所有变更,Review 质量会更好,因为 Reviewer 没有参与编写过程。

Q: Auto Memory 记录的内容会影响哪些 Session?

A: Auto Memory 是 per-repository 的,所有该仓库的 Worktrees 共享同一份 memory。也就是说,在 main 分支上让 Claude 学到的东西,在 feature 分支的 Session 里也会生效。这通常是好事,但偶尔会出现"在一个场景下学到的临时习惯影响到另一个场景"的问题------定期用 /memory 检查和清理是好习惯。

参考资料


说实话,Claude Code 在大型代码库里真正发挥出来需要一段适应期。不是工具本身难,而是思维方式要转变------你不再是在"写代码",而是在"指挥一个有能力但需要明确边界的工程师"

上下文管理、权限配置、CLAUDE.md 设计,这些看起来像是繁琐的前置工作,但它们决定了你是把 Claude Code 当成一个省心的协作者还是一个每次都要从头解释的新手。我现在在同一个 8 万行代码库里,效率比半年前高了不止 3 倍,差距完全在这些配置和使用习惯上。

下一篇打算写 Claude Code Subagent 和 Agent Teams 的组合玩法------多个 AI 并行工作、自动协调任务、合并结果,这个玩起来更有意思。感兴趣的关注一下,不然算法不一定推得到你。如果你身边有人也在用 Claude Code 做大型项目,这篇可以直接转给他,省他自己踩一遍坑。

相关推荐
ANnianStriver1 小时前
PetLumina 03 — 后端目录重构与 Web 管理后台搭建
java·前端·ai·重构·ai编程·claude code
爱听歌的周童鞋3 小时前
Learn-Claude-Code | 笔记 | Multi-Agent Platform | s20_new Comprehensive Agent
llm·agent·multi-agent·claude code·comprehensive
SiYuanFeng4 小时前
如何在使用claude code的时候,不需要一直点yes
claude code
螺丝钉code16 小时前
JAVA项目 Claude code CLAUDE.md 到底应该怎么写
java·人工智能·claude code
Allenliu _Andy19 小时前
2026 最新版|免登录适配国内网络 Claude Code 终端版安装配置教程(Windows)
ide·chatgpt·openai·ai编程·claude code
小徐敲java1 天前
Claude Code Worktree(工作树) 完整实战指南(本地并行开发、分支管理、避坑全解)
claude code
艺杯羹1 天前
Claude Code 实现 Computer Use:让 AI 操控你的 Windows 电脑(MCP 平替方案)
vscode·ai·ai编程·模型·claude code
小明_GLC1 天前
Opencode Go接入Claude Code
pycharm·claude code·open code
薛瑄2 天前
在Claude Desktop 中使用Code、CoWork 国内详细使用教程,从安装到使用
ai·ai编程·claude·claude code·claude desktop·coding plan