mod 是什么:插件里的事件处理函数
按官方文档,mod 是一个改变 Claude Code 外观和行为的插件,由 JavaScript 或 TypeScript 写的事件处理函数组成:Claude 准备调用工具、你提交提示词、界面某个部分要绘制时,Claude Code 就调用对应的函数。 文档把这些函数叫 hook;原来写在 settings 文件里、跑 shell 命令或 HTTP 请求的 hooks,现在改叫 settings hook。
hook 在 Claude Code 处理事件之前运行,由它决定接下来发生什么:
- 观察:记下发生了什么,事件照常继续,比如统计工具调用次数;
- 改写:先改动事件再放行,比如在 spinner 文字后面加上计数;
- 接管:自己处理事件,原本的行为不再运行,比如拒绝一条命令。
hook 要做自身代码以外的事(画界面、加命令、调用模型、读文件、联网等)只能通过 mods API,也就是代码里的 $;正因为只有这一个出口,Claude Code 才能在安装前列出一个 mod 会做什么。 几个 mod 处理同一事件时按加载顺序执行:最先加载的最先看到事件、最后拿到结果,不同作者的 mod 因此可以叠加。
Claude Code 自己的部分功能也已经是 mod,比如 /diff 由内置的 cc-plugin-diff 绘制面板,可以在 /plugin 里停用(/diff 会退回原来的内置版本),也可以换成你自己的。Anthropic 表示会逐步把更多内置功能改成 mod。
mods 能做、hooks / Skills / MCP 做不到的事
settings hook、skill、状态栏和 MCP 服务器都在 Claude Code 外部工作:要么跑一个脚本,要么给 Claude 一段文字或几样工具。mod 在 Claude Code 内部运行,所以多了这些本事:
- 画一个能操作的界面:对话旁的面板或提示框上方的信息带,带标签页、按钮和输入框;
- 重画 Claude Code 自己的界面:比如工具调用那一行、spinner、Claude 向你提问的对话框;
- 介入工具调用或请求:先扣住工具调用问你、不运行工具直接给结果,或把某次请求发给另一个模型;
- 在命令上跑自己的代码:/命令直接执行你的函数,不占 Claude 的回合,Claude 干活时也能用;
- 在 hook 之间共享数据:同一文件里的变量共用,一个 hook 记录,另一个 hook 展示。
官方博客举的例子还有:在提示词送到模型前改写它、重试一次工具调用、批准或拒绝权限请求、在 Claude 读到工具输出前抹掉其中的密钥。官方文档的对比表:
| Mod | Settings hook | Skill | MCP 服务器 | |
|---|---|---|---|---|
| 是什么 | 插件里的函数,由 Claude Code 在自己的进程里调用 | 在生命周期事件上运行的 shell 命令、HTTP 请求或提示词 | 一份写给 Claude 读的 SKILL.md 说明 | 给 Claude 提供工具的外部进程或服务 |
| 能改什么 | 工具调用、提示词、命令、回合,以及界面画什么 | 工具调用或提示词放不放行、工具调用的参数和结果、补充给 Claude 的上下文 | Claude 知道什么、做什么 | Claude 有哪些工具 |
| 能在界面上画东西 | 能 | 不能 | 不能 | 不能 |
| 用什么写 | JavaScript 或 TypeScript | 一个脚本加 settings.json 里的一条配置 | Markdown | 任意语言写的服务 |
| 什么时候选它 | 想要面板、提示框上方的信息带、自定义命令,或要改写事件 | 手上已有脚本,想拦截、放行或记录事件 | 同样的说明总在反复粘贴进对话 | Claude 需要连上外部系统 |
一个插件可以同时装这几样,mod 可以和 skill、MCP 服务器放在同一个插件里发布。官方建议:settings hook、skill 或 MCP 已经能做到的,先对照上表再决定写不写 mod。 不熟悉这几样,可以先看 Hooks 与 Subagents、Skills 和 MCP 教程。
开始之前:版本要求
- 终端:Claude Code v2.1.287 或更高,运行
claude --version查看,版本低就先更新。 - 桌面 App:App 自带一份 Claude Code,从 v2.1.286 起支持 mods;在 Code 标签页的本地会话里输入
/status,看 Claude Code 那一行。 - 默认开启:早期体验时设置过
CLAUDE_CODE_ENABLE_FUNCTION_HOOKS的,把它删掉——v2.1.287 起会忽略这个变量,设成 0 也关不掉 mods。 - 看加载了哪些 mod:输入
/plugin,标签页下方的灰字会写1 mod active · first-mod这样的数量和名字(不含内置 mod)。
先玩官方示例:三个现成的 mod
Anthropic 在 GitHub 仓库 anthropics/claude-code-playground 的 claude-code/mods 目录放了示例 mod,每个都是完整插件,README 写了它是怎么做出来的。仓库按原样提供,不提供支持。
token-weather:在提示框上方画出你上下文窗口的「天气预报」blast-radius:遇到有风险的 shell 命令(比如 rm -rf 或强制推送)先扣住,显示它会改动什么,再给你继续或取消两个按钮replay-theater:新增一个 /replay 命令,一步步回放 Claude 上一轮对文件做的修改
想试一个,clone 仓库后用 --plugin-dir 加载某个 mod 的目录,只在本次会话生效;想长期用,把 clone 下来的 claude-code/mods 目录添加为插件市场,再从 claude-code-playground-mods 安装:
# 试一次:clone 仓库,只在本次会话加载某个示例
git clone https://github.com/anthropics/claude-code-playground
claude --plugin-dir ./claude-code-playground/claude-code/mods/token-weather
# 长期用:在 Claude Code 会话里把目录添加为插件市场,再安装
/plugin marketplace add ./claude-code-playground/claude-code/mods
/plugin install token-weather@claude-code-playground-mods市场指向你本地的副本,副本移走或删掉,mod 就不再加载。示例同样以你的权限运行,加载前先按后文「安全」一节看看它要做什么。
最省事:让 Claude 帮你写
在交互式会话里用你自己的话描述想要的 mod,Claude 就会写。它依据内置的 plugin-authoring skill,里面写明了 mod 放在哪、你的版本有哪些事件和方法、怎么加载;需要时会自动加载,也可以输入 /plugin-authoring 手动加载。
- 描述需求,比如「做一个在提示框上方显示当前 git 分支的 mod」。Claude 会把它写进本会话专属的目录
~/.claude/dev-mods/(后接会话 ID)。~/.claude是受保护路径,default 和 acceptEdits 模式下每建一个文件都会先问你。 - 决定热重载:Claude 保存第一个文件时,Claude Code 会问是否为本会话开启热重载。选 Enable for this session,mod 在本轮结束时加载,之后每轮改动都自动重载;选 Not now,文件留着,下次启动这个会话时再加载。
- 确认并试用:
/plugin里按 Tab 切到 Installed 能看到它,也能在这里关掉;效果不对就告诉 Claude 改哪里,本轮结束即重载。
注意:Claude 写的 mod 只在写它的会话里加载,目录超过 cleanupPeriodDays 会被清掉,想保留就复制出来(如 ~/mods/git-branch),以后用 claude --plugin-dir ~/mods/git-branch 加载。 没人能批准的会话(claude -p、dontAsk 模式)、未信任的工作区、用 --safe-mode 或 --bare 启动、设了 disableAllHooks 或被组织托管设置禁止时,它不会加载。让 Claude 写 mod 本身也在消耗你的套餐额度。
自己写第一个 mod:三个文件
照官方教程做一个 first-mod:统计 Claude 调用工具的次数,显示在 spinner 旁边,再加一个 /tally 命令。不需要 Node.js、打包工具或构建步骤,Claude Code 直接加载 .js 和 .ts 文件。 最小的 mod 就三个文件:.claude-plugin/plugin.json、hooks/hooks.json、hooks/register.js。
first-mod/
├── .claude-plugin/
│ └── plugin.json
└── hooks/
├── hooks.json
└── register.js第 1 步,建目录:
mkdir -p first-mod/.claude-plugin first-mod/hooks第 2 步,插件清单 first-mod/.claude-plugin/plugin.json,mod 不需要额外字段;名字别像 Anthropic 自己的(比如以 claude- 开头),否则校验不通过:
{
"name": "first-mod",
"version": "0.1.0",
"description": "Counts Claude's tool calls, shows the count beside the spinner, and adds a /tally command",
"author": { "name": "Your Name" }
}第 3 步,first-mod/hooks/hooks.json 里的 modules 指向代码文件(相对 hooks.json,只写一个)。有这个键,插件才算 mod:
{
"description": "The first-mod hooks module",
"modules": ["./register.js"]
}第 4 步,写代码 first-mod/hooks/register.js。mod 加载时,Claude Code 调用你导出的 register 并传入 on,每调用一次 on 就给一个事件注册一个 hook:
// 几个 hook 共用的计数
let calls = 0
// mod 加载时,Claude Code 调用一次 register
export function register(on) {
// 会话开始时注册 /tally 命令,然后照常放行(观察)
on('session.start', async ($, e, next) => {
await $.command.register({
name: 'tally',
description: 'Show how many tool calls Claude has made',
})
return next(e)
})
// Claude 每次要用工具时加 1,并请界面重画(观察)
on('tool.call', async ($, e, next) => {
calls += 1
$.ui.invalidate('ui.render')
return next(e)
})
// 只在输入 /tally 时运行,自己返回文字(接管)
on('command.run', { command: 'tally' }, async () => {
return { text: 'Claude has made ' + calls + ' tool calls since this mod loaded' }
})
// 保留原来的 spinner,在后面加上计数(改写)
on('ui.render', { component: 'Spinner' }, async ($, e, next) => {
return next({ ...e, props: { ...e.props, suffix: ' · tool calls: ' + calls + '…' } })
})
}每个 hook 拿到三个参数:$ 是 mods API,e 是事件内容(比如工具名和参数),next 把事件交给后面的 mod 和 Claude Code 自己的处理并返回结果。session.start 和 tool.call 是观察,最后都 return next(e);command.run 是接管,自己返回结果、不调用 next,{ command: 'tally' } 是只对 /tally 生效的过滤器;ui.render 是改写,把加了计数的事件副本交给 next。
第 5 步,加载并试用:
# 只在这一次会话加载 first-mod
claude --plugin-dir ./first-mod
# 不进交互界面,直接测 /tally
claude -p "/tally" --plugin-dir ./first-mod
# 输出:first-mod: Claude has made 0 tool calls since this mod loaded让 Claude 做几件要用工具的事(比如 list the files here and read the README),spinner 会显示 Thinking · tool calls: 2… 这样递增的数字;再输入 /tally,会看到 first-mod: Claude has made 2 tool calls since this mod loaded(数字以你的为准)。命令列表里没有 /tally,就是模块没加载上。
第 6 步,边跑边改:会话别关,把 ' · tool calls: ' 改成 ' · tools used: ' 并保存,对话里会提示 first-mod 已重载,下一次 spinner 就是新文字。用 --plugin-dir 加载的目录一改就热重载,重载会重新运行 register,所以计数归零。
想用 TypeScript:文件改名为 register.ts,modules 写成 ["./register.ts"] 即可。用 --plugin-dir 加载时,Claude Code 会在 mod 目录的 .claude-plugin/types/ 里写入与你当前版本一致的 .d.ts 类型声明,编辑器就能补全和类型检查。事件和方法会随版本变化,网页文档和类型文件不一致时,以类型文件为准。
安装、校验、测试、关闭与分享
安装。mod 以插件形式从插件市场安装:会话里用 /plugin install <plugin>@<marketplace>,终端里用 claude plugin install <plugin>@<marketplace>。在终端装好时会话还开着,就在会话里运行 /reload-plugins,否则下次启动生效。
校验。claude plugin validate 不运行你的代码,只做 Claude Code 加载 mod 时同样的检查和静态分析:hooks: 一行列出处理的事件(花括号里是过滤条件),calls: 一行列出调用的每个 mods API 方法,读写环境变量的还会多出 env reads: / env writes:。first-mod 的结果:
claude plugin validate ./first-mod
❯ ./register.js hooks: session.start, tool.call, command.run{command=tally}, ui.render{component=Spinner}
❯ ./register.js calls: $.command.register, $.ui.invalidate
✔ Validation passed想处理的事件没出现在 hooks 一行,那个 hook 就不会被调用,多半是事件名拼错(会报 "tool.calls" is not an event 这样的错)。另外 $ 的调用要写全(如 $.store.get('notes')),不要赋给变量或解构,事件名要写成字符串字面量,否则校验不过。
测试。claude plugin test 不需要会话、登录或网络,就能跑 mod 的自动化测试:触发事件,再检查 hook 做了什么。
关闭。按范围选:
- 关一个:在
/plugin的 Installed 标签页停用或卸载它所在的插件; - 本次会话全关:用
--safe-mode启动,其他自定义也会一起关; - 所有会话全关:在
~/.claude/settings.json里设"disableAllHooks": true,settings hooks 和自定义状态栏也会停,组织托管的照常运行。
这些开关不影响内置 mod(如 /diff),内置的要在 /plugin 里单独停用。
分享。给几个人用就发目录或 zip;团队放进自己的插件市场(比如一个私有仓库);全组织由管理员用托管设置安装;公开就公开市场仓库,或提交到 Anthropic 的插件目录。 开发时一直用 --plugin-dir 指向目录:已安装的插件按版本缓存,不升版本号重装,改动不会生效。分发细节见 Claude Code Plugins 指南。
安全:一个 mod 能碰到什么
官方博客说得很直接:mods 和 Claude Code 本身一样能访问你的电脑,不在沙箱里,只装信任来源的,就像在电脑上装任何代码一样。文档列出 mod 加载后能做的事:
- 以你的身份操作电脑:读写你的账户能访问的任何文件、启动程序、发网络请求;
- 读到你的密钥:环境变量和设置文件,包括放在里面的 API key;
- 看到整个会话:你发的每条提示词、Claude 的每一次工具调用;
- 改动会话:改写提示词或工具调用、像你亲手输入一样提交提示词、给你的另一个会话发消息;
- 不问你就行动:在你被询问之前批准一次工具调用;
- 花你的额度:用你的套餐或 API key 调用模型。
开了 sandboxing 也一样:沙箱只隔离 Claude 运行的 Bash 命令,mod 启动的进程在沙箱外(见沙箱指南)。会批准工具调用的 mod,能批准本该由 ask 规则弹窗询问、或被你自己的 PreToolUse hook 拦下的调用。 mod 唯一改不了的是权限确认框:它能重画大部分界面,但改不了权限提示显示给你的内容。
- 只从信任的作者和插件市场安装。
- 装之前先拿到插件文件(比如 clone 仓库),运行
claude plugin validate ./some-mod,看 hooks、calls 两行列出的事件和调用,和它声称的功能对不对得上。 - 留意 API key:mod 读得到环境变量;另外帮助中心提醒,设置了
ANTHROPIC_API_KEY时 Claude Code 会改用这个 key、按 API 计费,而不走订阅额度。 - 怀疑某个 mod 有问题,先用
--safe-mode启动排查。
mod 在哪些地方生效
hook 在任何加载了这个插件的会话里都会运行;但 mod 画出来的面板、信息带和替换过的行,只有终端和桌面 App 会显示:
| 在哪里运行 Claude Code | hook 会运行 | mod 画的界面会显示 |
|---|---|---|
终端里的 claude(含编辑器内置终端、JetBrains 插件) | 是 | 是 |
| 桌面 App 的 Code 标签页(WSL 会话除外) | 是 | 是,标为仅限终端的元素除外 |
| 桌面 App 里的 WSL 会话 | 否,WSL 会话不支持插件 | 否 |
| VS Code 扩展的聊天面板 | 是 | 否 |
claude -p 与 Agent SDK | 是 | 否 |
| 从 claude.ai 或手机 App 用 Remote Control | 是,在你电脑上的会话里运行 | 显示在你电脑的终端里 |
| 云端会话 | 是,前提是插件能带到云端会话 | 否 |
会画界面的 mod 可以判断自己跑在哪个应用里,在不显示界面的地方退回成对话里的一行文字或命令的文字回复。所以给 VS Code 用户或 CI 里的 claude -p 写 mod 也有意义:拦截、记录这类不靠界面的逻辑照样运行。
团队和企业:管理员怎么管
- 沿用插件管控:管理员可以放行或拦截插件市场;Team 和 Enterprise 由所有者在管理后台设置,用 Claude API 或第三方 API 的,由管理员把托管设置推送到成员电脑。
- 内置守卫 sec-default:在 Team、Enterprise 和有托管设置的电脑上,这个内置 mod 最先加载,阻止用户自己装的 mod 做高风险的事,比如绕过权限 deny 规则;管理员让自己的 mod 先加载时,要把 sec-default 加进列表才能保留它的限制。
- 只允许组织的 mod:组织设置 allowManagedModsOnly 后,用户自己的 mod 不再加载;它和 disableAllHooks 一样只停 mod,插件里的 skills、命令、agents 和 MCP 服务器照常加载。
- 团队用法:官方举的例子有对话旁的面板显示 CI/CD 状态、命令碰生产配置前必须确认、一个最先加载的 mod 记录其他 mod 的每次调用用于审计。
托管设置的写法可参考Claude Code 企业配置指南。
该用哪档套餐:谁该买什么
mods 不单独收费,官方文档对它只写了版本要求。但它跑在 Claude Code 里,而按 Anthropic 定价页,Claude Code 包含在所有付费套餐里(个人用户就是 Pro 和 Max),Free 没有;它和网页、桌面、手机端共用一份额度——写代码、让 Claude 写 mod、mod 调用模型,扣的都是这一份。
- Claude Pro(官方 $20/月):代充到自己的账号 ¥249 · 成品号 ¥329
- Claude Max 5x(官方 $100/月):代充到自己的账号 ¥999 · 成品号暂时缺货
- Claude Max 20x(官方 $200/月):代充到自己的账号 ¥1,799 · 成品号暂时缺货
- 想试 mods、平时偶尔用 Claude Code:Pro 就够,代充 ¥249。写个 first-mod、装一两个示例,用不了多少额度。
- 每天让 Claude Code 跑任务、Pro 常撞上限:帮助中心建议升 Max 5x(官方 $100/月,每个会话的额度约为 Pro 的 5 倍),代充 ¥999。
- Max 5x 也常不够:再升 Max 20x(官方 $200/月,约为 Pro 的 20 倍),代充 ¥1,799。Max 的会话额度每 5 小时重置,另有每周上限。
- 公司团队:要统一管控插件市场和 mod,走官方 Team / Enterprise。
代充还是成品号。代充开通在你自己的账号上:下单页粘贴 claude.ai 的 Cookie-Editor JSON,付款前系统预检,通常 5–30 分钟到账,凭证只用一次、交付后清除。Max 代充要求账号能正常登录、没被封;从没用银行卡开过会员的 Free 账号不能买 Max;新注册的号要等 3–15 天才能充 Max 20x。 不符合就买成品号:一单一个账号、只给你一人用,按商品说明可绑定自己的邮箱;付款后填收件邮箱并点击 Cloudflare 发来的验证邮件,Max 成品号人工发货,订单页显示 30 分钟到约 4 小时;Pro 成品号收到后在订单页提交 Organization ID。 之后在 Claude Code 里用同一个 Claude 账号登录即可。详见成品号怎么买、靠不靠谱和Max 5x 还是 20x。
续订与退款。每单 30 天,到期前 7、3、1 天提醒;成品号在个人中心 → 订单历史 →「续订」,按同档代充价计费;代充到期直接下新单。因 Anthropic 区域政策调整导致服务不可用的,按未使用天数退款;因违反 Anthropic 使用政策被封号的不退款;退款 1 个工作日内处理。 有问题请及时联系右下角在线客服(8:00–23:00),也可以发邮件到 support@claudemax.shop。
ClaudeMax 不是 Anthropic 官方,也不是授权经销商;自 2024 年 11 月运营至今,累计服务超过 20,000 名用户(我们自己的统计),有 ICP 备案。本文按 2026-10-07 核对的官方文档写成,mods 的事件和接口以官方最新文档为准。