Claude Code Hooks、Skills 与斜杠命令:区别、选型和最小配置
需要复用审查步骤,先写 skill;需要每次工具调用前检查一个具体条件,配置 hook。斜杠命令是调用入口,自定义 commands 已并入 skills,技能既能由人调用,也能由 Claude 按需加载。
文章目录

选择 Claude Code 的 hooks、skills 和斜杠命令,可以先看你要完成什么:复用一套审查、写作或迁移方法,用 skill;在指定事件发生时执行检查,用 hook;控制启动时机或会话设置,用对应的 / 入口。 它们可以配合,但不是三个互斥的功能。
截至 2026 年 10 月 4 日,官方文档已明确:自定义 commands 合并到了 skills。.claude/commands/review-notes.md 和 .claude/skills/review-notes/SKILL.md 都能提供 /review-notes,旧命令文件仍可使用。Skill 默认允许用户直接调用,也允许 Claude 在相关任务中加载,因此“命令手动、技能自动”不能作为通用定义。官方 Skills 文档
本文先帮你选机制,再给出一套变更审查 skill 和一个保护 .env 文件的最小 hook。代码示例的 JSON、YAML 和 Python 分支做过离线检查;没有在 Claude Code 中安装、调用或验证模型输出。
先区分斜杠入口背后执行的是什么
输入 / 是一个操作入口,入口背后可能是固定控制逻辑,也可能是一套交给模型执行的指令。看到斜杠,不能直接判断是否调用模型、是否消耗 token,或是否修改文件。
| 类型 | 做什么 | 典型例子 | 怎样确认 |
|---|---|---|---|
| 内置控制命令 | 大多数直接执行固定逻辑,管理会话或设置 | /help、/permissions、/skills | 看当前会话菜单及官方命令参考 |
| 捆绑技能 | Claude Code 随产品提供的提示词流程,由 Claude 使用工具执行 | /code-review、/debug、/claude-api | 官方命令表在用途列标为 Skill;可用性受版本和功能影响 |
| 自定义技能或旧命令文件 | 你维护的说明、步骤和资料,通过 /name 或模型加载使用 | /review-notes | 看技能文件、调用控制字段和 /skills |
| 事件钩子(hook) | 运行时到达指定事件后,执行匹配的处理器 | PreToolUse 的文件检查 | 用 /hooks 检查事件、匹配条件和处理器 |
这是当前 命令参考 与 捆绑技能说明 的区分。不同版本、平台和已启用功能可能提供不同入口,先检查自己的会话菜单,再照例子操作。
例如,想让 Claude 协助 Claude API 项目,可以输入 /claude-api;已有 API 代码需要迁移时,可用 /claude-api migrate。它是捆绑技能,会加载对应语言的参考资料;代码导入 anthropic 或 @anthropic-ai/sdk 时也可能自动激活。它不是“任何 API 设置都由一个内置命令完成”,更不代表无需凭证或可以直接发布项目。Claude API 技能说明
按具体任务选机制,先保留最小流程
| 现在的需求 | 先选什么 | 选择理由与下一步 |
|---|---|---|
| 每次审查都想使用同一套证据和报告格式 | 自定义 skill | 把方法写进 SKILL.md,先用 /review-notes 文件路径 显式试用 |
| 发布检查需要你决定何时开始 | 手动调用的 skill | 设置 disable-model-invocation: true;把发布授权与检查步骤分别写清 |
每次 Edit 或 Write 前都要检查目标是否为 .env | PreToolUse command hook | 用事件和工具名定位,再在脚本里检查路径;下面提供可离线验证的例子 |
| 编辑完成后需要格式化 | PostToolUse hook | 动作已经发生,适合后处理;格式化失败不能撤销刚才的编辑 |
| 希望停止前由模型判断任务是否完成 | 支持该事件的 prompt 或 agent hook | 可以做判断,但要接受模型误判、成本与延迟,并设计无法完成时的退出方式 |
| Claude 缺少远程 PR、当前文档或浏览器访问 | 现有工具或 MCP 集成 | Skill 教方法,不能凭空提供外部访问权限 |
最后一种需求可以继续看 按工作流选择 Claude Code MCP,先判断缺的是仓库、文档、浏览器还是观测数据。本篇只处理技能与钩子的分工。

文件位置可以帮助维护,但不决定全部行为。一个 skill 也可以由人通过斜杠调用;hook 也可以调用模型做判断。真正影响选择的是:由谁启动、执行什么、失败时能改变哪一步。
写一个可手动调用的变更审查 skill
如果你反复粘贴同一份审查要求,先把它变成一个 skill,比同时增加命令包装、hook 和多个脚本更容易检查。下面的例子适合“阅读某个现有文件,输出风险和验证建议”,不负责执行修改或发布。
前提是已经安装并启动 Claude Code,项目中有待审查文件。入口文件名必须是 SKILL.md,区分大小写。以项目级技能为例,文件放在 .claude/skills/review-notes/SKILL.md,内容如下:
---
name: review-notes
description: 阅读指定代码文件,给出有位置和证据的变更审查意见
argument-hint: "[项目内文件路径]"
disable-model-invocation: true
---
审查用户指定的文件:$ARGUMENTS。
1. 如果没有参数,询问待审查文件路径,然后停止本次审查。
2. 读取指定文件及理解其行为所需的直接依赖;文件不存在时说明问题,不猜测内容。
3. 按 [检查清单](checklist.md) 检查行为。
4. 只报告能够指出文件位置和具体触发条件的问题;把不确定项标成待验证。
5. 输出“发现、依据、建议验证”三栏;未发现明确问题时说明检查范围。
6. 本流程只阅读和提出建议,不编辑文件、不提交、不发布。同目录的 checklist.md 内容为:
# 变更审查清单
- 输入为空或格式错误时,代码走向哪里?
- 外部调用失败后,是否向调用者保留可识别的错误?
- 状态更新是否可能发生在验证之前?
- 哪个具体输入或已有测试可以验证发现?文件中的 YAML frontmatter 必须从第一行的 --- 开始,字段名需准确。YAML 解析失败或字段拼写错误时,技能可能仍加载,但预期的调用控制不会生效;不要只靠菜单出现来判断配置正确。
$ARGUMENTS 会替换为技能名后的参数。例如项目中确实存在 src/auth.ts 时,在 Claude Code 提示框输入:
/review-notes src/auth.ts成功的信号是:/skills 中能够找到 review-notes,调用后 Claude 阅读目标文件,输出带位置或检查范围的意见。菜单出现只说明技能被发现,不能证明审查质量;再核对回答是否遵循清单、是否把猜测当成事实。没有参数、路径不存在或依赖无法读取时,应得到明确说明,而不是一份假审查报告。
新建技能目录后若没有被发现,可以使用 /reload-skills 重新扫描。当前文档说明技能目录的文件变化通常会在会话中被发现;如果会话开始时顶层 skills 目录尚不存在,则需要重新扫描。创建与配置技能、支持文件
辅助文件按需读取,让入口保持简洁;没有额外资料的小 skill 也可以成立。它的价值在于可复用,不取决于必须配几个脚本。旧 .claude/commands/review-notes.md 若已经能完成同样任务,不需要为了目录变化立即迁移;需要同目录清单、脚本或其他支持文件时,再采用技能目录更方便。
调用开关与工具权限要分开理解
上面的 disable-model-invocation: true 是调用控制:让你决定何时开始。正文中的“不编辑文件”是流程要求,两者都不能替代工具权限策略。
| 字段设置 | 用户能否输入 /name | Claude 能否按相关性调用 | 适合什么 |
|---|---|---|---|
| 两个字段都用默认值 | 能 | 能 | 可直接调用,也可按需加载的通用方法 |
disable-model-invocation: true | 能 | 不能 | 由人控制启动时机的流程 |
user-invocable: false | 不能 | 能 | 供模型加载的背景知识 |
user-invocable: false 不只是从菜单隐藏,直接输入 /name 也不会运行。disable-model-invocation: true 则同时避免把描述加入模型用于自动选择的技能列表。配置前先决定要限制哪一方,别把两个开关都设上却仍期待正常调用。调用控制说明
另一个容易误用的字段是 allowed-tools。例如 allowed-tools: Read Grep 预先批准列出的工具,不会把其他工具从可用列表移除。未列出的工具仍受正常权限设置约束;不能因此宣称整个技能已被强制限制为只读。若要移除工具,应理解 disallowed-tools;需要长期禁止某类工具,则使用权限设置中的 deny 规则。技能工具预授权
这些临时控制还有明确期限:技能正文在调用后会留在对话中,跨后续轮次保留;allowed-tools 的授权及 disallowed-tools 的工具移除会在下一条用户消息时清除。内容仍在,不代表授权也仍在。组织启用 allowManagedPermissionRulesOnly 时,受影响来源的 allowed-tools 还会被忽略,适用行为要求 v2.1.282 或更高版本,不应通过改配置绕开组织规则。内容生命周期、托管权限规则
Hook 的触发由事件决定,判断方式有五种
Hook 由事件、可选匹配条件和处理器组成。例如 PreToolUse 表示工具调用之前,Write|Edit 匹配工具名,command 指定执行脚本。配置生效且事件匹配时,运行时启动处理器,无需模型先决定“我要不要加载这个 skill”。
当前官方文档列出了五种处理器,支持的事件组合仍需查对应事件说明:
type | 如何执行 | 适合的工作 | 需要考虑什么 |
|---|---|---|---|
command | 执行 shell 命令,事件 JSON 通过标准输入传入 | 路径检查、固定规则、格式化 | 脚本依赖、退出码、超时与副作用 |
http | 将事件 JSON POST 到 URL | 由已有服务处理校验或记录 | 数据去向、服务可用性、响应协议 |
mcp_tool | 调用已配置 MCP 服务器的工具 | 使用现有集成执行事件动作 | 服务器与工具权限、事件支持范围 |
prompt | 单轮模型评估 | 根据事件输入作有限判断 | 模型误判、token 成本与等待时间 |
agent | 多轮验证,可使用工具 | 需要读文件或执行检查的验证 | 实验性功能、成本、时限及执行范围 |
因此,事件触发确定,不等于判断结果确定。一个纯脚本可以按明确条件稳定返回结果;prompt 和 agent hook 仍包含模型判断。官方支持它们,不能笼统说“hooks 不允许主观判断”,也不能把自动触发解释成质量保证。Hook 工作方式、Prompt hooks
例如 Stop hook 判断任务未完成时,可以阻止停止、让 Claude 继续工作。但如果成功条件永远无法满足,就可能反复检查和继续执行。使用判断型 hook 前,应定义可检查的条件、超时和无法完成时的处理方式;需要你决定什么时候开始的复杂审查,仍可保留为手动 skill。
配置一个仅保护 .env 写入的 hook
下面的例子只检查 Claude Code 的 Write 和 Edit 工具,阻止写入文件名为 .env 或以 .env. 开头的文件,包含 .env.example。它不会读取文件内容,也不会发送网络请求。需要 macOS 或 Linux、可用的 Python 3,以及一个专门用于试验的项目。
将下面脚本保存为项目根目录下的 scripts/guard-env.py。它通过 Python 标准库读取输入,不需要安装第三方包,也不需要可执行权限,因为配置会显式调用 python3。
import json
import sys
from pathlib import PurePosixPath
def block(reason):
print(reason, file=sys.stderr)
return 2
def main():
try:
event = json.load(sys.stdin)
except (json.JSONDecodeError, UnicodeDecodeError):
return block("无法解析 hook 输入;请检查事件 JSON。")
if not isinstance(event, dict):
return block("hook 输入必须是 JSON 对象。")
if event.get("hook_event_name") != "PreToolUse":
return 0
if event.get("tool_name") not in ("Write", "Edit"):
return 0
tool_input = event.get("tool_input")
if not isinstance(tool_input, dict):
return block("Write/Edit 输入缺少 tool_input 对象。")
file_path = tool_input.get("file_path")
if not isinstance(file_path, str) or not file_path:
return block("Write/Edit 输入缺少有效的 file_path。")
name = PurePosixPath(file_path.replace("\\", "/")).name
if name == ".env" or name.startswith(".env."):
return block("已阻止 Write/Edit 修改环境文件,请由维护者处理。")
return 0
if __name__ == "__main__":
sys.exit(main())再把下面 hooks 配置合并进该测试项目的 .claude/settings.json。如果已有其他设置或 hook,要合并对应字段和数组,不要用这份对象覆盖整个文件。CLAUDE_PROJECT_DIR 由 Claude Code 提供;路径加引号可处理项目名中的空格。
{
"hooks": {
"PreToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "python3 \"$CLAUDE_PROJECT_DIR/scripts/guard-env.py\"",
"timeout": 10
}
]
}
]
}
}个人配置 ~/.claude/settings.json 会影响多个项目,项目配置 .claude/settings.json 用于共享,本地项目配置 .claude/settings.local.json 用于个人设置。先选择范围再配置;/hooks 可查看已注册的事件与处理器,直接编辑配置后文件监听器通常会自动加载,未检测到变化时再重启会话。配置位置
先离线检查,再确认实际触发
在脚本所在项目根目录执行下面的输入模拟,不会创建或修改 .env:
printf '%s\n' '{"hook_event_name":"PreToolUse","tool_name":"Write","tool_input":{"file_path":"/tmp/hook-demo/.env","content":"demo"}}' | python3 scripts/guard-env.py
printf '退出码:%s\n' "$?"预期标准错误显示阻止原因,退出码为 2。再把路径换成 /tmp/hook-demo/notes.txt 重试,预期没有输出,退出码为 0。本次离线检查还覆盖了 Windows 风格的 .env.local 路径、非目标工具、错误事件、缺失路径和无效 JSON;结果符合脚本定义。它只证明解析和分支行为,不证明 Claude Code 已发现配置或真正触发了事件。
实际接入时,在测试项目的 /hooks 中确认 PreToolUse、Write|Edit 和脚本命令都已注册,再用无敏感内容的测试路径让 Claude 尝试 Write 或 Edit。成功判据是环境文件写入在发生前被阻止,并显示原因;普通文件进入正常权限流程。用 Bash 写文件不会触发这里的 Write|Edit 匹配,不能用那个结果判断此示例失效。
这个例子是窄规则,不是完整文件安全边界。它不覆盖 Bash、PowerShell、其他工具或文件名别名,也不能保证其他处理器没有副作用。需要更广的访问约束时,结合工具权限和操作系统隔离处理,别把一个文件名检查扩称为防泄露系统。PreToolUse 输入和决策
退出码的含义随事件变化
脚本使用一套简单协议:不输出 JSON,靠退出码和标准错误反馈。对这个 PreToolUse 例子,0 表示没有异议,不等于批准工具调用;2 会阻止这次工具调用,标准错误给出原因。
不能把这个规则直接套在所有事件上:
| 事件 | 返回 2 会怎样 |
|---|---|
PreToolUse | 工具尚未执行,阻止工具调用 |
PostToolUse | 将标准错误反馈给 Claude;工具已经执行,无法撤销 |
Stop | 阻止停止,让对话继续 |
SessionStart | 向用户显示标准错误,会话仍继续 |
其他非零退出码通常是非阻断错误,但还要看结构化 JSON 是否有效,以及事件自身的例外。例如 WorktreeCreate 对任何非零退出码都按失败处理。需要 allow、ask 等结构化决策时,应改用对应事件的 JSON 输出协议,不要混用两套协议后凭退出码猜结果。退出码参考及事件表
组合时分清职责,也分清什么时候失效
变更审查和文件保护可以一起使用:你输入 /review-notes src/auth.ts 启动审查,skill 提供方法;项目级 hook 在任何匹配的写入前检查 .env 文件名。审查建议需要解释证据,路径规则只需返回通过或阻止,职责清楚就容易定位问题。

同一事件匹配的 hooks 会并行执行,所有处理器完成后再合并结果。一个 hook 拒绝动作,不会阻止另一个 hook 先完成日志记录或其他副作用;PreToolUse 权限决策按最严格结果合并。异步处理器完成时也不能追溯阻止已经执行的动作。多个 hooks 的结果合并
还有三个容易混淆的期限:
- 技能正文:调用后进入对话,跨轮次保留;上下文压缩时仍受保留预算影响。
- 技能工具授权或移除:
allowed-tools和disallowed-tools在下一条用户消息时清除。 - 技能 frontmatter 中的 hooks:调用技能时注册,通常保留到会话结束,不会在该技能当前轮次结束时自动卸载。
once: true可在首次成功执行后移除;阻断、失败或超时不算成功。子代理自己的 hooks 则只在该子代理运行期间有效。
这些是不同机制,不能用“skill 已结束”推断其 hook 已经停止。上面的 .env 例子放在项目设置中,不属于技能临时授权。技能与子代理中的 hooks
维护时留下可读的说明:谁启动、检查什么、失败时怎么处理、允许什么副作用、什么时候删除。若一个斜杠入口只重复调用同一个 skill,通常没必要再维护一份提示词;若一个 hook 越来越像长篇审查方法,考虑把方法保留在 skill,hook 只负责需要自动发生的事件动作。
常见问题
自定义 slash commands 还要迁移吗?
不必全部迁移。官方明确旧 .claude/commands/*.md 继续工作,并已与 skills 合并。需要同目录支持文件或更完整的技能组织时,再用 .claude/skills/review-notes/SKILL.md;入口文件名必须准确。官方兼容说明
Skills 只能由 Claude 自动触发吗?
不是。默认既可由用户输入 /name,也可由 Claude 按需加载。disable-model-invocation: true 只保留用户调用;user-invocable: false 只保留模型调用,直接输入也不会运行。调用控制
allowed-tools: Read 能保证 skill 只读吗?
不能。它预先批准 Read,不移除其他工具。要区分技能正文中的行为要求、临时工具移除和长期权限 deny 规则,不能把预授权当作工具白名单。工具权限说明
Hooks 能保证每次判断都正确吗?
不能。事件匹配控制的是何时执行,模型型处理器仍可能误判,脚本也可能规则不完整。能明确检查的条件优先用简单脚本;需要模型判断时,为失败、超时和无法满足的条件设计处理方式。处理器类型
Hook 出错后,刚才的文件修改会撤销吗?
不会因为 PostToolUse 出错就自动撤销。要在工具执行前阻止,应使用支持该决策的 PreToolUse;工具已经运行时,后置 hook 只能按该事件的协议反馈或控制后续流程。事件与退出码
先把一个具体任务做通:可复用步骤成为 skill,启动时机由合适的调用入口控制,事件规则由 hook 执行。配置发现、脚本分支和实际触发分别检查,才知道问题出在入口、方法、权限还是事件上。
参考来源4
本文引用的外部页面,按正文出现顺序排列。最后更新于 2026年10月5日。
参考来源4
本文引用的外部页面,按正文出现顺序排列。最后更新于 2026年10月5日。





