前面五章里,我们装好了 Claude Code、发出了指令、走出了卡壳、设计了权限。这一章讲的是改造工具本身。扩展这种东西,光记住名字是用不起来的。真正有用的是“我现在这个不满,该用哪一个来解”的对照表。

选型地图 —— 四个问题就能定下来

扩展有六种,但要想的只有四件事:用嘴说说够不够/要不要确定地生效/要不要分到另一个语境里/要不要连到外部去——按这个顺序自问一遍,答案基本就唯一了。

Q1
用嘴说说够不够

偶尔漏掉也不致命的话,写成文字就够了。→ CLAUDE.md(全局前提)/Skills(特定工作的流程)

Q2
要不要确定地生效

哪怕漏一次都受不了,那就用机制去拦。→ hooks。设置已启用且事件与条件匹配时,它会运行。

Q3
要不要分到另一个语境里

不想让海量输出把正题挤掉,就放到外面去做,只拿回结论。→ subagents

Q4
要不要连到外部去

需要 AI 不可能知道的信息(数据库里的当前值、任务系统里的内容)时。→ MCP

第五个问题是“要不要分发给别人”——要分发就用 plugins。最容易混淆的是 Q1 和 Q2,也就是 CLAUDE.md、Skills、hooks。三者看着都差不多,区别在于什么时候被读取、由谁来执行。

CLAUDE.md —— 区分加载与遵守

CLAUDE.md 放在会被加载的位置,就能在每次会话中提供项目前提。跨项目的通用指令可放在 ~/.claude/CLAUDE.md。它是文字指令,不是强制控制操作权限的配置。

智能体说读过文件却没有照做时,应分别查看下面三个问题。

  • 是否加载?在 /context 的 Memory files 中查看是否列出了 CLAUDE.md 和规则。启动位置与排除设置会影响加载范围。直接加载的 AGENTS.md 不显示在该列表中,因此仅凭未列出不能断定未读
  • 压缩后是否恢复?项目根目录 CLAUDE.md 会在 /compact 后从磁盘重新读取并注入。子目录 CLAUDE.md 与路径规则,则在读取匹配文件时重新加载。只在对话中约定的事项,处理方式不同
  • 是否影响实际操作?即使已经加载,也要另行检查规则含糊和指令冲突的问题。不能认定最新指令始终优先,应写清适用范围与例外条件

官方建议每个 CLAUDE.md 文件少于 200 行。这既不是加载截断线,也不是保证遵守的界限。保留每次都需要的规则,把细节分开并写明读取条件。通过 @path 导入全部内容,并不会减少启动上下文。偶尔使用的流程可以放进 Skills,只适用于特定文件的指令可使用路径规则。

以上依据官方记忆文档。区分方法的实例与工具差异见如何排查 AI 智能体忽略规则。

“我读过了”不是遵守规则的证据。加载列表与差异、测试结果应分别检查。可以机械验证的条件应交给下一节的 hooks 或 CI,并报告未验证范围。

hooks —— 条件匹配时运行检查

“不要改写 .env”这样的文字指令,无法保证某个遵守率。如果需要在执行前检查条件并拦截操作,应考虑权限设置和 hooks。

本节讲的是运行 shell 命令的 command 类型 hooks。已启用的设置匹配事件与条件时,由 Claude Code 本体启动它们,无须模型记得调用。不过,如果在设置中被禁用,或属于未覆盖的执行路径,它们就不会运行。概览见 Claude Code hooks 是什么。下面列出九个代表性事件,并非完整列表。

SessionStart 开始或恢复时 UserPromptSubmit 发送之后立刻 [可拦截] PreToolUse 调用工具之前=门卫 [可拦截] PostToolUse 工具成功之后=格式化(无法撤销已完成的操作) Notification 等待输入、等待授权 Stop 回答结束 [可拦截] SubagentStop 子智能体结束 [可拦截] SessionEnd 会话结束 PreCompact 压缩之前 [可拦截]

不同事件能阻止的事情不同。执行前拦截工具,与阻止回答结束以便继续工作,并不是同一种操作。在 PreToolUse 拒绝危险操作,在 PostToolUse 自动格式化,是两个常用入口。配置写在 settings.json 的 "hooks" 键下。文件位置决定作用范围(~/.claude/ = 用户,.claude/ = 共享,settings.local.json = 个人)。

下面把开头的“不要改写 .env”变成一套机制。这是把官方指南中“阻止编辑受保护文件”的例子限定到 .env 的写法。需要准备的是配置和脚本两样东西。

① .claude/settings.json——在调用 Edit 或 Write 之前运行脚本。

{ "hooks": { "PreToolUse": [ { "matcher": "Edit|Write", "hooks": [ { "type": "command", "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/protect-env.sh" } ] } ] } }

② .claude/hooks/protect-env.sh——如果编辑目标的文件名以 .env 开头(包括 .env.local 等),就阻止编辑。在 macOS 和 Linux 上,用 chmod +x .claude/hooks/protect-env.sh 赋予执行权限。

#!/bin/bash # .claude/hooks/protect-env.sh command -v jq >/dev/null || { echo "未找到 jq,已阻止编辑" >&2; exit 2; } FILE_PATH=$(jq -r '.tool_input.file_path // empty') FILE_PATH="${FILE_PATH//\\//}" # 把 Windows 的 \ 统一为 / if [[ "${FILE_PATH##*/}" == .env* ]]; then echo "Blocked: $FILE_PATH 是 .env 文件,不予编辑" >&2 exit 2 fi exit 0

结构是事件名 → 匹配条件与命令的数组。matcher 指定工具名,"Edit|Write" 匹配 Edit 或 Write 中的任意一个(省略则匹配全部工具)。钩子从标准输入接收 JSON,对于 Edit 和 Write,tool_input.file_path 中是编辑目标的绝对路径。Windows 上这个路径的分隔符是 \,所以脚本先把它统一为 / 再比较。用退出码 2 阻止时,标准错误输出的文字会作为拒绝理由传给 Claude,Claude 读到后会考虑换一种做法。1 被视为非阻断错误,操作会继续,所以要阻止时请用 2。0 表示不提出异议,进入正常的权限检查。

脚本使用 bash 和 jq(官方指南的例子同样以 jq 为前提)。在 Windows 上,钩子由 Git Bash 执行;没有 Git Bash 时则由 PowerShell 执行,因此这个例子需要 Git Bash。为了避免在找不到 jq 时直接放行,脚本的第一步就会在这种情况下阻止编辑。

钩子能把限制收紧,但不能把限制放松。 就算它返回放行,也只是省掉一次弹窗,拒绝规则始终优先。PreToolUse 的拒绝在跳过全部批准的模式下也照样有效,所以可以拿它当第 5 章放松出来的那一截的兜底。

测试方法与官方指南相同。请 Claude“在 .env 中加一行注释”,编辑前就会被拦下,Blocked: 这句话会返回给 Claude。同时也要确认 .env 以外的文件仍能照常编辑。如果把脚本路径写错,只会出现 Failed with non-blocking status code 的通知,门其实一直开着,所以也要留意这条通知。另外,这个例子只拦截 Edit 和 Write 两个工具,通过 Bash 或 PowerShell 命令改写文件属于其他路径。请根据想拦截的范围扩大对象。输出格式与事件差异见官方 Hooks 指南。

代价也应提前考虑:command 类型的钩子会以你的用户权限自动执行 shell 命令,你的账户能访问的文件,它都可以修改甚至删除。官方也要求在添加之前阅读并测试所有命令。只配置可信的命令,并校验输入。直接编辑配置文件所做的更改通常会自动生效。通过 /hooks 查看注册情况;若未生效,先检查 JSON 和文件位置,再重启会话。

subagents —— 把语境分开再交出去

完整测试输出和庞大日志会让本来只打算浏览的大段文本占满上下文,挤走重要前提。subagents 把这部分工作放在独立上下文中执行,再返回结论摘要。它们通常拥有独立的上下文、指令和工具权限,因此父智能体必须明确提供所需信息。通过会话分叉继承父会话历史的执行方式属于例外,且不同于技能的 context: fork。报告是摘要,所以还应要求提供必要证据和未解决的问题。

  • 分出去划算——面很宽的调查/伴随大量输出的核对/只要结论就行的自足型任务
  • 分出去吃亏——需要按顺序处理/来回沟通频繁/会改同一批文件的并行作业/一两步就能改完的修正

它是标准功能,不做配置也能用。想加自定义定义,就写在 .claude/agents/<名称>.md(想通用就放 ~/.claude/agents/),用 YAML 前置元数据写上 name / description / tools / model。管理用 /agents,调用写 @agent-<名称>。先从标准自带的探索型、计划型、通用型用起就好。

决定它会不会被调用的关键是 description。主智能体是看着这段文字来决定要不要委派的,说明含糊会降低被自动选中的可能性。要具体写清做什么,以及什么时候用——同样的坑在 Skills 里也有。

容易和它混淆的 Agent Teams,是让多个独立会话通过共享任务清单来协作的机制。它处于实验阶段、需要主动开启、默认关闭(CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1)。因为跑的是另外的实例,所以令牌消耗大,而且不能嵌套。两者的区别在 subagents 与 Agent Teams 的区别 里做了对比。拿不准就用单个会话或者 subagents。

Skills —— 把流程变成资产

面对“每次都按这套流程来”的固定套路,Skills 的长处在于它只在需要的时候才被打开。它的实体是一个以 SKILL.md 为核心的目录:开头写 name 和 description,下面用 Markdown 写流程,还可以一并放上 reference/ 和 scripts/。只要放进 .claude/skills/(项目)或 ~/.claude/skills/(通用),它就会被识别。

核心是渐进式披露。通常先把技能名称和说明列表放入上下文,再通过自动选择或显式调用 /skill-name 加载正文,附带资料则按需读取。说明列表本身也占上下文;技能较多时,说明可能因预算而缩短或省略。应写清 description,并分别验证技能是否被调用、流程是否得到预期结果。写法见 Claude Agent Skills 是什么。

一句话概括:CLAUDE.md = 常规加载的前提;Skills = 自动选择或显式调用后打开的流程;command 类型 hooks = 由已配置的事件与条件触发的处理。

MCP —— 把手伸到外部系统

MCP(Model Context Protocol)是一套用于访问外部数据和操作的标准,例如读取数据库中的当前值或任务系统中的工单。常见连接方式如下。排查问题时,应结合连接方式与错误详情。

  • 本地(stdio)——服务器作为电脑上的子进程启动。线索是可执行文件路径、必需的环境变量与服务器错误输出
  • 远程(HTTP)——通过 URL 连接服务器。线索是 URL、网络、服务器端错误与凭据

先查看 /mcp 中的状态和详情。failed 既可能出现在本地服务器,也可能出现在远程服务器。如果 Issue: 在 claude mcp get <name> 的输出中包含 HTTP 状态码或错误正文,也应阅读。needs authentication 提示应检查认证;pending approval 则是重新审视项目服务器批准状态的入口。如果固定的 Authorization 请求头在连接时被 401/403 拒绝,即使问题在认证,状态也会显示为 failed。具体处理方法见 Claude Code MCP 连接错误:原因与修复。

将共享配置文件 .mcp.json 放在项目根目录。各服务器的 env 用于传递 stdio 服务器所需的变量;HTTP 认证则根据服务要求使用 OAuth 或 headers。不要把实际密钥直接写进共享文件;应引用环境变量,例如 ${API_KEY}。某些变量名,包括 Claude Code 自身的凭据,在远程 URL 和请求头中会展开为空字符串,详见官方变量展开规则。

工具定义默认按需加载。 在启用工具搜索的典型配置下,起初只有工具名称和服务器说明进入上下文。禁用搜索、不受支持的环境或配置了 alwaysLoad 的服务器等情况,会预先加载定义。输出也会占用上下文,因此请通过 /context 查看实际用量,并停用不使用的服务器。

plugins —— 打成一包分发出去

Plugins 可以将技能、子智能体定义、hooks 和 MCP 配置打包分发。如果单个插件需要清单文件,应放在 .claude-plugin/plugin.json。标准目录结构把 skills/、agents/、hooks/hooks.json 和 .mcp.json 放在插件自身的根目录,不要将它们放进 .claude-plugin/。只使用标准目录结构的插件可以省略清单文件。

/plugin marketplace add owner/repo ← 登记一个目录源 /plugin install name@marketplace ← 再从里面逐个安装 /plugin list ← 列出通过市场安装的插件

以上是通过市场安装的基本步骤。仅登记目录源,不会安装插件。/plugin list 列出的是通过该途径安装的插件,不包括技能目录或同步等其他途径提供的所有插件。作用范围分为 user(自己的所有项目)、project(共享配置)和 local(仅自己在当前项目中使用)。即使采用 project,每位成员也仍需安装来自外部来源的插件。managed 范围由管理员集中管理,并限制用户修改配置。自行制作的步骤见 Claude Code 插件与市场:使用、制作和发布。

插件能够以你的权限执行任意代码,官方文档对此有明确警告。社区上架项目会经过 Anthropic 的自动验证与安全审查,但这并不保证它们会按预期工作。应检查发布者、所含代码和 MCP 服务器。第 5 章的权限设计,也适用于这里由他人编写的代码。

从哪个开始装 —— 顺序的问题

虽然列了六种,但并不需要全都装上。在还没有困扰的时候就装,增加的只有配置的复杂度。顺序要从症状出发。

  • 每次都在交代同样的话 → CLAUDE.md。只涉及某项特定工作的话,就用 Skills
  • 写了却不被遵守 → 先逐项排查加载、适用范围和冲突。可机械判定的条件交给 hooks
  • 上下文一下子就满 → 把重的调查工作交给 subagents/把不用的 MCP 停掉
  • AI 够不到那些信息 → 上 MCP。一个一个接,看着通了再接下一个
  • 想把同一套配置分发出去 → plugins。只打包你自己已经用顺手的东西
  • 没什么特别的困扰 → 什么都别装。这才是最好的状态

最后一行不是玩笑。扩展也会增加卡壳的来源——“Claude Code 怎么怪怪的”,真相往往是你自己加上去的那一层。所以第 4 章的排查要排在前面。

小结

  • 选型的标准是四个问题——用嘴说说够不够(CLAUDE.md、Skills)/要不要确定地生效(hooks)/要不要分到另一个语境(subagents)/要不要连到外部(MCP)。要分发就用 plugins
  • CLAUDE.md 保存持久指令,根目录文件在压缩后会重新注入。缩短文字不能保证遵守,应分别检查加载与实际行为
  • command 类型 hooks 在配置条件匹配时由 Claude Code 运行。应核查执行路径与阻断行为;事后运行的钩子不能撤销已完成的操作
  • subagents 在另一个上下文里干活,只把摘要带回来。不适合按顺序处理和频繁来回
  • Skills 采用渐进式披露,需要时才加载正文。应写清说明以便自动选择;即使显式调用,也须验证流程结果
  • MCP 是访问外部系统的标准。排查问题时,要将 /mcp 的状态与连接方式及错误详情结合起来
  • plugins 是分发用的盒子。别人的代码会以你的权限运行,所以要核实发布方
  • 装的顺序从症状出发。等困扰真的出现了,再一个一个来

工具本身的对比与取舍,放在 AI 编程实践课程第 6 章“用扩展功能拓展能力” 里讲。

扩展得越多,消耗也就越大。最后一章我们来讲长期用下去所需要的运营方法。请前往 第 7 章“成本与用量上限”。