
写模板这事得从一次特别狼狈的经历说起。那时候我刚把一个中型项目塞给 Claude Code 做重构结果发现每天早上一开工光是把项目背景、技术栈约束、目录结构、编码偏好这些上下文重新交代一遍就得花掉十几分钟。更要命的是同一个问题上午问它和下午问它产出的代码风格完全是两个人写的——上午还规规矩矩用函数组件下午它就给我整了一堆 class 组件。让 AI 写代码不新鲜让 AI 稳定地按一个团队的规范写代码才是真问题。后来我把项目里那些反复唠叨的常识全部沉淀成了一套 claude-code-templates 模板体系。简单说就是用 CLAUDE.md 配置文件固化项目知识用提示词模板统一编码风格用脚手架模板快速生成新模块用技能模板封装常见的代码审查、测试生成工作流。这套东西用下来上下文 token 消耗省了三成左右新项目从零到能跑通构建基本就是一碗茶的功夫。这篇文章就把我搭这套模板的完整思路、每一步的实际操作、还有踩过的一堆坑从头到尾捋一遍给也在用 Claude Code 的朋友们做个参考。1. 为什么要给 Claude Code 建一套模板1.1 裸用 Claude Code 的三个痛点很多刚接触 Claude Code 的人第一感受是这玩意儿挺聪明第二感受就是怎么这么不听话。其实问题不在模型本身而在你没给它一套稳定的工作约定。第一个痛点是上下文反复交代。每次开一个新会话Claude 对项目一无所知。你得重新告诉它我们是微服务架构服务间走 gRPC数据库用 PostgreSQLORM 是 Prisma代码风格是 Airbnb 那套。这话一天说三遍Token 费倒是小事关键是每次交代的口径还不一样——有时候忘了说 Prisma它就开始给你生成裸 SQL你还得返工。第二个痛点是输出风格漂移。Claude 默认会根据你提问的语气、补充信息的多少、甚至上下文里的示例代码来调整自己的输出风格。同一个函数你给它看一个用了箭头函数的文件它就全程箭头函数你给它看一个用了 function 关键字的文件它立马换风格。一个人用的时候无所谓一个团队用的时候就乱了套——代码评审的时候一半时间在争论风格问题。第三个痛点是工具链配置割裂。有人配了 MCP 服务器有人没配有人开了 hooks 做自动格式化有人不知道有这个功能有人用斜杠命令触发代码审查有人全靠嘴说帮忙看看这段代码。结果同一个项目Claude Code 在不同人手里表现出来的能力天差地别。1.2 模板体系的四个层次我把这套 claude-code-templates 拆成四个层次各管一摊事层次形态作用范围解决的问题更新频率配置模板CLAUDE.md 系列文件全局 / 项目 / 目录项目常识、工具链配置、约束规则低频随项目演进提示词模板自定义斜杠命令、指令片段会话级统一提问方式和编码风格中频随实践优化脚手架模板目录骨架 变量替换 init 脚本新项目 / 新模块快速生成符合规范的代码骨架低频随技术栈升级技能模板封装好的工作流审查、测试、重构会话级把复杂任务拆成可复用的步骤中频随团队实践迭代这有点像一个团队给新人准备的入职手册 代码规范 微服务脚手架 工作流 SOP。配置模板告诉 Claude我们团队是什么情况提示词模板告诉它遇到不同情况该怎么说话脚手架模板解决从零开始怎么写的问题技能模板解决复杂任务按什么步骤做的问题。1.3 模板带来的实际收益这套东西我跑了大概半年手头同时维护三个项目说说实测数据会话上下文 token 消耗降低约 30% 到 40%。项目级上下文直接通过 CLAUDE.md 注入不用每次对话反复粘贴。一次对话完成完整需求的比例明显提升。以前一个给订单模块加导出功能的需求经常要来回拉扯四五轮现在基本两轮内搞定——因为它一开始就知道代码放哪、风格用什么、测试怎么写。让新同事接手项目时他不需要读完整个 README 才能开始用 Claude Code模板里已经沉淀了核心知识。其中收益最大的其实是稳定。代码风格稳定了提交记录稳定了测试风格也稳定了。对做技术管理的人来说这比省那点 Token 重要得多。2. CLAUDE.md 配置模板把项目常识固化成文件2.1 三级配置体系与加载优先级CLAUDE.md 是 Claude Code 的核心配置文件相当于给 Claude 的一份项目说明书。它有一套三级配置体系加载时按从全局到局部的顺序逐层覆盖企业级全局配置~/.claude/CLAUDE.md放所有项目通用的规则比如代码注释用中文还是英文提交信息按 Conventional Commits 规范写。项目级配置项目根目录的CLAUDE.md放该项目特有的知识比如技术栈、目录结构、常用命令、模块说明。目录级配置子目录下的CLAUDE.md放局部规则比如src/api/CLAUDE.md里专门写 API 层的约定。这个机制有点像 Git 配置的 system/global/local 三级体系。越具体的配置优先级越高子配置会覆盖父配置的同名规则。注意目录级配置并不是递归覆盖的Claude Code 只会加载它实际读取文件时所在目录的 CLAUDE.md。你打开根目录的文件时它看的是根配置进入src/api目录操作时才会加载那层的补充说明。2.2 一个实用的项目级模板长什么样这是我目前在用的一个项目级 CLAUDE.md 模板结构上分了五块# 项目订单中心服务 ## 项目概述 - 微服务架构下的订单核心服务提供订单创建、支付回调、退款、查询接口 - 内部通过 gRPC 通信对外提供 RESTful APIOpenAPI 3.0 规范 ## 技术栈 - Node.js 20 TypeScript 5.xstrict 模式 - 框架Fastify - ORMPrisma PostgreSQL 15 - 缓存Redis 7ioredis 客户端 - 消息队列RabbitMQamqplib 客户端 ## 常用命令 - 安装依赖pnpm install - 本地开发pnpm dev监听 3000 端口 - 跑测试pnpm testvitest - 代码检查pnpm linteslint prettier - 生成 Prisma Clientpnpm prisma:generate ## 目录结构 - src/apiHTTP 路由层只做参数校验和响应封装 - src/service业务逻辑层事务和领域逻辑都在这层 - src/repository数据访问层通过 Prisma 操作数据库 - src/queue消息队列消费者 - prisma/schema.prisma数据模型定义 ## 编码约束 - # ALLOW src/api, src/service, src/repository, prisma - # DENY src/legacy - 禁止在 API 层写业务逻辑 - 所有对外接口必须返回统一的 { code, data, message } 结构 - 数据库表名用 snake_case字段名用 camelCase - 新增依赖必须先在 package.json 中声明不允许代码里直接 require 未声明模块这里说几个值得注意的设计细节。# ALLOW和# DENY规则是目录权限控制告诉 Claude 哪些目录可以读写、哪些目录不要碰。src/legacy是我们还没来得及重构的老代码模型一旦读了那部分代码很容易被带偏直接在 DENY 里封掉。注意 DENY 规则不会阻止模型读取文件做理解但会阻止它在没有明确许可时修改这些目录里的内容——对保护老代码非常有用。编码约束这一节是关键。你写得越具体Claude 生成的代码就越符合你的预期。像禁止在 API 层写业务逻辑这种话看起来很基础但实测下来特别管用——以前 Claude 特别喜欢在路由回调里直接查数据库现在基本不犯了。2.3 模板里该放什么不该放什么写 CLAUDE.md 最大的误区是恨不得把所有信息都塞进去。我最早那份配置写了两千多行结果 Claude 面对超载的说明反而抓不住重点该按规范做的没做到不该问的乱问。我的经验是放稳定的不放易变的放结论不放过程。要放的技术栈、目录结构、编码约束、常用命令、架构决策的结论。这些信息短时间内不会变放进模板可以减少每次会话的重复说明。不要放的具体的接口文档、数据库表结构、每个模块的详细设计。这些东西变化频繁应该通过提示词或者文档引用按需加载而不是固化在配置里。不要放的具体某次对话的上下文、待办事项、临时性的说明。这些内容会污染长期配置导致 Claude 在后续所有会话里都带着过时的信息。对了还有一条安全红线绝对不要往 CLAUDE.md 里写任何密钥、密码、Token。模板文件往往会进 Git 仓库而且会随代码被模型加载密钥放进模板等于裸奔。2.4 自定义斜杠命令把高频请求固化成快捷键CLAUDE.md 里还支持定义自定义斜杠命令类似于给 Claude 设置快捷键。比如我定义了一个/cleanup命令用来清理无用代码## 命令/cleanup 清理指定目录中的无用代码包括 1. 未使用的变量、函数、导入 2. 永远不会执行的分支 3. 被注释掉的代码块 执行时逐项列出修改内容经用户确认后再改文件。定义好之后任何时候输入/cleanupClaude 就会按这个指令执行任务。指令里可以写得很具体包括执行的步骤、输出的格式、需要确认的事项。我把团队里高频的请求全部命令化了。代码审查用/review提交信息生成用/commit测试生成用/tests日志排查用/troubleshoot。这些命令的好处是让团队成员的提问方式标准化了——以前有人说帮我看看代码有人说review 一下有人说这代码咋样现在统一一个/review搞定。3. 项目脚手架模板实战从零生成一个合规的 TypeScript 库3.1 脚手架模板的组织方式CLAUDE.md 解决的是已有项目的知识沉淀脚手架模板解决的是新项目从零开始的问题。Claude Code 支持把一组文件和目录结构定义成模板用claude --template参数引用配合会话变量和初始化脚本可以自动生成一个完整的项目骨架。一个标准的脚手架模板包含以下部分my-cli-template/ ├── templates/ # 模板文件目录支持 .tmpl 后缀的变量替换 ├── .claude-config.json # 模板元数据 ├── template.schema.json # 变量定义与校验规则 └── init.py # 初始化脚本变量预处理、环境检查等模板文件放在templates/目录下。templates/下的所有内容会被完整复制到目标目录其中以.tmpl结尾的文件会经过变量替换把{{variableName}}替换为实际值。3.2 一个 TypeScript CLI 工具的完整示例我以最近做的一个 TypeScript CLI 工具模板为例展示整个配置过程。先看.claude-config.json{ template: { name: ts-cli, description: TypeScript CLI 工具项目模板, category: application, prepare: python3 init.py, tags: [typescript, cli, node], schema: template.schema.json } }然后是核心的template.schema.json用来定义模板支持的会话变量{ $schema: https://json-schema.org/draft/07/schema#, type: object, properties: { projectSlug: { type: string, description: 项目 slug用于包名和目录名如 my-tool, pattern: ^[a-z0-9-]$ }, projectDescription: { type: string, description: 项目简短描述, default: A CLI tool built with Node.js and TypeScript }, packageManager: { type: string, description: 包管理器, enum: [pnpm, npm, yarn], default: pnpm }, nodeVersion: { type: string, description: Node.js 主版本号, default: 20 } }, required: [projectSlug] }再看看templates/目录里几个关键文件。首先是templates/package.json.tmpl{ name: {{projectSlug}}, version: 0.1.0, description: {{projectDescription}}, type: module, bin: { {{projectSlug}}: ./dist/index.js }, engines: { node: 20.0.0 }, scripts: { build: tsc -p tsconfig.json, lint: eslint src --ext .ts, test: vitest run }, devDependencies: { typescript: ^5.3.0, vitest: ^1.0.0, eslint: ^8.0.0 } }然后是templates/CLAUDE.md.tmpl这是新项目的配置模板。注意这里把新项目要用 Claude Code 时需要的初始约定也一并生成好了# 项目{{projectSlug}} {{projectDescription}} ## 技术栈 - Node.js {{nodeVersion}} TypeScript 5.xstrict 模式 - 包管理器{{packageManager}} ## 常用命令 - 安装依赖{{packageManager}} install - 本地构建{{packageManager}} run build - 跑测试{{packageManager}} test - 代码检查{{packageManager}} run lint ## 编码约束 - 所有代码必须通过 TypeScript strict 模式检查 - 单元测试使用 vitest测试文件放在 src 目录下命名规范为 *.test.ts3.3 初始化脚本与变量替换逻辑init.py是模板初始化的核心逻辑负责在变量替换之前做一些必要的准备工作。比如检查目标目录是否已存在、校验 Node.js 版本、根据用户输入动态生成变量值。#!/usr/bin/env python3 import os import re import json def main(): target_dir os.environ.get(TEMPLATE_TARGET_DIR, .) vars_file os.environ.get(TEMPLATE_VARS_FILE, ) # 确保目标目录为空或不存在 if os.path.exists(target_dir) and os.listdir(target_dir): print(Target directory is not empty. Aborting.) exit(1) # 检查 Node.js 版本 node_version os.popen(node --version).read().strip() major_version int(node_version.split(.)[0].replace(v, )) if major_version 20: print(Node.js 20 or higher is required.) exit(1) # 读取模板变量并补充派生变量 vars {} if vars_file: with open(vars_file) as f: vars json.load(f) # 派生变量从 projectSlug 推导出没有连字符的驼峰版本 if projectSlug in vars: camel_case .join(part.capitalize() for part in vars[projectSlug].split(-)) vars[projectNameCamel] camel_case[0].lower() camel_case[1:] # 写回变量文件供后续模板替换使用 with open(vars_file, w) as f: json.dump(vars, f, indent2) if __name__ __main__: main()这个脚本干了两件事检查环境是否满足要求以及派生新的模板变量。projectNameCamel就是我从projectSlug推导出来的——虽然template.schema.json里没定义但 init 脚本可以在运行时追加变量后续的模板替换阶段会使用更新后的变量集合。使用模板时运行claude --template ts-cli --target my-new-toolClaude Code 会加载模板定义询问缺失的变量值比如projectDescription执行init.py然后把templates/下的文件复制到my-new-tool目录完成变量替换。3.4 变量替换的校验规则变量替换本身不复杂但有几个容易踩坑的地方。pattern校验在template.schema.json中给projectSlug加了pattern: ^[a-z0-9-]$防止用户输入带空格、大写字母或特殊字符的目录名。这个校验会在交互式对话中被 Claude 检查也可以在 init 脚本里作为兜底校验。required字段projectSlug是必填项其他变量有默认值。如果把所有变量都设为必填新手使用模板时会很不耐烦把有合理默认值的变量设为可选可以大幅降低使用门槛。模板文件编码.tmpl文件本质上是普通文本文件替换时直接替换{{variableName}}。如果模板内容本身需要包含大括号比如 JSON 模板注意不要和变量语法冲突。实际操作中我遇到过在package.json.tmpl里写 scripts 时大括号被错误识别的情况解决办法是模板文件里尽量少写带大括号的复杂嵌套结构或者用 init 脚本动态生成而不是依赖静态模板。提示Claude Code 的模板机制是一个逐步演进的功能。如果你用的版本不支持某些字段最直接的判断方式是运行claude --help查看当前版本对--template参数的支持程度或者直接看官方文档。我这边写的内容基于常见的模板实现方式会在实际操作中根据版本微调。4. 团队模板库管理把个人经验升级成组织资产4.1 模板仓库的目录与命名规范当模板从一个变成一批个人经验开始变成团队资产这时候就需要一个专门的模板仓库来管理。我建议用一个独立的 Git 仓库存所有模板目录结构长这样claude-code-templates/ ├── configs/ │ ├── base/ │ │ └── CLAUDE.md # 企业级全局配置 │ └── project/ │ ├── ts-service/ │ │ └── CLAUDE.md # TypeScript 微服务项目配置 │ └── python-service/ │ └── CLAUDE.md # Python 服务项目配置 ├── prompts/ │ ├── code-review.md # 代码审查提示词模板 │ ├── test-generation.md # 测试生成提示词模板 │ └── refactoring.md # 重构提示词模板 ├── scaffolds/ │ ├── ts-cli/ │ │ ├── .claude-config.json │ │ ├── template.schema.json │ │ ├── init.py │ │ └── templates/ │ └── ts-service/ │ └── ... └── README.md # 模板库总说明每个模板的slug命名遵循[技术栈]-[类型]的格式如ts-cli、ts-service、py-service。slug 就是使用模板时输入的标识符所以要保持简短、无空格、无特殊字符。4.2 每个模板必须包含的元数据维护一个模板库最怕的是模板多了之后没人知道每个模板是干嘛的、什么时候用。我要求每个模板的.claude-config.json里必须写清楚这几个字段name模板的唯一标识和目录名保持一致。description模板的描述。这里不能写TypeScript 模板这种废话要写清楚适用范围比如适用于 Node.js 20 TypeScript 5 的 CLI 工具项目包含 vitest 测试和 eslint 配置。category模板分类用application完整应用、module项目内模块、config配置文件来区分。tags一些方便检索的关键词比如typescript、cli、node、fastify。这些字段写得好团队成员在使用claude --template时才能快速找到合适的模板。description 写得越准确越不容易出现这个人拿后端服务模板去生成前端项目这种低级错误。4.3 模板的版本管理与评审机制模板仓库也是 Git 仓库所以版本管理天然有保障。但实际操作中我发现一个很容易被忽视的问题模板变更的频率和代码库不一样。代码仓库里改动通常是某个具体功能的实现但模板仓库里一个字段的改动可能会影响所有使用该模板的项目。比如你把ts-cli模板里的nodeVersion默认值从 20 改成 22所有新生成的 CLI 项目都会跟着变。所以模板的改动必须走评审不能像改业务代码那样随随便便就推上去。我给团队定的模板评审检查表[ ] 本次改动的目的和影响范围是否在 PR 描述中写清楚了[ ] 变更是否向后兼容对已有的项目会有影响吗[ ] 是否有新增变量需要在template.schema.json中注册[ ] 是否运行过init.py的完整流程验证了新变量替换正常[ ] 是否更新了 README 中对应的模板说明4.4 如何让团队成员愿意用模板很多人以为上了模板体系团队成员就会乖乖用。实际上我发现真正能推下去的从来不靠强制。第一模板要尽量降低使用门槛。如果模板里的变量太多、必填项太多大家用一次就觉得烦。我给模板设计的原则是最多三个必填变量其他全靠默认值或者 init 脚本自动推导。projectSlug必填这个绕不开projectDescription有默认值packageManager有默认值。这样用户基本上只需要回答一个问题就能生成项目。第二模板要默认比人工初始化更好。如果模板生成的代码和手写的质量一样那没人愿意学新工具。但如果模板生成的目录结构更规范、自带测试、自动配好 lint用一次就能感觉到效率和规范性上的提升自然有人用。第三定期看数据。我会看团队里的使用情况比如哪个模板被调用了多少次、哪个模板多次被修改。如果一个模板每次用都被大改说明模板本身有问题如果一个模板完全没人用说明它不适合团队的实际场景要么改进要么删掉。5. 常见问题与排查技巧实录5.1 模板相关问题速查表现象原因解决方式CLAUDE.md 配置不生效配置层级错误项目级配置覆盖了用户级配置文件编码或格式问题先确认文件位置是否正确用claude doctor或版本命令验证配置加载检查文件是否为 UTF-8 编码{{variable}}没有被替换原样输出.tmpl后缀缺失变量名拼写错误变量未在 schema 中定义确认模板文件是否以.tmpl结尾对照template.schema.json逐一检查变量名变量替换时报错或校验失败pattern正则写错变量值包含非法字符init 脚本返回非零退出码查看报错信息定位校验规则修正正则或放宽校验在 init 脚本中增加详细的错误提示init 脚本执行失败Python 缺少依赖环境变量TEMPLATE_TARGET_DIR未设置目录非空为 init 脚本增加健壮的检查逻辑输出明确的失败原因生成的 README 里没有项目描述projectDescription是可选字段用户跳过了输入在 schema 里把描述设为必填或者在 init 脚本中从其他变量派生CLAUDE.md 太长导致 Claude 抓不住重点配置里塞了太多临时性、细节性内容做减法只保留稳定信息易变内容用提示词动态提供团队内有人不加载项目级配置Claude Code 版本不一致在错误目录下启动在 README中明确启动路径用 alias 固定启动目录5.2 我踩过的坑第一个坑是把 CLAUDE.md 写得像百科全书。最早我恨不得把整个项目的架构设计文档都塞进配置里结果 Claude 在处理简单任务时也带着一堆无关上下文反而干扰判断。后来我学到一个经验配置模板只解决高频、稳定、必备的信息低频细节用提示词动态加载。我甚至专门写了一个/docs命令需要时让它读取指定文档而不是把所有文档都塞进 CLAUDE.md。第二个坑是安全性问题。有一次我把数据库连接字符串写进了项目级 CLAUDE.md虽然仓库是私有的但团队里所有人都能看到这个文件任何能接触仓库的人都能拿到生产库的地址。从那以后我定了死规矩模板和配置文件里禁止出现任何敏感信息一律用环境变量引用。第三个坑是过度自动化。有段时间我试图把所有事情都做成模板连怎么写提交信息怎么发 Pull Request都要用斜杠命令驱动。结果团队成员反而抗拒——本来一句话能说清楚的事非得多记一个命令。后来我砍掉了大部分低价值的命令只保留真正高频的代码审查和测试生成使用率反而上来了。第四个坑是忘记模板版本兼容性。有一回我改了模板里的目录结构新生成的代码和旧项目差异很大结果团队里两个项目并行维护一个用旧结构一个用新结构代码风格再次分裂。现在我对模板里的结构性字段格外谨慎非必要不改真要改会在 PR 描述里写清楚对已有项目的影响。5.3 让我受益最大的三个模板最后分享三个我在实际工作中收益最高的模板它们也是这套 claude-code-templates 体系里最值得复制的。第一个是代码审查模板。以前让 Claude 做 code review输出经常是大而化之的客套话比如整体设计不错但要注意边界情况。加了 review 提示词模板之后它开始按检查清单逐项审查类型安全、异常处理、性能隐患、测试覆盖、命名规范、依赖合理性。这个模板让 AI 代码审查从形式主义变成了真能找出问题。第二个是测试生成模板。Claude 默认生成的测试往往顺着代码实现来写很容易写出验证了代码本身的假测试。我在模板里加了几个约束必须覆盖正常路径、异常路径、边界值断言要验证行为而不是验证实现每个测试要有明确的业务场景描述。效果立竿见影测试质量提升了一个档次。第三个是重构模板。这是我自己用的最多、对日常开发影响最大的一个。重构模板会先让 Claude 分析代码结构、识别坏味道、给出重构方案经确认后才动手改代码改完自动跑测试。这样一个流程走下来重构的成功率明显提升回滚的情况也少了很多。这三个模板的共同点不是写得好而是把流程拆细了。模板的本质不是告诉 AI要做什么而是告诉它分几步做、每步做到什么程度。这比一句帮我重构这段代码有效得多。我自己在迭代这套模板体系的时候最大的体会是模板永远不是一次写成的而是跟着团队的实践不断打磨出来的。最开始只需要解决最痛的那一两个问题比如代码风格、上下文重复交代然后用上一段时间根据实际效果慢慢加东西。等到模板库逐渐完善你会发现它不只是给 Claude 用的说明书更是团队技术沉淀的活文档。这个仓库里的每一份模板记录的都是一次实际踩坑后的反思——这种价值比省下来的那点 token 和对话时间要长远得多。