文章目录
-
- 摘要
- [SEO 摘要](#SEO 摘要)
- 目录
- 开篇
- 核心知识点
-
- [1. 为什么需要自定义 Skill](#1. 为什么需要自定义 Skill)
-
- [1.1 内置 Skill 的局限](#1.1 内置 Skill 的局限)
- [1.2 自定义 Skill 的价值](#1.2 自定义 Skill 的价值)
- [1.3 Skill 开发 vs 普通脚本](#1.3 Skill 开发 vs 普通脚本)
- [2. Skill 创建标准流程](#2. Skill 创建标准流程)
-
- [2.1 流程概览](#2.1 流程概览)
- [2.2 Step 1: 确定目标和功能](#2.2 Step 1: 确定目标和功能)
- [2.3 Step 2: 创建目录结构](#2.3 Step 2: 创建目录结构)
- [3. SKILL.md 编写规范](#3. SKILL.md 编写规范)
-
- [3.1 文件结构](#3.1 文件结构)
- [3.2 Metadata 板块](#3.2 Metadata 板块)
- [3.3 Trigger 板块(关键)](#3.3 Trigger 板块(关键))
- [3.4 Capabilities 板块](#3.4 Capabilities 板块)
- [4.5 Error Handling 板块](#4.5 Error Handling 板块)
- [4.6 Configuration 板块](#4.6 Configuration 板块)
- [3.7 Changelog 板块](#3.7 Changelog 板块)
- [4. scripts 脚本开发](#4. scripts 脚本开发)
-
- [4.1 语言选择](#4.1 语言选择)
- [4.2 Python 脚本模板](#4.2 Python 脚本模板)
- [4.3 Shell 脚本模板](#4.3 Shell 脚本模板)
- [4.4 脚本规范](#4.4 脚本规范)
专栏定位 :OpenClaw 从入门到精通(第 13 章)
适读人群:开发者、技术爱好者、AI应用创业者
摘要
虽然 OpenClaw 提供了丰富的内置 Skills,但真正的超能力来自于你自己开发的定制化 Skills。本章将手把手教你从零创建一个完整的 Skill:Skill 创建标准流程、SKILL.md 编写规范、scripts 脚本编写、references 文档编写。最后通过一个完整的「Git 操作 Skill」实战案例,串联所有知识点。学完本章,你将能够根据业务需求开发任何你需要的 Skill。
SEO 摘要
OpenClaw 自定义 Skill 开发教程、SKILL.md 编写规范、scripts 脚本开发、references 文档编写、Git Skill 实战案例。
目录
- 为什么需要自定义 Skill
- Skill 创建标准流程
- SKILL.md 编写规范
- scripts 脚本开发
- references 文档编写
- 实战:创建 Git 操作 Skill
- 发布到 ClawHub
- 常见错误与避坑指南
- 术语注释
- 面试高频问答
- 深度扩展
- 附录
- 系列总结(第 01-13 章)
- 版权声明
开篇
OpenClaw 内置的 Skills 解决了 80% 的常见需求,但总有那么 20% 的场景,是通用 Skill 覆盖不到的。
比如:
- 你们公司有自己的内部系统,需要操作特定的 API
- 你的团队使用 Jira 来管理任务,需要和 OpenClaw 集成
- 你想要一个能自动操作你们公司内部后台的工具
这些时候,你就需要自己开发 Skill。
好消息是:开发一个 Skill 并不难。一个基本的 Skill 只需要:
- 一个
SKILL.md定义文件 - 一个或几个脚本文件
只要掌握这两个核心,你就能构建任何你需要的工具。
核心知识点
1. 为什么需要自定义 Skill
1.1 内置 Skill 的局限
| 痛点 | 描述 |
|---|---|
| 内部系统 | 公司的 CRM、ERP、内部工具 |
| 定制化 | 特殊的工作流程和逻辑 |
| 私有 API | 第三方服务没有公开 API |
| 特定场景 | 行业特定的业务逻辑 |
1.2 自定义 Skill 的价值
没有自定义 Skill:
用户 → 手动操作 → 30 分钟
↓
有自定义 Skill:
用户 → OpenClaw → 自动操作 → 30 秒
1.3 Skill 开发 vs 普通脚本
| 维度 | 普通脚本 | Skill |
|---|---|---|
| 调用方式 | 手动运行 | OpenClaw 自然语言触发 |
| 上下文 | 无 | 有(知道用户是谁、当前项目) |
| 参数传递 | 手动传参 | 通过自然语言理解 |
| 输出 | 打印到终端 | 整合到对话中 |
| 可复用性 | 低 | 高 |
2. Skill 创建标准流程
2.1 流程概览
Step 1: 确定 Skill 的目标和功能
Step 2: 创建 Skill 目录结构
Step 3: 编写 SKILL.md
Step 4: 开发 scripts
Step 5: 编写 references 文档
Step 6: 测试 Skill
Step 7: 发布到 ClawHub(可选)
2.2 Step 1: 确定目标和功能
在动手之前,先回答以下问题:
- 这个 Skill 要解决什么问题?
- 用户会用什么话触发这个 Skill?(触发词)
- 需要调用哪些外部 API 或工具?
- 输入和输出是什么?
- 有哪些边界条件和错误处理?
2.3 Step 2: 创建目录结构
bash
# 在 skills 目录下创建新的 Skill
cd ~/.openclaw/skills
mkdir git-workflow
cd git-workflow
# 创建子目录
mkdir -p scripts references assets
完整目录结构:
skills/
└── git-workflow/
├── SKILL.md # 必填:Skill 定义文件
├── scripts/ # 必填:脚本目录
│ ├── main.py # 主脚本
│ └── utils.py # 辅助脚本(可选)
├── references/ # 可选:参考文档
│ ├── usage.md
│ └── api.md
└── assets/ # 可选:静态资源
└── logo.png
3. SKILL.md 编写规范
3.1 文件结构
markdown
# Skill: [Skill 名称]
## Metadata
[基本信息]
## Description
[详细描述]
## Trigger
[何时触发]
## Capabilities
[提供的能力]
## Parameters
[参数说明]
## Examples
[使用示例]
## Configuration
[配置说明]
## Limitations
[已知限制]
## Changelog
[版本历史]
3.2 Metadata 板块
markdown
## Metadata
- **Name:** git-workflow
- **Version:** 1.0.0
- **Author:** Your Name
- **License:** MIT
- **Repository:** https://github.com/yourname/openclaw-skill-git
- **Tags:** git, workflow, development
- **Min OpenClaw Version:** 1.0.0
3.3 Trigger 板块(关键)
Trigger 决定何时使用这个 Skill:
markdown
## Trigger
### Auto-Trigger Keywords
触发这个 Skill 的关键词:
- "git"
- "分支"
- "branch"
- "merge"
- "pr"
- "pull request"
- "代码审查"
- "git flow"
### Context Patterns
更具体的触发场景:
- "帮我创建一个新分支"
- "查看当前分支状态"
- "把这个分支合并到 main"
- "创建一个 PR"
- "最近有哪些提交"
### NOT Trigger When
不应该触发这个 Skill 的情况:
- 用户在说 GitHub 的 Git(可能是其他意思)
- 用户只是在问 Git 是什么(概念性问题)
3.4 Capabilities 板块
定义 Skill 提供的能力:
markdown
## Capabilities
### 1. create_branch
**Description:** 创建新的 Git 分支
**Parameters:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| name | string | 是 | 分支名称 |
| base | string | 否 | 基于哪个分支创建,默认当前分支 |
**Example:**
Input: name="feature/new-feature", base="main"
Output: Successfully created branch 'feature/new-feature' from 'main'
### 2. list_branches
**Description:** 列出所有本地和远程分支
**Parameters:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| local | boolean | 否 | 只显示本地分支 |
| remote | boolean | 否 | 只显示远程分支 |
**Example:**
Input: local=true, remote=false
Output: 显示所有本地分支,当前分支用 * 标记
### 3. create_pr
**Description:** 创建 Pull Request
**Parameters:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| title | string | 是 | PR 标题 |
| body | string | 否 | PR 描述 |
| base | string | 否 | 目标分支,默认 main |
| draft | boolean | 否 | 是否为草稿 PR |
**Example:**
Input: title="feat: add new feature", body="这个 PR 添加了...", base="main"
Output: PR 创建成功: https://github.com/xxx/yyy/pull/123
### 4. recent_commits
**Description:** 查看最近的提交记录
**Parameters:**
| 参数 | 类型 | 必填 | 说明 |
|------|------|------|------|
| count | integer | 否 | 显示多少条,默认 10 |
| author | string | 否 | 只显示某个作者的提交 |
**Example:**
Input: count=5
Output:
- abc1234 (2026-03-30) feat: add login
- def5678 (2026-03-29) fix: resolve bug
...
4.5 Error Handling 板块
markdown
## Error Handling
| 错误情况 | 返回信息 | 处理方式 |
|---------|---------|---------|
| 不是 Git 仓库 | "当前目录不是 Git 仓库" | 提示用户切换目录 |
| 分支已存在 | "分支 {name} 已存在" | 提示用其他名称 |
| 合并冲突 | "存在未解决的合并冲突" | 提示先解决冲突 |
| Git 未安装 | "Git 未安装或不在 PATH 中" | 提示安装 Git |
| 网络错误 | "无法连接到远程仓库" | 检查网络连接 |
4.6 Configuration 板块
markdown
## Configuration
### Required Environment Variables
- `GIT_DEFAULT_REMOTE`: 默认远程仓库名称,默认 origin
### Optional Environment Variables
- `GIT_DEFAULT_BASE_BRANCH`: 默认基础分支,默认 main
- `GIT_PR_TEMPLATE`: PR 描述模板
### GitHub Integration (Optional)
如果需要创建 PR,需要配置:
- `GITHUB_TOKEN`: GitHub Personal Access Token
3.7 Changelog 板块
markdown
## Changelog
### v1.0.0 (2026-03-30)
- 初始版本
- 支持 create_branch, list_branches, create_pr, recent_commits
### v1.1.0 (2026-04-15)
- 添加 merge_branch 功能
- 修复分支列表显示问题
4. scripts 脚本开发
4.1 语言选择
| 语言 | 优势 | 适用场景 |
|---|---|---|
| Python | 生态丰富、易读 | API 调用、数据处理 |
| Shell | 简洁、Unix 工具集成 | Git、系统命令 |
| Node.js | JSON 处理好、异步 | Webhook、实时处理 |
推荐:优先使用 Python(大多数场景),Shell(系统命令集成)。
4.2 Python 脚本模板
python
#!/usr/bin/env python3
"""
Git Workflow Skill - Git 操作辅助工具
"""
import sys
import json
import subprocess
from typing import Dict, Any, Optional, List
# ==================== CLI 接口 ====================
def main():
"""主入口,解析命令行参数并执行对应功能"""
if len(sys.argv) < 2:
print(json.dumps({"error": "Usage: python main.py <action> [args...]"}))
sys.exit(1)
action = sys.argv[1]
args = sys.argv[2:]
# 调用对应的处理函数
if action == "create_branch":
result = create_branch(*args)
elif action == "list_branches":
result = list_branches(*args)
elif action == "create_pr":
result = create_pr(*args)
elif action == "recent_commits":
result = recent_commits(*args)
else:
result = {"error": f"Unknown action: {action}"}
# 输出 JSON 格式结果
print(json.dumps(result, ensure_ascii=False))
# ==================== 功能实现 ====================
def run_git_command(*args) -> subprocess.CompletedProcess:
"""执行 Git 命令的辅助函数"""
try:
result = subprocess.run(
["git"] + list(args),
capture_output=True,
text=True,
check=True
)
return result
except subprocess.CalledProcessError as e:
return e
except FileNotFoundError:
raise RuntimeError("Git is not installed or not in PATH")
def create_branch(name: str, base: str = "HEAD") -> Dict[str, Any]:
"""创建新分支"""
if not name:
return {"error": "Branch name is required"}
# 检查分支是否已存在
check = run_git_command("rev-parse", "--verify", name)
if check.returncode == 0:
return {"error": f"Branch '{name}' already exists"}
# 创建分支
result = run_git_command("checkout", "-b", name)
if result.returncode != 0:
return {"error": f"Failed to create branch: {result.stderr}"}
return {
"success": True,
"message": f"Successfully created and switched to branch '{name}'",
"branch": name
}
def list_branches(local: bool = True, remote: bool = True) -> Dict[str, Any]:
"""列出分支"""
branches = {"local": [], "remote": []}
if local:
result = run_git_command("branch")
if result.returncode == 0:
current = result.stdout.strip().split("\n")
branches["local"] = [
{"name": b.strip("* ").strip(), "current": "*" in b}
for b in current if b.strip()
]
if remote:
result = run_git_command("branch", "-r")
if result.returncode == 0:
branches["remote"] = [
b.strip()
for b in result.stdout.strip().split("\n")
if b.strip() and "->" not in b
]
return {"success": True, "branches": branches}
def recent_commits(count: int = 10, author: Optional[str] = None) -> Dict[str, Any]:
"""查看最近的提交"""
cmd = ["log", f"-{count}", "--pretty=format:%H|%s|%ad|%an", "--date=short"]
if author:
cmd.extend(["--author", author])
result = run_git_command(*cmd)
if result.returncode != 0:
return {"error": f"Failed to get commits: {result.stderr}"}
commits = []
for line in result.stdout.strip().split("\n"):
if "|" in line:
parts = line.split("|")
if len(parts) == 4:
commits.append({
"hash": parts[0],
"message": parts[1],
"date": parts[2],
"author": parts[3]
})
return {"success": True, "count": len(commits), "commits": commits}
def create_pr(title: str, body: str = "", base: str = "main", draft: bool = False) -> Dict[str, Any]:
"""创建 Pull Request(需要 GitHub CLI)"""
# 检查 gh CLI 是否可用
try:
subprocess.run(["gh", "--version"], capture_output=True, check=True)
except (subprocess.CalledProcessError, FileNotFoundError):
return {"error": "GitHub CLI (gh) is not installed or not in PATH"}
cmd = ["gh", "pr", "create", "--title", title]
if body:
cmd.extend(["--body", body])
cmd.extend(["--base", base])
if draft:
cmd.append("--draft")
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
return {"error": f"Failed to create PR: {result.stderr}"}
return {
"success": True,
"message": "Pull Request created successfully",
"url": result.stdout.strip()
}
# ==================== 入口 ====================
if __name__ == "__main__":
main()
4.3 Shell 脚本模板
bash
#!/usr/bin/env bash
# Git Workflow Skill - Shell 实现
set -e
# 解析参数
ACTION="$1"
shift
case "$ACTION" in
"status")
git status
;;
"log")
COUNT="${1:-10}"
git log --oneline -n "$COUNT"
;;
"branches")
git branch -a
;;
"current_branch")
git branch --show-current
;;
*)
echo "{\"error\": \"Unknown action: $ACTION\"}"
exit 1
;;
esac
4.4 脚本规范
输入输出规范:
- 主脚本通过命令行参数接收指令
- 输出统一使用 JSON 格式(stdout)
- 错误信息输出到 stderr
错误处理规范:
python
def main():
try:
# 业务逻辑
pass
except GitNotFoundError:
print(json.dumps({"error": "Git is not installed"}))
sys.exit(1)
except Exception as e:
print(json.dumps({"eTEST INJECTION WORKS