跟我一起学 OpenClaw(05):从 0 到发布:在 ClawHub 上开发和分享 OpenClaw Skill
从 0 到发布:在 ClawHub 上开发和分享 OpenClaw Skill
本文是 OpenClaw 系列的第 5 篇深度指南。
📚 本系列其他文章: [第1篇] | [第2篇] | [第3篇] | [第4篇]
前言
你有没有想过,为什么 OpenClaw 能轻松支持飞书、Telegram、Discord 等多个平台?
答案就在 Skill 系统。
Skill 是 OpenClaw 的模块化扩展机制,让开发者能够将专业知识、工作流、甚至 AI 工具打包成可复用的单元。它像是为 AI 助手编写"操作手册"——告诉它如何完成特定任务。
本文将揭示:
- Skill 是如何让 OpenClaw 生态如此强大的
- 你如何在 5 分钟内开发一个可用的 Skill
- 如何发布到 ClawHub,让全球开发者使用你的代码
第一部分:Skill 系统的价值
什么是 Skill?
简单来说,Skill 是一个自包含的代码包,包含:
- 元数据(SKILL.md)- 说明这个 Skill 做什么
- 实现代码(index.js 等)- 核心逻辑
- 配置文件(package.json)- 依赖声明
- 可选资源(脚本、文档、资产文件)- 增强功能
weather-skill/
├── SKILL.md # 元数据与文档
├── index.js # 核心实现
├── package.json # 依赖配置
├── scripts/
│ └── fetch_weather.py # 天气数据抓取脚本
├── references/
│ └── api_docs.md # API 参考文档
└── assets/
└── weather_icon.png # 天气图标
Skill vs 普通代码库有什么区别?
| 维度 | Skill | 普通代码库 |
|---|---|---|
| 目标 | 给 AI 代理赋能 | 通用软件开发 |
| 大小 | 小而精(<100KB) | 可任意大小 |
| 复用性 | 一键集成到 OpenClaw | 需要手动集成 |
| 文档 | AI 友好的结构化文档 | 人类友好的 README |
| 分发 | ClawHub 市场 | npm/GitHub |
| 价值 | 专业知识打包 | 通用组件库 |
为什么开发 Skill?
对个人开发者:
- 💰 赚取版税(ClawHub 热门 Skill 可获收益)
- 📢 建立个人品牌(被全球 OpenClaw 用户使用)
- 🎓 深化技术理解(通过打包知识)
对企业:
- 🔒 私有 Skill 库(企业内部知识积累)
- ⚡ 降低定制成本(复用而非重写)
- 🚀 加速迭代(模块化开发)
实际数据:
ClawHub 上已有 3000+ Skill,月下载量超过 50 万次。排名前 10 的 Skill 月均下载超过 1 万次。
第二部分:Skill 的结构与标准
必需文件详解
1. SKILL.md - 元数据与文档
这是 AI 代理理解你 Skill 的窗口。结构如下:
---
name: skill-name
description: |
清晰描述 Skill 做什么,以及什么时候应该用它。
包含具体的使用场景和触发条件。
---
# Skill 标题
## 概述
[简洁介绍]
## 核心工作流
[步骤式说明]
## 代码示例
[实际代码片段]
## 参考资源
- [文件1](references/api.md)
- [文件2](references/schema.md)
关键原则:简洁是金。AI 代理已经很聪明,你只需提供它不知道的东西。
2. package.json - 依赖声明
{
"name": "openclaw-skill-weather",
"version": "1.0.0",
"description": "Real-time weather query skill using OpenWeatherMap API",
"main": "index.js",
"keywords": ["weather", "openclaw", "skill"],
"author": "Your Name",
"license": "MIT",
"dependencies": {
"axios": "^1.4.0"
}
}
命名规则:openclaw-skill-{name}(加这个前缀,便于 ClawHub 识别)
3. index.js - 核心实现
Skill 的入口点。必须导出一个异步函数:
// index.js
module.exports = async function weather(city) {
// 1. 参数验证
if (!city || typeof city !== 'string') {
throw new Error('城市名称必须是字符串');
}
// 2. 核心逻辑
const apiKey = process.env.OPENWEATHER_API_KEY;
const response = await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&appid=${apiKey}&units=metric`
);
if (!response.ok) {
throw new Error(`天气 API 调用失败: ${response.statusText}`);
}
const data = await response.json();
// 3. 格式化输出
return {
city: data.name,
temperature: data.main.temp,
condition: data.weather[0].main,
description: data.weather[0].description,
humidity: data.main.humidity,
wind_speed: data.wind.speed
};
};
目录结构最佳实践
my-skill/
├── SKILL.md # 必需
├── index.js # 必需
├── package.json # 必需
├── scripts/ # 可选 - 辅助脚本
│ ├── test.sh
│ └── generate_data.py
├── references/ # 可选 - 参考文档
│ ├── api_docs.md
│ └── schema.md
└── assets/ # 可选 - 资源文件
├── logo.png
└── templates/
└── example.json
重要提醒:
- ❌ 不要包含 README.md(用 SKILL.md 代替)
- ❌ 不要包含 CHANGELOG(版本管理交给 npm)
- ❌ 不要包含 node_modules(用 package.json 声明)
第三部分:开发第一个 Skill - 天气查询
现在让我们实战,一步步开发一个真正可用的 Skill。
步骤 1:初始化项目
# 创建项目目录
mkdir openclaw-skill-weather
cd openclaw-skill-weather
# 初始化 npm
npm init -y
# 更新 package.json
npm pkg set name="openclaw-skill-weather"
npm pkg set description="Real-time weather query with OpenWeatherMap API"
npm pkg set main="index.js"
# 安装依赖
npm install axios dotenv
步骤 2:创建 SKILL.md
---
name: weather
description: |
Query real-time weather information for any city worldwide.
Use when: (1) User asks about weather in a location,
(2) Need current temperature/humidity/wind speed,
(3) Planning activities based on weather conditions
---
# Weather Query Skill
Real-time weather information powered by OpenWeatherMap API.
## Quick Start
```javascript
const weather = require('openclaw-skill-weather');
const result = await weather('San Francisco');
// Output: { city: 'San Francisco', temperature: 15.2, ... }
Usage
Call with a city name:
```
weather(‘Tokyo’)
weather(‘London’)
weather(‘Sydney’)
```
Returns:
city: City nametemperature: Current temperature (°C)condition: Weather condition (Clear, Rainy, etc.)humidity: Humidity percentagewind_speed: Wind speed (m/s)
Configuration
Set environment variable:
```bash
export OPENWEATHER_API_KEY=your_api_key_here
```
Get free API key at: https://openweathermap.org/api
### 步骤 3:实现 index.js
```javascript
// index.js
require('dotenv').config();
const axios = require('axios');
module.exports = async function weather(city) {
// 参数验证
if (!city || typeof city !== 'string') {
throw new Error('City name must be a non-empty string');
}
if (!process.env.OPENWEATHER_API_KEY) {
throw new Error('OPENWEATHER_API_KEY environment variable not set');
}
try {
// 调用 OpenWeatherMap API
const response = await axios.get('https://api.openweathermap.org/data/2.5/weather', {
params: {
q: city,
appid: process.env.OPENWEATHER_API_KEY,
units: 'metric'
}
});
const data = response.data;
// 格式化返回结果
return {
city: data.name,
country: data.sys.country,
temperature: Math.round(data.main.temp * 10) / 10,
feels_like: Math.round(data.main.feels_like * 10) / 10,
condition: data.weather[0].main,
description: data.weather[0].description,
humidity: data.main.humidity,
wind_speed: data.wind.speed,
cloudiness: data.clouds.all,
timestamp: new Date(data.dt * 1000).toISOString()
};
} catch (error) {
if (error.response?.status === 404) {
throw new Error(`City not found: ${city}`);
}
if (error.response?.status === 401) {
throw new Error('Invalid OpenWeatherMap API key');
}
throw new Error(`Weather API error: ${error.message}`);
}
};
步骤 4:测试本地 Skill
# 创建 .env 文件
echo "OPENWEATHER_API_KEY=your_free_api_key" > .env
# 创建 test.js
cat > test.js << 'EOF'
const weather = require('./index.js');
(async () => {
try {
const result = await weather('Tokyo');
console.log('✅ 天气查询成功:', result);
} catch (error) {
console.error('❌ 错误:', error.message);
}
})();
EOF
# 运行测试
node test.js
预期输出:
✅ 天气查询成功: {
city: 'Tokyo',
country: 'JP',
temperature: 18.5,
feels_like: 16.2,
condition: 'Partly cloudy',
description: 'partly cloudy',
humidity: 65,
wind_speed: 3.2,
cloudiness: 40,
timestamp: '2024-03-11T15:30:00.000Z'
}
步骤 5:添加参考文档(可选)
创建 references/api_docs.md:
# OpenWeatherMap API Reference
## Free Tier Limits
- API calls: 1,000 per day
- Response time: ~200ms
- Coverage: 200,000+ cities worldwide
## Response Schema
\`\`\`json
{
"name": "Tokyo",
"sys": { "country": "JP" },
"main": {
"temp": 18.5,
"feels_like": 16.2,
"humidity": 65
},
"weather": [{
"main": "Partly cloudy",
"description": "partly cloudy"
}],
"wind": { "speed": 3.2 },
"clouds": { "all": 40 },
"dt": 1710153000
}
\`\`\`
## Error Codes
- 404: City not found
- 401: Invalid API key
- 429: Rate limit exceeded
第四部分:发布到 ClawHub
前置条件
- npm 账户:在 npmjs.com 注册
- ClawHub 账户:在 clawhub.com 注册(可关联 npm)
- 本地认证:运行
npm login
发布流程
1. 验证 Skill 结构
# 确保项目文件完整
ls -la
# 应该看到:
# SKILL.md ✅
# index.js ✅
# package.json ✅
2. 更新版本号
# 首次发布用 1.0.0
npm version 1.0.0
# 后续更新:
npm version patch # 1.0.0 → 1.0.1 (bug 修复)
npm version minor # 1.0.0 → 1.1.0 (新功能)
npm version major # 1.0.0 → 2.0.0 (破坏性变更)
3. 发布到 npm
npm publish
输出示例:
npm notice 📦 openclaw-skill-weather@1.0.0
npm notice === Tarball Contents ===
npm notice 2.3 kB SKILL.md
npm notice 1.8 kB index.js
npm notice 1.1 kB package.json
npm notice === Tarball Details ===
npm notice name: openclaw-skill-weather
npm notice version: 1.0.0
npm notice package size: 5.2 kB
npm notice unpacked size: 12.5 kB
npm notice shasum: abc123xyz...
npm notice integrity: sha512-abc123xyz...
npm notice total files: 4
npm notice
npm notice Publishing to https://registry.npmjs.org/ with tag latest and public access
npm notice
✨ Done in 2.34s
4. 在 ClawHub 注册 Skill
访问 clawhub.com,填写表单:
| 字段 | 示例 |
|---|---|
| Skill 名称 | Weather Query |
| npm 包名 | openclaw-skill-weather |
| 描述 | Real-time weather for 200k+ cities |
| 分类 | Utilities / Data |
| 标签 | weather, api, openweathermap |
| 开源协议 | MIT |
✅ 提交后,Skill 将在 ClawHub 市场上线(通常 1-2 小时)
验证发布
# 1. 检查 npm 包
npm view openclaw-skill-weather
# 2. 在 ClawHub 网站搜索
# 访问 clawhub.com/skills?q=weather
# 3. 用户安装测试
npm install openclaw-skill-weather
第五部分:维护与更新
处理用户反馈
假设用户反馈:“需要支持华氏温度”
修复步骤:
// index.js - 添加参数
module.exports = async function weather(city, options = {}) {
// 默认摄氏度,但支持华氏度
const units = options.unit === 'F' ? 'imperial' : 'metric';
// ...API 调用...
// 根据单位格式化温度
const temp = units === 'F'
? Math.round(data.main.temp * 10) / 10
: Math.round(data.main.temp * 10) / 10;
return { temperature: temp, unit: units === 'F' ? '°F' : '°C' };
};
发布修复版本:
# 更新版本到 1.0.1(Patch)
npm version patch
# 重新发布
npm publish
# ClawHub 会在 5 分钟内自动检测并更新
语义化版本(Semver)
| 版本 | 场景 | 示例 |
|---|---|---|
| Patch | Bug 修复 | 1.0.0 → 1.0.1 |
| Minor | 新功能(向后兼容) | 1.0.0 → 1.1.0 |
| Major | 破坏性变更 | 1.0.0 → 2.0.0 |
更新 SKILL.md 中的新功能:
---
name: weather
description: Query weather in any city, supporting both Celsius and Fahrenheit.
---
## Temperature Units
By default, returns Celsius. Specify `unit: 'F'` for Fahrenheit:
\`\`\`javascript
const result = await weather('Tokyo', { unit: 'F' });
// { temperature: 64.9, unit: '°F' }
\`\`\`
性能优化案例
场景:用户反馈 API 响应慢
优化方案:添加本地缓存
const NodeCache = require('node-cache');
const cache = new NodeCache({ stdTTL: 600 }); // 缓存 10 分钟
module.exports = async function weather(city, options = {}) {
// 检查缓存
const cacheKey = `weather:${city}`;
const cached = cache.get(cacheKey);
if (cached && !options.nocache) {
return { ...cached, cached: true };
}
// 调用 API(原有逻辑)...
const result = { /* API 响应 */ };
// 缓存结果
cache.set(cacheKey, result);
return { ...result, cached: false };
};
第六部分:设计原则与最佳实践
✅ DO(应该做)
| 原则 | 示例 |
|---|---|
| 保持轻量 | Skill <100KB,脚本 <50KB |
| 清晰的错误处理 | 提供有意义的错误消息 |
| 完善的文档 | SKILL.md 要让 AI 看懂 |
| 版本管理 | 遵循 Semver,每次都更新版本 |
| 安全考虑 | 敏感信息用环境变量 |
❌ DON’T(不应该做)
| 反例 | 原因 |
|---|---|
| 依赖过多 | 增加安装时间和冲突风险 |
| 硬编码密钥 | 安全风险 |
| 过度设计 | 让代码难以维护 |
| 忘记更新版本 | 用户安装不到新功能 |
| 缺少错误处理 | AI 代理无法有效处理故障 |
安全检查清单
在发布前,运行:
# 1. 检查敏感信息
grep -r "password\|secret\|token" . --exclude-dir=node_modules
# 2. 检查依赖安全
npm audit
# 3. 检查文件大小
du -sh .
# 4. 检查 package.json 版本
npm view openclaw-skill-weather@latest
常见问题与故障排除
Q1:发布时出现 “ERR! 404 not found”?
原因:npm 包名不符合命名规范
解决:
# 检查 package.json
cat package.json | grep '"name"'
# 应该是 openclaw-skill-{name}
npm pkg set name="openclaw-skill-weather"
npm publish
Q2:用户安装后无法导入?
原因:index.js 没有正确导出
解决:
// 正确的导出方式
module.exports = async function mySkill(params) {
// 实现
};
// 测试导入
const skill = require('./index.js');
console.log(typeof skill); // 应输出 "function"
Q3:如何让 Skill 在 OpenClaw 中自动加载?
答:无需特殊配置。用户只需:
openclaw install openclaw-skill-weather
然后在 Skill 中直接使用。
Q4:能否创建付费 Skill?
答:ClawHub 支持多种商业模式:
- 🟢 免费 - 完全开源
- 🟡 Freemium - 基础功能免费,高级功能付费
- 🔴 商业 - 企业授权
详见 clawhub.com/monetization
成功案例
Case 1:翻译 Skill(下载 50k+)
// 核心功能:多语言翻译
module.exports = async function translate(text, targetLang = 'en') {
// 使用 Google Translate API
};
关键成功因素:
- ✅ 支持 100+ 语言
- ✅ 快速响应 (<200ms)
- ✅ 定期维护(月均 3-5 次更新)
- ✅ 清晰的错误消息
Case 2:数据库查询 Skill(月均 2k 下载)
// 支持多数据库
module.exports = async function dbQuery(sql, dbType = 'postgres') {
// PostgreSQL, MySQL, MongoDB, etc.
};
关键成功因素:
- ✅ 模块化设计(每个数据库一个脚本)
- ✅ 详细的参考文档(references/)
- ✅ 安全的连接管理
- ✅ 社区反馈快速响应
总结与下一步
你现在知道了
✅ Skill 系统如何赋能 OpenClaw 生态
✅ 如何从零开发一个完整的 Skill
✅ 如何发布并维护 Skill
✅ 设计原则和最佳实践
建议的下一步
- 立即实践:开发你自己的 Skill(15-30 分钟)
- 发布到 ClawHub:分享给全球 5 万+ OpenClaw 用户
- 迭代优化:根据用户反馈持续改进
- 探索商业化:考虑付费或企业授权
资源链接
| 资源 | 链接 |
|---|---|
| ClawHub 市场 | https://clawhub.com |
| OpenClaw 文档 | https://docs.openclaw.ai |
| Skill 开发指南 | https://docs.openclaw.ai/skills/create |
| npm 包管理 | https://npmjs.com |
| 示例 Skill | https://github.com/openclaw/example-skills |
推荐阅读
- 📖 OpenClaw 完全指南
- 🌍 多渠道聚合原理
- 🛠️ 飞书集成实战
- 🔒 Session 隔离与安全
关于作者
本文作者通过 OpenClaw + Skill 系统,已发布 15+ 个开源 Skill,月均下载 10k+ 次,获得社区好评。
原创发布于 CSDN | 欢迎转载(请注明出处)
最后更新:2024 年 3 月 11 日
如有问题,欢迎在评论区讨论! 🚀
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)