
OpenClaw 装好了,模型也配了,Telegram 也接了。然后呢?
你让它帮你查天气,它说”我没有这个能力”。你让它帮你管理 Notion 笔记,它也说不行。你去 ClawHub 搜,发现那个技能上次更新是一个月前,还不兼容最新版。
这时候你有两个选择:等别人写,或者自己动手。
今天这篇文章,我带你从零开始,用 TypeScript 给 OpenClaw 写一个自定义插件。不是那种”Hello World”级别的演示,而是一个真正能用的工具——一个 GitHub 仓库监控插件,能定时检查你关注的项目有没有新 Release,然后通过消息平台通知你。
整个过程 10 分钟。代码不超过 100 行。
先搞清楚:Skill 和 Plugin 有什么区别
OpenClaw 有两套扩展机制,很多人搞混。
Skill(技能) 是自然语言驱动的。一个 Skill 就是一个文件夹,核心是 SKILL.md 文件——用 Markdown 写的”使用说明书”。你告诉 AI “这个工具是做什么的、什么时候该用、怎么用”,AI 自己判断何时调用。
1 2
| my-skill/ └── SKILL.md # 用自然语言告诉 AI 怎么用这个工具
|
Plugin(插件) 是代码驱动的。用 TypeScript 写,通过 jiti 在运行时加载,能注册工具、钩子、频道、模型提供商,甚至自定义斜杠命令。它跑在 Gateway 进程里,和核心代码共享同一个信任边界。
1 2 3 4
| my-plugin/ ├── openclaw.plugin.json # 插件清单 ├── index.ts # 入口文件 └── package.json # 依赖管理
|
什么时候用 Skill,什么时候用 Plugin?
| 场景 |
推荐 |
| 教 AI 用已有的命令行工具 |
Skill |
| 定义 Agent 的行为规则 |
Skill |
| 包装一个 API 调用 |
Skill 或 Plugin |
| 注册新的消息平台(如钉钉) |
Plugin |
| 注册新的模型提供商 |
Plugin |
| 添加自定义生命周期钩子 |
Plugin |
| 需要复杂状态管理和类型安全 |
Plugin |
简单说:Skill 是给 AI 看的说明书,Plugin 是给 Gateway 跑的代码。 今天我们聚焦 Plugin。
Plugin 的核心 API:5 分钟看懂
OpenClaw 的 Plugin API 极其简洁。一个插件只需要导出一个函数或一个对象:
方式一:导出函数(最简单)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| import type { PluginAPI } from 'openclaw/plugin-sdk';
export default function(api: PluginAPI) { api.registerTool({ name: 'my-tool', description: '这是我的工具', parameters: { type: 'object', properties: { query: { type: 'string', description: '查询内容' } }, required: ['query'] }, execute: async (params) => { return { result: `你查询了: ${params.query}` }; } }); }
|
方式二:导出对象(推荐,支持配置校验)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import type { PluginAPI } from 'openclaw/plugin-sdk';
export default { id: 'my-plugin', name: 'My Plugin', configSchema: { type: 'object', properties: { apiKey: { type: 'string' } } }, register(api: PluginAPI) { } };
|
register(api) 里可以调用的注册方法:
| 方法 |
作用 |
registerTool |
注册一个 AI 可调用的工具 |
registerHook |
注册生命周期钩子 |
registerChannel |
注册新的消息平台 |
registerProvider |
注册模型提供商 |
registerCommand |
注册斜杠命令(不经过 AI) |
registerHttpRoute |
注册 HTTP 路由 |
registerService |
注册后台服务 |
就这些。没有复杂的继承链,没有抽象工厂,没有装饰器魔法。一个函数,注册你想要的能力,完事。
实战:写一个 GitHub Release 监控插件
现在来写一个真正有用的插件。需求很简单:
- 监控指定的 GitHub 仓库
- 发现新 Release 时通知用户
- 支持通过斜杠命令手动检查
第 1 步:创建项目结构
1 2
| mkdir github-release-monitor cd github-release-monitor
|
创建 package.json:
1 2 3 4 5 6
| { "name": "openclaw-github-release-monitor", "version": "1.0.0", "main": "index.ts", "dependencies": {} }
|
创建插件清单 openclaw.plugin.json:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| { "id": "github-release-monitor", "name": "GitHub Release Monitor", "version": "1.0.0", "description": "Monitor GitHub repos for new releases", "entry": "index.ts", "configSchema": { "type": "object", "properties": { "repos": { "type": "array", "items": { "type": "string" }, "description": "要监控的仓库列表,格式: owner/repo" }, "githubToken": { "type": "string", "description": "GitHub Personal Access Token(可选,提高 API 限额)" } } } }
|
第 2 步:编写核心逻辑
创建 index.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
| import type { PluginAPI } from 'openclaw/plugin-sdk';
interface ReleaseInfo { repo: string; tag: string; name: string; url: string; publishedAt: string; }
const notifiedReleases = new Set<string>();
async function checkRelease( repo: string, token?: string ): Promise<ReleaseInfo | null> { const headers: Record<string, string> = { 'Accept': 'application/vnd.github.v3+json', 'User-Agent': 'OpenClaw-Plugin' }; if (token) { headers['Authorization'] = `Bearer ${token}`; }
const res = await fetch( `https://api.github.com/repos/${repo}/releases/latest`, { headers } );
if (!res.ok) return null;
const data = await res.json(); const key = `${repo}@${data.tag_name}`;
if (notifiedReleases.has(key)) return null; notifiedReleases.add(key);
return { repo, tag: data.tag_name, name: data.name || data.tag_name, url: data.html_url, publishedAt: data.published_at }; }
export default { id: 'github-release-monitor', name: 'GitHub Release Monitor',
register(api: PluginAPI) { const config = api.getConfig(); const repos: string[] = config?.repos || []; const token: string | undefined = config?.githubToken;
api.registerTool({ name: 'check_github_releases', description: '检查指定 GitHub 仓库的最新 Release', parameters: { type: 'object', properties: { repo: { type: 'string', description: '仓库名,格式: owner/repo' } }, required: ['repo'] }, execute: async (params: { repo: string }) => { const res = await fetch( `https://api.github.com/repos/${params.repo}/releases/latest`, { headers: { 'Accept': 'application/vnd.github.v3+json', 'User-Agent': 'OpenClaw-Plugin', ...(token ? { 'Authorization': `Bearer ${token}` } : {}) } } );
if (!res.ok) { return { error: `无法获取 ${params.repo} 的 Release 信息` }; }
const data = await res.json(); return { repo: params.repo, latest_release: data.name || data.tag_name, tag: data.tag_name, published_at: data.published_at, url: data.html_url, body: data.body?.slice(0, 500) }; } });
api.registerCommand({ name: 'releases', description: '检查所有监控仓库的最新 Release', execute: async () => { if (repos.length === 0) { return '未配置监控仓库。请在插件配置中添加 repos 列表。'; }
const results = await Promise.all( repos.map(repo => checkRelease(repo, token)) );
const newReleases = results.filter(Boolean) as ReleaseInfo[];
if (newReleases.length === 0) { return '所有监控仓库暂无新 Release。'; }
return newReleases .map(r => `📦 ${r.repo} 发布了 ${r.tag}\n ${r.name}\n ${r.url}`) .join('\n\n'); } }); } };
|
第 3 步:安装和测试
1 2 3 4 5 6 7 8 9 10 11 12
| openclaw plugins install -l ./github-release-monitor
openclaw plugins enable github-release-monitor
openclaw config set plugins.entries.github-release-monitor.config.repos \ '["facebook/react", "openclaw/openclaw", "denoland/deno"]'
openclaw gateway restart
|
测试:
AI 会自动调用你注册的 check_github_releases 工具,返回最新 Release 信息。
从写代码到跑起来,不到 10 分钟。
进阶:给插件加上生命周期钩子
上面的插件已经能用了,但它是被动的——需要你主动去问。如果想让它定时自动检查呢?
可以用 registerHook 注册一个定时钩子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| api.registerHook({ event: 'cron', schedule: '0 */6 * * *', handler: async (ctx) => { const results = await Promise.all( repos.map(repo => checkRelease(repo, token)) );
const newReleases = results.filter(Boolean) as ReleaseInfo[];
if (newReleases.length > 0) { const message = newReleases .map(r => `📦 ${r.repo} 发布了 ${r.tag}: ${r.name}\n${r.url}`) .join('\n\n');
await ctx.notify(message); } } });
|
这样每 6 小时,插件会自动检查所有监控仓库,有新 Release 就主动推送通知。
插件开发的 5 个最佳实践
1. 用链接模式开发
1
| openclaw plugins install -l ./my-plugin
|
-l 参数创建符号链接而不是复制文件。修改代码后只需重启 Gateway,不用反复 install。这个体验类似于 npm link。
2. 善用 openclaw plugins doctor
这个命令会诊断所有插件的状态——加载失败、配置错误、依赖缺失,一目了然。调试时先跑一遍 doctor,能省大量时间。
3. 配置校验放在 configSchema 里
不要在代码里手动校验配置。把 JSON Schema 写进 openclaw.plugin.json 的 configSchema 字段里,OpenClaw 会在加载前自动校验,给用户清晰的错误提示。
4. 注意插件发现的优先级
OpenClaw 扫描插件的顺序:
1 2 3 4
| 1. plugins.load.paths(配置路径) ← 最高优先级 2. <workspace>/.openclaw/extensions/ (工作区) 3. ~/.openclaw/extensions/ (全局) 4. 内置插件 ← 最低优先级
|
同名插件,高优先级的会覆盖低优先级的。这意味着你可以 Fork 任何内置插件,放到工作区目录下做自定义修改,而不需要动内置代码。
5. 安全意识
插件跑在 Gateway 进程里,没有沙箱隔离。它和核心代码共享同一个进程。这意味着:
- 不要在插件里执行不受信任的代码
- API Key 等敏感信息用
openclaw config set 管理,不要硬编码
- 发布到 ClawHub 前仔细审查代码,社区已经发现过恶意插件
发布到 ClawHub
插件写好测试通过后,可以发布到 ClawHub 让更多人使用。
打包
发布
1 2 3 4 5
| npm install -g clawhub
clawhub publish ./openclaw-github-release-monitor-1.0.0.tgz
|
发布时需要设置标签(如 github、monitoring、release)和版本策略。用户可以通过一条命令安装:
1
| clawhub install github-release-monitor
|
截至目前,ClawHub 上已有超过 5400 个 Skills 和数百个 Plugins。生态还在快速增长。
更简单的路:用 Skill 解决 80% 的问题
最后说一个实话:大多数场景下,你根本不需要写 Plugin。
如果你只是想让 AI 学会一个新能力,写一个 SKILL.md 就够了。5 分钟搞定,不用写 TypeScript,不用重启 Gateway。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| --- name: github-release-checker description: 检查 GitHub 仓库的最新 Release 信息 ---
# GitHub Release 检查
当用户询问某个 GitHub 项目的最新版本或 Release 时使用此技能。
## 使用方法
使用 curl 调用 GitHub API:
`url -s https://api.github.com/repos/{owner}/{repo}/releases/latest `
## 输出要求
- 提取 tag_name、name、published_at、html_url 字段 - 用简洁的中文告诉用户最新版本号和发布时间 - 附上 Release 页面链接
|
把这个文件夹放到 ~/.openclaw/skills/github-release-checker/ 下面,AI 就自动学会了。
Skill 适合 80% 的场景,Plugin 解决剩下 20% 需要深度集成的问题。 先用 Skill 试试,不够了再升级到 Plugin。
写在最后
OpenClaw 的扩展系统设计得非常克制——Skill 用自然语言,Plugin 用 TypeScript,各有分工,互不干扰。
这种设计带来了一个巨大的好处:任何人都能参与扩展。不会写代码的人用 Skill,会写代码的人用 Plugin。社区因此爆发——3 个月内贡献了 5400 多个扩展,覆盖了从邮件管理到智能家居的几乎所有场景。
如果你今天只记住一件事:先写 SKILL.md,不够了再写 TypeScript。 最简单的方案,往往是最好的方案。
你给 OpenClaw 写过什么有意思的 Skill 或 Plugin?有没有什么场景是现有扩展覆盖不了、必须自己动手的?欢迎在评论区分享你的开发经验和踩过的坑。