CLAUDE.md:Global vs Project,什么该放哪里
Claude Code 会在两个层级读取 CLAUDE.md。user-global 文件在 ~/CLAUDE.md(或 ~/.claude/CLAUDE.md),每个项目、每次会话都会加载。project-local CLAUDE.md 在 repo root,只在你处理这个 repo 时加载。两份文件都会被读,内容会叠加。决定什么内容放哪里,是 harness 里最重要、也最容易做错的选择之一。
为什么要拆成两层
这个拆分不是 cosmetic。它存在,是因为有些规则属于 你,有些规则属于 项目。把两者混在一起,会产生很可预测的失败。
属于你的规则,是关于你怎么工作:你的沟通风格、你的工具、你的操作习惯、你在所有项目里的 conventions。你切换项目时,它们不变。它们也不需要和 collaborators 协商。它们住在 ~/CLAUDE.md,你碰的每个项目都会继承。
属于项目的规则,是关于这个项目是什么,以及团队决定怎么操作。你离开或别人加入时,它们不变。它们由团队决定,编码在 repo 里,对每个贡献者和每个碰代码的 agent 同样适用。它们住在项目的 CLAUDE.md,和其他 project state 放在一起。
当你把项目规则放进 ~/CLAUDE.md,规则会跟着你走,而不是跟着项目走。这意味着 collaborator clone 同一个 repo,会得到不同的 agent experience。当你把个人偏好放进项目文件,它们会被 ship 给所有人,包括不共享这些偏好的 collaborators。两种都会制造 friction。
global 文件里该放什么
对大多数用户来说,八类内容适合放在 ~/CLAUDE.md。
沟通风格。 用什么语言跟你说话,要多短,什么语气,有没有称呼。agent 的沟通偏好是个人的,不应该每个项目都变。
你到处都用的通用硬规则。 “Never edit lockfiles by hand,” “never push directly to main,” “all changes through PR.” 如果你对每个项目都这样要求,就放 global,不要在十五个 project files 里重复。
你机器的操作备注。 工具在哪里,你用什么 shell,什么 virtualization platform,什么 code editor。agent 知道你的本地环境有帮助;项目不需要知道。
默认 tools 和 aliases。 “Prefer rg over grep,” “I have a shortcut kw that means kalami + worktree.” 这些是个人 ergonomics 偏好。
你的知识库。 你的 Armory、AIMD experience library、wiki、scratchpad 的 paths。这些属于你,不属于项目。
缺少 context 时的默认行为。 “When unsure, ask one specific question, not three.” “Don't create new files in the home directory.” 无论哪个项目都该生效的个人 defaults。
你的 workflow conventions。 “I review code before pushing,” “I want a plan before any 3+ step task,” “I expect commit messages in imperative mood.” 这是你怎么工作,不是项目怎么工作。
你的 meta-rules。 “Tell me what you're about to do before each tool call.” 这些塑造 agent 和你这个人的互动方式。
project 文件里该放什么
不管谁来贡献,下面六类内容通常属于项目的 CLAUDE.md。
项目描述。 这个项目做什么。给谁用。跑什么 stack。每份写得好的 project CLAUDE.md 的第一段都应该有。
团队决定的流程规则。 Branching strategy、commit conventions、PR requirements、test requirements、release process。这些是 team contracts,每个 contributor 都必须遵守。
项目专属 tooling。 Build commands、test commands、dev environment setup、package manager。不同项目用不同工具,这些需要在项目文件里 pin 住。
架构决定。 “Monolith, not microservices.” “State via Jotai, not Zustand.” “Use TanStack Query for server state.” 项目已经做过、agent 不该重新辩论的决定。
codebase 的操作事实。 “This path is a symlink.” “The Playwright suite is flaky on Tuesdays.” “The migration in 0042 is intentionally non-reversible.” 这些 project-specific knowledge 会跨贡献者长期存在。
项目原则。 三到七条,带 rationale。团队同意适用于这个 codebase 的 principles。不同项目可以有不同 principles,这里就是它们该去的地方。
override mechanic
当同一条规则同时出现在两份文件里,project rule 赢。这是 Claude Code 里有文档、也符合预期的行为。它也带来一个常见困惑:global rule 写 “use bun”,被 project rule “use npm” 覆盖,且没有任何 warning。agent 会听话切换,但 global rule 仍然留在你的 ~/CLAUDE.md,看起来像应该适用。
纪律是把 overrides 写明确。project file 覆盖 global rule 时,行里应该写清楚:Use npm — overrides ~/CLAUDE.md § Tools (project CI requires npm)。这让 override 可追踪,也告诉 agent 这个冲突是故意的。
相反情况更难抓:project rule 无意中和 global rule 冲突。AgentLint v0.4(planned)会检查 global-vs-project contradictions,并报出未声明的 overrides。在那之前,手动 sweep 的方式是 grep 两份文件里的相同 nouns,然后查冲突。
迁移模式
有两种迁移模式很常见。
把 project rule 提升到 global。 你连续在三份 project CLAUDE.md 里写了同一条规则。这就是它该变 global 的信号。把它移到 ~/CLAUDE.md 一次,删掉三个 project files 里的重复项,跑 AgentLint 确认它们没有把这条规则重新作为 override 引入。
把 global rule 降到 project。 你有一条 global rule,其实不适用于新项目。诱惑是往 project file 里加例外。更好的路径是先检查这条 global rule 对你 大多数 项目是否正确。如果是,在新项目里加明确 override。如果不是,这条 global rule 本身就错了,把它降到真正适用的项目里。
原则是:~/CLAUDE.md 应该编码几乎普遍适用于你工作的规则。如果你发现 30% 项目都在 override 某条 global rule,那条 global rule 就是错的。
一个完整例子
下面是同一组规则,正确分配后的样子:
~/CLAUDE.md (excerpt):
## Communication
- Talk to me in spoken Chinese during chat. Code, comments,
commits, docs in English.
- Be terse. No "Let me know if..." trailers.
- Default discussion mode unless I use action verbs.
## Universal rules
- All changes go through PR. No direct pushes to main.
- Don't edit lockfiles by hand. Use the package manager.
- No secrets in commits. .env* is gitignored globally.
## Operational
- I work on a Mac Studio M4 Max. Tools live at /opt/homebrew/bin.
- I prefer rg over grep, fd over find, bat over cat.
- My scratch dir is /tmp; my project dir is ~/Projects.
Project CLAUDE.md (excerpt, same conceptual cluster):
## Project
A real-time collaboration tool. TypeScript, React, Yjs,
Postgres, Redis, deployed on Fly.io.
## Process
- Branch from main, PR, squash-merge.
- Tests required: Vitest unit + Playwright E2E.
- Use bun, not npm — overrides ~/CLAUDE.md § Tools.
## Architecture
- Monolith. We tried microservices in Q3 2024 — do not propose.
- State: TanStack Query for server, Zustand for client. No Redux.
- CRDT via Yjs. Do not propose Automerge or Y.js wrappers.
## Operational
- Postgres 16 + Redis 7 via docker-compose; `bun dev:up`.
- Playwright requires `bun exec playwright install` after clone.
- CI runs Linux only — Mac/Windows local issues do not fail CI.
注意:global file 讲的是 你 怎么工作;project file 讲的是 项目 怎么工作。它们共享 “rules” 这个抽象,但分区很干净。project file 里的 bun, not npm 明确引用了 global override,所以冲突是故意且可追踪的。
这周该做什么
两个实际练习。第一,读你的 ~/CLAUDE.md 和你最常工作的项目的 CLAUDE.md。找出 ~/CLAUDE.md 里其实是 project-specific 的规则(提到只有一个项目用的 tool、引用只有一个项目有的 path)。把它们移到 project file。再找出 project file 里其实是个人偏好的规则(你的沟通风格、你的 shortcuts)。把它们移到 global。重新分配通常会让两份文件都变短。
第二,确保每个未声明的 override 要么被声明,要么被删除。grep 两份文件里的 common nouns(build command、package manager、test runner、branching strategy)。哪里冲突,就在 project file 加明确的 “overrides ~/CLAUDE.md § X” tag。agent 会感谢这种 disambiguation,未来冷读两份文件的 contributors 也会。