Claude Code 我已经用了不短的时间,刚开始跟大多数人一样,直接在终端里甩几句自然语言让它干活。表面看确实自由,可真放到项目里跑上两周,你就会碰到一个非常现实的问题:同一套评审规范、提交约束、测试流程,我几乎是每天重新解释一遍,而且无论我提示得多细,它在不同会话里的发挥依然忽高忽低。直到我静下心把常用指令全部整理成 Commands,又在它执行动作的链路上挂了 Hooks,才觉得 Claude Code 从“一个能写代码的高级聊天窗口”变成了“一个能被工程纪律约束的协作者”。这篇文章是把我在真实仓库里配置和使用这两套系统的经验做一次完整复盘,适合已经装好 Claude Code、想把它从玩具变成生产力工具的人。
先说结论:Commands 解决的是“怎么让模型稳定地听指令”,Hooks 解决的是“怎么在关键动作上卡住它、不让它乱来”。这两件事单独拎出来都不算复杂,但配合好了,能把一个通用 Agent 调教成符合你团队习惯的专用工具。
1. 为什么自然语言协作会失灵:Commands 想解决的真问题
1.1 我踩过的“同一件事每次重说一遍”的坑
很多人的第一反应是:Claude Code 连得上模型、能读仓库、能执行命令,那我还配置什么?直接打字不行吗?
行,但会非常累。
我最开始常让它做的事是“帮我按仓库规范生成提交说明”。第一次我写了很长一段:要看 git diff、要识别改动类型、要按 Conventional Commits 写标题、正文要解释为什么这么改、不允许提交调试代码。它干得不错,我很满意。第二次我让它在另一个分支上做同样的事,它开始自由发挥,标题风格不一样,正文写成了 changelog,甚至把调试开关也写进了提交。后来我把这段提示词复制出来,每次粘贴,还是有问题:粘贴得太长它抓不住重点,粘贴得太短它又回到了自由发挥。
再比如代码评审。我的团队对安全性、异常处理、测试补充有固定的检查顺序。靠自然语言我每次都要把顺序重申一遍,偶尔忘了一个环节,评审结果差异就很明显。
这些场景有个共同特征:任务本身是稳定、可枚举、有固定流程的,只不过每次喂给模型时的“输入”不一样。这就是 Commands 应该出场的时机。
1.2 命令文件如何把“嘱咐”变成模型上下文的一部分
Claude Code 的 Commands 不是一个独立程序,也不是一段要被解释执行的脚本。它的本质是斜杠触发的 Markdown 提示词模板。你把一段写好的指令放在指定目录里,然后在对话里输入 /命令名,这个文件的内容会被当成指令注入到当次请求里,模型就能稳定地“看到”一套完整规则。
这个设计我觉得非常聪明。区别于其他工具把命令做成菜单项、插件函数,Claude Code 把最重要的“人味”留给了提示词本身。你需要约束的不是某个函数的参数,而是模型在过程中的理解和判断。一份写得好、写得具体的 Markdown 模板,比任何封装都直接。
你可以把它理解成给一个实习生写工作手册:手册不能规定他打字时手指怎么放,但能规定他一接到任务该先看什么、后做什么、产出物长什么样、遇到冲突找谁确认。Commands 就是这份手册的载体。
1.3 两个层面的收益:个人效率与团队一致性
配置命令后的第一个收益是个人效率。不需要再回忆上次的措辞,一条命令天然保持上次的品味。对我这种经常同时维护几个仓库的人来说,这套机制等于把我的操作习惯搬到了云端。
第二个收益是团队一致性。.claude/commands/ 是项目目录下的普通文件,完全可以提交进 Git。新人克隆仓库后,输入 / 就能看到项目里预设的命令,不需要去翻几十页的 Wiki。他用命令生成的东西,和资深同事用命令生成的东西,风格基本一致,这直接降低了评审成本。
我还在团队里做过一个实验:让两个同事分别用自然语言和命令去生成同一份发布说明,前者需要来回打磨 3 轮,后者基本一次通过。差异不在模型聪明不聪明,而在后者接收到的上下文更完整、更稳定。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Commands 的落地姿势:目录、模板与参数化设计
2.1 命令文件放哪里:项目级与用户级的分工
命令不是装一个插件就有的,而是要你自己建立目录结构。Claude Code 会从两个位置加载自定义命令:
- 项目级:
.claude/commands/,跟随仓库走,团队共享; - 用户级:
~/.claude/commands/,只对当前用户生效,适合放自己跟项目无关的习惯命令。
我常用的策略是:凡是跟仓库规范、技术栈、交付流程相关的命令放项目级;凡是“帮我整理 commit message”“帮我解释这段代码”这类通用动作放用户级。这样既不污染团队配置,又能最大化自己的效率。
文件命名有几个细节值得注意。
我最初把所有命令扁平堆在一个目录里,结果没到十个就乱成一团。后来发现它支持按子目录组织,也就是说文件放 .claude/commands/code/review.md,触发的命令就是 /code/review。我按照「动作领域 + 具体场景」的规则建了几个子目录,命令库瞬间清爽了。
命名上还有个容易踩的小坑:文件名里的连字符会原样出现在命令里。叫 do-commit.md,敲的时候就要打 /do-commit,手感和视觉都不如直接叫 commit.md 舒服。建议尽量少用连字符。
同级文件夹下如果存在同名文件,项目级命令会覆盖用户级命令。这个行为是合理的:团队通过项目级配置统一规范,个人的习惯命令可以作为兜底,但一旦仓库里出现了同名命令,就以项目的为准。
2.2 一个最小命令文件的骨架
命令文件内容分两部分:文件头部的 YAML 元信息和主体 Markdown 指令。YAML 里的 description 字段尤其重要,它决定了命令列表里显示什么,也会影响模型对你意图的理解。不要小看这段描述,写得含糊的命令很容易被在错误场景触发。
下面是我的一个典型项目级命令 /review 的简化版本:
markdown复制---
description: 按团队规范检查当前改动,输出结构化 Code Review 意见
---
你是一名严格的高级代码评审员。请基于当前分支相对主干分支的 diff 进行检查。
执行步骤:
1. 先运行 `git status` 和 `git diff --stat` 了解改动范围。
2. 获取具体 diff 内容,逐文件阅读。
3. 按如下顺序检查:
- 是否存在安全问题(注入、敏感信息、权限缺失);
- 是否存在异常被吞掉的情况;
- 新代码是否有对应测试,测试是否断言了关键行为;
- 是否引入明显的不必要复杂度。
4. 输出格式:
- 先给一个总体结论:通过 / 需修改;
- 再按“问题严重程度”列出条目,每条包含文件位置、问题描述、修改建议;
- 只报告真实存在的缺陷,不要为了凑数而挑刺。
正文里不需要写“请友善”这类情绪词,多写“执行步骤”和“输出格式”这种硬约束。一个命令是否好用,通常取决于你对输出格式的定义是否精准。模型需要在最后知道你要什么形态的结果,否则它默认给你长篇大论。
