别光装 Skill,自己写一个!OpenClaw 自定义 Skill 开发踩坑全记录

最近刷掘金全是「OpenClaw 必装 Skills 推荐」「十大神级 Skills」,说实话这些文章我也看了不少,装了一堆别人的 Skill。

但用了两周发现一个问题:别人的 Skill 永远差那么一点意思。

要么功能太重装了一堆用不上的依赖,要么关键场景没覆盖到,要么配置项写死了改不了。

索性自己动手写。折腾了两天,踩了不少坑,写这篇把完整过程记录下来。读完你也能 30 分钟搞出自己的第一个 Skill。

先说结论

步骤 耗时 难度
理解 Skill 结构 5 分钟
SKILL.md 10 分钟 ⭐⭐
写脚本逻辑 10 分钟 ⭐⭐
调试 + 测试 15 分钟 ⭐⭐⭐
发布到 ClawHub 5 分钟

总共不到 1 小时。说真的,比我预想的简单太多了。

为什么要自己写 Skill?

先说我遇到的具体痛点:

我每天用 OpenClaw 帮我做代码审查,它调 Claude 帮我看代码逻辑没问题,但有些简单的格式检查(缩进、命名规范、import 排序)也用 Claude,一天下来 token 烧得心疼。

我想要一个 Skill:简单的 lint 类任务走便宜模型,复杂的逻辑分析走 Claude/GPT-4o。找了一圈 ClawHub,要么是纯模型切换的,要么是纯 lint 工具的,没有把两者结合的。

行吧,自己写。

OpenClaw Skill 的结构(比你想的简单)

一个 Skill 其实就是一个文件夹,核心只需要一个文件:

perl 复制代码
my-smart-reviewer/
├── SKILL.md          # 必须有,Skill 的灵魂
├── scripts/          # 可选,放脚本
│   └── analyze.py
└── references/       # 可选,放参考文档
    └── style-guide.md

SKILL.md 才是真正的「代码」。OpenClaw 读这个文件来理解 Skill 该干什么,说白了就是一份结构化的 prompt。

第一步:写 SKILL.md

这是我的 smart-reviewer Skill 的 SKILL.md

markdown 复制代码
---
name: smart-reviewer
description: 智能代码审查 - 简单问题走轻量模型,复杂逻辑走强模型
version: 1.0.0
triggers:
  - "review"
  - "代码审查"
  - "帮我看看这段代码"
tools:
  - bash
  - read
  - write
---

# Smart Code Reviewer

你是一个智能代码审查助手。收到代码审查请求时,按以下流程处理:

## 第一步:分类

先快速扫描代码,将问题分为两类:

**轻量级问题(用快速模型处理):**
- 格式问题(缩进、空格、换行)
- 命名规范(驼峰/下划线不统一)
- import 排序和未使用的 import
- 简单的类型标注缺失

**重度问题(用强模型处理):**
- 逻辑错误和边界条件
- 安全漏洞(注入、XSS、权限问题)
- 性能问题和算法优化
- 架构设计建议

## 第二步:执行审查

对于轻量级问题,调用 scripts/analyze.py 进行自动检测:

```bash
python3 scripts/analyze.py --file <目标文件> --check lint

对于重度问题,直接用你的推理能力深度分析。

第三步:输出报告

用表格格式输出,包含:严重程度、行号、问题描述、建议修复

python 复制代码
看到没?**SKILL.md 本质就是一个增强版的 system prompt**,但它有结构化的 frontmatter 让 OpenClaw 知道什么时候触发、需要什么权限。

## 第二步:写脚本(可选但推荐)

`scripts/analyze.py` 负责轻量级检查,不需要调大模型:

```python
#!/usr/bin/env python3
"""Smart Reviewer - 轻量级代码检查脚本"""

import ast
import sys
import json
import re
from pathlib import Path

def check_naming(code: str) -> list:
    """检查命名规范"""
    issues = []
    tree = ast.parse(code)

    for node in ast.walk(tree):
        # 函数名应该是 snake_case
        if isinstance(node, ast.FunctionDef):
            if not re.match(r'^[a-z_][a-z0-9_]*$', node.name):
                issues.append({
                    "line": node.lineno,
                    "severity": "warning",
                    "message": f"函数名 '{node.name}' 不符合 snake_case 规范",
                    "suggestion": f"建议改为 '{to_snake_case(node.name)}'"
                })

        # 类名应该是 PascalCase
        if isinstance(node, ast.ClassDef):
            if not re.match(r'^[A-Z][a-zA-Z0-9]*$', node.name):
                issues.append({
                    "line": node.lineno,
                    "severity": "warning",
                    "message": f"类名 '{node.name}' 不符合 PascalCase 规范"
                })

    return issues

def check_unused_imports(code: str) -> list:
    """检查未使用的 import"""
    issues = []
    tree = ast.parse(code)

    imported_names = set()
    for node in ast.walk(tree):
        if isinstance(node, ast.Import):
            for alias in node.names:
                name = alias.asname or alias.name
                imported_names.add((name, node.lineno))
        elif isinstance(node, ast.ImportFrom):
            for alias in node.names:
                name = alias.asname or alias.name
                imported_names.add((name, node.lineno))

    # 检查是否在代码中被使用
    for name, lineno in imported_names:
        # 简单的文本搜索(ast 级别的引用分析更准,但这里够用了)
        usage_count = len(re.findall(rf'\b{re.escape(name)}\b', code))
        if usage_count <= 1:  # 只在 import 行出现
            issues.append({
                "line": lineno,
                "severity": "info",
                "message": f"'{name}' 导入后似乎未使用",
                "suggestion": "如确认未使用,建议移除"
            })

    return issues

def to_snake_case(name: str) -> str:
    """驼峰转下划线"""
    s = re.sub(r'([A-Z]+)([A-Z][a-z])', r'\1_\2', name)
    s = re.sub(r'([a-z\d])([A-Z])', r'\1_\2', s)
    return s.lower()

def main():
    import argparse
    parser = argparse.ArgumentParser()
    parser.add_argument('--file', required=True)
    parser.add_argument('--check', default='all',
                       choices=['lint', 'naming', 'imports', 'all'])
    args = parser.parse_args()

    code = Path(args.file).read_text()
    issues = []

    if args.check in ('naming', 'lint', 'all'):
        issues.extend(check_naming(code))
    if args.check in ('imports', 'lint', 'all'):
        issues.extend(check_unused_imports(code))

    # 按行号排序输出
    issues.sort(key=lambda x: x['line'])
    print(json.dumps(issues, ensure_ascii=False, indent=2))

if __name__ == '__main__':
    main()

这段代码纯 Python 标准库,零依赖,不需要 pip install 任何东西。这一点很重要------别给你的 Skill 加一堆依赖,用户装的时候出问题你都没法帮他排查。

第三步:安装和测试

把文件夹放到 OpenClaw 的 Skills 目录:

bash 复制代码
# OpenClaw 的 skills 目录
cp -r my-smart-reviewer ~/.openclaw/skills/

# 验证 Skill 被识别
openclaw skills list

输出应该能看到你的 Skill:

scss 复制代码
✅ smart-reviewer (v1.0.0) - 智能代码审查

然后在 OpenClaw 里输入触发词测试:

shell 复制代码
> /smart-reviewer 帮我看看 src/api/handler.py

踩坑记录(精华部分)

坑 1:SKILL.md 的 frontmatter 格式超级严格

我一开始 triggers 写成了字符串而不是数组:

yaml 复制代码
# ❌ 错误
triggers: "review"

# ✅ 正确
triggers:
  - "review"

OpenClaw 直接无视了这个 Skill,也不报错,我找了半小时才发现。

坑 2:scripts 里的文件要加执行权限

bash 复制代码
chmod +x scripts/analyze.py

没加权限的话,OpenClaw 调脚本会报 Permission denied,但错误信息藏在日志里,界面上只显示「执行失败」。

坑 3:别在 Skill 里硬编码模型名

一开始我在 SKILL.md 里写死了 使用 gpt-4o-mini 处理轻量任务,结果换了 API 提供商就跑不动了。

正确做法是写意图,不写具体模型:

markdown 复制代码
# ❌ 不好
对于轻量级问题,调用 gpt-4o-mini 处理

# ✅ 更好
对于轻量级问题,使用当前配置中最经济的模型处理

这样不管你的 OpenClaw 后面接的是 OpenAI 官方、还是 ofox.ai 这种聚合接口,都能正常工作。说到这个,我现在 OpenClaw 的 API 后端用的就是聚合接口,一个 key 能调 50 多个模型,切换模型改个参数就行,省去了管理一堆 API key 的麻烦。

坑 4:ClawHub 上的恶意 Skill 问题

这个要特别提醒一下。今年 1-2 月安全研究员在 ClawHub 上发现了 800 多个恶意 Skill ,有的会偷 .env 里的 API key,有的会在你不知道的情况下往外部服务器发请求。

所以:

  1. 装别人的 Skill 前一定要看源码,特别是 scripts 目录
  2. 检查 tools 声明------如果一个「翻译 Skill」要求 bash 和 network 权限,那就很可疑
  3. 优先用有 ✅ 标记的官方审核 Skill

进阶:让 Skill 支持配置

如果你想让用户自定义参数,可以在 SKILL.md 里加配置声明:

yaml 复制代码
---
name: smart-reviewer
config:
  severity_threshold:
    type: string
    default: "warning"
    description: "最低报告级别: info, warning, error"
  max_issues:
    type: number
    default: 20
    description: "单次审查最多报告的问题数"
---

用户通过 openclaw.json 自定义:

json 复制代码
{
  "skills": {
    "smart-reviewer": {
      "enabled": true,
      "config": {
        "severity_threshold": "error",
        "max_issues": 10
      }
    }
  }
}

发布到 ClawHub

写好之后发布也很简单:

bash 复制代码
# 1. fork ClawHub 仓库
git clone https://github.com/openclaw/clawhub.git
cd clawhub

# 2. 把你的 Skill 放进去
cp -r ~/my-smart-reviewer skills/smart-reviewer

# 3. 提 PR
git checkout -b add-smart-reviewer
git add .
git commit -m "feat: add smart-reviewer skill"
git push origin add-smart-reviewer

当然你也可以不发 ClawHub,直接放自己的 GitHub 仓库,别人用 openclaw skills install github:你的用户名/仓库名 就能装。

小结

自己写 OpenClaw Skill 远没有想象中那么难,核心就是一个 SKILL.md 文件 + 可选的脚本

与其在 ClawHub 上大海捞针找别人的 Skill,不如花 30 分钟针对自己的需求写一个。毕竟最懂你工作流的人是你自己。

我后面准备再写几个 Skill:

  • 一个自动生成 commit message 的(根据 diff 内容和项目规范)
  • 一个日报生成器(自动汇总今天改了哪些文件、解了哪些 issue)

如果你也写了好玩的 Skill,评论区分享一下 👇

相关推荐
鲲志4 小时前
骡子快跑MuleRun:自进化AI数字员工开启“养骡”替代“养虾”的Agent普及元年
agent
zone77394 小时前
007:RAG 入门-向量嵌入与检索
后端·面试·agent
数据智能老司机5 小时前
Harness Engineering 深度解读:AI Agent 时代的工程范式革命
agent
孟健5 小时前
AI Agent 已经开始攻击 GitHub Actions:我整理了 7 条最该先做的加固清单
安全·github·agent
得物技术6 小时前
从IDE到Terminal:适合后端宝宝体质的Claude Code工作流|得物技术
agent·ai编程·claude
xun_xing8 小时前
一篇文章让你彻底熟悉AI大模型(二)
llm·openai·agent
德莱厄斯9 小时前
比阿里开源的 page-agent 更强?AutoPilot: 网页内置一个真正能"稳定跑完"的智能体
前端·agent·浏览器
东邪狂想9 小时前
LangChain LCEL详解
agent