10分钟上手!用TypeScript给OpenClaw写一个自定义插件(附完整代码)

cover

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
// index.ts
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
// index.ts
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;
}

// 记录已通知过的 Release
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;

// 注册工具:让 AI 可以主动检查 Release
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"]'

# 重启 Gateway 让插件生效
openclaw gateway restart

测试:

1
2
3
4
5
# 方式 1:使用斜杠命令
# 在聊天窗口输入 /releases

# 方式 2:自然语言触发
# "帮我检查一下 openclaw/openclaw 的最新版本"

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
// 在 register(api) 里添加
api.registerHook({
event: 'cron',
schedule: '0 */6 * * *', // 每 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

1
openclaw plugins doctor

这个命令会诊断所有插件的状态——加载失败、配置错误、依赖缺失,一目了然。调试时先跑一遍 doctor,能省大量时间。

3. 配置校验放在 configSchema 里

不要在代码里手动校验配置。把 JSON Schema 写进 openclaw.plugin.jsonconfigSchema 字段里,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
npm pack
# 生成 openclaw-github-release-monitor-1.0.0.tgz

发布

1
2
3
4
5
# 安装 ClawHub CLI
npm install -g clawhub

# 发布
clawhub publish ./openclaw-github-release-monitor-1.0.0.tgz

发布时需要设置标签(如 githubmonitoringrelease)和版本策略。用户可以通过一条命令安装:

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?有没有什么场景是现有扩展覆盖不了、必须自己动手的?欢迎在评论区分享你的开发经验和踩过的坑。