开始之前,先让 Claude Code 表演一段"闪身步":

这是 Claude Code 根据我的提示词描述,直接生成的一个 Mods。
它的功能并不复杂:
我提交完了提示词、Claude Code 的回合开始时,终端窗口先一个"闪身步",闪到后台默默工作。
等这个回合结束,终端窗口再一个"闪身步",闪回前台,等着我来审查完成的结果。
主打一个契合现在"不再盯着 Agent 的中间步骤,直接看交付"的交互形式。
那么,Mods 到底是什么?它又是怎么做到这一点的呢?
Mods 是什么
如果你读过我们之前介绍 Claude Code Hooks 机制的文章,应该已经知道:
所谓 Hooks,就是由用户自己定义的、在 Claude Code 工作流程中的某些特定时刻自动触发的操作。它最常见的形式,是一条 Shell 命令。
比如,可以让 Claude 每次改完文件后,自动跑一遍代码格式化。又或者,在它每次准备执行命令前,先检查一下有没有危险操作。

Hooks 并不是什么魔法。
它就像衣帽架上的钩子,是 Claude Code 在设计之初就预留好的"挂钩位置"。你只要把自己的功能逻辑挂上去,它就会在对应的时刻,稳定可靠地执行。

而 Mods,你可以把它理解为"常驻在 Claude Code 里面的 Hooks"。
原来的 Hooks 更像一次性用品:每发生一个事件,就在 Claude Code 外面跑一次脚本,跑完就结束,下一次再从头开始。
而 Mods 则更像长期用品。它本质上是一段 JavaScript 或 TypeScript 代码,加载之后,就常驻在会话里。
它能记住状态,也能反过来调用 Claude Code 的能力。

正因为"住"在了 Claude Code 里面,Mods 能触及的范围比 Hooks 要广得多:
-
挂在事件上 :和 Hooks 一样挂在各种事件上,但不止能观察,还能改写,甚至直接接管。比如跳过工具运行,直接把结果交给 Claude。
-
在界面上绘制 :在特定的界面位置自由绘制,比如提示框上方的横条、侧边面板、状态行等等。
-
调用能力 API :扩展 Claude Code 的能力边界,比如注册新的斜杠命令、给 Claude 注册新工具、调用模型、运行本地程序等等。
用一张表来对比一下两者:
| 对比项 | Hooks | Mods | | --- | --- | --- | | 是什么 | 设置文件里配置的命令、HTTP 请求或提示词 | 插件里的一段 JavaScript / TypeScript 代码 | | 在哪里运行 | Claude Code 外面,每个事件单独跑一次 | Claude Code 里面,常驻在会话中 | | 能改变什么 | 以"把关"为主:决定工具调用和提示词能否继续,修改工具的参数和结果,或者给 Claude 补充上下文 | 不止把关,还能"动手":改写或接管工具调用、提示词和斜杠命令,改写发给模型的请求,跟踪每个回合,还能决定界面上画什么 | | 能否绘制界面 | 不能 | 能 |
Mods 能做什么?
正如我们前面所说,Mods 能做的事情,基本上可以归为三类:
-
事件钩子
-
界面绘制
-
能力 API
而我们的"闪身步" Mods,刚好基本覆盖了这三类场景。接下来,就以它为例,逐一讲解这三类场景主要用法。
事件钩子
事件钩子是 Mods 的入口。
Claude Code 在每一个即将采取行动的时刻,都会触发一个事件。比如提交提示词、调用工具、向模型发送请求、开始或结束一个回合等等。
Mods 里的钩子,会在 Claude Code 真正行动之前先拿到这个事件,再决定接下来怎么走。
和原来的 Hooks 不同,同一个事件上的多个钩子,会像中间件一样串成一条链。链的最末端,才是 Claude Code 自己的行为。
你可以把它想象成一条流水线:事件从第一个钩子出发,一站一站往下传。每个钩子都可以把它交给下一站,也可以中途把它拦下。

于是就有了三种用法:
-
观察:事件原样往下传,钩子只是顺带做点自己的事,比如记录日志、更新界面。
-
改写:把事件改过之后再往下传,比如给提示词补充上下文,或者修改 Claude 要执行的命令。
-
接管:不再往下传,由钩子直接给出结果。比如拦下一条危险命令,并说明原因。Claude 会把这段说明当作工具的返回结果来读,然后换一种做法。

闪身步只用到了其中最简单的一种用法:观察。
-
观察到回合开始(
turn.start)事件时,字符小人向右一闪,把终端窗口带出屏幕; -
观察到回合结束(
turn.complete)事件时,字符小人再向左一闪,将窗口从右侧带回。
整个过程中,它不会改变 Claude Code 的任何行为。
界面绘制
界面绘制,是让 Mods 可以直接改变 Claude Code 的界面。
Mods 能绘制的每一个位置,称为"渲染站点"。
它的工作方式有点像"点单":
每当 Claude Code 准备绘制某个渲染站点时,都会先触发一个绘制事件,问 Mods 这里要画什么。
Mods 返回一棵由文本、布局、按钮等元素组成的"元素树",Claude Code 再照着它,把画面渲染到终端或桌面应用里。

渲染站点大致可以分为两类,以下这张图就展示了 mod 在终端会话中可以绘制的位置:

第一类,是 Mods 专属的位置 。对应上图的橙底实线边框的部分。
比如提示框上方的横条、侧边面板。还有提示框下方的状态行、右上角的通知,以及会话记录里的日志行。
在这些位置上,Mods 可以放置文字、按钮、输入框、下拉列表,以及彩色的字符网格,做成可以交互的小工具,甚至小游戏。
第二类,是 Claude Code 自己绘制的界面 。对应上图的灰底虚线边框的部分。
比如会话消息、工具调用行、加载动画,以及 Claude 向你提问的对话框。
Mods 可以只改其中的某个细节,比如在加载动画后面加一句提示,也可以把它整个替换掉。
当然,并不是所有界面都能改。比如提示词输入框、请求你授权的权限确认框,就仍然归 Claude Code 自己管,Mods 无法改变它们显示的内容,对应上图的灰底无边框的部分。
闪身步就是把字符小人画在侧边面板(Sidebar)里。

不过,这个面板只有在终端足够宽时,才会出现在右侧。终端不够宽、面板放不下时,闪身步就会改画在提示框上方的横条里。

另外,闪身步的动画效果,也需要绕个弯才能实现。因为绘制出来的画面本质上只是一张快照。想让它动起来,就得不断重绘。
闪身步会把动画的方向、当前帧等状态记录下来,每隔 120 毫秒推进一帧。状态一变,Claude Code 就会自动重绘。
一帧接一帧地连起来,就成了站定、起势、三帧闪身、收脚的完整动作。一次闪身步,大约 1.2 秒。
而小人本身,则采用的是经典的字符画形式。这其实是为了适应终端画面做的妥协。在 Claude Code 的桌面版上,则可以把它换成更生动的 SVG 图形。
能力 API
如果说事件钩子决定了 Mods "什么时候做",那能力 API 决定的就是 Mods "能做什么"。
Mods 的代码本身,不能直接读写文件、访问网络或启动程序。所有这些操作,都要通过 Claude Code 提供的能力 API 来完成。

能力 API 的主要用途可归纳为这几类:
-
添加命令和工具:给用户注册新的斜杠命令,或者给 Claude 注册它可以自主调用的新工具。
-
调用模型:在对话之外,向模型提一个小问题,比如给一段文本分类,或者做个总结。
-
后台运行:通过计时器定期执行任务,比如每分钟检查一次 CI 状态,并显示在状态行里。
-
访问文件、进程和网络:读写文件、运行本地命令、发起网络请求。
也正因为 Mods 对外的一切操作都必须经过能力 API,Claude Code 才能在安装之前,就列出一个 Mods 挂了哪些事件、会调用哪些能力。
这就像手机 App 在安装前,会列出它要申请哪些权限一样。
而闪身步,则主要用到了其中三种能力:
-
计时器:按 120 毫秒的节拍推进动画,同时把动画和窗口脚本安排到后台执行。
-
状态:记住动画播到了哪一帧、窗口当前是否已经隐藏。这样既不会重复飞出,也不会在窗口没隐藏时误飞回来。
-
运行本地程序:Mods 本身无法挪动终端窗口,于是闪身步调用了 macOS 自带的 AppleScript 脚本,让窗口滑出屏幕并最小化,再从右侧飞回原位。
合起来看:一个回合里的接力
三类能力其实单独来看,都不复杂。而这个闪身步 Mods 真正花心思的地方,在于让它们在一个回合里让这三类能力接力配合。

回合开始时,事件钩子先观察到 turn.start,再交给计时器,把动画和窗口脚本安排到后台。Claude Code 照常开工,不受影响。
接着,就打开侧边面板进行界面绘制,放不下就画在横条里。
计时器每 120 毫秒推进一帧,并把帧号记进状态。状态一变,界面就自动重绘,小人向右闪身。
小人闪到一半,能力 API 运行 AppleScript,把窗口带出屏幕并最小化,同时在状态里记下"窗口已隐藏"。

回合结束时,流程反过来再走一遍。
事件钩子观察到 turn.complete,状态确认窗口确实藏着。界面先让小人站在右边缘,再由脚本把窗口从右侧带回来。
窗口飞到一半,脚本发出信号,小人随即向左闪身,人和窗口一起落位。
事件钩子决定什么时候开始,能力 API 负责计时、记状态和挪窗口,界面绘制负责把这一切画给你看。三类能力各管一摊,又环环相扣。
Mods 怎么写?
编写 Mods
正如开头所说,写 Mods 并不需要你亲自动手写代码。
直接在 Claude Code 会话中描述你想要的 Mods,Claude 就会帮你写出来。
比如,我让 Claude Code 为我写一个"闪身步" Mods 用的提示词就是这样的:
bash
帮我写一个 Claude Code mod:shanshen-step(闪身步)。参考 GIF:<GIF 的绝对路径>(闪身步舞蹈,8 fps,蓝色背景,左下角有黄色字幕)。
效果:Claude 开始干活(主循环的 turn.start)时,小人向右闪一下,把 Terminal 窗口拽出屏幕并最小化;干完活(主循环的 turn.complete,子代理的忽略)时,窗口飞回来,小人向左闪一下,把窗口带回原位。hook 里不能阻塞,用 $.clock 交给后台;任务串行执行。
小人:
- 用参考 GIF 逐帧抠出人物(去掉背景、踢脚线、字幕,但别把站在字幕上方的脚一起抹掉),转成高密度 ASCII 字符画,风格是 `@B0M8` 这类字母型字符,要密:人占格子 12% 以上就画,色调往密的一端推。
- 姿势用:f10 站立,f01 起,f02--f04 闪,f05 收。GIF 里这次闪身是往右移动的;向左用镜像。
- 按头部对齐,脚落在同一行。
- 深色和浅色终端各一套(按 /config 里的 theme)。
- 预生成多档尺寸,按面板或条带能给的行数挑最大能放下的一档。
- 生成脚本放进插件,可以重新生成。
动画(每帧 120 毫秒):
- 只闪一次:站 0.4 秒 → 起 → 3 帧闪身 → 收 → 站一会儿。
- 闪的距离要大,一次闪大约 1.8 个身宽,身后带速度线。
- 向右从中间偏右闪到右边缘;向左从右边缘闪回起点,站 1 秒后收起。
- 画在 $.ui.open 打开的面板里;面板没显示(isPlaced: false)就关掉它,改画在提示框上方的条带里。
时序(最重要,动画和窗口要交叠):
- 飞出:向右动画播到中间那一帧就开始飞窗口,看起来像小人把窗口拽走。
- 飞回:
1. 先把小人站在右边缘的那一帧画好,再开始飞窗口。
2. 窗口飞到一半时,脚本往 stderr 报一声,插件实时读到($.process.spawn),立刻从"起"开始闪。
3. 窗口后半程放慢,跟闪身同时落位。
窗口(AppleScript,放在插件的 scripts/ 里,用 osascript 加参数数组调用):
- 我会同时开多个 Terminal 窗口,不能用 front window。按本会话所在 tab 的 tty 找到窗口(从当前进程往上找第一个有 tty 的祖先进程),记下 window id 和位置,飞回时按 id 找回来。记录文件按 tty 分开。
- 记得处理负坐标。
- 只在以下情况动窗口:macOS 的 Terminal.app(TERM_PROGRAM 是 Apple_Terminal)、终端界面、userConfig 开关 flyWindow 开着(默认开)。其他情况只播动画。
- 用 $.state 记"窗口已隐藏":不重复飞出,没隐藏时不飞回;session.end 时藏着就飞回。
调试:/shanshen right 和 /shanshen left 只播动画,不动窗口。
完成后:
1. 跑 claude plugin validate、tsc、osacompile(脚本不要真的运行)。
2. 为动画帧和触发时序写 claude plugin test 并跑通,时序要用模拟时钟验证"中点"那两个交接。
3. 告诉我怎么用 claude --plugin-dir 加载。
收到这样的描述后,Claude 会调用一个名为 plugin-authoring 的内置 skill,帮你完成 Mods 的编写和测试:


它甚至还会顺手为你加上调试命令。
比如在闪身步这个例子里,它就提供了 /shanshen right 和 /shanshen left 两个命令,让我们可以直接预览动画效果,不必每次都跑一遍完整流程。

使用 Mods
默认情况下,Claude 写好的 Mods 只会在创建它的那个会话中加载。
Claude Code 里有一个 cleanupPeriodDays 参数,用来设置会话记录和其他应用数据的保留天数。
一旦超过这个天数,Claude Code 就会删除该会话的 mods 文件夹,里面的 Mods 也会跟着消失。
所以,想长期保留一个 Mods,需要把它的目录从 mods 文件夹复制到你自己的位置,例如 ~/mods/shanshen-step。
之后启动 Claude Code 时,运行 claude --plugin-dir ~/mods/shanshen-step,就能显式加载它。
写在最后
Mods 发布后,很多人第一时间把它和 DeepSeek Harness 放在一起比较。
DeepSeek Harness 主张"一切皆插件":模型、工具、会话、沙箱,乃至 Agent Loop 和 UI,全都可以拆下来换掉。
DSH 团队负责人崔添翼也评价,两者殊途同归,只是 Claude Code 目前只把一部分能力开放成了 Mods。
这个判断没错。但"只开放一部分",恰恰契合了 Mods 这个词的含义。
打个比方:
DeepSeek Harness 更像一套游戏引擎,你可以从零搭出一款自己的游戏;
而 Claude Code 的 Mods,更像游戏里的 Mod。游戏本身已经打磨好了,你要做的,只是让它更合你的心意。
两者没有高下之分,只是服务的人不同:一边是想从底层造一个 Agent 的人,一边是想把手上的 Agent 用得更顺手的人。

用 Mods,你不需要重写 Agent Loop,也不需要自己调教上下文和权限。Claude Code 把这些最难、最容易出错的部分留在核心里,只打开了事件、界面和能力这三扇门。
所以,Mods 的价值不在于能改多少,而在于:在一个已经足够好用的 Agent 上,加上专属于你的那一部分。
就像开头的那个"闪身步" Mods。
