ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Claude Code 模板配置指南:从 CLAUDE.md 到自定义命令与 hooks

Claude Code 模板配置指南:从 CLAUDE.md 到自定义命令与 hooks

claude-code-templates 这个项目名,乍看像是一个平平无奇的模板仓库,但用过一段时间后我发现,它其实是 Claude Code 从“能跑”到“好用”的关键一层。Claude Code 默认状态下就像一个对项目一无所知的实习生,你让它写代码,它能写,但并不知道你仓库里的命名习惯、测试命令、提交规范、目录边界。你说一句它就做一版,往往做出来的东西看着能跑,却和你团队的真实约定对不上。把 CLAUDE.md、自定义命令、钩子脚本、子代理定义整理成一套 templates,本质上是在给 AI 装“事前记忆”。

这篇文章想把我在整理和使用 claude-code-templates 过程中的思路、踩坑和可直接抄走的配置完整写下来。不论你是刚接触 Claude Code 的新手,还是已经在日常用 AI 做代码审查的老手,只要想在下一个项目里让 AI 的表现更接近“资深协作同事”,这套模板设计就值得往下看。

1. 为什么 Claude Code 不能裸着干活

1.1 没有模板时的一个典型翻车现场

我先描述一个很常见的场景。你有一条待办:给项目加一个用户反馈接口。然后直接在项目根目录启动 Claude Code,输入指令“把用户反馈功能加上”。它就开始行动了。它会读几个文件,然后开始写代码。表面上没问题,但几次下来你会发现几个固定的毛病。

最典型的是,它默认用npm,但项目用的其实是pnpm;它默认把新组件放在src/components下,但项目约定是放在src/features/feedback这种按业务拆分的目录里;它写的接口没有挂在已有的错误处理中间件后面,因为项目里统一用ApiError封装异常,它并不知道。这些问题的根源不是模型能力,而是缺少“上下文约定”。很多时候你需要在对话里反复纠正它:用 pnpm,用这个目录,看下现有 controller 怎么写的。每开一个新会话,同样的纠正过程又会再来一遍。

有人会把这归结为“提示词没写清楚”,但这个结论太粗糙。真正的做法是把这类约定沉淀成可复用、可版本化的文件。claude-code-templates 解决的就是这个问题:它不是一次性 prompt,而是项目里的一组“规则文件”,让 AI 每次启动时自动读到。

1.2 模板的真正价值:把语境压缩成可重用文件

传统脚手架(scaffold)解决的是“代码文件从哪里来”,AI 时代的模板解决的是“AI 对这个项目的假设从哪里来”。你可以把 Claude Code 的上下文理解成三部分:系统内置的通用能力、你输入的即时对话、项目目录里的配置文件。模板影响的是最后一部分,而且这部分最容易被忽视。

我在实践中非常依赖的一个类比是“入职手册”。新同事入职要读团队规范,知道用什么包管理器、代码怎么分层、提交信息怎么写。CLAUDE.md 就是给 AI 看的入职手册。而自定义命令和钩子相当于把团队里“惯例动作”固化成快捷键和自动检查。一套好的 templates 能让 AI 少猜几百次,也让每次会话的输出稳定性高一大截。我整理模板库时的一个硬性指标是:同一个任务,在不同日期、不同会话里执行,产出的代码风格和目录结构要能保持基本一致。没有模板,这点很难做到。

2. 四层模板体系:配置不是堆上去的

我最早也犯过把配置全塞进 CLAUDE.md 的毛病。结果文件越来越长,AI 的上下文被无关信息占据,反而忽略了真正重要的规则。后来我把它拆成四层,各管各的事情。

2.1 第一层:CLAUDE.md,项目的“宪法”

CLAUDE.md 是 Claude Code 在启动时自动读取的项目级记忆文件,放在项目根目录。这里只放最稳定的、适用于整个仓库的信息:项目定位、技术栈、常用命令、代码风格、目录结构、提交规范。它就像宪法,不轻易改,但优先级最高。我见过很多人把一次性任务的细节也写进去,比如“记得把某个接口的 timeout 改成 10 秒”,这会导致文件迅速腐化,AI 分不清什么是长期规则、什么是一次性的临时要求。

全局层面还有~/.claude/CLAUDE.md,它相当于个人级或机器级的默认宪法。两者会合并,全局内容是基础,项目内容覆盖或补充。我一般在全局文件里写跨项目通用的偏好,在项目文件里写当前仓库特有的规矩。

2.2 第二层:.claude/commands,斜杠命令快捷入口

这一层对应的是.claude/commands/目录下的 Markdown 文件。每个文件定义一个斜杠命令,例如你在对话里输入/review,Claude Code 就会读取对应的命令文件,执行里面定义的提示词任务。这就像终端里的 alias,把一段你每次要重复打的复杂 prompt 保存成一个短命令。

我强烈建议把一切“每次都要啰嗦一遍”的工作流固化到这一层:代码评审、写提交信息、生成单元测试、分析依赖升级影响、检查环境配置。因为这些工作流包含固定动作,适合模板化。命令的优势是只在调用时才进入上下文,平时不占用任何记忆空间。

2.3 第三层:hooks,自动化的“守门人”

Hooks 是比命令更底层的自动化机制。它可以在 Claude Code 调用某个工具之前或之后触发脚本,也可以在你提交 prompt 或会话结束时触发。配置在.claude/settings.json或.claude/settings.local.json里。

这一层适合放“不需要 AI 判断”的硬性规则。比如:每次 AI 写文件之后自动跑 prettier 格式化;AI 执行敏感 bash 命令之前打印警告;测试跑完之后的输出自动记录到另一个文件。它是模板库里最像“程序”的部分,因为它不是思维指导,而是事件驱动的执行逻辑。

2.4 第四层:.claude/agents,子代理分工

第四层是子代理。Claude Code 支持在.claude/agents/下定义专门的子代理,每个子代理有独立的系统提示词和工具权限。简单说,它是在主对话之外建立的一个“专门角色”,比如code-reviewer、security-auditor、docs-writer。

我的体会是,子代理特别适合那些需要高度专注、不希望被主任务打扰的环节。主模型可以负责组织代码,子代理可以并行审查问题。把这四个层次拆开之后,模板库的维护成本大大下降:项目规范变动时改第一层,工作流步骤变动时改第二层,自动化规则变动时改第三层,专业角色变动时改第四层。互不干扰,也不会出现“一个配置改动,其他功能跟着坏掉”的情况。

层级文件位置加载时机典型用途
CLAUDE.md根目录或子目录会话启动自动加载项目背景、约定、命令
commands.claude/commands/*.md斜杠命令被调用时加载评审、测试、提交信息
hooks.claude/settings*.json事件触发时执行格式化、拦截、记录
agents.claude/agents/*.md被主模型调用时加载专项审查、文档撰写

3. 实操第一层:写一份能镇住场子的 CLAUDE.md

3.1 一份可以直接抄的 CLAUDE.md 模板

写 CLAUDE.md 不需要什么特殊语法,它本质就是带结构性说明的 Markdown 文本。下面这份是我在几个 React + TypeScript 项目里反复用过的模板,只改了项目名和技术栈,效果很稳定。

# CLAUDE.md 你是本项目的资深前端开发工程师,负责功能开发、代码重构、审查和调试。 回答时先分析现有代码,再给方案,不臆想不存在的接口。 ## 项目信息 - 项目类型:中后台 Web 应用 - 技术栈:React 18 + TypeScript + Vite + TailwindCSS - 包管理器:pnpm - 测试框架:Vitest + Testing Library - 构建产物:dist/ ## 常用命令 - 启动开发环境:pnpm dev - 单元测试:pnpm test - 类型检查:pnpm typecheck - 构建:pnpm build ## 目录约定 - src/features/ 下按业务模块组织,禁止在 features 之间交叉引用内部实现 - src/components/ 只放跨模块共享的基础组件 - src/api/ 集中管理请求封装,禁止在组件里直接写 fetch ## 编码规范 - 组件使用函数组件和 hooks,不使用 class 组件 - 文件命名:组件用 PascalCase,工具函数用 camelCase - 变量命名要能自解释,禁止无意义的单字母变量 - 提交信息格式:<type>(<scope>): <subject>,例如 fix(auth): 修复登录态过期问题 ## 处理原则 - 修改现有代码前,先阅读相关文件的完整内容 - 新增依赖需要给出理由,优先使用项目内已有依赖 - 涉及样式时,优先使用 TailwindCSS 的原子类,不写私有 CSS 文件

这份模板的关键在于第三部分和第四部分的边界。第三部分描述项目事实,是客观信息,AI 要无条件遵从;第四部分的规则带有“原则”性质,AI 在行动时需要先对齐。模板里我故意写了“不臆想不存在的接口”,这句能在生成时省去很多幻觉接口的麻烦。

3.2 模板各部分的作用与调整

第一段角色定义很重要。我试过不写角色,直接给一堆项目描述,AI 的态度会明显更“含混”,回答会更像百科而非同事。写出“你是本项目的资深前端开发工程师”这句话,会引导输出风格偏向“有判断力的执行者”。如果你希望 AI 更像文档顾问或测试工程师,就改这一段。

常用命令放到 CLAUDE.md 里看起来笨,但收益很大。AI 会从这段学到“这个项目用 pnpm 而不是 npm”,并在后续执行命令时自动使用正确工具。这比你在对话里反复强调有效得多。目录约定和编码规范是模板里最需要结合真实项目定制的内容。我建议不要从网上直接复制一份长长的规则,而是先跑一个“基准任务”,比如让 AI 新写一个模块,观察它哪里违背了约定,然后把这些约定补进去。

3.3 分层 CLAUDE.md 的使用时机

Claude Code 还支持子目录里的 CLAUDE.md。意味着你可以在src/features/auth/CLAUDE.md里写只适用于认证模块的规则,AI 在处理那个目录的文件时会读到这个子级文件。这个特性非常强大,适合大型仓库里不同模块差异明显的场景。

但要注意,子目录 CLAUDE.md 不是取代根目录文件,而是在根目录规则基础上的补充。我见过有人把根目录的规范压缩到几乎没内容,全部分散到子目录里,结果 AI 在其他任务里完全失去对项目整体结构的感知。正确姿势是根目录写通用规范,子目录写局部差异。文件长度方面,我个人的经验是一份 CLAUDE.md 控制在 40 到 80 行,超过这个量,AI 反而容易依赖摘要而丢掉细节。

4. 实操第二层:把常用工作流固化成斜杠命令

4.1 命令文件的结构和坑

.claude/commands/下的每个 Markdown 文件对应一个命令,文件名去掉.md就是命令名。文件顶部用 YAML 块声明命令属性,下面是执行时的提示词正文。一个基本结构是这样:

--- name: review description: 审查当前分支的改动并输出评审意见 allowed-tools: Read, Grep, Glob, Bash, Write --- 请对当前分支相对主分支的改动做一次完整代码评审。 先执行 `git diff --stat` 和 `git diff` 查看改动, 再调用必要的读取工具了解上下文。 输出格式: 1. 按严重程度分组:阻塞性问题、建议修改、非阻塞建议 2. 每个问题给出文件路径、行号和修改建议 3. 最后给一个 1 到 10 的总体评分

执行方式是在对话里输入/review。初次使用容易踩的坑是 YAML 里的allowed-tools写得太宽或太窄。写太宽,AI 会调用不必要的工具,产生大量无用日志;写太窄,它又没法完成读取操作,命令直接报错。基准配置是Read, Grep, Glob, Bash,需要写文件再加Write。

4.2 三个高频命令模板示例

命令模板的价值在于让高频动作保持一致性。下面这几个命令我几乎每个项目都会带上。

第一个是提交信息命令/commit:

--- name: commit description: 根据暂存区改动生成符合规范的 Git 提交命令 allowed-tools: Bash --- 先用 `git status` 和 `git diff --cached` 查看暂存区和改动内容。 根据改动生成一条提交信息,必须符合项目的提交信息规范。 规范:<type>(<scope>): <subject>,type 为 feat/fix/refactor/docs/test/chore。 输出时直接给出可以执行的完整命令,不要输出解释。

第二个是测试补全命令/add-tests。这个命令适合那种“写代码很快但补测试靠催”的 AI:

--- name: add-tests description: 为最近改动的函数或组件补充单元测试 allowed-tools: Read, Grep, Glob, Bash, Write --- 先查看最近改动的源码文件,找到其中尚未覆盖的函数和组件。 参考仓库里已有的测试风格,用 Vitest 和 Testing Library 补写测试。 要求: - 测试覆盖正常路径和至少一个边界/异常路径 - 不 mock 掉被测试函数的真实行为,除非必要 - 写完先运行 `pnpm test -- <file>` 确认通过

第三个是重构命令/refactor,用来让 AI 以“最小改动”逻辑完成重构而非重写:

--- name: refactor description: 对指定模块进行低风险重构 allowed-tools: Read, Grep, Glob, Bash, Write --- 对用户指定的代码进行重构。重构的目的是改善结构和可维护性,不改变对外行为。 执行步骤: 1. 完整读取目标文件和相关依赖文件 2. 列出当前存在的问题 3. 描述重构方案,重点说明为什么这样改 4. 逐步修改并同时运行类型检查和测试

使用前后注意一点:命令一旦开始执行,它是一个独立会话,里面的文件修改和上下文不会自动带回到你之前的对话里。如果命令执行完你还要继续让 AI 基于修改结果进一步操作,最好先把它引入的结果通过 git diff 或复制关键输出回到主对话中。

4.3 命令的调试和版本差异

命令没生效时,我会逐个检查这几项:文件是不是在.claude/commands/下;文件名后缀是不是.md;YAML 里的name是否和文件名一致;description 是否以动词开头并清楚描述功能。最容易隐蔽的问题是 front matter 里用了 tab 缩进,导致解析失败。Claude Code 的命令文件对 YAML 解析要求比较严格,我建议全部用空格缩进,不要用 tab。

还有一个版本相关的点:不同版本的 Claude Code 对命令字段的理解有差异。比如有些版本支持model字段来指定处理命令使用的模型,有些版本支持agent字段。我的习惯是在模板库的 README 里标注“基于 Claude Code 1.0.x 版本验证”,并在升级前先跑一次/help查看当前环境支持的命令字段。

5. 实操第三层:用 hooks 建立自动规矩

5.1 hooks 的基本配置方式

hooks 配置在.claude/settings.json里。一个最小配置长这样:

{ "hooks": { "PostToolUse": [ { "matcher": "Write", "hooks": [ { "type": "command", "command": ["npx", "prettier", "--write", "$CLAUDE_FILE"] } ] } ] } }

这里的matcher匹配工具名,PostToolUse表示在工具调用完成后触发。$CLAUDE_FILE是 Claude Code 提供的环境变量之一,在不同事件里对应不同含义,在工具后事件里通常指向被写入的文件路径。这个配置的效果是:AI 每次通过 Write 工具写文件后,自动执行 prettier 格式化。不用指望 AI 记得格式化,钩子替它做了。

5.2 几个典型的 hook 场景

第一个场景是测试门禁。在Bash命令中检测到pnpm test时,自动在测试前设置超时提醒,或在测试后生成结果摘要。这个可以用PreToolUse和PostToolUse分开做。

第二个场景是敏感命令确认。比如在PreToolUse里 matcher 匹配到Bash,然后在命令内容里搜索rm -rf或git push --force,匹配到就把命令直接拦截。hook 可以通过返回一个特殊 JSON 结构来阻止执行:

{ "hookSpecificOutput": { "hookEventName": "PreToolUse", "permissionDecision": "deny", "permissionReason": "检测到危险命令,已由 hooks 拦截" } }

第三个场景是写日志。在每次工具调用结束后,把工具名、输入摘要、输出状态追加到.claude/hook-log.md。这种能力对排查 AI 的行为特别有帮助。当某个会话行为异常时,日志里能还原每一步的工具调用轨迹,比盯着屏幕猜高效得多。

5.3 让 hook 不反噬自己的注意事项

hooks 最大的坑是循环执行。比如 hook 里用 Write 写日志文件,而你的 PostToolUse matcher 又是Write,那 hook 执行时写的文件又会触发 hook,形成无限循环。我在settings.json里给写日志的配置专门指定 matcher 为除了日志文件外的路径,或者把日志写到.claude/log/目录并在 matcher 里用路径前缀排除。

另一个容易忽视的问题是性能。如果 PostToolUse 里的命令是npx,每次触发都要重新下载或检查依赖,会明显拖慢流程。我建议直接把命令指向本地安装的二进制,例如node_modules/.bin/prettier,或者使用type: "plugin"的方式调用模板库里预先打包好的插件。hooks 是“执行规则”而不是“思考规则”,任何需要模型判断的逻辑都不要放进 hooks,否则既浪费 token 又难以调试。

6. 实操第四层:子代理模板,让专业的事交给专业角色

6.1 子代理适合干什么

子代理是我后期用得最多的一个层。它的本质是:定义一个小型专用模型,带独立人格和工具边界,可以被主对话按需唤起,专门做某一类高专注任务。普通提示词的问题是,主模型在做整体编码时,注意力会不断被切换,审查质量和文档质量都会下降。子代理就好比你有一个主工程师,还有专门的测试工程师、代码审查工程师、安全工程师。需要时喊一个进来,干完就退出,不干扰主流程。

适合做成子代理的场景通常有三个特征:任务边界清晰,例如“只审查安全风险”;需要固定输出格式,例如“必须按表格输出漏洞清单”;与主任务解耦,例如“这个审查结果可以先产出,主代码写完之后再回来处理”。不建议把和主任务强耦合的多轮对话塞进子代理,那会增加不必要的上下文切换成本。

6.2 一个最小可用的子代理模板

在.claude/agents/下新建一个 Markdown 文件,文件名就是子代理的名字。一个最小模板长这样:

--- name: security-reviewer description: 代码安全审查专家,专注注入漏洞、越权风险和敏感信息泄露 tools: Read, Grep, Glob, Bash --- 你是一位经验丰富的应用安全工程师。 审查任务的目标是发现代码中的安全风险,而不是修改代码。 执行时: 1. 先阅读目标文件和周边依赖 2. 重点检查用户输入、文件路径拼接、间接访问控制、硬编码密钥 3. 每个风险必须说明危害、触发路径、修复建议 4. 如果没有风险,明确输出“未发现高风险问题”

使用时,可以在主对话里直接说“调用 security-reviewer 审查刚才改动的接口”。主模型会读取该子代理的定义并执行任务。如果模板库里有多个子代理,最好在description里写清楚这个代理适合什么任务,主模型才能准确唤起。我见过有人把所有子代理 description 写得模棱两可,结果主模型调用时无法判断该用哪个,直接影响效果。

6.3 子代理和命令的配合

子代理和斜杠命令可以形成很好的搭配。比如定义/security-check命令,它的提示词是调用security-reviewer子代理去检查整个仓库的改动。命令负责捕获用户意图,子代理负责专业执行,两层各司其职。这种配合还有一个好处:命令可以被团队共享,但子代理的能力可以独立演进。今天你发现安全审查需要增加“依赖漏洞扫描”维度,你只需要改子代理的模板,不需要改动命令入口。

如果子代理执行结果需要回到主对话,最好不要在子代理内部做大的修改操作,而是让它输出结构化报告。主模型拿到报告后决定怎么处理。这样可以避免子代理因为权限过大而直接改坏代码,也更容易追踪问题源头。

7. 新项目接入模板的完整流程

7.1 从模板仓库复制起步

最快的方式是直接用 degit 复制一份模板仓库:

npx degit user/claude-code-templates my-project cd my-project

我这里假设你已经把 claude-code-templates 仓库 fork 或整理成了自己的版本。如果模板仓库包含多种技术栈,一般会按目录区分,比如templates/react-vite、templates/python-fastapi。复制之后先做三件事:确认CLAUDE.md里的技术栈和目录约定和实际项目一致;跑一次claude启动,看根目录文件是否被正确加载;执行一个斜杠命令,比如/review,看命令是否正常响应。

7.2 全局默认模板的配置

如果你希望每个新项目都有基础的 AI 协作规范,可以在全局目录里放一份通用 CLAUDE.md。全局路径一般是~/.claude/CLAUDE.md。我会在全局文件里写“与具体项目无关”的偏好,例如:代码修改使用中文注释或英文注释的选择,输出涉及命令时必须给出完整可执行命令,遇到不确定需求时先提问再动手。

全局命令也可以放在~/.claude/commands/,这样你在任意项目里都能用到/commit、/review这类通用命令。项目内命令会覆盖或补充全局命令,命名冲突时项目内优先。这个机制让模板库可以分两层演进,个人偏好放全局,团队规范放项目。

7.3 团队协作里模板如何演进

模板库最怕变成一次性摆设。我见过的团队做法是:把.claude/目录和CLAUDE.md纳入 git 版本管理,任何改动都走 pull request,并在 PR 描述里写明这个改动是针对哪次任务暴露的问题。比如一次评审发现 AI 提交信息格式总是不对,那就改进/commit命令模板;发现 AI 总在某个业务目录里写基础组件,那就更新 CLAUDE.md 的目录约定。

这种演进方式的好处是,模板逐渐变成团队的“AI 工作手册”,既沉淀项目知识,又保留决策历史。新成员入职后,读一遍模板就能理解项目的 AI 协作方式,不再需要靠口头传递。

8. 常见问题与排坑实录

8.1 高频率问题速查表

现象排查方向解决方案
CLAUDE.md 不生效文件位置、文件名放在项目根目录,确认文件名大写 CLAUDE.md
斜杠命令找不到目录、YAML 解析文件必须放 .claude/commands/,front matter 用空格缩进
命令没按预期执行allowed-tools 设置检查工具清单是否包含所需工具
hooks 没触发matcher 大小写、事件名matcher 需精确匹配工具名,如 Write 不是 write
上下文超限CLAUDE.md 太长精简根目录文件,将细节移到子目录或命令里
会话行为漂移CLAUDE.md 规则不清晰用“禁止”“必须”等强约束词,避免模糊表述
子代理调用不了description 太模糊在 description 里写清适用任务类型

8.2 我踩过的三个特殊坑

第一个坑是 CLAUDE.md 放在 src 目录下而不是项目根目录。因为我是从模板仓库里复制的,当时把子目录下的 CLAUDE.md 完全复制走了,导致 AI 永远只以子目录视角看问题,整体项目结构感知全丢。后来我在模板库里加了启动检查脚本,用来确认根目录 CLAUDE.md 是否存在。

第二个坑是 hook 里的$CLAUDE_FILE在Write事件中不一定总是指向被写入的最终文件。某些版本里它指向会话当前工作目录或临时文件。我最后不再依赖单一环境变量,而是在 hook 脚本里通过上下文参数重新解析文件路径。所以如果你要复制我上面的 prettier hook,先确认当前版本的$CLAUDE_FILE行为。

第三个坑是命令和 hooks 里同时修改了同一份文件。比如/review命令让 AI 在对话里生成修改意见后直接改代码,而 hooks 里又有一个文件写入后的格式化钩子。如果两个逻辑的目录假设不一致,AI 可能改同一行代码两次,出现冲突。我的解决方式是明确命令负责“给出可操作的修改点”,实际的格式化和测试交给 hooks,互不抢任务。

最后一个经验,模板不是越复杂越好。我见过有人把.claude/目录塞了三十多个文件,每个文件都写得很长,最后 AI 启动时光读取这些定义就消耗了大量上下文。真正有效的模板库应该像一份精炼的团队手册:核心规则十来条,命令五六个,hooks 两三个,子代理一两个。先跑一个完整项目周期,再根据真实痛点逐步增加内容,比一开始堆满配置要靠谱得多。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进