如果你用过 Claude Code,一定经历过这种挫败感:模型能力很强,但每次新开会话都像换了个新同事。上次你花十分钟讲清楚的项目背景,这次又要重新讲一遍;讲完之后,它产出的代码风格和上次可能还是两套。团队里如果多几个人在用它,情况更乱——不同人对同一段代码的评审标准各说各话。问题不出在模型本身,而在于我们从来没把"经验"固化成结构化的 claude-code-templates。
坦白说,我一开始也不知道模板体系这个词。最开始就是随手写几行 prompt,用久了发现重复劳动太多,才认真开始整理 CLAUDE.md、自定义斜杠命令、子代理这些配置文件。整套东西成型之后,使用体验几乎是换了个工具:新会话不用再预热,模型对项目的理解非常稳定,连团队新人上手都快了很多。这篇文章不写空泛的原则,直接把我实际在用的模板目录、每个文件里的配置、为什么这么放、踩过哪些坑都摊开给你看。不管你是刚接触 Claude Code 的新手,还是已经用了很久但对效率不满意的人,这套思路都能直接参考。文中配置以我常用的版本为基础,版本升级后个别字段可能有差异,但设计逻辑是通用的。
1. 为什么需要一套模板体系而不是靠临场发挥
1.1 会话记忆天然是"碎片化"的
先想清楚一个事实:Claude Code 每次启动新会话时,模型对你的项目其实一无所知。对话上下文只存在于本次会话内,用完即走。官方提供了上下文压缩机制,但压缩之后保留的是摘要,摘要不等于完整信息——你上次对某个模块设计意图的详细解释,压缩后往往只剩一两句话。
这意味着每次新会话都是一次"重新建立理解"的过程。你讲得越清楚,它表现越好;你懒得多说两句,它就按自己默认的偏好干活。这就像带实习生,你不给他写交接文档,那每次都得口述一遍,而且每次口述的内容还不一样。人受不了这种重复劳动,模型更受不了——因为它每次看到的都是一个残缺版的项目理解。
1.2 模板体系解决的三件事
根据我自己的实际使用体验,一套好的模板体系主要解决三个问题:
- 上下文稳定性。通过 CLAUDE.md 和各级记忆文件,把项目背景、技术栈、目录职责、编码规范固化成持久配置。不管谁开新会话、不管开了多少次,模型读到的项目背景都是一致的。
- 流程标准化。通过自定义斜杠命令和子代理配置,把"代码审查""生成变更日志""排查数据库问题"这类高频操作封装成固定模板。操作路径一样,输出格式一样,避免每次自由度太大导致结果不可控。
- 质量一致性。模板里写明红线、优先级和输出格式后,模型在关键决策点上的表现会稳定很多。比如我要求所有慢查询必须先通过执行计划验证再下结论,这条规则写进模板之后,它就基本不再犯"凭经验猜性能"的毛病。
这三件事如果用一句话概括,就是把"会消失的对话经验"变成"不会消失的项目资产"。这也是 claude-code-templates 这个方向真正的价值所在。
2. CLAUDE.md:整个模板体系的基石
2.1 三级作用域与加载机制
CLAUDE.md 是 Claude Code 自动读取的项目记忆文件,它有三层作用域,加载时按优先级合并:
| 作用域 | 位置 | 适用场景 |
|---|---|---|
| 用户级 | ~/.claude/CLAUDE.md | 个人全局偏好,比如你常用的工具链、通用编码风格 |
| 项目级 | 项目根目录的CLAUDE.md | 当前仓库的技术栈、架构、常用命令、红线 |
| 目录级 | 子目录下的CLAUDE.md | 某个模块特有的约定,比如 handler 目录记录 API 层规范 |
加载机制上有一点要特别注意:项目级的 CLAUDE.md 是"一个仓库一份"的主记忆,但它同时也会读取子目录级的记忆文件,并且能通过 import 引用外部 markdown 文档。如果你把所有内容堆在根目录一个文件里,文件会越来越庞杂,token 消耗也越来越高。我见过有人把整本架构文档塞进去,结果模型每次处理时上下文被挤占得很厉害。合理的做法是分层:根目录放最核心的约束,细节放子目录或独立文档按需引入。
实际体验中我发现,目录级 CLAUDE.md 对大型仓库尤其有用。之前我在一个多模块代码库工作,订单、支付、库存三个模块的领域规则差别很大,全写进根目录不仅冗长,还容易让模型在处理某个具体模块时被无关信息干扰。把领域规则拆到各模块子目录之后,整体准确率明显提升。
2.2 一份实用的 CLAUDE.md 应该包含什么
我自己的写法遵循一个原则:CLAUDE.md 不是说明书,而是决策规则集。它回答的是"在这个项目里,做决定时要注意什么",而不是"这个项目的代码怎么组织"。
下面是我一个后端网关项目的示例,结构可以直接参考:
# 项目概览 这是一个用 Go 编写的 API 网关,核心模块为路由转发、限流、JWT 鉴权。 # 代码结构 - internal/handler:HTTP 层,只做参数绑定和响应封装 - internal/middleware:中间件链,限流、鉴权都在这里 - pkg/ratelimit:核心限流算法,独立模块,禁止被 handler 直接依赖 # 编码规范 - 错误处理必须用 fmt.Errorf 包装上下文,禁止裸 return err - 所有对外接口需要有注释,说明调用方和失败场景 - 新增依赖时,在 PR 描述里说明为什么引入 # 常用命令 - make test:跑全部单测 - make lint:按项目统一 lint 规则检查 # 红线 - pkg/ratelimit 的算法逻辑不允许自行修改,有疑问先联系维护者 - 任何日志里禁止输出请求头中的 Authorization 字段这份文件的核心价值在最后两段。模型读完之后,它在"改代码时会不会违反红线""错误处理用哪种风格"这些高频决策点上就有了明确依据。你不需要在每次会话里反复口头叮嘱这些事情。
2.3 容易写错的几个点
第一个坑是写得太"虚"。比如"请遵循最佳实践""写出高质量的代码"这类句子,模型读了没有任何约束力,因为它不知道你说的"最佳实践"具体指什么。模板里要有可判断、可执行的标准,比如"错误必须返回包装上下文"。
第二个坑是规则冲突。项目级 CLAUDE.md 说可以用某个工具,子目录级又说禁止,模型就会困惑。我习惯按"更细粒度优先"的原则处理,但要在文件里明确写出来,否则模型只能靠猜。
第三个坑是忽略版本兼容。Claude Code 的版本迭代很快,不同版本对 CLAUDE.md 的读取策略、最长 token 限制都有变化,尤其文件很长时新版本会自动做摘要处理。换句话说,你写再长的 CLAUDE.md,模型最终读到的可能是摘要而不是全文。所以与其面面俱到,不如精简到关键决策规则。
3. 自定义斜杠命令:把高频操作封装成一条 / 指令
3.1 斜杠命令的本质
如果说 CLAUDE.md 解决的是"背景知识"问题,自定义斜杠命令解决的就是"操作流程"问题。它本质是一个带 frontmatter 的 Markdown 提示词模板,放在项目的.claude/commands/目录下,文件名就是命令名。比如放一个review.md,会话里输入/review就能触发对应的审查流程。
这是我实际项目里抽出来的代码审查命令:
--- description: 按项目规范执行一次代码审查 argument-hint: <文件或目录,可为空> --- 请以资深 reviewer 的身份审查我在 $ARGUMENTS 中指定的代码。 如果 $ARGUMENTS 为空,则审查当前会话中最近修改的文件。 审查优先级: 1. 并发安全和数据竞争问题 2. 错误处理是否符合 CLAUDE.md 中的项目规范 3. 性能和资源释放问题,比如 goroutine 泄漏、连接未关闭 4. 命名、结构、可读性 输出格式: 按 "严重 / 一般 / 建议" 三个级别分组列出; 每条结论必须附上对应代码位置和修改建议; 不要只报问题,要给出可落地的改法。这个命令好用的点有两个。第一是$ARGUMENTS变量让命令可以接收会话里的临时输入,比如/review internal/handler,一个模板就能覆盖任意审查范围。第二是它内部引用了 CLAUDE.md 的规则——注意看第二点,它写的是"是否符合 CLAUDE.md 中的项目规范",这等于把知识层和流程层串起来了。
3.2 frontmatter 里值得设的字段
斜杠命令的 frontmatter 有几个字段,我最常用的是description和argument-hint。description会被 Claude Code 用来做命令的自动推荐,写清楚一点,会话里补全也更方便。argument-hint是给用户看的参数提示,比如写<文件路径>,调用方就知道该输入什么。
另一个容易被忽略的是allowed-tools字段,它可以限制命令执行时模型能调用的工具。比如一个只想让模型做静态审查的 review 命令,可以只开放 Read、Grep、Glob 这类读取工具,关掉 Bash、Edit。好处是命令行为更可控,不会出现"你说只审查,它却擅自改了代码"的情况。但字段别写得过死,比如某些审查场景确实需要跑测试验证问题时,不给 Bash 它就只能干看了。
3.3 命令的组织方式
命令多起来之后,目录树可以这样规划:
.claude/commands/ ├── review.md ├── changelog.md ├── commit.md ├── db/ │ ├── explain.md │ └── migrate.md └── infra/ └── deploy-check.md子目录不是必须的,但命令超过十个之后,只靠名字前缀分类很难管理。db/explain.md这样的组织方式,会话里输入/db/explain就能触发。我的经验是:命令不要贪多,只封装"频率高、流程可复用、输出格式有要求"的操作。一次性任务反而适合直接对话,写进模板只会增加负担。
4. 子代理模板:让不同角色各司其职
4.1 子代理配置的基本结构
Claude Code 的子代理机制相当于你定义了一批"虚拟同事",每个同事有自己擅长的事、自己的工具权限和自己的职责边界。配置放在.claude/agents/目录下的 Markdown 文件里,通过 frontmatter 指定角色信息。
以我常用的数据库专家子代理为例:
--- name: db-expert description: 排查数据库 schema、查询性能、索引设计问题 tools: Read, Grep, Glob, Bash model: sonnet --- 你是项目里的数据库专家。你的职责边界: - 只响应与 schema、查询性能、索引、迁移脚本相关的请求 - 其他问题一律转回主代理,不要越权处理 处理流程: 1. 先定位问题涉及的 SQL 与表结构,禁止没有依据的猜测 2. 对慢查询,必须先用 EXPLAIN ANALYZE 取得实际执行计划 3. 给出结论时附上可直接执行的 SQL 示例 注意事项: - 不要在未确认索引是否已存在时就建议建索引 - 涉及大表变更时,同时给出回滚方案几个字段值得细说。model可以指定子代理使用的模型,读多写少的分析任务可以选更快的模型来省成本。tools限制它能调用的工具,这比在主对话里口头说"你只能用读取工具"可靠得多。description是主代理路由任务时的判断依据,它写的是"排查数据库相关问题",主代理遇到相关任务时才会把它拉出来。
4.2 子代理与主代理的协作边界
很多人的误区是把子代理定义成一个"更全能的小号 Claude",这完全浪费了它的价值。子代理的意义恰恰在于"窄":限制职责范围、限制工具、限制输出偏好,这样它在自己领域里的表现才稳定。
我踩过的坑之一,是给一个子代理开了太多权限。当时我想让它全自动处理告警,于是 Read、Bash、Edit 全开,结果它在一轮操作里既改了配置又改了代码,最后问题没解决反而把现场搞乱了。后来我把这类子代理的权限收敛成"只诊断、不修改",再配一个独立的修复命令执行变更,整体就稳定多了。
另一个值得注意的点是:子代理之间不要职责重叠。你既建了一个db-expert负责所有 SQL,又建一个query-optimizer也负责 SQL 性能,主代理在路由时就会困惑。我建议每个子代理的 description 里刻意把边界写窄一点,甚至可以写上"涉及 X 的请求不要响应",路由会更干净。
4.3 模板化子代理的实际收益
抛开概念,子代理模板给我带来的实际收益主要在两方面。一是并行性:有些任务是"总-分"型的,主代理可以先把子任务委派给多个子代理,理论上能更快完成。二是上下文隔离:比如在大型仓库里做性能排查,子代理可以在自己专注的上下文里处理 SQL 问题,不会被整个项目的其他无关内容干扰。对长会话尤其友好,主上下文的 token 空间可以省下不少。
5. 钩子(Hooks)与配置文件的联动
5.1 钩子的触发时机
钩子机制是 Claude Code 在"事件发生前或发生后"执行外部脚本的接口。它本身不是模板,但它是模板体系里最容易被忽略的一环,因为很多项目级规范光靠提示词约束不住,必须靠程序保证。常见的事件类型包括:
| 事件 | 触发时机 | 典型用途 |
|---|---|---|
| PreToolUse | 模型即将调用工具前 | 拦截危险命令,校验参数 |
| PostToolUse | 工具执行完成后 | 自动格式化、自动跑测试 |
| UserPromptSubmit | 用户提交新消息时 | 注入额外的上下文或告警 |
| SessionStart | 会话启动时 | 加载外部笔记、初始化环境 |
| Stop | 模型结束一轮输出时 | 触发后续处理脚本 |
钩子配置写在settings.json里,可以放在用户级~/.claude/settings.json,也可以放在项目级.claude/settings.json。我一般把团队共享的放项目级,把个人偏好放用户级。
5.2 模板与钩子的配合场景
举一个我实际在用的例子。我给自己定了一条规矩:不允许模型在未确认环境信息的情况下直接改部署脚本。光在 CLAUDE.md 里写这句是管不住的,于是我在 PreToolUse 里加了一个钩子,匹配 Bash 事件,如果检测到命令里包含某个危险关键词,就返回阻止信息:
{ "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "node .claude/hooks/guard.mjs" } ] } ] } }这个钩子脚本本身就是一个可复用的模板:团队里换人、换机器,只要把.claude/hooks目录随仓库一起克隆下来,规则就自动生效,不需要每个人手动配置。从这层意义上说,钩子是对模板体系的"强制保险"——提示词管软约束,钩子管硬约束。
5.3 钩子设计的三个注意点
第一,钩子脚本必须快速返回。PreToolUse 钩子执行慢的话,会明显拖慢整个会话响应。我的脚本里都做超时保护,逻辑复杂的情况先把耗时操作丢到后台,或者只做快速判断。第二,失败要优雅。钩子挂了不应该打断主流程,尽量让脚本返回明确的非阻塞退出码,并打印可读日志。第三,匹配规则要尽量窄。matcher写得越宽,误触发的概率越大;我一般只对需要管制的工具和命令模式加钩子,其余的一律放行。
6. 模板库的落地组织与常见坑
6.1 一套我推荐的项目模板目录结构
把前面几层放在一起,我目前项目里沉淀出来的标准模板目录长这样:
<project_root>/ ├── CLAUDE.md ├── .claude/ │ ├── settings.json │ ├── commands/ │ │ ├── review.md │ │ ├── changelog.md │ │ └── db/explain.md │ ├── agents/ │ │ └── db-expert.md │ └── hooks/ │ └── guard.mjs这套结构的核心思路是"配置即仓库的一部分"。CLAUDE.md 和 .claude 目录都提交进 Git,团队成员 clone 下来就会得到完全一致的 AI 协作环境。这也是 claude-code-templates 最有价值的地方——它不只是一堆文件,而是一套可以被版本管理、被 diff 审查的"团队 AI 工作协议"。
6.2 从零搭建而不是一次性设计完整
如果你现在才开始,我的建议是不要一上来就把所有配置铺满。先只建一个最小可用的 CLAUDE.md,主要写项目背景和红线,用两周时间观察模型在哪里还是反复出错,再把对应规则补进去;然后封装出现频率最高的那两三条斜杠命令。我自己就是从"只有一页 CLAUDE.md"开始,迭代到现在的完整结构,中间每一次补充都有真实的失败案例支撑。
这么做的原因是:模板里写进规则,本质上是在给模型加约束,约束越多,误伤和冲突的概率也越大。如果一开始就把所有想到的规则都塞进去,很容易出现相互矛盾或约束过严导致模型不敢动手的情况。从真实痛点出发增量添加,每次加规则都问自己"它能解决哪个具体问题"。
6.3 我踩过印象最深的几个坑
第一个坑是模板目录没放进版本控制。当时为了图方便,我把自定义命令放在个人全局目录只自己用,结果换一台电脑全部丢失,团队协作时别人也没法共享。后来我统一改成"项目内优先、全局只存个人偏好"的策略。
第二个坑是过度抽象。有一阵我觉得命令写得越好越安全,于是给每个子代理都追加大量限制和流程描述,结果模型花了大量 token 去读"人设",反而影响了核心任务的执行效率。子代理描述控制在几百字内就好,讲边界、讲流程、讲输出要求,不用写长篇背景故事。
第三个坑是忽略版本差异。我有一次在一个老版本项目里直接套了新版的 hooks 配置,结果事件类型不识别,钩子静默失效。所以模板库要跟着 Claude Code 版本走,升级后务必回归测试一遍核心命令和钩子。
6.4 通过模板库实现多项目复用
最后说跨项目复用。我个人的做法是单独维护一个 dotfiles 仓库,把打磨好的模板按项目类型分类,比如go-service/、web-frontend/、infra-tool/。新项目初始化时把对应类型目录复制过去,再花半小时根据项目差异调整 CLAUDE.md 和命令参数。这样做的效率比每次从零写配置高很多,也便于把新踩到的坑沉淀回模板库。
复制过去并不是结束。每次在新项目里发现某个模板写得不够好,我就回到模板库里改一处,让后续所有新项目都受益。坚持了两个月左右,模板库的质量明显比单项目里的临时文件高出一个量级。
最后再分享一个小技巧:模板库里的每个命令和 CLAUDE.md 编号版本,改动时顺手在文件头加一行# last-updated日期。等到你对比不同时间段模型表现时,就能知道哪些变更真正起了正向作用,哪些反而拖了后腿,而不至于改着改着忘了当前这套配置是为什么长成这样的。