Claude Code 不理解整个项目怎么办

Claude Code 一直在改同几个文件、或完全忽略别的目录——用 CLAUDE.md 锚定上下文。

你让 Claude Code 在一个中等规模仓库里做改动,结果它反复修改 src/index.ts 一个文件,完全忽略你提到的 apps/web/packages/api/;或者在 monorepo 里它根本看不出 workspace 关系,要不就是把测试写在了源码同目录而不是 __tests__/——这都是同一个根本问题:Claude Code 缺少项目地图。

Claude Code 本质是一个带文件工具的 LLM 会话,它对你项目的全部认知来自三件事:当前工作目录、CLAUDE.md(如果有)、以及你 prompt 里提到的路径。三者任一缺失或失真,它就会陷入”以管窥豹”的模式。

常见原因

按命中率从高到低:

1. 没有 CLAUDE.md,每次会话都从零开始

最高频原因。Claude Code 启动时会自动读取工作目录里的 CLAUDE.md(以及向上递归的 ~/.claude/CLAUDE.md./.claude/CLAUDE.md),把内容注入 system prompt。没有这个文件,它只能靠 ls 一层一层探,遇到 monorepo 基本就迷路。

如何判断:在项目根跑 ls CLAUDE.md。不存在就是这种情况。

2. 工作目录起点不对

如果你从 apps/web/ 子目录启动 Claude Code,它默认只把这一层当成”项目”,看不到 packages/shared/ 里的共享类型。反过来如果从 ~/code/ 这种父目录启动,它会被几十个无关项目淹没。

如何判断:会话开始时跑 !pwd 看工作目录,对照真实项目根(通常是有 .git/package.json workspaces 的那一层)。

3. node_modules / dist / .next 等大目录干扰

虽然 Claude Code 默认有一些 ignore 规则,但它的 Grep 和 Glob 工具仍可能扫到 node_modules 里的 vendored 代码,把”框架的 Button 组件”当成你的实现。

如何判断:让 Claude Code 列出”项目里所有 Button 组件路径”,如果结果里有 node_modules/...,就是这个原因。

4. monorepo 没说明 workspace 拓扑

pnpm workspace、Turborepo、Nx 这种结构,包之间靠 workspace:* 互相引用。Claude Code 不会主动跑 pnpm-workspace.yamlnx.json 推理依赖图,需要你在 CLAUDE.md 里手写。

如何判断:让 Claude Code “列出本仓库所有包及其相互依赖”,如果只能列出当前包,就是这种情况。

5. 你的 prompt 用了模糊指代

“修一下登录的 bug”——它不知道登录在哪。“那个组件不对”——它不知道哪个。模糊指代让 Claude Code 优先猜上次接触的文件,不一定对。

如何判断:回看上一轮 prompt,如果不含具体文件路径或函数名,就是这种情况。

6. 上下文窗口被低价值内容塞满

如果你早期让它读了大量日志、build 输出或长 stack trace,后续真正相关的代码就被挤出活跃窗口。Claude Code 会显得”记不住前面说过什么”。

如何判断:会话进行很久了(30+ 轮),且最近几轮的回答开始忘记早期约定。

最短修复路径

Step 1:写一份 CLAUDE.md 项目地图

在项目根创建 CLAUDE.md(不超过 100 行,太长反而稀释关键信息):

# Project Map

This is a pnpm monorepo with 3 workspaces:
- `apps/web/`  Next.js frontend (port 3000)
- `apps/api/`  Hono backend (port 8787, Cloudflare Worker)
- `packages/shared/`  Zod schemas + types used by both

## Conventions

- TypeScript strict mode everywhere
- Tests live in `__tests__/` next to source, use Vitest
- API routes follow REST: `GET /resource`, `POST /resource`, etc.
- Never edit files under `packages/shared/dist/` — those are build output

## Commands

- `pnpm dev` — runs web + api concurrently
- `pnpm test` — runs all workspaces
- `pnpm typecheck` — must pass before commit

## Don't touch

- `infra/terraform/` — managed by ops team
- `apps/web/public/legacy/` — frozen, do not modify

Step 2:从正确的工作目录启动

确认项目根(有 .git/pnpm-workspace.yaml 的那一层),从那里启动:

cd ~/code/my-monorepo
claude   # 或你的等价命令

不要从 ~/code/ 启动后再 cd 进去——Claude Code 的初始扫描已经完成了。

Step 3:加 .claudeignore 或在 CLAUDE.md 里声明

如果项目有 vendored 代码或大型 generated 文件,列出来:

# .claudeignore (或在 CLAUDE.md 里写)
node_modules/
dist/
.next/
.turbo/
coverage/
*.generated.ts
public/legacy/

Step 4:第一轮 prompt 用”读这些再开工”

新会话第一句别直接派活,先:

请先读 CLAUDE.md,然后用 ls 列出 apps/ 和 packages/ 的结构,
确认你理解了 workspace 布局。然后我们再开始。

让它建立心智模型再行动,比直接派活后它又来回试错快得多。

Step 5:用绝对路径派活

不要说”修登录 bug”,说”修 apps/web/src/pages/login.tsx 第 42 行 handleSubmit 里的错误处理”。具体路径让 Claude Code 跳过猜的环节。

Step 6:长会话定期 /compact 或开新窗口

会话超过 30-40 轮、或者上下文窗口超过 60% 时,用 /compact 让 Claude Code 自己总结当前状态,然后开新窗口贴回去。比硬撑到 token 耗尽强。

预防建议

  • CLAUDE.md 是活文档:新增模块、改了约定就同步更新,否则很快就过时
  • 每个 workspace / 子项目都放一份 CLAUDE.md,Claude Code 会按工作目录读最近的那份
  • 复杂任务用”先列计划再执行”的两段式 prompt,让它先确认理解再动手
  • 重要约定(“测试要先写 in-memory mock”)写在 CLAUDE.md 而不是每次 prompt 里重复
  • 长 session 主动 /compact,别等上下文塞满了才被动截断

相关阅读

标签: #Claude #排查 #排查