让 Claude Code按规则自动工作
前六天你一直在"对话式"使用 Claude Code——今天你将学会编程化它。
用 Hooks 在每次工具调用前后自动执行安全检查或日志记录,
用 Skills 把十步操作封装成一个 /command,
用 MCP 让 Claude 直接查数据库、读 Issue、调外部 API。
Claude Code 从此不只是助手——它是可编排的自动化引擎。
思维导图
Hooks — 在工具调用前后插入自动化
Hooks 是 Claude Code 的事件系统—— 你可以在特定时机(工具调用前、调用后、会话开始、会话结束等)自动执行脚本。 最常见的用途:阻止危险命令、记录操作日志、注入安全检查。
Hook 事件类型
| 事件 | 触发时机 | 典型用途 |
|---|---|---|
| PreToolUse | 工具执行之前 | 阻止危险命令、安全检查、权限验证 |
| PostToolUse | 工具执行之后 | 操作日志、结果审计、通知 |
| Notification | 通知触发时 | 发送到 Slack / 邮件 / Webhook |
| Stop | Claude 完成回复时 | 自动验证、运行 lint |
| SessionStart | 会话开始时 | 环境检查、初始化 |
| UserPromptSubmit | 用户提交 prompt 前 | 输入过滤、prompt 增强 |
配置格式
Hooks 在 settings.json 中配置,三层嵌套:事件 → 匹配器 → 处理器。
// .claude/settings.json 或 .claude/settings.local.json { "hooks": { "PreToolUse": [ { "matcher": "Bash", // 匹配 Bash 工具 "hooks": [ { "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/validate.sh" } ] } ] } }
实战: 阻止危险的 rm -rf 命令
#!/bin/bash — .claude/hooks/block-rm.sh # 从 stdin 读取 JSON 输入 COMMAND=$(jq -r '.tool_input.command' < /dev/stdin) if echo "$COMMAND" | grep -q 'rm -rf'; then # 返回 JSON 阻止执行 jq -n '{ hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "deny", permissionDecisionReason: "rm -rf 已被 Hook 策略阻止" } }' else # exit 0 + 无输出 = 允许继续 exit 0 fi
Hook 处理器类型
| 类型 | 说明 | 使用场景 |
|---|---|---|
| command | 执行本地脚本,JSON 通过 stdin 传入 | 安全检查、日志记录、自定义验证 |
| http | 发送 POST 请求到 URL | Webhook 通知、外部审计 API |
| prompt | 让 Claude 做 yes/no 判断 | 需要 AI 判断的安全策略 |
| mcp_tool | 调用 MCP 服务器上的工具 | 调用外部安全扫描、审计系统 |
Hook 的输入与输出
Matcher 匹配规则
Matcher 决定 hook 在哪些工具上触发。"Bash" 精确匹配 Bash 工具;"mcp__.*" 用正则匹配所有 MCP 工具;留空或写 "*" 匹配所有工具。还可以用 "if" 字段做更精细的过滤——比如 "if": "Bash(rm *)" 只在 Bash 执行 rm 命令时触发。
Hook 不能被绕过
一旦在 settings.json 中配置了 hook,它会在每次匹配的工具调用时自动执行——Claude 无法跳过它。这就是为什么 hook 是安全策略的最佳载体:把"不允许删除生产数据库"编码为 hook,比口头告诉 Claude 可靠一万倍。用 /hooks 命令可以查看当前所有活跃的 hooks。
Skills — 把复杂工作流封装成一句命令
Skills(前身是 Custom Commands)让你把多步操作封装成 /command。
一个 Markdown 文件就是一个 Skill——
定义 Claude 应该做什么、能用哪些工具、接受什么参数。
在 / 菜单中选择,一键执行。
创建你的第一个 Skill
# 创建 Skill 目录和文件 $ mkdir -p .claude/skills/fix-issue $ cat > .claude/skills/fix-issue/SKILL.md << 'EOF' --- name: fix-issue description: 从 GitHub Issue 获取描述并修复 argument-hint: [issue-number] arguments: [issue_number] allowed-tools: Read Grep Glob Bash(gh *) Edit --- ## 上下文 - Issue 详情: !`gh issue view $issue_number` ## 任务 1. 阅读上面的 Issue 描述,理解要修复的问题 2. 用 Grep 和 Read 在代码中定位相关文件 3. 实现修复 4. 运行测试确认修复正确 5. 提交代码并在 commit message 中关联 Issue #$issue_number EOF # 使用: 在 Claude Code 中输入 > /fix-issue 42
Skill 文件结构
| Frontmatter 字段 | 说明 | 示例 |
|---|---|---|
| name | 命令名(小写、连字符) | fix-issue |
| description | 功能描述,显示在 / 菜单 | 从 GitHub Issue 修复 Bug |
| arguments | 命名参数列表 | [issue_number, priority] |
| allowed-tools | 免确认工具白名单 | Read Grep Bash(npm *) |
| model | 指定模型 | claude-opus-4-6 |
| context | 设为 fork 在子 agent 中运行 | fork |
动态上下文注入
用 !`command` 语法在 Skill 加载时自动执行 shell 命令,将结果注入 Claude 的上下文:
# .claude/skills/pr-review/SKILL.md --- name: pr-review description: 审查当前分支的 PR context: fork agent: Explore allowed-tools: Bash(gh *) --- ## PR 上下文 - PR diff: !`gh pr diff` - PR 评论: !`gh pr view --comments` - 变更文件: !`gh pr diff --name-only` ## 审查要求 1. 检查安全漏洞 (OWASP Top 10) 2. 检查性能反模式 3. 检查代码风格一致性 4. 给出改进建议
Skill 存放位置
.claude/skills/ — 项目级
放在项目的 .claude/skills/ 目录下,通过 Git 与团队共享。团队成员 clone 仓库后自动获得所有 Skills。适合团队统一的工作流,比如 /deploy、/fix-issue、/pr-review。
~/.claude/skills/ — 个人级
放在用户主目录下,在所有项目中可用。适合个人习惯的通用工具,比如 /explain(解释代码)、/refactor(重构选中代码)、/daily-standup(生成日报)。
MCP 服务器 — 连接外部工具与数据源
MCP(Model Context Protocol)让 Claude Code突破本地文件系统的边界—— 直接查询数据库、读取 Issue Tracker、调用 Sentry 错误监控、 甚至连接 Figma 获取设计稿。所有交互使用自然语言,不需要你写胶水代码。
添加 MCP 服务器
# 方式 1: HTTP 远程服务器 $ claude mcp add --transport http github \ https://api.githubcopilot.com/mcp/ \ --header "Authorization: Bearer $GITHUB_TOKEN" # 方式 2: 本地 stdio 服务器 $ claude mcp add --transport stdio database \ -- npx -y @bytebase/dbhub \ --dsn "postgresql://readonly:pass@host:5432/mydb" # 方式 3: 带 OAuth 认证的服务 $ claude mcp add --transport http sentry \ https://mcp.sentry.dev/mcp # 然后在 Claude Code 中用 /mcp 完成 OAuth 登录 # 查看已配置的服务器 $ claude mcp list # 在 Claude Code 中检查状态 > /mcp
.mcp.json 配置文件
// 项目根目录 .mcp.json — 团队共享 { "mcpServers": { "database": { "type": "stdio", "command": "npx", "args": ["-y", "@bytebase/dbhub"], "env": { "DB_DSN": "${DATABASE_URL}" // 支持环境变量展开 } }, "github": { "type": "http", "url": "https://api.githubcopilot.com/mcp/", "headers": { "Authorization": "Bearer ${GITHUB_TOKEN}" } } } }
MCP 使用场景
| 场景 | MCP 服务器 | 你可以说 |
|---|---|---|
| 查数据库 | @bytebase/dbhub | "users 表里有多少活跃用户?" |
| 错误监控 | Sentry MCP | "最近 24 小时有哪些新错误?" |
| Issue 管理 | GitHub / Linear MCP | "把 Issue #42 的描述读给我听" |
| 设计稿 | Figma MCP | "按照 Figma 中的设计实现这个组件" |
| 自定义 API | 自建 MCP 服务器 | "调用内部 API 获取用户配置" |
Scope 决定谁能用
MCP 有三个 scope:--scope local(只有你能用,存 ~/.claude.json)、--scope project(团队共享,存 .mcp.json)、--scope user(你所有项目,存 ~/.claude.json)。团队共享的数据库连接放 project scope,个人 API Key 放 local scope。
环境变量保护敏感信息
.mcp.json 中使用 ${VAR} 或 ${VAR:-default} 引用环境变量。永远不要把 API Key 明文写在 .mcp.json 里——它可能被 commit 到 Git。把敏感信息放在 .env 或系统环境变量中,让 .mcp.json 只包含变量引用。
配置层级与安全策略
理解 Claude Code 的配置层级是正确使用 Hooks/Skills/MCP 的前提—— 在哪里配置决定了谁受影响、能否被覆盖。
配置优先级(从高到低)
| 层级 | 位置 | 影响范围 | 是否共享 |
|---|---|---|---|
| Managed | 系统级 | 所有用户、不可覆盖 | IT 部署 |
| Local | .claude/settings.local.json | 你 + 此项目 | 否 (gitignore) |
| Project | .claude/settings.json | 团队 + 此项目 | 是 (git) |
| User | ~/.claude/settings.json | 你 + 所有项目 | 否 |
实战: 团队安全策略编排
// .claude/settings.json — 团队共享安全策略 { "hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [{ "type": "command", "if": "Bash(rm *)", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/block-rm.sh" }] }, { "matcher": "Write", "hooks": [{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/audit-write.sh" }] } ], "Stop": [ { "hooks": [{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/auto-lint.sh" }] } ] }, "permissions": { "allow": ["Bash(npm run *)", "Bash(npx vitest *)"] } }
什么该放哪里
团队安全策略 → .claude/settings.json(所有人必须遵守的规则)。个人 API Key / 调试用 Hook → .claude/settings.local.json(不进版本控制)。跨项目的通用工具 → ~/.claude/settings.json(个人全局设置)。分清楚这三层,就不会"配了但不生效"或"敏感信息被提交"。
编码策略 > 口头约定
"不要删除生产数据"写在 wiki 里没人看。写成 Hook 后,每次 Claude 执行 rm 命令都会被自动拦截。"提交前必须跑 lint"写在 README 里经常忘。写成 Stop Hook 后,Claude 每次完成任务都会自动检查。把规则变成代码,让自动化执行你的意志。
工作流编排 — 把一切串起来
Hooks、Skills 和 MCP 不是孤立的—— 它们组合在一起就是一个可编程的自动化 pipeline。
组合示例: 自动化 Bug 修复流水线
# Skill: /fix-sentry — 从 Sentry 获取错误并自动修复 --- name: fix-sentry description: 从 Sentry 获取最新错误并修复 allowed-tools: Read Grep Glob Edit Bash(npm test *) --- ## Sentry 上下文 最新错误列表: !`claude mcp call sentry get_issues --limit 5` ## 工作流 1. 阅读错误详情,找到堆栈中的源文件和行号 2. Read 对应源文件,分析根因 3. Edit 修复代码 4. 运行测试确认修复 5. 为此 Bug 写一个回归测试 6. 提交代码,commit message 关联 Sentry Issue ID # 配合 Hook: 修复后自动通知 Slack # settings.json 中添加 PostToolUse Hook # 当 Bash(git commit) 执行成功后,发送 Webhook 到 Slack
更多编排模式
Skill + MCP
/deploy staging Skill 内部调用 MCP 查数据库确认迁移状态,然后执行部署脚本。把"部署前检查清单"自动化。
Hook + Skill
PreToolUse Hook 在每次 Write 时检查文件是否在保护列表里。Stop Hook 在 Claude 完成任务后自动调用 /pr-review Skill 做一轮自审。
SessionStart + MCP
SessionStart Hook 自动从 Issue Tracker 拉取今日待办,Claude 会话一开始就知道你今天要做什么——"早上好,你有 3 个待处理 Issue"。
动手练习
今天的练习会修改你项目的 .claude/ 目录。
如果你还没有这个目录,Claude Code 已经在首次运行时创建过了。
Lab 1 — 创建一个 PreToolUse Hook
写一个 Hook,在 Claude 执行任何 Bash 命令时记录日志。
# 创建 hook 脚本 $ mkdir -p .claude/hooks $ cat > .claude/hooks/log-bash.sh << 'EOF' #!/bin/bash INPUT=$(cat /dev/stdin) COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // "unknown"') TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') echo "$TIMESTAMP | BASH | $COMMAND" >> .claude/hooks/audit.log EOF $ chmod +x .claude/hooks/log-bash.sh # 在 settings.local.json 中配置 # 让 Claude 帮你配: > 在 .claude/settings.local.json 中添加一个 PreToolUse Hook, > 匹配 Bash 工具,执行 .claude/hooks/log-bash.sh # 然后执行一些操作,检查日志 > 运行 ls 命令 $ cat .claude/hooks/audit.log
Lab 2 — 创建一个自定义 Skill
创建一个 /explain 命令,让 Claude 用大白话解释一个函数。
# 创建 Skill $ mkdir -p .claude/skills/explain $ cat > .claude/skills/explain/SKILL.md << 'EOF' --- name: explain description: 用大白话解释一个函数或文件 argument-hint: [file-path] arguments: [path] allowed-tools: Read Grep --- ## 任务 读取 $path 文件的内容,然后: 1. 用一句话总结这个文件/函数的目的 2. 列出输入和输出 3. 解释核心逻辑(用非技术人员能理解的语言) 4. 指出可能的坑(边界条件、隐含假设) EOF # 使用 > /explain src/utils/parseCSV.ts
Lab 3 — 配置 MCP 服务器 (可选)
如果你有 GitHub Token,可以尝试添加 GitHub MCP 服务器。
# 添加 GitHub MCP (需要 GITHUB_TOKEN 环境变量) $ claude mcp add --transport http github \ https://api.githubcopilot.com/mcp/ \ --header "Authorization: Bearer $GITHUB_TOKEN" # 检查连接状态 > /mcp # 如果连接成功,尝试: > 列出这个仓库最近的 5 个 Issue > 读一下 Issue #1 的内容
Lab 4 — 查看现有配置
# 用 /hooks 查看所有活跃的 hooks > /hooks # 用 /mcp 查看所有 MCP 服务器状态 > /mcp # 让 Claude 解释你的配置 > 读一下 .claude/settings.json 和 .claude/settings.local.json > 告诉我当前配置了哪些 hook 和权限
常见疑问
Q1 Hook 脚本报错了怎么办?会影响 Claude 的操作吗? +
看 exit code。exit 2 = 阻止操作,stderr 内容会展示给 Claude;exit 0 = 正常,stdout 的 JSON 会被解析;其他 exit code = 非阻塞错误,操作继续但 Claude 会看到警告。如果你的脚本意外 crash(比如 jq 没安装),它的 exit code 通常不是 0 也不是 2,所以操作会继续但你会在日志中看到错误。建议先在终端手动测试 hook 脚本,确保它能正确解析 JSON 输入。
Q2 Skills 和老版的 Custom Commands 有什么区别? +
Skills 是 Custom Commands 的现代替代品。核心区别:Skills 支持完整的 frontmatter 配置(指定 model、context、agent 等),支持 !`shell` 动态上下文注入,支持 context: fork 在独立子 agent 中运行避免污染主会话。老版 .claude/commands/ 目录仍然可用,但新功能都在 Skills 上。建议迁移到 .claude/skills/——文件格式几乎一样,只是目录不同。
Q3 MCP 服务器安全吗?Claude 能直接操作我的数据库? +
MCP 服务器的安全性取决于你怎么配置它。最佳实践:(1) 数据库连接用只读 (readonly) 账号——Claude 能查询但不能修改数据。(2) API Token 的权限要最小化。(3) 敏感信息放环境变量而不是明文写在 .mcp.json 里。(4) 用 --scope local 避免团队成员意外使用你的凭证。Claude 调用 MCP 工具时也会经过正常的权限确认流程,你可以看到它要调用什么工具、传什么参数。
Q4 Hook 会拖慢 Claude 的执行速度吗? +
会增加少量延迟,但通常不明显。Command hook 的默认超时是 600 秒,但大部分 hook 脚本在毫秒级完成。如果你的 hook 需要调用外部 API,设置合理的 timeout 避免卡住。HTTP hook 的延迟取决于网络。Prompt hook 默认 30 秒超时。如果 hook 超时,它会被 kill,操作继续执行。建议:安全关键的 hook 保持轻量——做一个快速检查就好,不要在 hook 里做复杂计算。
Q5 我能让 Skill 自动触发吗?还是必须手动 /command? +
默认情况下 Skill 既可以手动调用也可以被 Claude 自动调用——如果你的 description 和 when_to_use 写得足够清晰,Claude 在合适的场景会主动调用它。如果你只想手动触发,设置 disable-model-invocation: true——Claude 不会自己调用但你仍可以用 /command 触发。反过来,设置 user-invocable: false 则只有 Claude 能调用,不出现在 / 菜单中——适合作为其他工作流的"内部组件"。
复盘问题
- PreToolUse Hook 的输入和输出格式是什么?exit code 0 和 exit code 2 分别代表什么?
- Skill 的
!`command`语法有什么作用?为什么它比在 Skill 里让 Claude 运行命令更好? - MCP 服务器的三个 scope 分别存放在哪里?什么类型的配置应该放在哪个 scope?
- 配置优先级从高到低是什么?如果 project settings 和 local settings 有冲突,谁赢?
- 描述一个结合 Hook + Skill + MCP 的工作流编排场景,说明每个组件各自负责什么。
今日检查清单
- 理解 Hook 事件类型(PreToolUse / PostToolUse / Stop / SessionStart 等)
- 成功创建并测试了至少一个 Hook(日志记录或命令阻止)
- 创建了至少一个自定义 Skill,理解 SKILL.md 的 frontmatter 和 !`command` 语法
- 了解 MCP 服务器的概念和配置方式(即使没有实际配置)
- 掌握配置层级优先级(Managed > Local > Project > User)
- 能区分什么配置该放 settings.json vs settings.local.json
- 理解"编码策略 > 口头约定"的自动化哲学
推荐阅读
Claude Code Hooks 官方文档
完整的 Hook 事件列表、输入输出格式、matcher 语法和示例。包含高级用法如 HTTP Hooks 和 MCP Tool Hooks——今天只介绍了最常用的 Command Hook。
Skills 官方文档
Skill frontmatter 字段完整参考、context: fork 的子 agent 运行模式、与 Agent SDK 的集成方式。还有大量社区 Skill 示例可以直接复用。
MCP 服务器生态
已有大量可用的 MCP 服务器:GitHub、Sentry、Notion、Figma、PostgreSQL、MongoDB、Slack 等。在配置之前先看看有没有现成的——大概率有人已经做好了。
Day 08 预告
大型代码库 — 多文件重构 · 代码迁移 · 架构重组
前七天你学会了在单文件范围内高效使用 Claude Code——明天进入深水区。你将学习如何让 Claude 进行跨文件重构(重命名一个被 200 个文件引用的函数)、代码迁移(从 JavaScript 迁移到 TypeScript)、架构重组(拆分巨型模块)。掌握 Agent 子任务分发和 Explore 模式,在大型代码库中保持精准控制。