用子代理和钩子落实 Claude Code 规则
文章介绍如何组合子代理、钩子和斜杠命令,将项目约定落实为具体工作流。重点包括限制审查代理权限、显式传递任务上下文,以及用脚本执行规则和统一审查输出。
完整中文译文
CLAUDE.md 告诉 Claude Code 该做什么。Subagent、hook 和 slash command 则让这些要求真正落地:让专注于特定任务的审查者只使用有限的工具,用 shell 脚本强制执行规则,而不是指望模型记住规则,再用一个词的命令触发你的工作流。
Subagent:.claude/agents/*.md
一个 Subagent 就是一个带有 YAML frontmatter 的 Markdown 文件,其中包含 name、description,以及可选的 tools 列表。description 告诉 Claude 何时委派任务;写上“Use PROACTIVELY after…”就能让它自动调用。每个 Subagent 都在独立的全新上下文中运行,因此不会挤占主对话的上下文,也看不到主对话:你需要把确切的文件和目标传给它。
最小权限:给代码审查者或安全审计者只开放 Read、Grep、Glob。只要它无法编辑,就无法擅自“修复”你没有要求它改动的内容。
每个 Subagent 只负责一项工作:planner、code-reviewer、test-writer、debugger、security-auditor、docs-writer 这几种角色就能满足大多数团队的需要。
约定输出格式:“按 MUST / SHOULD / NIT 分类报告,并附上 path:line”,比“审查代码”更有效。
在 Claude Code 中运行 /agents,即可列出、创建和编辑 Subagent。
Hook:模型无法跳过的规则
Hook 配置在 .claude/settings.json 的 "hooks" 字段下。每个事件(PreToolUse、PostToolUse、Stop 等)都可以通过 matcher 匹配工具名称(如 Bash、Edit|Write),并指定要执行的命令。Hook 通过 stdin 接收 JSON 格式的工具调用信息。退出码 2 会阻止操作,并把 stderr 中的消息反馈给 Claude;退出码 0 则允许操作。
针对 Bash 的 PreToolUse:阻止 rm -rf、git push --force、git reset --hard、curl | sh,以及向 main 推送代码。
针对 Read|Edit|Write 的 PreToolUse:拒绝访问 .env、*.pem 和 lockfile,同时允许访问 .env.example。
针对 Edit|Write 的 PostToolUse:对编辑过的文件运行 formatter。不要在这里阻止操作。
Stop:代码发生变化时运行测试;退出码 2 会让 Claude 继续工作。检查 stop_hook_active,避免陷入循环。
Hook 以你的用户权限运行。启用前务必阅读每个脚本,并将它们纳入版本控制。同时在同一个文件中配置 permissions.deny 条目,作为第二层防护。
Slash command:.claude/commands/*.md
每个文件都会变成一个 /filename 命令。用 $ARGUMENTS 获取命令后输入的内容,并在 frontmatter 中配置 description、argument-hint、allowed-tools 等字段。好的命令会把多个 Subagent 串起来:/feature = 规划 → 实现 → test-writer → 运行测试 → code-reviewer → 总结。
免费代码片段:直接复制使用
.claude/hooks/block-dangerous-bash.sh 复制
#!/usr/bin/env bash
# PreToolUse (matcher: Bash). Exit 2 = block; stderr is shown to Claude.
cmd=$(jq -r '.tool_input.command // ""')
deny=(
'rm -rf /' 'rm -rf ~' 'rm -rf \*' 'rm -rf \.' 'git push --force' 'git push -f' 'git reset --hard'
'git clean -fd' 'DROP DATABASE' 'DROP TABLE' 'TRUNCATE ' 'supabase db reset' 'prisma migrate reset'
'alembic downgrade base' 'chmod -R 777' 'mkfs' 'dd if=' ':(){'
)
for p in "${deny[@]}"; do
if printf '%s' "$cmd" | grep -qiF -- "${p//\\/}"; then
echo "Blocked by .claude/hooks/block-dangerous-bash.sh: '$p' is destructive. Explain why it's needed and ask the human to run it." >&2
exit 2
fi
done
if printf '%s' "$cmd" | grep -qE '(curl|wget)[^|]*\|\s*(ba|z)?sh'; then
echo "Blocked: piping a download into a shell. Download, inspect, then ask." >&2; exit 2
fi
if printf '%s' "$cmd" | grep -qE 'git push[^&;|]*\b(main|master)\b'; then
echo "Blocked: pushing to main/master. Push a branch and open a PR." >&2; exit 2
fi
exit 0
Claude Code 的 Subagent 存放在哪里?
项目级 Subagent 放在 .claude/agents/ 中,以带有 YAML frontmatter 的 Markdown 文件保存,包含 name、description 和可选的 tools。个人级 Subagent 放在 ~/.claude/agents/ 中。使用 /agents 管理它们。
如何在 Claude Code 中阻止危险命令?
在 .claude/settings.json 中添加一个 matcher 为 Bash 的 PreToolUse hook。脚本从 stdin 读取工具调用的 JSON,并以退出码 2 结束来阻止操作;stderr 中的内容会显示给 Claude。再添加相应的 permissions.deny 规则,作为第二层防护。
Claude Code hook 中的退出码 2 是什么意思?
退出码 2 会阻止操作(对于 PreToolUse),或让 Claude 继续工作(对于 Stop),并将 stderr 反馈给 Claude。退出码 0 表示允许。其他退出码表示不会阻止操作的错误,错误会显示给你。
如何让 Claude Code 在结束前运行测试?
使用 Stop hook,在代码发生变化时运行测试命令,并在测试失败时以退出码 2 结束。检查输入中的 stop_hook_active 字段,如果为 true,就以退出码 0 结束,避免 hook 无限循环。
Subagent 能看到主对话吗?
不能。每个 Subagent 都从一个全新的上下文窗口开始,只能拿到你交给它的任务,因此委派时要附上文件路径和目标。
想要整套工具?
Claude Code Kit($24)包含一份填空式 CLAUDE.md、6 个遵循最小权限原则的 Subagent、10 个 slash command、一份配置好权限和 hook 连接关系的 settings.json,以及 4 个经过测试的 hook(危险 Bash、敏感文件、lockfile、格式化、停止前运行测试)。
购买 Claude Code Kit · $24 购买 FastAPI Kit · $19
还没准备好购买完整套装?可以先从 One-File Agent Rules($9)开始,它提供一份适用于任何技术栈的通用 AGENTS.md;也可以通过电子邮件领取免费的 Starter AGENTS.md。
首发周优惠:在 Stripe 结账时使用优惠码 LAUNCH,购买任意套装可享七折,有效期至 2026 年 10 月 28 日。支持 14 天退款。
本文最初发布于 agentkitdrawer.com。
如需进一步处理,可以考虑屏蔽此人和/或举报滥用行为。