CLAUDE.md + Claude Code 配置实战:代码规范率从 60% 干到 95%,完整模板直接抄
上个月我们组新来了两个实习生,代码风格五花八门——有人写 camelCase,有人写 snake_case,Claude Code 生成的代码也跟着"入乡随俗",一会儿这个风格一会儿那个。我跑了一下 ESLint,规范通过率大概 60% 出头。老板说你搞定这事,别让 AI 写出来的代码还要人肉 review 半天。
折腾了大概三天,最后靠一份 CLAUDE.md 把 Claude Code 生成代码的 lint 通过率拉到 95% 左右。核心思路就一句话:别跟模型讲道理,给它可执行的规则 + 反例,它就老实了。
这篇适合谁
- 用 Claude Code 日常写业务代码,但生成结果经常不符合团队 lint 规范的
- 想把 ESLint / Prettier 规则"注入"给 AI,省掉反复纠正的来回
- 项目里有多个子目录(前端/后端/SDK),不同目录规范不同,需要分层配置的
- 听说过 CLAUDE.md 但不知道怎么写、写什么字段才有效的
整体流程
- 理解 CLAUDE.md 的三级作用域(全局 → 仓库 → 子目录)
- 编写核心规范段落:命名、类型、错误处理
- 把现有 lint 规则翻译成 CLAUDE.md 的可执行指令
- 针对模型的已知偏差做定向纠正
- 验证 + 迭代
graph TD
A[全局 ~/.claude/CLAUDE.md] -->|兜底规则| B[仓库根目录 /project/CLAUDE.md]
B -->|通用规范| C[子目录 /project/src/api/CLAUDE.md]
B -->|通用规范| D[子目录 /project/src/ui/CLAUDE.md]
C -->|API 层专属规则| E[Claude Code 生成代码]
D -->|UI 层专属规则| E
先说结论
以下数据为作者实测,测试条件有限,仅供参考。
| 配置项 | 对规范率的影响 | 优先级 |
|---|---|---|
| 函数命名规则 + 反例 | 最高,实测默认偏差最明显的地方 | P0 |
| 返回类型强制声明 | 高,不写这条它经常推断为 any | P0 |
| 错误处理模板 | 中高,减少 try-catch 风格不一致 | P1 |
| import 排序规则 | 中,不影响功能但 lint 会报 | P2 |
| 注释格式 | 低,锦上添花 | P3 |
第一步:创建基础 CLAUDE.md
在项目根目录创建文件,先写最小可用版本:
## Code Style
- Use TypeScript strict mode; no `any` type allowed
- All functions must have explicit return type annotations
- Prefer `const` over `let`; never use `var`
就这三条,已经能干掉大约 30% 的 lint 报错了。关键是每条规则都是祈使句 + 具体约束,别写"尽量用 const"这种模糊话。
第二步:注入 lint 规则上下文
这一步是核心。把你 .eslintrc 里最常被违反的规则翻译成自然语言指令:
## Naming Convention
- Functions: camelCase, verb-first (e.g., getUserById, parseConfig)
- WRONG: get_user_by_id, GetUserById, userGet
- Components: PascalCase (e.g., UserProfile, DataTable)
- Constants: UPPER_SNAKE_CASE (e.g., MAX_RETRY_COUNT)
注意 WRONG: 这一行——反例比正例更管用。我测下来,不写反例时模型有一定概率输出 get_user_by_id 这种 Python 风格命名(估计训练数据里 Python 占比太高),加了反例后这个比例明显下降。(具体数字因测试条件不同会有差异,这里不给出精确值。)
第三步:处理模型的已知偏差
一开始我觉得大模型不至于有固定偏差吧?但实测下来确实有几个"坏习惯":
偏差 1:函数命名喜欢用名词开头
它经常生成 userFetch 而不是 fetchUser。纠正方法:
## Function Naming Override
- MUST start with a verb: get/set/fetch/parse/handle/create/delete
- NEVER use noun-first naming like userFetch, dataProcess
- If unsure, use pattern: verbNoun (fetchUser, NOT userFetch)
偏差 2:错误处理偷懒
不加约束的时候它经常写空的 catch 块,或者直接 console.log(error) 完事。
## Error Handling
- Never use empty catch blocks
- Never use console.log for error handling in production code
- Pattern: catch(error) { throw new AppError(message, { cause: error }) }
偏差 3:返回类型推断
模型特别喜欢省略返回类型让 TS 自己推断,但我们团队规范要求显式声明:
## Return Types
- Every exported function MUST have explicit return type
- WRONG: export function getUser(id: string) { ... }
- RIGHT: export function getUser(id: string): Promise<User> { ... }
第四步:子目录级覆盖
我们项目前端用 React,后端用 Express,规范不完全一样。在 src/api/ 下单独放一份:
## API Layer Rules
- All handlers validate input with Zod schema before processing
- Return type must be Promise<ApiResponse<T>>
- Error responses follow RFC 7807 Problem Details format
子目录的 CLAUDE.md 会覆盖根目录的同名规则,就近原则生效。Claude Code 读取时不会输出格式化的冲突日志,规则静默合并,以最近一级目录的配置为准。
第五步:验证配置是否生效
最简单的验证方法——让 Claude Code 生成一个函数,然后跑 lint:
# 生成代码后直接跑 eslint 看通过率
npx eslint src/generated/ --format compact | wc -l
我的做法是每次改完 CLAUDE.md 就让它重新生成同一组函数(5 个不同场景),统计 lint error 数量。从最初平均 12 个 error 降到现在平均 0.8 个。
完整模板(直接复制)
这是我目前在用的根目录 CLAUDE.md,按需删减:
## Code Style
- TypeScript strict mode; no `any` type allowed
- Prefer `const` over `let`; never use `var`
- Max line length: 100 characters
## Naming Convention
- Functions: camelCase, verb-first (fetchUser, parseConfig)
- WRONG: get_user_by_id, GetUserById, userFetch
- Interfaces: PascalCase, I prefix 可选(按团队约定调整,TypeScript 官方风格指南不推荐 I 前缀)
- Types: PascalCase without prefix (UserResponse)
## Function Signatures
- Every exported function MUST have explicit return type
- Max 3 parameters; use options object for more
- WRONG: function process(a, b, c, d, e) {}
- RIGHT: function process(options: ProcessOptions): Result {}
## Error Handling
- Never use empty catch blocks
- Always wrap with custom AppError class
- Include original error as cause
## Imports
- Order: node builtins → external packages → internal modules
- Use named imports; avoid default exports
- One import per line when more than 3 named imports
不同场景怎么选
个人项目 / 小型 side project: 只写 Code Style + Naming Convention 两个 section 就够了,别搞太复杂,维护成本不值得。
中型团队(3-10 人): 根目录写通用规范,每个主要子目录(api/ui/shared)各一份覆盖。重点放在命名和错误处理上,这俩是 code review 时吵架最多的。
大型项目 / Monorepo: 建议配合 CI 验证——每次 PR 跑一遍 lint,CLAUDE.md 的效果直接体现在 CI 通过率上。
前端重型项目: 额外加 Component 和 Hook 的命名规范,模型在 React 组件命名上倒是比较规矩,主要问题出在自定义 Hook 的命名和返回值类型上。
踩坑记录 / 常见问题 FAQ
Q:CLAUDE.md 和 AGENTS.md 有什么区别?我该用哪个?
两者都是持久化的项目配置文件,都支持目录继承和多级覆盖,并非一个"临时"一个"长期"的关系。主要区别在于设计来源不同:CLAUDE.md 是 Claude Code 原生支持的配置文件;AGENTS.md 这一命名来自 OpenAI Agents SDK 的约定,是另一套体系的概念,不应混用。在 Claude Code 项目里,统一使用 CLAUDE.md 即可。
Q:写了 CLAUDE.md 但 Claude Code 好像没读到,怎么排查?
先确认文件名大小写正确(是 CLAUDE.md 不是 claude.md),然后确认文件位于 Claude Code 的工作目录内,或全局配置路径 ~/.claude/CLAUDE.md 下。Claude Code 不会输出特定格式的 warning 提示文件未找到,排查时建议直接在对话中询问"你读到了哪些配置文件"来确认加载状态。
Q:规则写太多会不会超 token 限制导致被截断?
我目前的配置大概 800 字左右,没遇到截断问题。CLAUDE.md 的具体 token 处理机制没有官方公开说明,建议把最重要的规则放在文件前面,整体控制在合理长度内,避免堆砌大量低优先级规则。
Q:能不能把整个 .eslintrc 贴进去?
别这么干。我试过把 200 行的 eslintrc 原样贴进去,结果 Claude 基本无视了大部分规则。JSON 格式的 lint 配置对模型来说不是"指令",它不知道该怎么执行。你需要把关键规则翻译成自然语言祈使句。
Q:不同模型对 CLAUDE.md 的遵从率有差异吗?
有。整体来看,能力更强的模型在处理复杂条件规则时遵从率更高(比如"当 X 条件满足时用 A 模式,否则用 B 模式"这种)。能力相对弱的模型在简单明确的规则上表现够用,但条件分支多了容易"选择性遗忘"。如果你的规范特别复杂,可以考虑关键模块用更高能力的模型跑,同时把规则尽量拆成独立的简单条目。
小结
折腾半天总结就三点:规则要具体到能直接判断对错、反例比正例更管用、按目录分层别一股脑全堆根目录。配置好之后 lint 通过率确实肉眼可见地上去了,code review 的时候不用再纠结格式问题,可以专注看逻辑。
这套配置我用了快两周,目前还在持续微调——比如最近发现模型在写测试代码时喜欢用 describe 嵌套三四层,正在试着加规则限制嵌套深度。等有新发现再更新。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐




所有评论(0)