claude-code 现在已经是不少人的日常开发伙伴了,但很多人用它的方式其实很有问题——打开终端,问一个问题,得到答案,完事。这样用不是不行,只是 claude-code 的能力完全没被释放出来。我之前在建完成了好几个小工具和内部系统之后,慢慢意识到一件事:真正让 claude-code 从"聊天机器人"变成"项目协作者"的关键,不是它本身有多聪明,而是你喂给它的上下文和约束有多清晰。这个 claude-code-templates 项目,就是把这些上下文固化成模板,放在项目的 CLAUDE.md 里,让每次会话都在同一套规则下工作。这篇东西是我基于自己折腾小半年的经验整理出来的,适合所有在用 claude-code 或类似 AI 编程助手的开发者,里面讲的东西可以直接抄。
1. 为什么要给 claude-code 做模板
1.1 claude-code 的原生问题:每一分钟都在重新开始
很多人第一次用 claude-code 的体验是这样的:在项目目录下输入claude,它确实能读你的代码,也能理解你的问题,但每次你说完需求,它给出来的代码风格、命名习惯、对测试的态度,跟你自己写的对不上。最头疼的是,同一个问题换个说法问它,它可能给出两种完全不同的方案。
这不是 claude-code 笨,也不是模型能力不够。问题在于 claude-code 虽然是编码助手,但它仍然是无状态的——每次会话开始,它对"你的项目应该怎么写"只有通用认知,没有项目专属认知。它不知道你的团队习惯在函数名前面加get还是fetch,不知道你把数据库连接统一放在哪个目录,更不知道你之前已经踩过某个第三方 SDK 的坑。这就好比你招了一个能力很强的外包,但他第一周上班,什么都要重新讲一遍,第二周你讲烦了,他也做不对。
模板的作用就在这儿:把"重新讲一遍"的内容固化下来,写进项目根目录的 CLAUDE.md,让 claude-code 每次启动都自动加载这些规则。它不是让 claude-code 变得更聪明,而是让它把精力集中在真正需要思考的问题上,而不是反复猜你的偏好。
1.2 没有模板的时候,工作流低效在哪里
我实测下来,没有模板的工作流大致是这种节奏:先跟 claude-code 说"帮我看一下这段代码有没有问题",它看完给你反馈,你再补充"这是个 React 项目,你按函数组件的写法来改",它改了,然后你再提醒"测试不要用 mock 库,我们统一用 vitest",它又调整一轮。一个下午下来,光是在对齐规则上就花了一半时间。
最典型的是代码风格不一致的问题。比如有个项目里既有 4 空格缩进的老代码,也有 2 空格缩进的新代码,claude-code 在修改老文件时经常自作主张把整个文件重新格式化,结果是它觉得自己"顺手整理了一下",在你的 code review 里却成了一堆噪音。还有依赖管理,它在不确定某个库是否已经安装的时候,会直接在 package.json 里塞一个它认为"应该可以"的版本,往往跟项目里实际用的版本冲突。
我自己统计过,在没有写 CLAUDE.md 的项目里,claude-code 生成的代码有三成左右需要人工调整风格或架构位置;写了模板之后,这个比例降到一成左右。这个对比非常明显,模板的投入产出比极高,写一份项目通用的规则文件,可能只需要小半天,但之后每一次会话都在受益。
1.3 这个模板适合给谁用
如果你只是偶尔拿 claude-code 补一段正则表达式,或者让它解释某个报错,那模板的价值确实不大,CLAUDE.md 对这种轻量使用反而显得啰嗦。但如果你满足下面任一条件,模板基本就是刚需:
- 你把 claude-code 用在真实项目上,而且不是一次性的修改,而是连续几周、几个迭代的开发;
- 你有团队协作的需求,希望每个人用 claude-code 时输出的代码风格没有太大差异;
- 你反复在做同一类项目(比如 Vue 后台、Python 数据处理、Node 脚本),发现每次都是从零跟它解释项目结构;
- 你遇到过它的错误决策,比如误删了不该删的代码、改了不该改的配置,想通过规则把它拦在门外。
我知道有些人听到"写模板"第一反应是又要搞一套流程文档,觉得很重。但 claude-code 的这个模板其实非常轻,它就是一个 Markdown 文件,你完全可以在某个项目里先写三五行试试,觉得有用了再加内容。它不是一次性交付的全量方案,而是一个可以逐周迭代的活文档。
2. 模板体系怎么搭:整体设计思路
2.1 三层结构:全局、项目、任务
我给模板体系定的设计原则是"分三层,各管各的"。这个想法借鉴了编程里的分层职责,避免所有东西都塞在一个大文件里,到后面连自己都懒得看。
第一层是全局偏好层。存放在用户机器上的约 ~/.claude/CLAUDE.md,这一层写的是你个人的通用编码偏好——比如你写 Python 时习惯用 type hints,写前端时坚持函数组件不用 class 组件,希望 claude-code 在改动代码之前先展示 diff。这些规则跟具体项目无关,是"你这个人"的偏好。用 claude-code 的时候它会自动读取这个全局文件,所以任何项目打开都带着你的个人基线。
第二层是项目约束层。存放在各项目根目录的 CLAUDE.md,这一层写的是当前项目的特殊性——技术栈、目录结构、命令、架构约定、禁止事项。这是模板体系里最核心的一层,因为项目特殊性正是 claude-code 最容易忽略的部分。比如某个项目虽然用了 webpack 但希望你别动这项配置,某个服务必须走特定的 header 鉴权,这类信息必须放在项目级文件里,全局文件不应该知道也不应该管这些。
第三层是任务指令层。当你需要处理某个特定任务时,比如做一次代码评审、迁移一个旧模块、修一个棘手的 bug,你可以在会话里用--append或直接在对话中附上本次任务的约束。这一层不适合放到前两层,因为它是临时的、一次性的,写进全局和项目文件反而会污染长期规则。
这个分层的好处是权责清晰。全局层稳定不动,项目层随项目演进,任务层用完即走。我在实践中最怕遇到的情况就是大家把这三个层级混在一起,比如把个人偏好写进项目的 CLAUDE.md,导致换个人来协作时一堆规则对他并不适用,反而干扰判断。
2.2 模板仓库的目录怎么组织
因为 claude-code 的模板最终要落到 CLAUDE.md 里,所以一个专门维护模板内容的仓库,目录设计要按"场景"来分,而不是按"语言"或"框架"来分。我见过有人按 JavaScript、Python、Go 这样分目录,结果一份前后端项目模板要拆到好几个文件里,维护成本高,复制也不方便。
更实用的组织方式是按"项目类型"来组织。比如我的模板仓库长这样:
claude-code-templates/ ├── README.md ├── web-frontend/ │ ├── CLAUDE.md │ ├── react-vite.md │ └── vue-element.md ├── backend-api/ │ ├── CLAUDE.md │ ├── node-express.md │ └── python-fastapi.md ├──># 项目:claude-code-templates ## 项目概览 这是一个维护 claude-code 项目模板的仓库。 技术栈:JavaScript、Node.js、Markdown。 主要用途:为不同项目场景生成 CLAUDE.md 模板。 ## 常用命令 - 安装依赖:npm install - 运行测试:npm test - 类型检查:npx tsc --noEmit ## 代码风格 - 使用 2 空格缩进,不使用分号。 - async/await 优先,避免 .then 链。 - 变量名使用 camelCase,常量使用 SCREAMING_SNAKE_CASE。 - 所有公共函数写 JSDoc 注释。 ## 架构约定 - 模板内容按场景目录存放,避免跨场景耦合。 - 模板中的占位符统一用 `{{项目名称}}` 风格,便于替换。 - 新增模板时先检查是否与已有模板存在内容重叠。 ## 禁止事项 - 不要修改 README.md 中的项目介绍部分。 - 不要引入额外的构建工具。 - 不要在模板仓库中放真实项目的敏感配置。 ## 版本记录 - 2025-03:初始模板。这份模板看着挺简单的,但它已经把"项目概览、命令、风格、架构、红线、版本"六个维度的信息都覆盖了。claude-code 有了这些信息之后,它知道你项目是干嘛的,知道测试要跑哪个命令,知道代码写成什么样算"合格",也知道哪些事碰不得。这些信息在没有任何模板时,是需要你在无数个对话里反复人工强调的。
3.2 逐段拆解模板的每个部分
先说说项目概览这一段。很多人觉得 claude-code 自己能读代码,为什么还要在模板里写项目简介?我的经验是,虽然它能读代码,但它判断项目性质的方式是扫描依赖和目录结构,这个过程不总是准确。你直接在模板里写清楚"这是干什么的、用什么技术栈",它就能更快地理解整个项目的上下文,不会出现把 Node 项目当成纯前端项目来给建议的情况。
常用命令这段的价值在于减少它瞎猜。没有命令信息时,claude-code 在需要跑测试的时候可能会自己猜"那应该是 npm test 吧",运气好能猜对,但像某些项目测试命令是pnpm test:unit这样的,它就完全猜不到。在命令缺失的情况下,它甚至会尝试安装一个新的测试框架来"帮"你运行测试,这种行为在真实项目里后果是灾难性的。把命令写进模板之后,它便不会去猜,也不会去安装无关依赖。
代码风格是模板里最直接影响生成结果的部分。claude-code 默认的代码风格接近市面上常见项目的平均风格,但它不知道你自己的偏好。比如我一份代码里习惯不用分号,但 claude-code 每次补全都会在行尾加分号,看起来非常别扭。在模板里明确声明"不使用分号"之后,这个问题立刻解决。风格规则要写得具体,像"代码要清晰"这种话等于没说,"变量命名用 camelCase"这类的才有约束力。
架构约定这段是给 claude-code 的"地图"。一个大型项目里,claude-code 常常会迷茫在哪里放新代码、该遵循什么模式。模板里写明"复用的组件放在 src/components/ 下,页面文件放在 src/pages/ 下",它生成的新代码就会自动落到正确的位置,而不是突然在根目录新建一个文件。项目结构越复杂,这一段的价值就越明显。
禁止事项是最能防止事故的内容。claude-code 的主动性有时候是灾难的根源——它可能看到某个代码"冗余"就主动删除,看到配置"不合理"就自动修改。这类行为在你不注意的时候可能已经改变了项目的关键逻辑。模板里用一条"不要修改 xxx"的规则,就能把这类事故挡在发生之前。红线规则一定要写得"小而明确",不要写"不要做出不合理的修改"这种它无法判断的话。
3.3 验证模板有没有生效
写完模板之后需要验证它确实被 claude-code 读到并且发挥作用,这个过程不能省。虽然 claude-code 正常情况下会自动加载 CLAUDE.md,但还是建议手动确认,特别是第一次写模板或者修改了文件名的时候。
最简单的验证方式是在项目目录下启动 claude-code,然后问它:"根据项目的 CLAUDE.md,我这个项目的测试命令是什么?" 如果它引用文件并正确回答npm test,说明加载链路没问题。如果回答"我看一下项目的 package.json 再告诉你",说明文件没有加载成功,这时检查文件名、所在目录和 claude-code 的启动位置。
第二个验证方式是让它做一次小任务,观察它是否遵守了模板里的风格约束。比如故意让它补全一个函数,如果它主动使用了 JSDoc、保持了 2 空格缩进、没有加分号,那这些规则就真的生效了。如果它写出来的代码跟模板要求的不一致,可能是模板里的措辞不够强,比如写了"尽量"、"可以"这类含混词,需要改成"必须""使用"这样的强指令。
我踩过一个教训:模板里写了"尽可能避免使用 any 类型",结果 claude-code 还是时不时用 any,因为它认为类型定义太复杂、用 any 是"合理的权衡"。改成"禁止使用 any 类型,除非有理由并在注释中说明"之后,行为就明显收敛了。这里面有个原理,AI 编程助手对"避免"这类弱约束的重视程度远低于"禁止"这类强约束,所以写规则的时候,该硬的地方一定要硬。
4. 场景化模板示例:从通用到专项
4.1 前端项目模板
前端项目是 claude-code 最常用的场景之一,但也是模板需求最复杂的场景。因为前端项目的技术栈组合很多,React、Vue、Angular 各有各的写法,构建工具又有 Vite、Webpack、Next.js 的差异。通用模板里写的规则,到了具体的前端项目里往往不够用。
我常用的前端模板里,除了通用规则外,还会追加这样几条:
## 前端项目特定规范 - 组件统一使用函数组件 + Hooks,禁止使用 class 组件。 - 全局状态统一使用 zustand,不要引入 Redux。 - 样式方案:Tailwind CSS,禁止引入 CSS Modules。 - 路由配置统一放在 src/router/index.ts,不要在页面内自定义路由跳转逻辑。 - 组件文件命名采用 PascalCase,样式类名采用 kebab-case。 - 运行代码检查:npm run lint -- --fix(提交前必须执行)为什么这些规则必须在模板里明确?举个例子,一个本来用 zustand 的小项目,claude-code 在一个状态管理场景里可能直接生成一段 Redux 代码,因为 Redux 在它的训练数据里最"经典",它默认"成熟方案比轻量方案更稳妥"。可实际上你的项目根本不需要也没打算引入 Redux。模板里的这条规则,既防止它引入新依赖,也避免项目里同时出现两套状态管理模式。
样式方案也是容易出分歧的地方。Tailwind 和 CSS Modules 都在用,claude-code 如果看到项目里有几个 .module.css 文件,可能沿用这个模式,也可能根据你一句"加个样式"就在 Tailwind 的写法上即兴发挥。在模板里把方案定死,它是不会私自开新路线的。
4.2 后端 API 项目模板
后端项目的重点不在代码风格,而在架构边界和数据安全。claude-code 在后端项目里最危险的时刻是它主动"造轮子"——自己实现一段认证逻辑、自己封装数据库操作,而不是复用项目已有的公共模块。
我的后端模板通常会包含这些约束:
## 后端项目特定规范 - 所有数据库访问必须通过 repository 层,禁止在控制器中直接操作数据库。 - 鉴权统一走 authMiddleware,新接口禁止写内联的 token 校验逻辑。 - API 响应格式统一为 { code, message, data },禁止直接返回原始数据。 - 新增依赖必须先检查 package.json 是否已有对应能力,否则需说明理由。 - 不要打印完整请求体或响应体日志,避免敏感信息泄漏。 - 所有接口必须有入参校验,禁止信任前端传入值。这里最值得讨论的是"禁止在控制器中直接操作数据库"这条。从模板角度来说,它是架构层面的约束,不是语法层面的约束。claude-code 只看一段代码的语法正确性,判断不出"这句话写在 controller 里是不是分层错误",只有明确的规则能拦住它。没有这个规则时,我确实见它生成过把数据库查询直接写在路由回调里的代码,功能是能跑,但后续要改事务、加缓存就非常困难。
日志与安全相关的内容也要提前写死。claude-code 为了帮你调试,可能会在代码里加 console.log 打印完整参数对象,这在开发环境还好,但很容易被一起提交到生产代码里。模板里明确"禁止打印完整请求体",这类代码就不会出现了。
4.3 测试与重构模板
测试场景的模板跟日常开发不太一样,它更多是"任务型"的。因为写测试的时候,claude-code 需要理解的是项目的测试策略,比如某些模块已经覆盖率很高不需要重测,某些极端边界是需要重点覆盖的。
测试模板的示例:
## 测试任务规则 - 单元测试文件与被测文件放在同一目录下,命名为 *.test.ts。 - 只使用 vitest 作为测试框架,不要引入 jest。 - Mock 原则:优先 mock 网络请求,不要 mock 被测函数内部实现细节。 - 测试应描述行为而非实现,"测试 add 函数输出"而不是"测试 add 函数内部调用了 binarySearch"。 - 新测试跑通后运行 npm test 确保全量通过,不要只跑单个文件。这种模板最直接的价值是避免 claude-code 在测试里使用过度 mock。它生成单元测试时有个坏习惯,喜欢把被测模块内部的依赖函数全部 mock 掉,导致测试跑通但完全失效——你改了函数内部逻辑测试还是通过,等于没测。模板里写明"不要 mock 内部实现细节",生成的测试就耐看多了。
重构类模板则更强调步骤和验证。claude-code 做重构时容易一次改动太多,你很难评审。我一般会在模板里限定重构步骤:"每次只重构一个函数,完成后运行类型检查和测试,确认通过后再继续下一项。" 这能让整个重构过程变得可追踪,出问题也能快速定位到是哪一步引入的。
5. 常见问题与排查技巧实录
5.1 模板写了却不生效
这是我最常被问到的问题,而且大多数时候原因都很简单。首先检查文件名,必须是 CLAUDE.md,大小写都对,不能是 CLAUDE.txt。其次检查位置,它必须在当前会话启动目录下。如果你在项目根目录启动了 claude-code,但 CLAUDE.md 放在 src/ 里,那是不会被加载的。
还有一种隐蔽的情况:如果你用了全局目录比如 ~/.claude/CLAUDE.md 和项目目录的 CLAUDE.md 同时存在,项目目录的规则会叠加到全局规则之上而不是替换。如果全局规则跟项目规则内容冲突,以哪个为准?实测下来项目级声明往往更具针对性,但最稳妥的做法还是避免在两个层级写互相矛盾的规则。我自己会定期全局检查一遍全局 CLAUDE.md,把已经过时或者跟所有项目都冲突的内容清理掉。
另外,CLAUDE.md 的改动不需要重启任何服务,但如果你当前正在一个长时间会话里,它可能不会重新扫描文件。遇到这种情况直接退出会话重新启动 claude-code,规则就会重新加载了。
5.2 规则冲突了怎么办
规则冲突一般发生在三层模板合并的时候。最常见的冲突是:全局说"统一使用 4 空格缩进",项目模板说"统一使用 2 空格缩进",claude-code 不知道听谁的。我的处理原则是,项目规则优先于全局规则。因为全局规则服务于"你这个人的通用偏好",而项目规则服务于"这个项目的实际需要",项目代码长期保持一致性比你的个人偏好更重要。
但 claude-code 本身不一定总是这样裁决,所以更保险的做法是,项目模板里显式写一句"本项目使用 2 空格缩进,此规则优先于全局配置"。这样明确声明之后就基本没有歧义了。如果发现它还是用了旧规则,可能是全局文件里的措辞太强,比如写了"必须始终使用 4 空格",可以同步改弱全局文件的语气,把"必须"改成"默认"。
还有一类规则冲突是模板里自相矛盾。比如某条说"禁止使用 any",另一条又说"第三方库缺失类型时可以直接使用 any"。这种矛盾会让 claude-code 选择困难,通常在生成代码时会优先执行更具体的规则,但有时候也会犹豫。所以写模板要避免把特殊情况写进去,特殊情况用任务层的临时指令去处理,不要长期放在模板里制造冲突。
5.3 模板越写越肥怎么办
模板刚建立的时候大家都喜欢往里加内容,今天加一条规则,明天加一条约束,几周之后就变成一个几十 KB 的大文件。这时候 claude-code 的表现反而变差,因为有用的规则被淹没在大量重复的、低价值的文本里了。它处理长上下文时,注意力是会被稀释的。
我给自己的原则是,超过 150 行之后就必须做减法。操作方法很简单:把模板里所有规则过一遍,标出哪些在过去两周会话里确实让 claude-code 改进了行为的,留着;那些写上去之后从来没观察到它违反过的,删掉,或者至少降级为注释。不是每条规则都有必要让 claude-code 遵守,有些规则只是你自己心理安慰,它们并不会被违反,也就不需要占用上下文空间。
另外一个思路:把对 AI 的规则和给人看的说明分开。CLAUDE.md 只放对 claude-code 行为的约束,项目背景介绍这些给团队成员看的信息放在 README 里,不要让模板文件承担文档职责。模板文件越聚焦,效率越高。
5.4 模板要不要进版本控制
要,而且必须在版本控制里。claude-code 的模板直接决定代码提交质量,它本身就是一种项目资产。但这里有一个隐藏的坑:如果你在模板里写了本地的绝对路径、团队成员的个人信息或者本地数据库连接串,这些内容进 Git 仓库会产生风险。
我的处理方式是在模板里只放占位符,比如项目根目录位于 {{项目根目录路径}},具体路径等团队成员克隆到本地后自行替换。其实大部分内容不需要占位符——技术栈、命令、代码风格都是通用的,只有极少数配置才涉及个人环境差异。模板进版本控制之后,模板的变更历史天然就是一份团队 AI 协作规范的演进记录,哪个迭代我们开始强制 lint、哪个项目我们决定不用 Redux,都看得清清楚楚,比口头通知靠谱得多。
团队协作时还要注意,模板更新要跟成员沟通。我自己遇到过一次:在 CI 重命名之后更新了模板里的运行命令,但另一个同事的本地分支还跑着旧模板,他让 claude-code 根据旧命令跑 CI,结果 claude-code 反复报错。这时候不用慌,把这个分支的 CLAUDE.md 拉到最新版就能解决。团队里同一仓库的 CLAUDE.md 有版本差异是常态,合并分支时注意处理这个文件就好。
5.5 一些执行层面的细节经验
最后分享几个我在大量使用中总结的执行细节,这些不是模板语法问题,但直接影响使用体验。
第一,CLAUDE.md 文件的编码要用 UTF-8,特别是要写中文注释或规则说明时。我之前在一个 Windows 环境下的项目模板里写过中文规则,因为文件保存成了 GBK 编码,claude-code 读出来的是一些乱码,规则自然就失效了。现在我的所有模板都强制用 UTF-8 保存,问题再没出现过。
第二,模板里的命令要放到对应的「场景」里。比如项目里大多数人都在用 Bun 而不是 npm,那模板里所有的命令都写bun install、bun test,不要写 npm。claude-code 有个倾向是使用"最常见"的包管理器,如果模板里不写清楚,它很可能在用了 bun 的项目里生成 npm 命令,虽然也能跑,但会额外引入一个 lockfile,造成冲突。
第三,别忽视"禁止事项"的威力。我发现很多人写 CLAUDE.md 时只写正面规则,比如"应该怎么做",很少写负面清单。但 claude-code 出错时基本都是越界,而不是做得不够。所以每次它做了一件你不希望它做的事,别急着改代码,先想想能不能把这件事写进禁止项里。用这样的方式迭代模板,模板的进化速度会非常快,因为每一版都是基于真实事故修正出来的。
基于我自己的实操经验,claude-code 的价值真的在模板之外已经被定了一大半,我见过太多人把时间浪费在和它重复解释项目背景上。如果你也正在用 claude-code,我真建议你从今天起花二十分钟列一个最简 CLAUDE.md,只写项目路径、常用命令和三条红线,然后跑一周看看差异。体验过"它第一次就知道你的规矩"之后,你就再也回不去那种从零解释的开发方式了。