Claude Code 的 Mod、Hook 和 Skill 怎么选:什么时候才需要 Mod

图1

Mod 是运行在 Claude Code 内部的可编程扩展,可以介入模型请求、工具调用和界面绘制。CLAUDE.md 与 skill 主要提供规则和流程;settings hook 也能拦截工具、调整参数或替换输出。需要改写单次模型请求、绘制交互面板时,才更能体现 Mod 的价值。

大多数需求用不上 Mod。先分清规则、流程、事件处理与外部工具接入,再判断是否需要 Mod 的运行时或界面能力。

让 Claude 编写三个 Mod,是原作者 Yanli Liu 的实验:自动选择思考力度、统计回答句长、测试未通过时暂停提交。第三个案例的第一版漏过了一次坏提交,修复方法是每次提交前重新运行测试。

Mod 以你的权限运行。安装前先检查来源与代码,再用 claude plugin validate 查看事件和能力;校验通过不代表代码安全。

  1. Mod 是什么

大多数人定制 Claude Code 的办法就那么几种:一份写着项目规则的 CLAUDE.md,几个 skill,也许再加一个跑测试的 hook。

10 月 1 日,Claude Code 2.1.287 新增了一层:mod(模组)。Mod 是运行在 Claude Code 内部的一小段代码,既能改变 Claude Code 的行为,也能改变它显示给你的内容。Claude Code 的创建者 Boris Cherny 评价说:

“Mods are absolutely insane.”(Mod 太疯狂了。)

所以,第一个问题是:Mod 和你已经在用的机制有什么区别,什么时候才需要它?本文结合 Anthropic 官方文档,整理 Yanli Liu 在 2026 年 10 月 6 日文章中的三个案例:

自己选择思考力度(effort)

衡量每条回答的可读性

测试未通过时,挂起 git commit

1.1 和已有机制的区别

Mod 是一组小函数,Claude Code 在特定事件发生时调用它们:你发送了 prompt,Claude 即将调用模型,某个工具即将运行,或者屏幕的某一部分即将绘制。每个函数可以放行事件、修改事件,也可以自己接管并作答,比如拒绝某条命令。

settings hook、skill、状态栏和 MCP server 分别通过事件脚本、指令或工具扩展 Claude Code;Mod 则能把运行时拦截和界面绘制放到同一套事件处理中。Anthropic 的 Mod 概览这样概括:

“A mod runs inside Claude Code, so it can do things they can’t.”(Mod 运行在 Claude Code 内部,所以能做到它们做不到的事。)

术语说明:Anthropic 也把 Mod 里的函数叫 “hook”。你可能已经熟悉的、在 settings.json 里配置的命令型 hook,现在改称 settings hook。本文沿用这个叫法。

“运行在内部”带来的额外能力,体现在下面三个案例中:

修改发给模型的每个请求:effort Mod

读取每条回答,并在下面显示一行结果:readable Mod

在屏幕上绘制界面,并在你做出选择之前挂起一条命令:tests-gate

1.2 安装与创建

Mod 作为插件安装,沿用 /plugin install。例如安装市场中的插件时,使用 /plugin install 插件名@市场名。终端版需要 Claude Code 2.1.287 或更高版本,可用 claude –version 检查。

由 Claude 编写 Mod 时,可以让它调用内置的 plugin-authoring skill。首次保存文件后,Claude Code 会询问是否为当前会话启用热重载;批准后,Mod 会随后续编辑重新加载。也可以手写:一个最小 Mod 由插件清单、hooks 配置和注册模块三个文件组成。

Claude 写出的 Mod 位于 ~/.claude/dev-mods/ 下的会话目录中,默认只在创建它的会话里加载。该目录会按 cleanupPeriodDays 清理。想长期保留,就把 Mod 文件夹复制到自己的目录,例如 ~/mods/readable,再这样启动:

claude --plugin-dir ~/mods/readable
  1. 选型:你真的需要 Mod 吗

图2

多数需求用已有机制就够了。可以按下面的顺序判断;如果一个需求涉及多个层次,也可以组合使用:

想让 Claude 了解项目里的某些事:写进 CLAUDE.md。

想让每条回答都保持某种风格:用 output style。

想让 Claude 处理某一类任务时都按同样的步骤来:写一个 skill。

想在固定时刻阻止、放行或调整某件事,比如工具运行之前:用 settings hook。

想让 Claude 连接外部系统、使用外部工具:用 MCP server。

想要交互面板、按请求调整模型或 effort,或者直接运行自定义代码的 /命令:再考虑 Mod。

2.1 反例:不需要 Mod 的场景——隐藏 API key

如果某条命令把 key 打印出来了,可以用 PostToolUse settings hook 在结果进入模型前替换输出。下面是原作者使用的简化示例,只匹配 sk-、ghp_、AKIA 三类格式;它只处理标准输出,不能覆盖所有密钥格式,也不处理标准错误。

#!/usr/bin/env python3
# PostToolUse:仅替换 Bash 标准输出中的示例密钥格式。
import json
import re
import sys

event = json.load(sys.stdin)
out = event.get("tool_response") or {}
pattern = re.compile(
    r"(sk-[A-Za-z0-9_-]{16,}|"
    r"ghp_[A-Za-z0-9]{20,}|"
    r"AKIA[0-9A-Z]{16})"
)
stdout = out.get("stdout", "")

if pattern.search(stdout):
    print(json.dumps({
        "hookSpecificOutput": {
            "hookEventName": "PostToolUse",
            "updatedToolOutput": {
                **out,
                "stdout": pattern.sub("[redacted]", stdout),
            },
        },
    }))

和其他 settings hook 一样,把它配置到 .claude/settings.json 里:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "python3 \"${CLAUDE_PROJECT_DIR}/.claude/hooks/redact-secrets.py\""
          }
        ]
      }
    ]
  }
}

在原作者的演示里,文件中放的是假 key;让 Claude 用 cat 打印后,模型看到的是:

OPENAI_API_KEY=[redacted]

Claude 甚至补了一句,这个值可能已经被 hook 替换了。

hooks 文档特别说明:替换只影响模型看到的结果,无法撤销已经执行的命令。OpenTelemetry 等遥测会在 hook 运行前采集原始输出;这段脚本不能当作完整的密钥防泄漏方案。

  1. 三个实战 Mod

三个案例都来自原作者的同一次 Claude Code 会话。下文的耗时与现象,是他在那次测试中的记录。

3.1 effort-by-task:让 Claude 自己选思考力度

图3

问到能否按任务自动选择 effort 时,原作者当时得到的答复是不能。这里讨论的是他的 Claude Code 会话与配置;effort 的可用档位仍取决于模型和版本。这个 Mod 的做法,是在请求发出前按规则覆盖 effort。

需求是:按 prompt 看起来的难度来选 effort。快速提问、重命名和小改动用 low;调试、设计和“为什么”类问题用 high;其余用 medium。规则要简单,不额外调用模型;在 spinner 旁显示选出的级别;再加一个 /effort-auto 命令来开关。实际使用的 prompt:

make a mod called effort-by-task that picks the thinking effort for each
request based on how hard my prompt looks: low for quick questions, renames
and small edits; high for debugging, design or 'why' questions; medium
otherwise. Use simple rules, no extra model call. Show the level it picked
next to the spinner, and add an /effort-auto command that turns it on or off.

核心逻辑是挂在 turn.step 上的 hook,在每次模型请求发出前改写 effort。下面是原文片段,省略了状态定义与辅助函数,不能单独运行:

on('turn.step', async function* ($, e, next) {
  const picked = await read($, level)
  if (
    e.agentId === undefined &&
    e.effort !== undefined &&
    picked !== null &&
    (await read($, isOn))
  ) {
    return yield* next({ ...e, effort: picked })
  }
  return yield* next(e)
})

实际测试的是原作者研究工具中的两个问题,以下耗时只代表这两次运行:

“没有推文时,window 脚本会输出什么?”以 low 运行,9 秒完成。

“为什么把书签保存在独立的 window-state.json 中,而不写入 archive.json?”以 high 运行,用了 17 秒。

事后,原作者检查会话日志,确认前两个请求分别以 low、high 发出,创建第二个 Mod 的请求则用了 medium。这说明规则在这次测试中生效,不能据此推出普遍的速度或质量提升。

自己做的时候,有两点要核对:

Claude Code 自带的 spinner 在那次测试中一直显示“thinking with high effort”,反映的是会话设置,和 Mod 为单个请求选出的档位可能不同。

Mod 自己的标签也只显示“选了什么”;模型不支持该档位时,标签不等于实际执行结果。

所以,应检查请求日志,而不是只看 spinner。基于关键词的规则也很粗糙:出现“why”就可能被判成难题,需要按自己的提问习惯调整。

适用场景:在模型请求发出前,按规则调整本次请求的参数。

3.2 readable:量化回答的可读性

图4

10 月 2 日,Andrej Karpathy 发帖说:

“We’ll be spending a lot more time trying to understand the outputs of language models.”(我们将花多得多的时间去理解语言模型的输出)

他的建议之一,是让模型用 ASD-STE100 来解释。这是一种最初为航空维修文档制定的受控英语。规则严格,所以他有时只要求接近这种风格;“80%”是近似描述,不是可计算的合规分数。

output style 负责提出写作要求;这个 Mod 额外在回答结束后计算并显示句长、最长句和总词数。原作者把风格切换与统计放进同一个 Mod:

make a mod called readable. After each answer, show one line under it saying
how readable the answer was: average words per sentence, the longest
sentence, and total words, ignoring code blocks. Also add a /readable command
that switches on Karpathy's tip: Claude writes explanations in about 80%
ASD-STE100 Simplified Technical English (short sentences, active voice,
simple words), but leaves code as it is. While it's on, show 'readable'
next to the spinner.

测量部分挂在 turn.complete 上,在回答结束时追加一行统计。原作者连续两次询问 –since-last 书签如何判定新内容,一次关闭模式,一次开启,并要求内容保持一致。每种设置只运行了一次:

关闭:平均每句 14.8 词,最长句 24 词,总计 369 词。

开启:平均每句 12.7 词,最长句 23 词,总计 395 词。

图5

句子在这组对照中变短了,总词数却增加了:Claude 用更多、更简单的句子表达相同内容,缩写也改成了“does not”“cannot”等完整形式。原作者觉得更清楚,也更生硬,只在需要快速读懂解释时开启。单次句长统计不能证明可读性或技术准确性一定更好。

适用场景:在界面里持续展示回答统计。句长与词数是辅助指标,仍需人工检查内容是否好懂。

3.3 tests-gate:测试未通过时暂停提交

原作者希望在输入框上方持续显示测试状态,提供“运行测试”按钮,并在 Claude 尝试提交时,给出可以自行选择的确认界面。示例测试命令是 python3 -m unittest discover -s tests。

第一版漏掉了一次坏提交。原作者让 Claude 把首次运行的时间窗口从 7 天改成 3 天,导致 63 个测试中的 2 个失败,但提交仍然通过了。

原因是 Claude 用 shell 中的 Python 脚本修改了文件,而 Mod 只监听常规文件编辑工具。它没看到编辑事件,就误以为上次“测试通过”的结果仍然有效。Mod 自己的测试也通过了,却没有覆盖这个真实操作路径。

修复方法:每次提交前重新跑测试。原作者让 Claude 调整逻辑,不再依赖“是否检测到文件编辑”。发现直接的 git commit 调用后,先运行一次新的测试;测试失败或无法完成时,暂停命令并提供三个选项:

重新运行测试

仍然提交

取消提交

复测时,面板显示 63 个测试中有 2 个失败。原作者让 Claude 添加一行注释并提交,这次界面弹出了选择;他选“取消提交”后,命令没有继续执行。

边界仍然存在。修复版只识别 Claude 的 Bash 工具直接发出的 git commit;脚本内部发起的提交仍可能绕过它。需要仓库层面的提交检查时,应另外配置 Git pre-commit 等机制,也要考虑这些机制自身的绕过方式。

适用场景:把测试状态、操作选择和命令暂停放进同一个界面。拦截逻辑要围绕真正关心的动作设计,并覆盖不同的执行路径。

  1. 安装前先检查能力与来源

图6

Mod 没有沙箱。按 Anthropic 文档的说法,Mod 以你的权限运行,可以读写你的文件、启动程序、发起网络请求。它能读到你的密钥,比如环境变量里的 API key,也能看到你发出的每条 prompt 和 Claude 的每次工具调用。

它甚至可以批准一个被你自己的 PreToolUse hook 拦下的工具调用。如果你开启了 Claude Code 的沙箱,Mod 启动的程序依然运行在沙箱之外。

所以,先在本地对 Mod 文件夹执行:

claude plugin validate ./tests-gate

它会列出这个 Mod 挂了哪些事件、请求 Claude Code 执行哪些操作,而且不会运行其中任何代码。以 tests-gate 为例:

❯ ./register.tsx hooks: session.start, tool.call, turn.complete, tool.call{tool=Bash}, ui.render{component=AbovePrompt}
❯ ./register.tsx calls: $.clock.after, $.process.run (via runSuite), $.state.get, $.state.set, $.ui.ask, $.ui.resolve

$.process.run 说明这个 Mod 会启动程序。校验输出帮助你了解它声明使用的事件和 API,但不能证明这些能力会被妥善使用,也不能替代源码审查与实际测试。

对测试门禁来说,启动程序符合预期;如果一个 Mod 只声称改改 spinner,却还会启动进程,就值得进一步检查。装完后需要排查时,可以用 claude –safe-mode 暂停已安装的 Mod 与其他自定义内容;Claude Code 内置的 Mod 仍会运行。

  1. 小结

从选型清单开始,CLAUDE.md、skill、output style 或 settings hook 往往就够了。

真需要 Mod 时,先让 Claude 做一件很小的事,看着它运行,然后故意去测,包括你没想到的那种情况。

用 claude plugin validate 查看 Mod 的事件与能力,并结合源码和测试判断;自己的 Mod 记得从临时会话目录中复制出来保存。

想在动手之前多看几个例子,可以看 Anthropic 在 claude-code-playground 仓库里提供的三个示例 Mod:token-weather、blast-radius 和 replay-theater。

来源与延伸阅读

案例来源:Yanli Liu,Claude Code Mods vs Hooks vs Skills: When You Need One(2026 年 10 月 6 日)。文中耗时、测试数量与使用感受均为原作者记录。

Anthropic:Mods 概览、能力与信任边界

Anthropic:创建、热重载与保存 Mod

Anthropic:Settings hooks 参考

Anthropic:三个示例 Mod 的源码

原文发布于 X:https://x.com/vincemask/status/2111068078905929732