OpenClaw Skills 技能创建器(Skill Creator)技能使用参考手册

2026-03-05 17:21 更新

概述

Skill Creator 是一个用于指导用户创建高质量 ClawHub 技能的指南,该技能本身就是技能创建的最佳实践示例,遵循 agentskills 开放规范,通过详细的文档提供完整的技能开发方法论。

关于技能

技能是模块化、自包含的包,通过提供专业知识、工作流和工具来扩展 Claude 的能力。可以将它们视为特定领域或任务的 "入门指南"—— 它们将 Claude 从通用代理转变为具备程序知识的专业代理,而这些程序知识是任何模型都无法完全具备的。

技能提供的内容

  1. 专业工作流 - 特定领域的多步骤流程
  2. 工具集成 - 用于处理特定文件格式或 API 的说明
  3. 领域专业知识 - 公司特定的知识、架构、业务逻辑
  4. 捆绑资源 - 用于复杂和重复任务的脚本、参考资料和资产

👤 作者:chindden
🦞 官方地址:https://clawhub.ai/chindden/skill-creator
👉 Skills 下载地址:skill-creator-0.1.0.zip

核心原则

简洁是关键

上下文窗口是公共资源。技能需要与 Claude 需要的其他所有内容共享上下文窗口:系统提示、对话历史、其他技能的元数据,以及实际的用户请求。

默认假设:Claude 已经非常智能。 只添加 Claude 还没有的上下文。质疑每一条信息:"Claude 真的需要这个解释吗?" 以及 "这段内容是否值得它的 token 成本?"

优先使用简洁的示例,而不是冗长的解释。

设置适当的自由度

将详细程度与任务的脆弱性和可变性相匹配:

  • 高自由度(基于文本的指令):当有多种有效方法、决策依赖于上下文,或者启发式方法指导方法时使用。
  • 中等自由度(带参数的伪代码或脚本):当存在首选模式、允许一定变化,或者配置会影响行为时使用。
  • 低自由度(特定脚本,少量参数):当操作脆弱且容易出错、一致性至关重要,或者必须遵循特定顺序时使用。

可以把 Claude 想象成在探索一条路径:两侧是悬崖的狭窄桥梁需要特定的护栏(低自由度),而开阔的场地允许多种路线(高自由度)。

技能的结构

每个技能都包含一个必需的 SKILL.md 文件和可选的捆绑资源:

skill-name/
├── SKILL.md (必需)
│   ├── YAML前置元数据 (必需)
│   │   ├── name: (必需)
│   │   └── description: (必需)
│   └── Markdown说明 (必需)
└── 捆绑资源 (可选)
    ├── scripts/          - 可执行代码(Python/Bash等)
    ├── references/       - 旨在根据需要加载到上下文中的文档
    └── assets/           - 用于输出的文件(模板、图标、字体等)

SKILL.md(必需)

每个 SKILL.md 都包含:

  • 前置元数据(YAML):包含namedescription字段。这些是 Claude 用来确定何时使用该技能的唯一字段,因此清晰、全面地描述该技能的功能以及使用场景非常重要。
  • 正文(Markdown):使用该技能的说明和指南。仅在技能触发后加载(如果有的话)。

捆绑资源(可选)

脚本(scripts/

用于需要确定性可靠性或重复编写的任务的可执行代码(Python/Bash 等)。

  • 何时包含:当相同的代码被重复编写,或者需要确定性可靠性时
  • 示例scripts/rotate_pdf.py用于 PDF 旋转任务
  • 优势:Token 高效、确定性强,无需加载到上下文中即可执行
  • 注意:Claude 可能仍需要读取脚本以进行补丁或环境特定的调整

参考资料(references/

旨在根据需要加载到上下文中,为 Claude 的流程和思考提供信息的文档和参考资料。

  • 何时包含:用于 Claude 在工作时需要参考的文档
  • 示例references/finance.md用于财务架构,references/mnda.md用于公司 NDA 模板,references/policies.md用于公司政策,references/api_docs.md用于 API 规范
  • 用例:数据库架构、API 文档、领域知识、公司政策、详细的工作流指南
  • 优势:保持 SKILL.md 简洁,仅在 Claude 确定需要时加载
  • 最佳实践:如果文件较大(>10000 字),在 SKILL.md) 中包含 grep 搜索模式
  • 避免重复:信息应该只存在于 SKILL.md) 或参考文件中,而不是两者都有。对于详细信息,优先使用参考文件,除非它是技能的核心内容 —— 这可以保持 SKILL.md) 简洁,同时使信息可发现,而不会占用上下文窗口。只在 SKILL.md 中保留必要的程序指令和工作流指南;将详细的参考资料、架构和示例移到参考文件中。

资产(assets/

不打算加载到上下文中,而是用于 Claude 生成的输出中的文件。

  • 何时包含:当技能需要将文件用于最终输出时
  • 示例assets/logo.png用于品牌资产,assets/slides.pptx用于 PowerPoint 模板,assets/frontend-template/用于 HTML/React 样板代码,assets/font.ttf用于排版
  • 用例:模板、图像、图标、样板代码、字体、可复制或修改的示例文档
  • 优势:将输出资源与文档分离,使 Claude 能够使用文件而无需将它们加载到上下文中

技能中不应包含的内容

技能应仅包含直接支持其功能的必要文件。请勿创建无关的文档或辅助文件,包括:

  • README.md
  • INSTALLATION_GUIDE.md
  • QUICK_REFERENCE.md
  • CHANGELOG.md
  • 等等

技能应仅包含 AI 代理完成手头工作所需的信息。它不应包含关于创建过程的辅助上下文、设置和测试程序、面向用户的文档等。创建额外的文档文件只会增加混乱和困惑。

渐进式披露设计原则

技能使用三级加载系统来高效管理上下文:

  1. 元数据(名称 + 描述) - 始终在上下文中(约 100 字)
  2. SKILL.md 正文 - 当技能触发时(<5000 字)
  3. 捆绑资源 - 根据 Claude 的需要(无限制,因为脚本可以在不读取到上下文窗口的情况下执行)

渐进式披露模式

SKILL.md 正文保持在必要的内容范围内,不超过 500 行,以最小化上下文膨胀。当接近此限制时,将内容拆分为单独的文件。当将内容拆分为其他文件时,非常重要的是要从 SKILL.md 中引用它们,并清楚地描述何时读取它们,以确保技能的读者知道它们的存在以及何时使用它们。

关键原则:当技能支持多种变体、框架或选项时,仅在 SKILL.md 中保留核心工作流和选择指南。将变体特定的详细信息(模式、示例、配置)移到单独的参考文件中。

模式 1:高级指南与参考资料

## PDF处理
## 快速开始
使用pdfplumber提取文本:
[代码示例]
## 高级功能
- **表单填写**:参见[FORMS.md](FORMS.md)获取完整指南
- **API参考**:参见[REFERENCE.md](REFERENCE.md)获取所有方法
- **示例**:参见[EXAMPLES.md](EXAMPLES.md)获取常见模式

Claude 仅在需要时加载 FORMS.mdREFERENCE.mdEXAMPLES.md

模式 2:特定领域的组织

对于包含多个领域的技能,按领域组织内容,以避免加载无关的上下文:

bigquery-skill/
├── SKILL.md (概述和导航)
└── reference/
    ├── finance.md (收入、计费指标)
    ├── sales.md (商机、销售漏斗)
    ├── product.md (API使用、功能)
    └── marketing.md (活动、归因)

当用户询问销售指标时,Claude 仅读取 sales.md

类似地,对于支持多个框架或变体的技能,按变体组织:

cloud-deploy/
├── SKILL.md (工作流 + 提供商选择)
└── references/
    ├── aws.md (AWS部署模式)
    ├── gcp.md (GCP部署模式)
    └── azure.md (Azure部署模式)

当用户选择 AWS 时,Claude 仅读取 aws.md

模式 3:条件详细信息

显示基本内容,链接到高级内容:

## DOCX处理
## 创建文档
使用docx-js创建新文档。参见[DOCX-JS.md](DOCX-JS.md)。
## 编辑文档
对于简单编辑,直接修改XML。
**对于跟踪更改**:参见[REDLINING.md](REDLINING.md)
**对于OOXML详细信息**:参见[OOXML.md](OOXML.md)

Claude 仅在用户需要这些功能时读取 REDLINING.mdOOXML.md

重要指南

  • 避免深层嵌套参考 - 保持参考文件与 SKILL.md 的深度为一级。所有参考文件应直接从 SKILL.md 链接。
  • 结构化较长的参考文件 - 对于超过 100 行的文件,在顶部包含目录,以便 Claude 在预览时可以看到完整范围。

技能创建流程

技能创建涉及以下步骤:

  1. 通过具体示例理解技能
  2. 规划可重用的技能内容(脚本、参考资料、资产)
  3. 初始化技能(运行 init_skill.py
  4. 编辑技能(实现资源并编写 SKILL.md
  5. 打包技能(运行 package_skill.py
  6. 根据实际使用情况迭代

按顺序遵循这些步骤,仅在有明确理由不适用时跳过。

步骤 1:通过具体示例理解技能

仅当技能的使用模式已经清晰理解时才跳过此步骤。即使处理现有技能,此步骤仍然有价值。

要创建有效的技能,需要清楚地理解该技能的具体使用示例。这种理解可以来自直接的用户示例,或者通过用户反馈验证的生成示例。

例如,在构建图像编辑器技能时,相关问题包括:

  • "图像编辑器技能应支持哪些功能?编辑、旋转,还是其他?"
  • "你能举一些这个技能的使用示例吗?"
  • "我可以想象用户会要求 ' 去除这张图片的红眼 ' 或 ' 旋转这张图片 '。你还能想象这个技能的其他使用方式吗?"
  • "用户会说什么来触发这个技能?"

为了避免使用户不知所措,不要在一条消息中问太多问题。从最重要的问题开始,根据需要跟进以提高有效性。

当对技能应支持的功能有清晰的认识时,结束此步骤。

步骤 2:规划可重用的技能内容

要将具体示例转化为有效的技能,请通过以下方式分析每个示例:

  1. 考虑如何从头开始执行示例
  2. 确定在重复执行这些工作流时有用的脚本、参考资料和资产

示例:当构建pdf-editor技能来处理 "帮我旋转这个 PDF" 这样的查询时,分析显示:

  1. 旋转 PDF 需要每次重写相同的代码
  2. scripts/rotate_pdf.py脚本将有助于存储在技能中

示例:当设计frontend-webapp-builder技能来处理 "帮我构建一个待办应用" 或 "帮我构建一个仪表板来跟踪我的步数" 这样的查询时,分析显示:

  1. 构建前端 web 应用每次都需要相同的样板 HTML/React 代码
  2. assets/hello-world/模板包含样板 HTML/React 项目文件,将有助于存储在技能中

示例:当构建big-query技能来处理 "今天有多少用户登录?" 这样的查询时,分析显示:

  1. 查询 BigQuery 需要每次重新发现表架构和关系
  2. references/schema.md文件记录表架构,将有助于存储在技能中

要确定技能的内容,请分析每个具体示例,创建要包含的可重用资源列表:脚本、参考资料和资产。

步骤 3:初始化技能

此时,实际创建技能。 仅当正在开发的技能已经存在,并且需要迭代或打包时,才跳过此步骤。在这种情况下,继续下一步。

当从头开始创建新技能时,始终运行init_skill.py脚本。该脚本方便地生成一个新的模板技能目录,自动包含技能所需的一切,使技能创建过程更加高效和可靠。

用法:

scripts/init_skill.py <skill-name> --path <output-directory>

该脚本:

  • 在指定路径创建技能目录
  • 生成带有适当前置元数据和 TODO 占位符的 SKILL.md 模板
  • 创建示例资源目录:scripts/references/assets/
  • 在每个目录中添加可以自定义或删除的示例文件

初始化后,根据需要自定义或删除生成的 SKILL.md 和示例文件。

步骤 4:编辑技能

当编辑(新生成的或现有的)技能时,请记住,该技能是为另一个 Claude 实例使用而创建的。包含对 Claude 有益且非显而易见的信息。考虑哪些程序知识、特定领域的详细信息或可重用资产将帮助另一个 Claude 实例更有效地执行这些任务。

学习经过验证的设计模式

根据技能的需求参考这些有用的指南:

  • 多步骤流程:参见 references/workflows.md 获取顺序工作流和条件逻辑
  • 特定输出格式或质量标准:参见 references/output-patterns.md 获取模板和示例模式

这些文件包含有效技能设计的既定最佳实践。

从可重用技能内容开始

要开始实现,请从上面确定的可重用资源开始:scripts/references/assets/文件。请注意,此步骤可能需要用户输入。例如,在实现brand-guidelines技能时,用户可能需要提供要存储在assets/中的品牌资产或模板,或要存储在references/中的文档。

添加的脚本必须通过实际运行进行测试,以确保没有错误,并且输出符合预期。如果有许多类似的脚本,只需要测试代表性样本,以确保它们都能正常工作,同时平衡完成时间。

任何不需要的示例文件和目录都应删除。初始化脚本在scripts/references/assets/中创建示例文件以演示结构,但大多数技能不需要所有这些文件。

更新 SKILL.md

编写指南:始终使用祈使 / 不定式形式。

前置元数据

编写带有namedescription的 YAML 前置元数据:

  • name:技能名称
  • description:这是技能的主要触发机制,帮助 Claude 理解何时使用该技能。
    • 包括技能的功能以及使用它的特定触发 / 上下文。
    • 所有 "何时使用此技能" 的信息都包含在这里 - 而不是在正文中。正文仅在触发后加载,因此正文中的 "何时使用此技能" 部分对 Claude 没有帮助。
    • docx技能的示例描述:"全面的文档创建、编辑和分析,支持跟踪更改、注释、格式保留和文本提取。当 Claude 需要处理专业文档(.docx 文件)时使用: (1) 创建新文档
      (2) 修改或编辑内容
      (3) 处理跟踪更改
      (4) 添加注释,或任何其他文档任务"

不要在 YAML 前置元数据中包含任何其他字段。

正文

编写使用技能及其捆绑资源的说明。

步骤 5:打包技能

技能开发完成后,必须将其打包为可分发的.skill 文件,与用户共享。打包过程会自动先验证技能,确保它满足所有要求:

scripts/package_skill.py <path/to/skill-folder>

可选的输出目录指定:

scripts/package_skill.py <path/to/skill-folder> ./dist

打包脚本将:

  1. 验证技能,自动检查:
    1. YAML 前置元数据格式和必填字段
    2. 技能命名约定和目录结构
    3. 描述的完整性和质量
    4. 文件组织和资源引用
  2. 打包技能(如果验证通过),创建一个以技能命名的.skill 文件(例如,my-skill.skill),包含所有文件并保持适当的目录结构以进行分发。.skill 文件是带有.skill 扩展名的 zip 文件。

如果验证失败,脚本将报告错误并退出,不创建包。修复所有验证错误,然后再次运行打包命令。

步骤 6:迭代

测试技能后,用户可能会要求改进。这通常在使用技能后立即发生,此时用户对技能的表现有清晰的上下文。

迭代工作流

  1. 在实际任务上使用技能
  2. 注意困难或低效的地方
  3. 确定应如何更新 SKILL.md 或捆绑资源
  4. 实施更改并再次测试

工作流模式

顺序工作流

对于复杂任务,将操作分解为清晰的顺序步骤。在 SKILL.md 的开头为 Claude 提供流程概述通常很有帮助:

填写PDF表单涉及以下步骤:
1. 分析表单(运行analyze_form.py)
2. 创建字段映射(编辑fields.json)
3. 验证映射(运行validate_fields.py)
4. 填写表单(运行fill_form.py)
5. 验证输出(运行verify_output.py)

条件工作流

对于带有分支逻辑的任务,指导 Claude 完成决策点:

1. 确定修改类型:
   **创建新内容?** → 遵循下面的"创建工作流"
   **编辑现有内容?** → 遵循下面的"编辑工作流"
2. 创建工作流:[步骤]
3. 编辑工作流:[步骤]

输出模式

当技能需要生成一致、高质量的输出时,使用这些模式。

模板模式

为输出格式提供模板。根据需要匹配严格程度。 对于严格要求(如 API 响应或数据格式)

## 报告结构
始终使用此精确模板结构:
## [分析标题]
## 执行摘要
[关键发现的一段概述]
## 关键发现
- 带有支持数据的发现1
- 带有支持数据的发现2
- 带有支持数据的发现3
## 建议
1. 具体的可操作建议
2. 具体的可操作建议

对于灵活指导(当适应有用时)

## 报告结构
这是一个合理的默认格式,但请使用你的最佳判断:
## [分析标题]
## 执行摘要
[概述]
## 关键发现
[根据发现调整部分]
## 建议
[根据具体情况定制]
根据具体分析类型调整部分。

示例模式

对于输出质量取决于查看示例的技能,提供输入 / 输出对:

## 提交消息格式
按照以下示例生成提交消息:
**示例1:**
输入:添加了基于JWT令牌的用户身份验证
输出:

feat (auth): 实现基于 JWT 的身份验证 添加登录端点和令牌验证中间件

**示例2:**
输入:修复了报告中日期显示不正确的错误
输出:

fix (reports): 修复时区转换中的日期格式 在报告生成中一致使用 UTC 时间戳

遵循此样式:类型(范围):简要描述,然后是详细说明。

示例比单独的描述更能帮助 Claude 理解所需的样式和详细程度。

工具代码说明

init_skill.py(技能初始化脚本)

#!/usr/bin/env python3
"""
技能初始化器 - 从模板创建新技能
用法:
    init_skill.py <skill-name> --path <path>
示例:
    init_skill.py my-new-skill --path skills/public
    init_skill.py my-api-helper --path skills/private
    init_skill.py custom-skill --path /custom/location
"""
import sys
from pathlib import Path


## 技能模板,用于生成SKILL.md的内容
SKILL_TEMPLATE = """---
name: {skill_name}
description: [TODO: 完成并提供该技能功能和使用场景的详细说明,包括何时使用该技能 - 特定场景、文件类型或触发任务。]
---
## {skill_title}
## 概述
[TODO: 1-2句话说明该技能的作用]
## 技能结构
[TODO: 选择最适合该技能目的的结构。常见模式:
**1. 基于工作流**(最适合顺序流程)
- 当有清晰的分步流程时效果良好
- 示例:DOCX技能,包含"工作流决策树" → "读取" → "创建" → "编辑"
- 结构:## 概述 → ## 工作流决策树 → ## 步骤1 → ## 步骤2...
**2. 基于任务**(最适合工具集合)
- 当技能提供不同操作/功能时效果良好
- 示例:PDF技能,包含"快速开始" → "合并PDF" → "拆分PDF" → "提取文本"
- 结构:## 概述 → ## 快速开始 → ## 任务类别1 → ## 任务类别2...
**3. 参考/指南**(最适合标准或规范)
- 适用于品牌指南、编码标准或要求
- 示例:品牌样式,包含"品牌指南" → "颜色" → "排版" → "功能"
- 结构:## 概述 → ## 指南 → ## 规范 → ## 使用...
**4. 基于功能**(最适合集成系统)
- 当技能提供多个相互关联的功能时效果良好
- 示例:产品管理,包含"核心功能" → 编号功能列表
- 结构:## 概述 → ## 核心功能 → ### 1. 功能 → ### 2. 功能...
模式可以根据需要混合和匹配。大多数技能会组合模式(例如,从基于任务开始,为复杂操作添加工作流)。
完成后删除整个"技能结构"部分 - 这只是指导。]
## [TODO: 根据选择的结构替换为第一个主要部分]
[TODO: 在此处添加内容。请参见现有技能中的示例:
- 技术技能的代码示例
- 复杂工作流的决策树
- 带有实际用户请求的具体示例
- 根据需要引用脚本/模板/参考资料]
## 资源
此技能包含示例资源目录,演示如何组织不同类型的捆绑资源:
### scripts/
可直接运行以执行特定操作的可执行代码(Python/Bash等)。
**其他技能中的示例:**
- PDF技能:`fill_fillable_fields.py`、`extract_form_field_info.py` - PDF处理工具
- DOCX技能:`document.py`、`utilities.py` - 文档处理Python模块
**适用场景:** Python脚本、shell脚本或任何执行自动化、数据处理或特定操作的可执行代码。
**注意:** 脚本可以在不加载到上下文的情况下执行,但Claude仍可以读取它们以进行补丁或环境调整。
### references/
旨在加载到上下文中,为Claude的流程和思考提供信息的文档和参考资料。
**其他技能中的示例:**
- 产品管理:`communication.md`、`context_building.md` - 详细的工作流指南
- BigQuery:API参考文档和查询示例
- 财务:架构文档、公司政策
**适用场景:** 深入文档、API参考、数据库架构、综合指南或Claude在工作时需要参考的任何详细信息。
### assets/
不打算加载到上下文中,而是用于Claude生成的输出中的文件。
**其他技能中的示例:**
- 品牌样式:PowerPoint模板文件(.pptx)、徽标文件
- 前端构建器:HTML/React样板项目目录
- 排版:字体文件(.ttf、.woff2)
**适用场景:** 模板、样板代码、文档模板、图像、图标、字体或任何要复制或用于最终输出的文件。
---
**任何不需要的目录都可以删除。** 并非每个技能都需要所有三种类型的资源。
"""


## 示例脚本模板,用于生成scripts目录下的示例文件
EXAMPLE_SCRIPT = '''#!/usr/bin/env python3
"""
{skill_name}的示例辅助脚本
这是一个可以直接执行的占位符脚本。
替换为实际实现或在不需要时删除。
其他技能中的实际示例脚本:
- pdf/scripts/fill_fillable_fields.py - 填充PDF表单字段
- pdf/scripts/convert_pdf_to_images.py - 将PDF页面转换为图像
"""
def main():
    print(f"这是{skill_name}的示例脚本")
    # TODO: 在此处添加实际脚本逻辑
    # 这可以是数据处理、文件转换、API调用等
if __name__ == "__main__":
    main()
'''


## 示例参考资料模板,用于生成references目录下的示例文件
EXAMPLE_REFERENCE = """# {skill_title}的参考文档
这是详细参考文档的占位符。
替换为实际参考内容或在不需要时删除。
其他技能中的实际参考文档示例:
- product-management/references/communication.md - 状态更新综合指南
- product-management/references/context_building.md - 深入了解上下文收集
- bigquery/references/ - API参考和查询示例
## 参考文档的适用场景
参考文档适用于:
- 综合API文档
- 详细工作流指南
- 复杂的多步骤流程
- 太长而无法放入主SKILL.md的信息
- 仅特定用例需要的内容
## 结构建议
### API参考示例
- 概述
- 身份验证
- 带示例的端点
- 错误代码
- 速率限制
### 工作流指南示例
- 先决条件
- 分步说明
- 常见模式
- 故障排除
- 最佳实践
"""


## 示例资产文件模板,用于生成assets目录下的示例文件
EXAMPLE_ASSET = """# 示例资产文件
此占位符表示资产文件的存储位置。
替换为实际资产文件(模板、图像、字体等)或在不需要时删除。
资产文件不打算加载到上下文中,而是用于Claude生成的输出中。
其他技能中的实际资产文件示例:
- 品牌指南:logo.png、slides_template.pptx
- 前端构建器:包含HTML/React样板代码的hello-world/目录
- 排版:custom-font.ttf、font-family.woff2
- 数据:sample_data.csv、test_dataset.json
## 常见资产类型
- 模板:.pptx、.docx、样板目录
- 图像:.png、.jpg、.svg、.gif
- 字体:.ttf、.otf、.woff、.woff2
- 样板代码:项目目录、启动文件
- 图标:.ico、.svg
- 数据文件:.csv、.json、.xml、.yaml
注意:这是文本占位符。实际资产可以是任何文件类型。
"""


def title_case_skill_name(skill_name):
    """将连字符分隔的技能名称转换为标题大小写用于显示。"""
    return ' '.join(word.capitalize() for word in skill_name.split('-'))


def init_skill(skill_name, path):
    """
    初始化新的技能目录并生成模板SKILL.md。
    参数:
        skill_name: 技能名称
        path: 技能目录的创建路径
    返回:
        创建的技能目录路径,如果出错则返回None
    """
    # 确定技能目录路径
    skill_dir = Path(path).resolve() / skill_name
    # 检查目录是否已存在
    if skill_dir.exists():
        print(f"❌ 错误:技能目录已存在:{skill_dir}")
        return None
    # 创建技能目录
    try:
        skill_dir.mkdir(parents=True, exist_ok=False)
        print(f"✅ 已创建技能目录:{skill_dir}")
    except Exception as e:
        print(f"❌ 创建目录时出错:{e}")
        return None
    # 从模板创建SKILL.md
    skill_title = title_case_skill_name(skill_name)
    skill_content = SKILL_TEMPLATE.format(
        skill_name=skill_name,
        skill_title=skill_title
    )
    skill_md_path = skill_dir / 'SKILL.md'
    try:
        skill_md_path.write_text(skill_content)
        print("✅ 已创建SKILL.md")
    except Exception as e:
        print(f"❌ 创建SKILL.md时出错:{e}")
        return None
    # 创建带有示例文件的资源目录
    try:
        # 创建scripts/目录并添加示例脚本
        scripts_dir = skill_dir / 'scripts'
        scripts_dir.mkdir(exist_ok=True)
        example_script = scripts_dir / 'example.py'
        example_script.write_text(EXAMPLE_SCRIPT.format(skill_name=skill_name))
        example_script.chmod(0o755)
        print("✅ 已创建scripts/example.py")
        # 创建references/目录并添加示例参考文档
        references_dir = skill_dir / 'references'
        references_dir.mkdir(exist_ok=True)
        example_reference = references_dir / 'api_reference.md'
        example_reference.write_text(EXAMPLE_REFERENCE.format(skill_title=skill_title))
        print("✅ 已创建references/api_reference.md")
        # 创建assets/目录并添加示例资产占位符
        assets_dir = skill_dir / 'assets'
        assets_dir.mkdir(exist_ok=True)
        example_asset = assets_dir / 'example_asset.txt'
        example_asset.write_text(EXAMPLE_ASSET)
        print("✅ 已创建assets/example_asset.txt")
    except Exception as e:
        print(f"❌ 创建资源目录时出错:{e}")
        return None
    # 打印下一步操作
    print(f"\n✅ 技能'{skill_name}'已成功初始化,路径为 {skill_dir}")
    print("\n下一步操作:")
    print("1. 编辑SKILL.md以完成TODO项并更新描述")
    print("2. 自定义或删除scripts/、references/和assets/中的示例文件")
    print("3. 准备好后运行验证器检查技能结构")
    return skill_dir


def main():
    if len(sys.argv) < 4 or sys.argv[2] != '--path':
        print("用法: init_skill.py <skill-name> --path <path>")
        print("\n技能名称要求:")
        print("  - 连字符分隔的标识符(例如,'data-analyzer')")
        print("  - 仅包含小写字母、数字和连字符")
        print("  - 最多40个字符")
        print("  - 必须与目录名称完全匹配")
        print("\n示例:")
        print("  init_skill.py my-new-skill --path skills/public")
        print("  init_skill.py my-api-helper --path skills/private")
        print("  init_skill.py custom-skill --path /custom/location")
        sys.exit(1)
    skill_name = sys.argv[1]
    path = sys.argv[3]
    print(f"🚀 正在初始化技能: {skill_name}")
    print(f"   位置: {path}")
    print()
    result = init_skill(skill_name, path)
    if result:
        sys.exit(0)
    else:
        sys.exit(1)


if __name__ == "__main__":
    main()

package_skill.py(技能打包脚本)

#!/usr/bin/env python3
"""
技能打包器 - 将技能文件夹创建为可分发的.skill文件
用法:
    python utils/package_skill.py <path/to/skill-folder> [output-directory]
示例:
    python utils/package_skill.py skills/public/my-skill
    python utils/package_skill.py skills/public/my-skill ./dist
"""
import sys
import zipfile
from pathlib import Path
from quick_validate import validate_skill


def package_skill(skill_path, output_dir=None):
    """
    将技能文件夹打包为.skill文件。
    参数:
        skill_path: 技能文件夹的路径
        output_dir: .skill文件的可选输出目录(默认为当前目录)
    返回:
        创建的.skill文件路径,如果出错则返回None
    """
    skill_path = Path(skill_path).resolve()
    # 验证技能文件夹是否存在
    if not skill_path.exists():
        print(f"❌ 错误:未找到技能文件夹:{skill_path}")
        return None
    if not skill_path.is_dir():
        print(f"❌ 错误:路径不是目录:{skill_path}")
        return None
    # 验证SKILL.md是否存在
    skill_md = skill_path / "SKILL.md"
    if not skill_md.exists():
        print(f"❌ 错误:在{skill_path}中未找到SKILL.md")
        return None
    # 打包前先进行验证
    print("🔍 正在验证技能...")
    valid, message = validate_skill(skill_path)
    if not valid:
        print(f"❌ 验证失败:{message}")
        print("   请在打包前修复验证错误。")
        return None
    print(f"✅ {message}\n")
    # 确定输出位置
    skill_name = skill_path.name
    if output_dir:
        output_path = Path(output_dir).resolve()
        output_path.mkdir(parents=True, exist_ok=True)
    else:
        output_path = Path.cwd()
    skill_filename = output_path / f"{skill_name}.skill"
    # 创建.skill文件(zip格式)
    try:
        with zipfile.ZipFile(skill_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
            # 遍历技能目录
            for file_path in skill_path.rglob('*'):
                if file_path.is_file():
                    # 计算zip中的相对路径
                    arcname = file_path.relative_to(skill_path.parent)
                    zipf.write(file_path, arcname)
                    print(f"  已添加: {arcname}")
        print(f"\n✅ 已成功将技能打包到: {skill_filename}")
        return skill_filename
    except Exception as e:
        print(f"❌ 创建.skill文件时出错:{e}")
        return None


def main():
    if len(sys.argv) < 2:
        print("用法: python utils/package_skill.py <path/to/skill-folder> [output-directory]")
        print("\n示例:")
        print("  python utils/package_skill.py skills/public/my-skill")
        print("  python utils/package_skill.py skills/public/my-skill ./dist")
        sys.exit(1)
    skill_path = sys.argv[1]
    output_dir = sys.argv[2] if len(sys.argv) > 2 else None
    print(f"📦 正在打包技能: {skill_path}")
    if output_dir:
        print(f"   输出目录: {output_dir}")
    print()
    result = package_skill(skill_path, output_dir)
    if result:
        sys.exit(0)
    else:
        sys.exit(1)


if __name__ == "__main__":
    main()

quick_validate.py(技能快速验证脚本)

#!/usr/bin/env python3
"""
技能快速验证脚本 - 简化版本
"""
import sys
import os
import re
import yaml
from pathlib import Path


def validate_skill(skill_path):
    """技能的基本验证"""
    skill_path = Path(skill_path)
    # 检查SKILL.md是否存在
    skill_md = skill_path / 'SKILL.md'
    if not skill_md.exists():
        return False, "未找到SKILL.md"
    # 读取并验证前置元数据
    content = skill_md.read_text()
    if not content.startswith('---'):
        return False, "未找到YAML前置元数据"
    # 提取前置元数据
    match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
    if not match:
        return False, "前置元数据格式无效"
    frontmatter_text = match.group(1)
    # 解析YAML前置元数据
    try:
        frontmatter = yaml.safe_load(frontmatter_text)
        if not isinstance(frontmatter, dict):
            return False, "前置元数据必须是YAML字典"
    except yaml.YAMLError as e:
        return False, f"前置元数据中的YAML无效: {e}"
    # 定义允许的属性
    ALLOWED_PROPERTIES = {'name', 'description', 'license', 'allowed-tools', 'metadata'}
    # 检查意外的属性(不包括metadata下的嵌套键)
    unexpected_keys = set(frontmatter.keys()) - ALLOWED_PROPERTIES
    if unexpected_keys:
        return False, (
            f"SKILL.md前置元数据中存在意外的键: {', '.join(sorted(unexpected_keys))}. "
            f"允许的属性是: {', '.join(sorted(ALLOWED_PROPERTIES))}"
        )
    # 检查必填字段
    if 'name' not in frontmatter:
        return False, "前置元数据中缺少'name'"
    if 'description' not in frontmatter:
        return False, "前置元数据中缺少'description'"
    # 提取名称进行验证
    name = frontmatter.get('name', '')
    if not isinstance(name, str):
        return False, f"名称必须是字符串,得到的是{type(name).__name__}"
    name = name.strip()
    if name:
        # 检查命名约定(连字符格式:小写字母、数字和连字符)
        if not re.match(r'^[a-z0-9-]+$', name):
            return False, f"名称'{name}'应该是连字符格式(仅包含小写字母、数字和连字符)"
        if name.startswith('-') or name.endswith('-') or '--' in name:
            return False, f"名称'{name}'不能以连字符开头/结尾,也不能包含连续的连字符"
        # 检查名称长度(根据规范最多64个字符)
        if len(name) > 64:
            return False, f"名称过长({len(name)}个字符)。最多64个字符。"
    # 提取并验证描述
    description = frontmatter.get('description', '')
    if not isinstance(description, str):
        return False, f"描述必须是字符串,得到的是{type(description).__name__}"
    description = description.strip()
    if description:
        # 检查是否包含尖括号
        if '<' in description or '>' in description:
            return False, "描述不能包含尖括号(<或>)"
        # 检查描述长度(根据规范最多1024个字符)
        if len(description) > 1024:
            return False, f"描述过长({len(description)}个字符)。最多1024个字符。"
    return True, "技能验证通过!"


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print("用法: python quick_validate.py <skill_directory>")
        sys.exit(1)

    
    valid, message = validate_skill(sys.argv[1])
    print(message)
    sys.exit(0 if valid else 1)

许可证信息

本项目采用 Apache License 2.0 许可证,完整条款可参考项目中的 LICENSE.txt 文件,该许可证允许你自由使用、修改、分发本项目的代码,同时需要保留原有的版权声明和许可证信息。

以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号