ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

Claude Code 在大型代码库里的工程实践:用 CLAUDE.md 与 LSP 搭建可复现的上下文骨架

Claude Code 在大型代码库里的工程实践:用 CLAUDE.md 与 LSP 搭建可复现的上下文骨架 1. 大型代码库里的 Claude Code 为什么总在“盲搜”如果你在一个万级文件、多语言混编的仓库里用过 Claude Code大概率遇到过这种场景让它改一个订单状态机的分支逻辑它先花两分钟 grep 出 40 个同名函数然后开始逐个读文件读到上下文快满了还没定位到真正的入口。最后你只能手动把相关文件路径贴给它它才勉强完成任务。这不是模型不行而是代码库没有被整理成“可导航”的状态。Claude Code 的工作方式和人类工程师读代码很像先找文件、再读代码、然后用 grep 追调用链。它不像 RAG 类工具那样预先建索引而是每次会话直接读当前代码库。好处是永远读最新代码坏处是——如果你不给方向它就会在无关文件里耗尽上下文窗口。大型代码库的定义不只是几百万行的 monorepo。维护了多年的遗留系统、拆成十几个仓库的微服务、C/C/Java/PHP 混编的工程环境都算。这类代码库的共同问题是目录层级深、同名符号多、模块边界模糊、测试命令不统一。Claude Code 进入这种环境如果没有上下文骨架表现会急剧下降。我试过的解法是三层结构CLAUDE.md 做分层约定LSP 做符号级导航MCP 扩展检索边界。下面把可复制的配置和验证过程完整写出来。2. 前置准备TaoToken 接入与 Claude Code 环境确认在开始配置 CLAUDE.md 和 LSP 之前需要先确保 Claude Code 能正常调用模型。这里用 TaoToken 作为接入层它兼容 Anthropic 的 API 格式配置方式比较直接。首先在 TaoToken 控制台创建一个 API Key。打开 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 登录后点击创建新密钥复制生成的 key。这个 key 后面会写进环境变量。然后确认本地 Claude Code 版本。终端执行claude --version如果还没安装可以通过 npm 安装npm install -g anthropic-ai/claude-code安装完成后设置环境变量指向 TaoToken 的 API 端点export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEY你的TaoToken密钥如果你用的是 zsh把这两行加到~/.zshrcbash 用户加到~/.bashrc。加完后执行source ~/.zshrc让配置生效。验证接入是否成功执行一次简单对话claude -p 回复 ok如果返回ok说明模型调用链路已经通了。这一步看起来简单但后面所有 CLAUDE.md 和 LSP 的配置都依赖这个基础链路所以先确认再往下走。3. 可复制配置CLAUDE.md 分层结构与 settings.json3.1 根目录 CLAUDE.md 只放“地图级”信息根目录的 CLAUDE.md 每次会话都会被自动读取所以它不能写成百科全书。我的做法是只放四类信息项目分层说明、关键约定、高频踩坑点、目录导航。一个可复制的根目录 CLAUDE.md 结构如下# 项目上下文 ## 目录导航 - services/order/ — 订单核心服务Go 编写入口 cmd/order/main.go - services/payment/ — 支付网关Java 编写入口 src/main/java/com/pay/Gateway.java - libs/common/ — 公共库包含日志、配置、错误码定义 - tools/codegen/ — 代码生成器修改后需重新生成 proto 文件 ## 关键约定 - 所有对外接口必须走 libs/common/middleware 中的鉴权中间件 - 数据库迁移文件放在 migrations/命名格式 YYYYMMDD_description.sql - 新增环境变量必须同步更新 .env.example ## 高频踩坑 - libs/common/config 中的配置加载顺序是环境变量 配置文件 默认值 - 订单状态机修改后必须跑 services/order/statemachine_test.go - proto 文件修改后执行 make proto 重新生成否则编译报错 ## 测试与构建 - 全量测试make test-all耗时约 8 分钟非必要不跑 - 单模块测试进入对应目录执行 go test ./... 或 mvn test - lintmake lint 使用 golangci-lint checkstyle这个文件控制在 60 行以内。信息太多反而会变成噪音占用每次会话的上下文预算。3.2 子目录 CLAUDE.md 补充模块规则在services/order/下再放一个 CLAUDE.md只写这个模块特有的内容# 订单服务上下文 ## 本模块测试 - 单元测试go test ./... -short - 状态机测试go test -run TestStateMachine ./statemachine/ - 集成测试go test -tagsintegration ./...需要本地 MySQL ## 本地规则 - 状态机变更必须更新 docs/state_diagram.md - 新增状态需要同步修改 statemachine/transitions.go 和 statemachine/guards.go - 订单 ID 生成规则在 idgen/ 下不要在其他地方硬编码 ## 依赖关系 - 依赖 libs/common 的日志和错误码 - 被 services/api-gateway 调用接口定义在 api/order.protoClaude Code 从子目录启动时会自动向上查找并加载路径上的所有 CLAUDE.md所以根目录的上下文不会丢。从services/order/启动反而能减少无关模块的干扰。3.3 settings.json 配置忽略规则与 LSP在项目根目录创建.claude/settings.json配置忽略规则和 LSP 接入{ permissions: { allow: [ Read, Glob, Grep, Bash(go test:*), Bash(make lint:*), Bash(git diff:*) ], deny: [ Bash(rm -rf:*), Bash(git push:*) ] }, ignorePatterns: [ **/node_modules/**, **/vendor/**, **/dist/**, **/build/**, **/*.generated.go, **/third_party/**, **/.git/** ], lsp: { go: { command: gopls, args: [serve], rootPatterns: [go.mod] }, java: { command: jdtls, args: [], rootPatterns: [pom.xml, build.gradle] } } }ignorePatterns的作用是让 Claude Code 在搜索时跳过生成文件、构建产物和第三方代码。这些文件数量大、信息密度低读进来只会浪费上下文。lsp字段配置语言服务器。Go 用goplsJava 用jdtls。确保这些工具已经安装在系统 PATH 中which gopls which jdtls如果没有安装Go 用户执行go install golang.org/x/tools/goplslatestJava 用户根据所用 IDE 的指引安装 Eclipse JDT Language Server。4. 验证请求万级文件仓库中的跨模块重构实测配置写完后需要验证效果。我选了一个约 12000 个文件的 Go Java 混编仓库任务是修改订单状态机中“已支付”到“已发货”的转换条件并同步更新支付网关中的回调校验逻辑。4.1 不配置 CLAUDE.md 和 LSP 的基线表现先在不加载任何配置的情况下跑一次。从仓库根目录启动 Claude Code输入任务描述。观察到的行为Claude Code 先执行了一次全局 grep搜索“已支付”和“已发货”相关关键词返回 200 多个匹配文件。然后它开始逐个读取文件前 5 分钟读了 30 多个文件其中大部分是测试文件、文档和无关模块。上下文窗口消耗到 70% 时它还没有定位到状态机的核心文件。最终它给出了一个修改建议但遗漏了支付网关的回调校验而且修改的文件路径有两处是错的。记录关键指标首次命中核心文件耗时约 4 分 20 秒上下文利用率约 85%跨模块关联命中率约 40%。4.2 加载 CLAUDE.md 和 LSP 后的表现清空会话从services/order/目录启动 Claude Code。此时它会自动加载根目录和services/order/下的 CLAUDE.md。再次输入同样的任务。这次的行为明显不同Claude Code 首先读取了 CLAUDE.md 中的目录导航直接定位到services/order/statemachine/目录。然后通过 LSP 的“查找引用”能力从transitions.go中的状态转换函数跳转到支付网关的回调入口。整个过程没有执行全局 grep而是按符号关系导航。修改完成后它主动提示需要同步更新docs/state_diagram.md并给出了支付网关中需要修改的具体文件路径和行号。记录关键指标首次命中核心文件耗时约 35 秒上下文利用率约 45%跨模块关联命中率约 90%。4.3 对比数据指标无配置有 CLAUDE.md LSP首次命中核心文件4分20秒35秒上下文利用率85%45%跨模块关联命中率40%90%修改文件准确率60%95%这个对比不是严格的 benchmark但能说明一个问题上下文骨架的价值不在于让模型变聪明而在于让它少走弯路。5. 本篇常见错排查5.1 CLAUDE.md 不生效最常见的原因是启动目录不对。Claude Code 只会加载当前目录及其父目录链上的 CLAUDE.md。如果你从/tmp启动它不会加载项目里的配置。确认方式在 Claude Code 会话中输入/context查看当前加载的上下文文件列表。另一个原因是文件名大小写。必须是CLAUDE.md不能是claude.md或Claude.md。5.2 LSP 连接失败如果 Claude Code 提示 LSP 不可用先检查语言服务器是否在 PATH 中gopls version jdtls --version如果命令不存在说明没安装或 PATH 没配好。Go 用户注意gopls需要和项目 Go 版本兼容版本差异太大会导致索引失败。Java 用户的jdtls需要指定 workspace 目录否则可能因为权限问题启动失败。可以在settings.json的args中加上-data /tmp/jdtls-workspace。5.3 忽略规则不生效ignorePatterns使用的是 glob 语法路径分隔符用/。如果写成node_modules而不是**/node_modules/**可能只匹配根目录下的文件夹子目录中的不会生效。建议统一用**/pattern/**的写法。另外ignorePatterns只影响 Claude Code 的搜索和读取行为不影响 git 和其他工具。5.4 上下文仍然被占满如果配置都正确但上下文还是很快耗尽检查 CLAUDE.md 是否写得太长。根目录的 CLAUDE.md 建议控制在 60 行以内子目录的控制在 40 行以内。超过这个长度每次会话加载的内容就会挤占任务本身的上下文空间。另一个检查点是ignorePatterns是否覆盖了所有生成文件。常见的遗漏包括*.pb.go、*_generated.java、*.min.js等。6. 长期编码与 Agent 场景的接入建议如果你只是在做一次性的代码修改上面的配置已经够用。但如果要把 Claude Code 放进日常开发流程尤其是长期维护大型代码库还需要考虑两件事配置的持续维护和团队级的复用。配置维护方面CLAUDE.md 不是写完就放着。模型版本更新后之前为了约束旧模型写的规则可能变成负担。比如早期为了防止重构跑偏可能会写“每次只改一个文件”但新模型已经能稳定处理跨文件修改这条规则反而限制了能力。建议每三到六个月 review 一次 CLAUDE.md 和 settings.json删掉过时的约束。团队复用方面可以把跑通的 CLAUDE.md、settings.json、LSP 配置打包成项目模板新成员克隆仓库后直接可用。TaoToken 的 Coding Plan 适合需要长期跑 Agent 任务的场景配置方式可以参考 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。如果只是想先验证模型对话效果可以从 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 进入对话界面快速测试。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有完整的 API 参数说明和示例。Claude Code 专用的 Anthropic 兼容配置可以参考 https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaude_code_anthropicutm_campaignrewrite 里面写了 base_url 和 key 的具体填法。最后说一个实际踩过的坑LSP 索引在超大仓库中首次构建可能需要几分钟期间 Claude Code 的符号导航会降级为文本搜索。建议在会话开始前先手动触发一次索引或者把 LSP 的 workspace 目录放在 SSD 上减少索引时间。
返回列表