给 AI 写一份项目说明书:CLAUDE.md 该填什么

AI 每次开新会话都要重新理解你的项目。CLAUDE.md 就是解决这件事的项目级记忆。这份模板七个板块,我用下来最有用的是「不要改」。

给 AI 写一份项目说明书:CLAUDE.md 该填什么

用 AI 写代码有个很具体的问题:它每次开新会话,对你的项目一无所知。

它会重新扫一遍目录,猜你的技术栈,猜你的代码风格,然后给出一个”通用最佳实践”级别的建议——而这往往和你的项目实际约定是冲突的。你得一遍遍纠正它:我们用 Maven 不用 Gradle、这个目录别动、错误不要 throw。

CLAUDE.md 就是解决这个的。它是项目根目录下的一个 Markdown 文件,每次会话开始时会被自动读取,相当于给 AI 一份项目说明书。

这份文档我在用,结构大概是这样。

模板

# [项目名] — CLAUDE.md

本文件优先于 user-level CLAUDE.md。

## 项目本质
一句话说明这个项目是做什么的。

## 技术栈
- Runtime: Node 20
- Framework: Fastify 5
- ORM: Drizzle
- Test: Vitest

## 关键约束
- 所有对外 API 必须有 zod schema 校验
- 禁止引入新的第三方 validation 库(我们用 zod)
- 数据库迁移走 drizzle-kit,不手动改 schema

## 不要改
- `/src/legacy/` 目录下所有文件(迁移中,容易出事)
- `package.json` 里的 node 版本

## 常用命令
- 跑测试:`pnpm test`
- 起开发:`pnpm dev`
- 数据库迁移:`pnpm db:migrate`

## 风格
- import 用绝对路径(`@/xxx`
- 错误用 Result 类型,不 throw
- 文件名用 kebab-case

## 遇到不确定的时候
- 先看 `/docs/architecture.md`
- 新增 API 前先看 `/src/api/_template.ts`

七个板块,下面说每个板块怎么写才有用。

项目本质:一句话,不是一段话

这个板块最容易写成废话。“这是一个电商后台管理系统”——这种 AI 自己扫两眼目录也能猜到。

写它要有具体信息:这个项目解决什么问题、谁在用、核心业务流程是什么

## 项目本质
医院患者全生命周期管理系统。核心是围着"患者"这一条主线,
把问诊、检查、用药、随访串起来,供医生和运营使用。

一句话,但 AI 立刻知道:领域是医疗、核心实体是患者、使用者是医生。它后续给的建议就不会往通用 CRUD 上跑了。

技术栈:写版本号

只写”用 Spring Boot”没有意义,写 Spring Boot 3.2 / JDK 17 / MyBatis-Plus 才有。

版本很重要,因为 AI 的训练数据有滞后性。你不写 JDK 17,它可能给你写一堆 Java 8 的写法,或者推荐一个和 Spring Boot 3 不兼容的依赖。

关键约束:写”禁止”

这个板块的名字是”约束”,但真正有用的是禁止项,不是”要做什么”。

因为”要做什么”AI 通常能猜对个七八分,而”不能做什么”它完全猜不到——每个项目的禁忌都不一样:

## 关键约束
- 禁止在 Service 层直接写 SQL,全部走 Mapper
- 禁止引入 lombok 之外的代码生成库
- 所有金额计算必须用 BigDecimal,不允许用 double

尤其是第三条这种,AI 不知道你踩过浮点数精度问题的坑,它给你写 double total = price * count 是完全可能的。写在约束里,它就不会。

不要改:这个板块救过我

这是整份文档里我最推荐加的,也是大部分模板里没有的。

它的作用是圈出雷区

## 不要改
- `/src/legacy/` 目录下所有文件(迁移中,容易出事)
- 数据库表结构(有下游系统在读,改了会炸)
- `application.yml` 里的线程池配置(调过参数,别动)

没有这个板块,AI 看到”这段旧代码写得不好”就会顺手重构,而它不知道那是正在迁移的、有外部依赖的、或者参数是你压测调出来的。

AI 不知道的信息,你不写进去它就当不存在。

常用命令:别让它猜

## 常用命令
- 跑测试:`mvn test -pl user-service`
- 起开发:`mvn spring-boot:run -Dspring-boot.run.profiles=dev`
- 构建:`mvn clean package -DskipTests`

不写的话,AI 会给你一个”标准”命令——而你的项目可能是多模块的、有 profile 的、跳过测试的。它跑不通,你还得纠正。

风格:写你真正会在 code review 里挑的

## 风格
- 包名全小写,类名 UpperCamelCase
- Controller 不写业务逻辑,只做参数校验和转发
- 异常统一走 GlobalExceptionHandler,不自己 try-catch 返回错误码
- 注释写"为什么",不写"做了什么"

最后一条我特别想强调。AI 默认会写大量描述性注释(// 遍历用户列表),而这恰恰是没价值的。写进风格里,它就会改成解释意图。

遇到不确定的时候:给它一条路

这是第二个我觉得很多人漏掉的板块。

AI 遇到不确定的情况,默认行为是,然后闷头做。你得给它一个更好的默认动作:

## 遇到不确定的时候
- 先看 `/docs/architecture.md`
- 新增接口前先看 `/src/modules/user/api.ts` 作为模板
- 都不确定就问我,不要自己假设

最后那句很关键。没有它,AI 会编一个看起来合理的方案往下做;有了它,它会停下来问你。

大部分 AI 写代码的翻车,不是它不会做,是它不确定时选择了硬做。

一个 Java 项目的完整例子

# 患者管理系统 — CLAUDE.md

## 项目本质
医院患者全生命周期管理。围着患者这条主线串起问诊、检查、用药、随访,
主要给医生和运营用,部分接口对公众号开放。

## 技术栈
- JDK 17 / Spring Boot 3.2
- MyBatis-Plus 3.5 / MySQL 8.0
- Redis 7(缓存 + 分布式锁)
- RabbitMQ(异步解耦)
- 构建:Maven 多模块

## 关键约束
- Service 层禁止直接写 SQL,全部走 Mapper
- 金额一律 BigDecimal,禁止 double
- 所有对外接口必须有参数校验注解
- 跨服务调用必须设置超时,不允许无限等待

## 不要改
- `common-legacy` 模块(迁移中)
- 数据库表结构(下游报表系统在直连读)
- `application-prod.yml` 里的线程池和连接池参数

## 常用命令
- 跑测试:`mvn test -pl service-patient`
- 起开发:`mvn spring-boot:run -Dspring-boot.run.profiles=dev`
- 构建:`mvn clean package -DskipTests`

## 风格
- Controller 只做校验和转发,不写业务
- 异常统一走 GlobalExceptionHandler
- 注释解释"为什么",不解释"做了什么"
- 事务注解加在 Service 方法上,不在 Controller

## 遇到不确定的时候
- 先看 `docs/architecture.md`
- 新增接口参考 `PatientController.java` 的写法
- 不确定就问我,别自己假设

两个常见的坑

写太长。 超过一屏之后,AI 对后半部分的遵循度会明显下降。控制在一屏内,实在要写更多就拆成多个文件,主文件里只放索引。

写空话。 “代码要清晰易读""遵循最佳实践”这种句子没有任何约束力。每一条都应该是一条可以被违反、并且违反了你会指出来的规则。


如果你已经有 CLAUDE.md,可以对照看看缺哪几个板块。我猜大多数缺的是「不要改」和「遇到不确定的时候」——这两个恰恰是防止 AI 帮倒忙的。

奇妙感 本文采用署名-非商业性使用-相同方式共享协议,转载请注明出处与作者。

目录