Claude Code 扩展指南:Skills、Subagents、Hooks 与 MCP

Posted on Mon 28 September 2026 in AI 编程 • Sucre Liu

别一上来就配全家桶

见过太多人在第一周就把 skills、subagents、hooks、MCP 全配一遍,结果哪个都没用明白,还把上下文塞得又贵又乱。

扩展层的每个东西都解决一个具体问题。先有痛点,再加配置。 官方给了一张"信号 → 动作"的对照表,我按经验重排了一下:

你观察到的信号 该加的东西
同一个约定它错第二次 写进 CLAUDE.md
同一段开场白你打第三次 存成一个 skill
同一套多步流程你贴第三次 存成一个 skill
你总在搬某个浏览器里的数据 接一个 MCP server
一个侧任务刷屏、输出你也不会再看 丢给 subagent
有件事必须每次发生、不能靠它自觉 写一个 hook
第二个仓库要同一套配置 打包成 plugin

五个机制,各管一段

  • CLAUDE.md:常驻上下文,每次会话都加载。
  • Skill:按需加载的知识或工作流,可以 /<name> 手动触发,也可以由它自动匹配。
  • Subagent:独立上下文里的工作者,干完只回一份摘要。
  • Hook:生命周期事件触发的脚本,确定性执行。
  • MCP:连接外部服务,给它目的明确的工具。
  • Plugin:把上面这些打包分发。

它们的上下文成本差异巨大,这是选型时最该看的一栏:

机制 何时加载 成本
CLAUDE.md 会话开始 每次请求都占
Skill 开始时只加载描述,用到才加载全文 低(仅描述常驻)
MCP 开始时只加载工具名,用到才拉 schema 低
Subagent 被派生时 与主会话隔离
Hook 触发时 零(除非它返回内容)

一句话总结选型:常驻的用 CLAUDE.md,按需的用 skill,隔离的用 subagent,必须发生的用 hook,连外部的用 MCP。

Skill:最灵活的一种

Skill 本质是一个带 frontmatter 的 markdown 文件,放在 .claude/skills/<name>/SKILL.md:

---
name: deploy
description: 把当前分支发布到预发环境。当用户要求部署或发布时使用。
---

# 部署流程

1. 运行 `npm run build`,失败即停止。
2. 运行 `npm test`,失败即停止。
3. 执行 `./deploy.sh --env staging`。
4. 输出发布版本号与访问地址。

两种用法:

  • 知识型:像 API 规范、团队约定这种参考资料,它需要时会自己加载;
  • 动作型:像 /deploy 这种有副作用的流程,由你手动触发。

有个实用开关:给有副作用的 skill 设 disable-model-invocation: true,它就只在你手动打 /deploy 时才出现,不会被模型自作主张调用,平时也不占上下文。对"会改生产"的流程,这个开关建议默认打开。

Subagent:买的是上下文隔离

Subagent 和 skill 最容易搞混。区别在于:

  • Skill 是加载进你当前上下文的可复用内容;
  • Subagent 有自己独立的上下文窗口,干完只回一份摘要。

所以 subagent 的真正价值不是"更专业",而是把中间过程挡在主会话之外。一个"读几十个文件找结论"的研究任务,用 subagent 做,你的主会话只收到结论,不会被几十个文件读操作撑爆。

自定义 subagent 就是 .claude/agents/ 下的一个 markdown:

---
name: refactorer
description: 对大量文件做机械式重构
isolation: worktree
tools: Read, Edit, Bash
---

对每个受影响的文件应用指定重构,然后运行测试并汇报结果。

注意 isolation: worktree——这个 subagent 会在自己的 git worktree 里跑,并行改文件也不会和你冲突。适合"批量、互相独立"的改动。

另外两个内置 subagent 值得知道:Explore(快、只读、专门找代码)和 Plan(只读、出方案)。它们会跳过主会话的自动记忆和一些上下文,所以更轻。让它们去"找找 X 在哪",比你自己在主会话里翻要省得多。

Hook:唯一能说"必须"的机制

前面反复强调过:CLAUDE.md 里的"不要做 X"是请求,不是保证。要确定性,用 hook。

hook 定义在 settings.json 里,绑定到生命周期事件。常见事件:

事件 时机
SessionStart 会话开始/恢复
UserPromptSubmit 你提交提示、模型处理前
PreToolUse 工具调用前,可拦截
PostToolUse 工具调用成功后
Stop 它结束这一轮回复时
PreCompact / PostCompact 上下文压缩前后

一个"每次编辑后自动格式化"的例子,注册 PostToolUse、匹配 Edit|Write:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write" }
        ]
      }
    ]
  }
}

hook 通过 stdin 收到 JSON 事件数据,用退出码和 stdout/stderr 回话:

  • exit 0:没意见,继续正常流程;
  • exit 2:拦截,stderr 作为反馈给模型;
  • exit 0 + stdout 输出 JSON:更精细的控制(放行/拒绝/转人工)。

还有两点值得注意:多个 hook 命中同一事件时会并行全部执行,一个 deny 不会阻止兄弟 hook 执行;以及 hook 默认不产生上下文成本,除非它把输出写回对话——一个 PostToolUse 跑 linter,结果会作为文本交给模型读,这既是有用,也是成本。

MCP:给它外部工具

MCP(Model Context Protocol)把外部系统变成它可调用的一组工具:查数据库、发消息、控浏览器都行。用 CLI 添加,比手改配置安全:

claude mcp add <name> --url <remote-url>

加完用 /mcp 看连接状态。几个经验:

  • MCP 的工具定义默认延迟加载,未使用时只占很少上下文,所以"多接几个"没有想象中贵;
  • MCP 负责连接和数据,skill 负责怎么用好这些工具——两者常常搭配:MCP 连上数据库,skill 记录表结构和查询范式;
  • 凭证优先走服务本身的 OAuth,别把 key 写进配置。

组合起来长什么样

真实配置往往是叠加的:

  • CLAUDE.md 写项目约定;
  • 一个 /deploy skill 固化发布流程;
  • 一个数据库 MCP 提供查询能力;
  • 一个 PostToolUse hook 每次编辑后跑 lint;
  • 研究类任务丢给 subagent。

按前面的"信号表"逐步长出来,比一次性设计更靠谱。每加一样,问一句:它解决的是常驻、按需、隔离还是确定性? 答不上来,就先别加。

小结

  • 扩展层五件套:常驻用 CLAUDE.md,按需用 skill,隔离用 subagent,确定性用 hook,外部用 MCP。
  • 上下文成本差异很大,选型先看"何时加载"。
  • 有副作用的 skill 开 disable-model-invocation;subagent 的价值在隔离;hook 是唯一的硬保证。
  • 按痛点增量配置,不要一次配齐。

下一篇讲并行与自动化:worktree 怎么隔离多个会话、后台代理和动态工作流什么时候用、以及如何用 headless 模式和 CI 把 Claude Code 接进流水线。