$ 接收,方法按命名空间分组,例如 $.ui 和 $.fs。事件决定何时运行 hook,mods API 是 hook 运行后调用的内容。
在开始之前,请构建您的第一个 mod。对于每个方法,请参阅 mods API 方法或阅读您的构建的类型。
添加命令或工具
mod 可以添加供用户运行的命令和供 Claude 调用的工具。在session.start hook 中注册两者。Claude Code 在第一个提示之前等待该 hook,因此您注册的内容从第一轮开始就可用。
添加命令
命令是供用户使用的。注册它,然后为其名称处理command.run。此示例添加了一个 /standup 命令,该命令接受可选的天数:
/standup 及其描述会出现在您键入 / 时看到的列表中。argumentHint 在您键入命令和空格后显示在提示中,如 /standup [days]。当您运行 /standup 3 时,第二个 hook 返回 Summary for the last 3 day(s): ...,并且成绩单在插件名称后显示该文本。hook 永远不会调用 next,因为该命令除了您的行为外没有其他行为。
您返回的 text 会打印在成绩单中,Claude 会读取它。要不打印任何内容,如仅打开窗格的命令,请返回 {}。要让命令在 Claude 工作时运行,请在注册中添加 immediate: true。
选择一个没有内置命令使用的名称。在会话中键入 / 以查看它们。$.command.register 对于已占用的名称会抛出异常,并显示诸如 "/focus" refused: it is the built-in /focus" 的消息。抛出异常的 hook 会被跳过,因此您的 session.start hook 的其余部分也不会运行。在该 hook 中最后注册命令,或将调用包装在 try 和 catch 中。
添加工具
工具是供 Claude 使用的。使用名称、Claude 读取的描述和其输入的 JSON Schema 注册它。Claude 在由mcp__、您的插件名称、两个下划线和您注册的名称组成的较长名称下看到它。您在 tool.call hook 中处理其调用,该 hook 被过滤到该完整名称。此示例来自名为 my-mod 的插件,注册 ticket,因此完整名称是 mcp__my-mod__ticket。它为 Claude 提供了一个在问题跟踪器中查找工单的工具:
mcp__my-mod__ticket。第二个 hook 获取工单并返回响应体,Claude 将其作为工具的结果读取。当服务器以错误状态回答时,Claude 读取 Lookup failed with status 和数字。
调用模型
mod 可以向模型提出自己的问题,在对话之外,用于排序或总结文本等小工作。$.model.complete 使用您的会话凭据向模型发送一个提示,并解析为回复。它没有对话历史。
此 hook 通过要求小型模型标记在其后键入的文本来回答 /triage 命令(注册为命令):
/triage the export button does nothing 时,mod 将该文本发送到模型并打印其答案,例如 Label: bug。Claude 的对话不是请求的一部分。当模型不回答时,标签是 unknown。
Claude API 失败不会拒绝调用,因此检查 r.isAnswered,当其为 false 时读取 r.reason。调用仅对 Claude Code 不会发送的请求拒绝,例如您的组织阻止的模型。您的构建的类型列出其他选项,例如 effort,限制给出 maxTokens 默认值。
$.model.fork({ prompt }) 改为在当前对话上提出一个问题,使用相同的模型和系统提示,因此 Claude API 从提示缓存为大部分内容提供服务。
这些调用使用用户的计划或 API 密钥。
在后台运行工作
超越一个事件的工作,例如每分钟检查一次,在您从session.start 启动的计时器上运行。hook 本身为一个事件运行,其自身运行时间限制为 10 秒。在 next 或 mods API 调用上花费的时间不计算,除了 $.clock.sleep。$.clock.every 和 $.clock.after 代替 setInterval 和 setTimeout,延迟以毫秒为单位:$.clock.after(5000, fn) 在五秒后调用 fn 一次。每个都返回一个带有 cancel() 方法的计时器,await $.clock.now() 给出以毫秒为单位的时间。
此 hook 每分钟查找一次拉取请求的检查,并在提示下显示结果。summarize 是您自己的函数,将命令的 JSON 输出转换为几个单词:
⚠、mod 的名称,然后是 checks: 和您的摘要。之后每分钟替换一次。计时器的回调在任何事件之外运行,因此它在轮次之间保持运行,不会启动一个。如果回调抛出异常,错误会进入调试日志,计时器在下一个间隔再次运行。
显示内容而不启动轮次
后台工作可以显示用户内容而不启动轮次。这些调用中的每一个都将文本放在不同的位置:从后台工作启动轮次
当后台工作发现需要 Claude 注意的内容时,它可以通过使用$.prompt.submit({ text }) 提交提示来启动轮次。Claude 在命名您的 mod 为发送者的句子后读取文本。要将其作为用户自己的话发送,不带该句子,请添加 asUser: true。调用等待直到会话空闲,然后启动新轮次。它在该轮次启动时解析,因此不要在 Claude 工作时运行的处理程序中 await 它。
停止后台工作
后台工作以两种方式停止。当模块重新加载时,计时器停止。对于 hook 内的长时间运行工作,next.signal 是一个 AbortSignal,当您的 hook 处理的事件被放弃时中止,例如当用户中断时,因此将其传递给任何长时间运行的内容。
在会话之间发送和接收消息
mod 可以向您的另一个会话或此会话的子代理之一发送纯文本消息,并观察到达和离开的消息。$.session.send({ to, text }) 发送一个,与 SendMessage 工具进行相同的传递。to 是 { sessionId } 用于会话,{ agentId } 用于来自 $.agent.list() 的子代理,或接收消息来自的字符串地址。调用在消息排队后解析,带有 { isDelivered: true }。当没有传递任何内容时,它使用 { isDelivered: false, reason } 解析,reason 说明原因。
此 hook 通过要求您在其后键入的 id 的会话获取状态来回答 /ping 命令(注册为命令):
Status? One line.。当没有传递任何内容时,右上角的小框给出原因并在几秒后消失。
两个事件让 mod 观察消息。从两者都返回 next(e) 以不变地传递每条消息:
设置为拒绝入站消息的会话在
session.receive 触发之前拒绝消息,因此 hook 永远看不到它。为您的批准而保留的消息首先到达 hook,因此 mod 可以读取您尚未批准的消息。hook 的 next(e) 在消息未传递时拒绝。
接收消息上的发送者名称是发送者写的任何内容,因此不要基于它做出决定。
访问文件、进程和网络
mod 通过 mods API 访问文件系统、进程和网络,具有与运行 Claude Code 的用户相同的权限。hooks 模块本身没有 Node.js API、没有计时器全局变量(如setTimeout),也没有自己的网络或文件访问。标准 JavaScript 和 Web API(如 URL、TextEncoder、AbortController 和 crypto.subtle)可用。下面的每个命名空间涵盖一种访问:
文件和进程有一些自己的规则:
- 路径:相对路径在会话的工作目录下
$.fs.list:将一个目录的条目作为{ name, kind, size, isLink }返回,不下降到子目录$.process.run:接受参数列表,不使用 shell。它解析为{ exitCode, stdout, stderr },无论退出代码如何。如果程序无法启动或在超时时仍在运行,它会拒绝,默认为 30 秒,因此将其包装在try和catch中。
$.,例如 fs.read 用于 $.fs.read。链中较早的 mod 可以观察、重写或拒绝您的调用,这是组织限制 mod 到达的方式。