diff --git a/builtin-skills.json b/builtin-skills.json
index bc23b88..a18f829 100644
--- a/builtin-skills.json
+++ b/builtin-skills.json
@@ -6,6 +6,7 @@
"manage-skills",
"manage-teams",
"s3-storage-operations",
+ "skill-creator",
"update-agent"
]
}
diff --git a/skills/skill-creator/SKILL.md b/skills/skill-creator/SKILL.md
new file mode 100644
index 0000000..0743a1f
--- /dev/null
+++ b/skills/skill-creator/SKILL.md
@@ -0,0 +1,389 @@
+---
+name: 技能创建器
+description: >-
+ 引导用户创建和编辑符合规范的 SKILL.md 技能包。支持 DesireCore 完整格式
+ (frontmatter 元数据 + L0/L1/L2 分层内容 + 脚本/参考/资产)和 Claude Code
+ 基础格式。Use when 用户要求创建新技能、更新已有技能、或将经验封装为可复用
+ 的技能包。
+version: 1.0.0
+type: meta
+risk_level: low
+status: enabled
+disable-model-invocation: true
+tags:
+ - skill
+ - creation
+ - meta
+ - template
+ - authoring
+metadata:
+ author: desirecore
+ updated_at: '2026-04-03'
+market:
+ icon: >-
+
+ short_desc: 引导创建符合规范的 SKILL.md 技能包,支持完整元数据与分层内容
+ category: productivity
+ maintainer:
+ name: DesireCore Official
+ verified: true
+ compatible_agents: []
+ channel: latest
+---
+
+# skill-creator 技能
+
+## L0:一句话摘要
+
+引导用户将需求、经验和工作流封装为结构化的 SKILL.md 技能包。
+
+## L1:概述与使用场景
+
+### 能力描述
+
+skill-creator 是一个**元技能(Meta-Skill)**,赋予 Agent 创建和编辑技能的能力。技能是模块化、自包含的能力包,通过 SKILL.md 为 Agent 提供专业知识、工作流和工具集成——将 Agent 从通用助手转变为领域专家。
+
+### 使用场景
+
+- 用户想把反复执行的工作流封装为可复用技能
+- 用户想创建新技能教会 Agent 新的能力
+- 用户想更新已有技能、优化其效果
+- 用户分享了参考资料,需要组织为结构化的技能包
+
+### 核心价值
+
+- **沉淀经验**:将个人知识和工作流固化为可复用的 Skill
+- **自我扩展**:创建的技能让 Agent 能力持续增长
+- **规范化**:生成符合标准的 SKILL.md,确保技能系统正确解析和分发
+
+## L2:详细规范
+
+### 关于技能
+
+技能是模块化、自包含的能力包,为 Agent 提供:
+
+1. **专业工作流** — 特定领域的多步骤流程
+2. **工具集成** — 处理特定文件格式或 API 的指南
+3. **领域知识** — 公司规范、业务逻辑、专业 Schema
+4. **捆绑资源** — 脚本、参考文档和资产文件
+
+### 核心原则
+
+#### 简洁优先
+
+上下文窗口是公共资源。技能与系统提示、对话历史、其他技能元数据和用户请求共享上下文窗口。
+
+**默认假设:AI 已经非常聪明。** 只添加 AI 不知道的内容。对每条信息问自己:"AI 真的需要这个解释吗?" "这段话值得它的 Token 成本吗?"
+
+优先使用简洁的例子而非冗长的解释。
+
+#### 设置适当的自由度
+
+根据任务的脆弱性和可变性匹配指令的具体程度:
+
+- **高自由度(文本指引)**:多种方案都可行时,决策依赖上下文
+- **中自由度(伪代码或带参脚本)**:存在首选模式,允许一定变化
+- **低自由度(固定脚本,少量参数)**:操作脆弱易错,一致性至关重要
+
+#### 渐进式披露
+
+技能使用三层加载系统高效管理上下文:
+
+1. **元数据(name + description)** — 始终在上下文中(~100 词)
+2. **SKILL.md body** — 技能触发时加载(<5k 词)
+3. **捆绑资源** — Agent 按需加载(无限制,脚本可直接执行无需读入上下文)
+
+### 技能结构
+
+```
+skill-name/
+├── SKILL.md (必须:技能定义文件)
+├── scripts/ (可选:可执行脚本)
+├── references/ (可选:参考文档)
+└── assets/ (可选:输出用资源文件)
+```
+
+#### SKILL.md 格式
+
+SKILL.md 由两部分组成:**Frontmatter(YAML 元数据)** 和 **Body(Markdown 指令)**。
+
+##### Frontmatter 字段
+
+**必填**:
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `description` | string | 技能用途描述。**必须包含 "Use when" 触发提示**——AI 据此判断何时使用该技能 |
+
+**推荐**:
+
+| 字段 | 类型 | 说明 | 默认值 |
+|------|------|------|--------|
+| `name` | string | 技能显示名称 | 目录名 |
+| `version` | string | 语义版本号(如 `1.0.0`) | — |
+| `type` | enum | `procedural` / `conversational` / `meta` | — |
+| `risk_level` | enum | `low` / `medium` / `high` | — |
+| `status` | enum | `enabled` / `disabled` | `enabled` |
+| `tags` | string[] | 标签列表 | — |
+| `metadata` | object | `author`、`updated_at` | — |
+
+**功能控制**:
+
+| 字段 | 类型 | 默认 | 说明 |
+|------|------|------|------|
+| `disable-model-invocation` | boolean | `true` | `true`=仅显式调用触发;`false`=自动注入 system prompt |
+| `user-invocable` | boolean | `true` | `false`=不出现在命令补全,仅作为背景知识 |
+| `allowed-tools` | string[] | — | 限制执行时可用的工具列表 |
+| `requires` | object | — | 依赖声明:`tools`、`optional_tools`、`connections` |
+
+完整字段表(含市场发布、JSON 输出、fork 执行等高级字段)见 [references/desirecore-format.md](references/desirecore-format.md)。
+
+> **Claude Code 兼容说明**:Claude Code 仅使用 `name` + `description`(+ 可选 `license`、`compatibility`)。这些字段在 DesireCore 中完全合法——DesireCore 格式是 Claude Code 的超集。
+
+##### Body 结构
+
+**推荐使用 L0/L1/L2 分层**:
+
+```markdown
+# skill-id 技能
+
+## L0:一句话摘要
+用一句话描述这个技能做什么。
+
+## L1:概述与使用场景
+### 能力描述 / ### 使用场景 / ### 核心价值
+
+## L2:详细规范
+### 具体操作步骤 / ### 错误处理
+```
+
+分层加载机制:
+- **L0**(~50 字):快速理解技能做什么
+- **L1**(~300 字):判断是否适用于当前任务
+- **L2**(不限):完整的执行指南
+
+> 分层不是强制的。如果技能内容简短(<100 行),可以不分层——解析器会以整段内容作为 fallback。Claude Code 的无分层格式在 DesireCore 中同样正常工作。
+
+#### Bundled Resources
+
+##### Scripts(`scripts/`)
+
+可执行代码(Python/Bash 等),用于需要确定性可靠性或被反复编写的任务。
+
+- **何时使用**:相同代码被反复编写,或需要确定性可靠性
+- **示例**:`scripts/rotate_pdf.py`(PDF 旋转)、`scripts/fill_form.py`(表单填充)
+- **优势**:Token 高效,确定性,可直接执行无需读入上下文
+- **注意**:脚本可能仍需被 AI 读取以做环境适配
+
+##### References(`references/`)
+
+文档和参考资料,按需加载到上下文中。
+
+- **何时使用**:AI 工作时需要参考的详细文档
+- **示例**:API 文档、数据库 Schema、领域知识、公司政策
+- **最佳实践**:大文件(>10k 词)在 SKILL.md 中提供 grep 搜索模式
+- **避免重复**:信息只放 SKILL.md 或 references 中的一处
+
+##### Assets(`assets/`)
+
+不加载到上下文、而是用于输出的文件。
+
+- **何时使用**:技能需要在最终输出中使用的文件
+- **示例**:PPT 模板、HTML 骨架、logo 图片、字体文件
+- **优势**:将输出资源与文档分离
+
+#### 不应包含的内容
+
+技能应只包含 AI 执行任务所需的文件。**不要**创建:README.md、INSTALLATION_GUIDE.md、CHANGELOG.md 等辅助文档。
+
+### 渐进式披露模式
+
+保持 SKILL.md body 在 500 行以内。接近限制时拆分到 references。
+
+**模式 1:高层指南 + 参考文件**
+
+```markdown
+# PDF Processing
+
+## Quick start
+[核心代码示例]
+
+## Advanced features
+- **Form filling**: See [FORMS.md](FORMS.md)
+- **API reference**: See [REFERENCE.md](REFERENCE.md)
+```
+
+**模式 2:按领域组织**
+
+```
+bigquery-skill/
+├── SKILL.md (overview)
+└── references/
+ ├── finance.md
+ ├── sales.md
+ └── product.md
+```
+
+用户问销售指标时,AI 只读 sales.md。
+
+**模式 3:基本内容 + 条件高级内容**
+
+```markdown
+## Editing documents
+For simple edits, modify the XML directly.
+**For tracked changes**: See [REDLINING.md](REDLINING.md)
+```
+
+**重要**:避免深层嵌套引用——references 只从 SKILL.md 直接链接一层。长 reference 文件(>100 行)在顶部加目录。
+
+### 创建流程
+
+1. 用具体例子理解技能需求
+2. 规划可复用资源(脚本、参考、资产)
+3. 初始化技能(运行 init_skill.py)
+4. 编辑技能(实现资源,编写 SKILL.md)
+5. 验证技能(运行 quick_validate.py)
+6. 安装技能
+7. 迭代优化
+
+#### 步骤 1:理解技能需求
+
+跳过此步仅当技能的使用模式已经完全清晰。即使处理已有技能时,此步仍有价值。
+
+通过具体例子理解技能将如何被使用。例如构建 image-editor 技能时:
+
+- "这个技能应支持哪些功能?编辑、旋转、其他?"
+- "能举几个使用场景吗?"
+- "什么操作应该触发这个技能?"
+
+避免一次问太多问题——从最重要的开始,按需跟进。当对技能应支持的功能有清晰认知时,结束此步。
+
+#### 步骤 2:规划资源
+
+分析每个例子:
+
+1. 考虑如何从零执行
+2. 识别哪些脚本、参考、资产在反复执行时有帮助
+
+示例分析:
+
+- `pdf-editor` 处理"旋转 PDF"→ 每次都要写相同代码 → `scripts/rotate_pdf.py`
+- `frontend-webapp-builder` 处理"创建 todo app"→ 每次都要写样板代码 → `assets/hello-world/`
+- `big-query` 处理"今天多少用户登录"→ 每次都要查 Schema → `references/schema.md`
+
+#### 步骤 3:初始化
+
+使用 init_skill.py 创建模板:
+
+```bash
+# DesireCore 完整格式(默认,推荐)
+scripts/init_skill.py --path
+
+# Claude Code 基础格式
+scripts/init_skill.py --path --format basic
+```
+
+默认生成 DesireCore 格式(含完整 frontmatter + L0/L1/L2 结构)。`--format basic` 生成 Claude Code 兼容的最小格式。
+
+初始化后,根据需要定制或删除生成的示例文件。
+
+#### 步骤 4:编辑技能
+
+##### 学习设计模式
+
+根据技能需求查阅参考:
+
+- **多步骤流程**:见 [references/workflows.md](references/workflows.md)
+- **输出格式标准**:见 [references/output-patterns.md](references/output-patterns.md)
+
+##### 从资源开始
+
+先实现步骤 2 识别的资源文件(scripts/、references/、assets/)。此步骤可能需要用户输入,如品牌资产需要用户提供 logo。
+
+添加的脚本必须实际运行测试,确保无 bug 且输出符合预期。不需要的示例文件应删除。
+
+##### 编写 SKILL.md
+
+**Frontmatter 编写要点**:
+
+- `description` 是最关键的字段——AI 据此判断何时触发技能
+- 在 description 中包含 "Use when" 触发提示和典型使用场景
+- 所有 "when to use" 信息放 description 中,不放 body 里(body 只在触发后加载)
+
+**Body 编写要点**:
+
+- 始终使用祈使句/不定式形式
+- L0 不超过一句话
+- L1 用于判断适用性,不超过 300 字
+- L2 放完整的操作步骤、API 调用、错误处理
+
+#### 步骤 5:验证
+
+```bash
+scripts/quick_validate.py
+```
+
+验证 SKILL.md 格式、frontmatter 字段合法性和目录结构。
+
+#### 步骤 6:安装
+
+**方式 A:通过 API 安装(推荐,需 Agent Service 运行中)**
+
+```bash
+PORT=$(cat ~/.desirecore/agent-service.port 2>/dev/null)
+
+# 安装为全局技能(所有 Agent 可见)
+curl -k -X POST "https://127.0.0.1:${PORT}/api/skills" \
+ -H "Content-Type: application/json" \
+ -d "{\"skillId\": \"\", \"content\": \"$(cat path/to/SKILL.md | jq -Rsa .)\"}"
+
+# 安装为 Agent 级技能(仅指定 Agent 可见)
+curl -k -X POST "https://127.0.0.1:${PORT}/api/agents//skills" \
+ -H "Content-Type: application/json" \
+ -d "{\"id\": \"\", \"fullContent\": \"$(cat path/to/SKILL.md | jq -Rsa .)\"}"
+```
+
+**方式 B:文件系统直写**
+
+```bash
+# 全局技能
+cp -r path/to/skill-name ~/.desirecore/skills/
+
+# Agent 级技能
+cp -r path/to/skill-name ~/.desirecore/agents//skills/
+```
+
+**方式 C:打包为 .skill 文件(Claude Code 兼容)**
+
+```bash
+scripts/package_skill.py
+```
+
+生成 `skill-name.skill` 文件(ZIP 格式),可在 Claude Code 中使用。
+
+#### 步骤 7:迭代
+
+1. 在真实任务中使用技能
+2. 观察不足或低效之处
+3. 确定 SKILL.md 或资源需要如何改进
+4. 实施修改并再次测试
+
+### 作用域说明
+
+技能存在三个作用域层级,按优先级从高到低:
+
+| 优先级 | 作用域 | 路径 | 可见范围 |
+|--------|--------|------|---------|
+| 最高 | Project | `.claude/skills/` | 当前项目所有 Agent |
+| 中 | Agent | `~/.desirecore/agents/{agentId}/skills/` | 仅该 Agent |
+| 最低 | Global | `~/.desirecore/skills/` | 所有 Agent |
+
+同名技能按优先级覆盖——高优先级的技能会遮蔽低优先级的同名技能。
diff --git a/skills/skill-creator/references/desirecore-format.md b/skills/skill-creator/references/desirecore-format.md
new file mode 100644
index 0000000..587ae6d
--- /dev/null
+++ b/skills/skill-creator/references/desirecore-format.md
@@ -0,0 +1,208 @@
+# DesireCore SKILL.md 完整格式参考
+
+## Frontmatter 完整字段表
+
+### 必填字段
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `description` | string | 技能用途描述,必须包含 "Use when" 触发提示 |
+
+### 推荐字段
+
+| 字段 | 类型 | 说明 | 示例 |
+|------|------|------|------|
+| `name` | string | 显示名称(中英文均可) | `"数据分析"` |
+| `version` | string | 语义版本号 | `"1.0.0"` |
+| `type` | enum | `procedural` / `conversational` / `meta` | `procedural` |
+| `risk_level` | enum | `low` / `medium` / `high` | `low` |
+| `status` | enum | `enabled` / `disabled` | `enabled` |
+| `tags` | string[] | 标签列表 | `[analysis, data]` |
+| `metadata.author` | string | 技能作者 | `"user"` |
+| `metadata.updated_at` | string | 更新日期 | `"2026-04-03"` |
+
+### 功能控制字段
+
+| 字段 | 类型 | 默认 | 说明 |
+|------|------|------|------|
+| `disable-model-invocation` | boolean | `true` | `true`=仅显式调用触发;`false`=自动注入 system prompt |
+| `user-invocable` | boolean | `true` | `false`=不出现在命令补全,仅作为背景知识 |
+| `allowed-tools` | string[] | 全部 | 限制执行时可用的工具列表(如 `["Edit", "Read", "Bash"]`) |
+| `model` | string | 继承 | 覆盖使用的模型 ID(如 `"claude-sonnet-4-20250514"`) |
+| `context` | enum | `default` | `fork`=在独立子 Agent 中执行 |
+| `agent` | string | — | `context=fork` 时子 Agent 的角色描述 |
+| `argument-hint` | string | — | 参数提示,显示在自动补全中(如 `""`) |
+
+### 依赖声明
+
+```yaml
+requires:
+ tools:
+ - Bash
+ - Read
+ optional_tools:
+ - Edit
+ connections:
+ - database-x
+```
+
+### 市场展示字段
+
+发布到市场时需要填写:
+
+```yaml
+market:
+ icon: >-
+
+ short_desc: 一句话简介,用于市场卡片展示
+ category: productivity
+ maintainer:
+ name: Your Name
+ verified: false
+ compatible_agents: []
+ required_client_version: "10.0.20"
+ channel: latest
+```
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `market.icon` | string | 内联 SVG 图标 |
+| `market.short_desc` | string | 一句话简介 |
+| `market.category` | string | 分类 slug(如 `productivity`、`knowledge`、`development`) |
+| `market.maintainer.name` | string | 维护者名称 |
+| `market.maintainer.verified` | boolean | 是否官方认证 |
+| `market.compatible_agents` | string[] | 兼容的 Agent ID |
+| `market.required_client_version` | string | 最低客户端版本(semver) |
+| `market.channel` | enum | `latest` / `stable` |
+
+### JSON 输出控制
+
+```yaml
+json_output:
+ enabled: true
+ shape: object
+```
+
+启用后,AI 的最终回复会被自动解析修复为合法 JSON。`shape` 指定顶层形状:`object`(默认)或 `array`。
+
+### Claude Code 兼容字段
+
+以下字段来自 Claude Code 规范,在 DesireCore 中同样合法(Schema 设置了 `additionalProperties: true`):
+
+| 字段 | 类型 | 说明 |
+|------|------|------|
+| `license` | string | 许可证声明 |
+| `compatibility` | string | 环境兼容性说明 |
+
+## type 类型详解
+
+| 类型 | 含义 | 交互模式 | 典型示例 |
+|------|------|---------|---------|
+| `procedural` | 流程型 | 按步骤执行,较少交互 | 数据分析、文档处理、API 操作 |
+| `conversational` | 对话型 | 多轮交互完成 | 需求收集、头脑风暴、方案评审 |
+| `meta` | 元技能 | 管理其他系统资源 | 创建 Agent、管理技能、团队管理 |
+
+## Body 分层详解
+
+### L0:一句话摘要
+
+- 不超过一句话(~50 字)
+- 用于快速理解技能做什么
+- 标题格式:`## L0:一句话摘要`
+
+### L1:概述与使用场景
+
+- 不超过 300 字
+- 用于判断当前任务是否适用该技能
+- 推荐子标题:`### 能力描述`、`### 使用场景`、`### 核心价值`
+- 标题格式:`## L1:概述与使用场景`
+
+### L2:详细规范
+
+- 无长度限制(但 SKILL.md 整体建议 <500 行)
+- 完整的执行指南、API 调用、错误处理、权限要求
+- 标题格式:`## L2:详细规范`
+
+### 分层加载机制
+
+- `disable-model-invocation: false` 时:L0 + L1 自动注入 system prompt
+- `disable-model-invocation: true` 时:显式调用时加载完整内容(L0 + L1 + L2)
+- 不分层时:整段内容作为 fallback
+
+## 完整示例
+
+### procedural 类型(数据分析)
+
+```yaml
+---
+name: 数据分析
+description: >-
+ 对结构化数据进行深度分析和可视化。Use when 用户要求分析
+ CSV/Excel 数据、生成统计报告、或创建数据图表。
+version: 1.0.0
+type: procedural
+risk_level: low
+status: enabled
+tags: [analysis, data, visualization]
+metadata:
+ author: user
+ updated_at: '2026-04-03'
+---
+
+# data-analysis 技能
+
+## L0:一句话摘要
+
+对结构化数据进行深度分析、统计和可视化。
+
+## L1:概述与使用场景
+
+### 能力描述
+
+支持 CSV、Excel、JSON 等格式数据的读取、清洗、统计分析和图表生成。
+
+### 使用场景
+
+- 分析销售数据并生成月度报告
+- 数据清洗和格式转换
+- 生成统计图表
+
+## L2:详细规范
+
+### 分析流程
+
+1. 读取并检查数据格式
+2. 数据清洗(缺失值、异常值)
+3. 统计分析
+4. 可视化输出
+```
+
+### meta 类型(资源管理)
+
+```yaml
+---
+name: 知识库管理
+description: >-
+ 管理 Agent 的知识库:导入文档、更新索引、清理过期内容。
+ Use when 用户要求导入新文档到知识库、更新或删除已有内容。
+version: 1.0.0
+type: meta
+risk_level: medium
+status: enabled
+disable-model-invocation: true
+tags: [knowledge, management, meta]
+metadata:
+ author: user
+ updated_at: '2026-04-03'
+---
+```
+
+## 与 Claude Code 格式对比
+
+| 维度 | Claude Code 格式 | DesireCore 格式 |
+|------|-----------------|----------------|
+| 必填 frontmatter | `name` + `description` | `description` |
+| 可选 frontmatter | `license`、`compatibility`、`metadata` | 20+ 字段(全部可选) |
+| Body 结构 | 自由 Markdown | L0/L1/L2 分层(推荐,非强制) |
+| 分发方式 | `.skill` ZIP 包 | API 安装 / 文件系统 / 市场 |
+| 兼容性 | — | DesireCore 是超集,完全向下兼容 |
diff --git a/skills/skill-creator/references/output-patterns.md b/skills/skill-creator/references/output-patterns.md
new file mode 100644
index 0000000..073ddda
--- /dev/null
+++ b/skills/skill-creator/references/output-patterns.md
@@ -0,0 +1,82 @@
+# Output Patterns
+
+Use these patterns when skills need to produce consistent, high-quality output.
+
+## Template Pattern
+
+Provide templates for output format. Match the level of strictness to your needs.
+
+**For strict requirements (like API responses or data formats):**
+
+```markdown
+## Report structure
+
+ALWAYS use this exact template structure:
+
+# [Analysis Title]
+
+## Executive summary
+[One-paragraph overview of key findings]
+
+## Key findings
+- Finding 1 with supporting data
+- Finding 2 with supporting data
+- Finding 3 with supporting data
+
+## Recommendations
+1. Specific actionable recommendation
+2. Specific actionable recommendation
+```
+
+**For flexible guidance (when adaptation is useful):**
+
+```markdown
+## Report structure
+
+Here is a sensible default format, but use your best judgment:
+
+# [Analysis Title]
+
+## Executive summary
+[Overview]
+
+## Key findings
+[Adapt sections based on what you discover]
+
+## Recommendations
+[Tailor to the specific context]
+
+Adjust sections as needed for the specific analysis type.
+```
+
+## Examples Pattern
+
+For skills where output quality depends on seeing examples, provide input/output pairs:
+
+```markdown
+## Commit message format
+
+Generate commit messages following these examples:
+
+**Example 1:**
+Input: Added user authentication with JWT tokens
+Output:
+```
+feat(auth): implement JWT-based authentication
+
+Add login endpoint and token validation middleware
+```
+
+**Example 2:**
+Input: Fixed bug where dates displayed incorrectly in reports
+Output:
+```
+fix(reports): correct date formatting in timezone conversion
+
+Use UTC timestamps consistently across report generation
+```
+
+Follow this style: type(scope): brief description, then detailed explanation.
+```
+
+Examples help Claude understand the desired style and level of detail more clearly than descriptions alone.
diff --git a/skills/skill-creator/references/workflows.md b/skills/skill-creator/references/workflows.md
new file mode 100644
index 0000000..a350c3c
--- /dev/null
+++ b/skills/skill-creator/references/workflows.md
@@ -0,0 +1,28 @@
+# Workflow Patterns
+
+## Sequential Workflows
+
+For complex tasks, break operations into clear, sequential steps. It is often helpful to give Claude an overview of the process towards the beginning of SKILL.md:
+
+```markdown
+Filling a PDF form involves these steps:
+
+1. Analyze the form (run analyze_form.py)
+2. Create field mapping (edit fields.json)
+3. Validate mapping (run validate_fields.py)
+4. Fill the form (run fill_form.py)
+5. Verify output (run verify_output.py)
+```
+
+## Conditional Workflows
+
+For tasks with branching logic, guide Claude through decision points:
+
+```markdown
+1. Determine the modification type:
+ **Creating new content?** → Follow "Creation workflow" below
+ **Editing existing content?** → Follow "Editing workflow" below
+
+2. Creation workflow: [steps]
+3. Editing workflow: [steps]
+```
\ No newline at end of file
diff --git a/skills/skill-creator/scripts/init_skill.py b/skills/skill-creator/scripts/init_skill.py
new file mode 100755
index 0000000..c595ed0
--- /dev/null
+++ b/skills/skill-creator/scripts/init_skill.py
@@ -0,0 +1,261 @@
+#!/usr/bin/env python3
+"""
+Skill Initializer - Creates a new skill from template
+
+Usage:
+ init_skill.py --path [--format basic|desirecore]
+
+Examples:
+ init_skill.py my-new-skill --path ~/.desirecore/skills
+ init_skill.py my-api-helper --path ~/.desirecore/skills --format basic
+"""
+
+import sys
+import argparse
+import re
+from pathlib import Path
+from datetime import date
+
+
+# ==================== DesireCore 完整格式模板 ====================
+
+DESIRECORE_TEMPLATE = """\
+---
+name: {skill_name}
+description: >-
+ [TODO: 完整描述技能用途。必须包含 "Use when" 触发提示,
+ 帮助 AI 判断何时使用该技能。]
+version: 1.0.0
+type: procedural
+risk_level: low
+status: enabled
+tags:
+ - [TODO: 添加标签]
+metadata:
+ author: user
+ updated_at: '{today}'
+---
+
+# {skill_title}
+
+## L0:一句话摘要
+
+[TODO: 用一句话描述这个技能做什么]
+
+## L1:概述与使用场景
+
+### 能力描述
+
+[TODO: 详细描述技能的核心能力]
+
+### 使用场景
+
+- [TODO: 场景 1]
+- [TODO: 场景 2]
+
+### 核心价值
+
+- [TODO: 价值 1]
+
+## L2:详细规范
+
+### 具体操作步骤
+
+[TODO: 按步骤描述执行流程]
+
+### 错误处理
+
+| 错误场景 | 处理方式 |
+|---------|---------|
+| [TODO] | [TODO] |
+"""
+
+
+# ==================== Claude Code 基础格式模板 ====================
+
+BASIC_TEMPLATE = """\
+---
+name: {skill_name}
+description: [TODO: Complete and informative explanation of what the skill does and when to use it. Include WHEN to use this skill - specific scenarios, file types, or tasks that trigger it.]
+---
+
+# {skill_title}
+
+## Overview
+
+[TODO: 1-2 sentences explaining what this skill enables]
+
+## [TODO: Replace with first main section]
+
+[TODO: Add content here]
+
+## Resources
+
+This skill includes example resource directories:
+
+### scripts/
+Executable code for tasks that require deterministic reliability.
+
+### references/
+Documentation and reference material loaded into context as needed.
+
+### assets/
+Files used within the output (templates, images, fonts, etc.).
+
+---
+
+**Delete any unneeded directories.** Not every skill requires all three.
+"""
+
+
+EXAMPLE_SCRIPT = '''\
+#!/usr/bin/env python3
+"""
+Example helper script for {skill_name}
+
+Replace with actual implementation or delete if not needed.
+"""
+
+def main():
+ print("Example script for {skill_name}")
+ # TODO: Add actual script logic
+
+if __name__ == "__main__":
+ main()
+'''
+
+EXAMPLE_REFERENCE = """\
+# Reference Documentation for {skill_title}
+
+Replace with actual reference content or delete if not needed.
+
+Reference docs are ideal for:
+- API documentation
+- Detailed workflow guides
+- Database schemas
+- Content too lengthy for main SKILL.md
+"""
+
+EXAMPLE_ASSET = """\
+This is a placeholder for asset files.
+Replace with actual assets (templates, images, fonts, etc.) or delete if not needed.
+
+Asset files are NOT loaded into context — they are used within the output.
+"""
+
+
+def title_case_skill_name(skill_name):
+ """Convert hyphenated skill name to Title Case."""
+ return ' '.join(word.capitalize() for word in skill_name.split('-'))
+
+
+def validate_skill_name(name):
+ """Validate skill name format (kebab-case)."""
+ if not re.match(r'^[a-z0-9][a-z0-9-]*[a-z0-9]$', name) and not re.match(r'^[a-z0-9]$', name):
+ return False, "Name must be kebab-case (lowercase letters, digits, hyphens)"
+ if '--' in name:
+ return False, "Name cannot contain consecutive hyphens"
+ if len(name) > 64:
+ return False, f"Name too long ({len(name)} chars, max 64)"
+ return True, ""
+
+
+def init_skill(skill_name, path, fmt='desirecore'):
+ """Initialize a new skill directory with template SKILL.md."""
+ skill_dir = Path(path).resolve() / skill_name
+
+ if skill_dir.exists():
+ print(f"❌ Error: Skill directory already exists: {skill_dir}")
+ return None
+
+ # Create skill directory
+ try:
+ skill_dir.mkdir(parents=True, exist_ok=False)
+ print(f"✅ Created skill directory: {skill_dir}")
+ except Exception as e:
+ print(f"❌ Error creating directory: {e}")
+ return None
+
+ # Create SKILL.md from template
+ skill_title = title_case_skill_name(skill_name)
+ template = DESIRECORE_TEMPLATE if fmt == 'desirecore' else BASIC_TEMPLATE
+ skill_content = template.format(
+ skill_name=skill_name,
+ skill_title=skill_title,
+ today=date.today().isoformat(),
+ )
+
+ skill_md_path = skill_dir / 'SKILL.md'
+ try:
+ skill_md_path.write_text(skill_content)
+ print(f"✅ Created SKILL.md ({fmt} format)")
+ except Exception as e:
+ print(f"❌ Error creating SKILL.md: {e}")
+ return None
+
+ # Create resource directories with example files
+ try:
+ 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("✅ Created scripts/example.py")
+
+ references_dir = skill_dir / 'references'
+ references_dir.mkdir(exist_ok=True)
+ example_ref = references_dir / 'api_reference.md'
+ example_ref.write_text(EXAMPLE_REFERENCE.format(skill_title=skill_title))
+ print("✅ Created references/api_reference.md")
+
+ 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("✅ Created assets/example_asset.txt")
+ except Exception as e:
+ print(f"❌ Error creating resource directories: {e}")
+ return None
+
+ print(f"\n✅ Skill '{skill_name}' initialized at {skill_dir}")
+ print("\nNext steps:")
+ print("1. Edit SKILL.md — complete TODO items and update description")
+ print("2. Customize or delete example files in scripts/, references/, assets/")
+ print("3. Run quick_validate.py to check the skill structure")
+
+ return skill_dir
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description='Initialize a new skill from template',
+ epilog='Examples:\n'
+ ' init_skill.py my-new-skill --path ~/.desirecore/skills\n'
+ ' init_skill.py my-api-helper --path ~/.desirecore/skills --format basic',
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ )
+ parser.add_argument('skill_name', help='Skill name (kebab-case, max 64 chars)')
+ parser.add_argument('--path', required=True, help='Parent directory for the skill')
+ parser.add_argument(
+ '--format', choices=['desirecore', 'basic'], default='desirecore',
+ help='Template format: desirecore (full, default) or basic (Claude Code compatible)',
+ )
+ args = parser.parse_args()
+
+ # Validate name
+ valid, msg = validate_skill_name(args.skill_name)
+ if not valid:
+ print(f"❌ Invalid skill name: {msg}")
+ sys.exit(1)
+
+ print(f"🚀 Initializing skill: {args.skill_name}")
+ print(f" Location: {args.path}")
+ print(f" Format: {args.format}")
+ print()
+
+ result = init_skill(args.skill_name, args.path, args.format)
+ sys.exit(0 if result else 1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/skills/skill-creator/scripts/package_skill.py b/skills/skill-creator/scripts/package_skill.py
new file mode 100755
index 0000000..29984da
--- /dev/null
+++ b/skills/skill-creator/scripts/package_skill.py
@@ -0,0 +1,213 @@
+#!/usr/bin/env python3
+"""
+Skill Packager & Installer
+
+Supports two modes:
+ - Package: Create a .skill file (ZIP) for Claude Code distribution
+ - Install: Install directly to DesireCore via HTTP API
+
+Usage:
+ # Package as .skill file (Claude Code compatible)
+ package_skill.py [output-directory]
+
+ # Install to DesireCore via API
+ package_skill.py --install [--scope global|agent] [--agent-id ]
+"""
+
+import sys
+import os
+import json
+import zipfile
+import argparse
+import ssl
+import urllib.request
+import urllib.error
+from pathlib import Path
+
+# Import validate_skill from sibling script
+_script_dir = Path(__file__).resolve().parent
+sys.path.insert(0, str(_script_dir))
+from quick_validate import validate_skill
+
+
+# ==================== Package Mode ====================
+
+def package_skill(skill_path, output_dir=None):
+ """Package a skill folder into a .skill file (ZIP format)."""
+ skill_path = Path(skill_path).resolve()
+
+ if not skill_path.exists():
+ print(f"❌ Error: Skill folder not found: {skill_path}")
+ return None
+
+ if not skill_path.is_dir():
+ print(f"❌ Error: Path is not a directory: {skill_path}")
+ return None
+
+ skill_md = skill_path / "SKILL.md"
+ if not skill_md.exists():
+ print(f"❌ Error: SKILL.md not found in {skill_path}")
+ return None
+
+ # Validate before packaging
+ print("🔍 Validating skill...")
+ valid, errors, warnings = validate_skill(skill_path)
+ if not valid:
+ print(f"❌ Validation failed:")
+ for e in errors:
+ print(f" ✗ {e}")
+ return None
+ if warnings:
+ for w in warnings:
+ print(f" ⚠ {w}")
+ print(f"✅ Validation passed\n")
+
+ # Determine output location
+ 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"
+
+ # Create .skill file (zip format)
+ try:
+ with zipfile.ZipFile(skill_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
+ for file_path in skill_path.rglob('*'):
+ if file_path.is_file():
+ arcname = file_path.relative_to(skill_path.parent)
+ zipf.write(file_path, arcname)
+ print(f" Added: {arcname}")
+
+ print(f"\n✅ Packaged to: {skill_filename}")
+ return skill_filename
+
+ except Exception as e:
+ print(f"❌ Error creating .skill file: {e}")
+ return None
+
+
+# ==================== Install Mode ====================
+
+def read_agent_service_port():
+ """Read Agent Service port from port file."""
+ port_file = Path.home() / '.desirecore' / 'agent-service.port'
+ if not port_file.exists():
+ return None
+ return port_file.read_text().strip()
+
+
+def install_skill(skill_path, scope='global', agent_id=None):
+ """Install a skill to DesireCore via HTTP API."""
+ skill_path = Path(skill_path).resolve()
+ skill_md = skill_path / 'SKILL.md'
+
+ if not skill_md.exists():
+ print(f"❌ Error: SKILL.md not found in {skill_path}")
+ return None
+
+ # Validate first
+ print("🔍 Validating skill...")
+ valid, errors, warnings = validate_skill(skill_path)
+ if not valid:
+ print(f"❌ Validation failed:")
+ for e in errors:
+ print(f" ✗ {e}")
+ return None
+ if warnings:
+ for w in warnings:
+ print(f" ⚠ {w}")
+ print(f"✅ Validation passed\n")
+
+ # Check Agent Service
+ port = read_agent_service_port()
+ if not port:
+ print("❌ Error: Agent Service not running (port file not found)")
+ print("\nFallback — install via file system:")
+ if scope == 'agent' and agent_id:
+ print(f" cp -r {skill_path} ~/.desirecore/agents/{agent_id}/skills/")
+ else:
+ print(f" cp -r {skill_path} ~/.desirecore/skills/")
+ return None
+
+ content = skill_md.read_text()
+ skill_id = skill_path.name
+
+ # Build API request
+ ctx = ssl.create_default_context()
+ ctx.check_hostname = False
+ ctx.verify_mode = ssl.CERT_NONE
+
+ if scope == 'agent':
+ if not agent_id:
+ print("❌ Error: --agent-id is required for agent scope")
+ return None
+ url = f"https://127.0.0.1:{port}/api/agents/{agent_id}/skills"
+ payload = {"id": skill_id, "fullContent": content}
+ else:
+ url = f"https://127.0.0.1:{port}/api/skills"
+ payload = {"skillId": skill_id, "content": content}
+
+ data = json.dumps(payload).encode('utf-8')
+ req = urllib.request.Request(
+ url, data=data, method='POST',
+ headers={'Content-Type': 'application/json'},
+ )
+
+ try:
+ with urllib.request.urlopen(req, context=ctx) as resp:
+ result = json.loads(resp.read())
+ print(f"✅ Installed '{skill_id}' ({scope} scope)")
+ return result
+ except urllib.error.HTTPError as e:
+ body = e.read().decode('utf-8', errors='replace')
+ print(f"❌ API error ({e.code}): {body}")
+ return None
+ except urllib.error.URLError as e:
+ print(f"❌ Connection error: {e.reason}")
+ print("Is Agent Service running?")
+ return None
+
+
+# ==================== Main ====================
+
+def main():
+ parser = argparse.ArgumentParser(
+ description='Package or install a skill',
+ epilog='Examples:\n'
+ ' package_skill.py my-skill/ # Package as .skill ZIP\n'
+ ' package_skill.py my-skill/ ./dist # Package to specific dir\n'
+ ' package_skill.py my-skill/ --install # Install via API (global)\n'
+ ' package_skill.py my-skill/ --install --scope agent --agent-id abc123',
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ )
+ parser.add_argument('skill_path', help='Path to skill folder')
+ parser.add_argument('output_dir', nargs='?', default=None,
+ help='Output directory for .skill file (package mode only)')
+ parser.add_argument('--install', action='store_true',
+ help='Install via DesireCore API instead of packaging')
+ parser.add_argument('--scope', choices=['global', 'agent'], default='global',
+ help='Installation scope (default: global)')
+ parser.add_argument('--agent-id',
+ help='Agent ID (required when --scope agent)')
+
+ args = parser.parse_args()
+
+ if args.install:
+ print(f"📦 Installing skill: {args.skill_path} ({args.scope} scope)")
+ print()
+ result = install_skill(args.skill_path, args.scope, args.agent_id)
+ else:
+ print(f"📦 Packaging skill: {args.skill_path}")
+ if args.output_dir:
+ print(f" Output: {args.output_dir}")
+ print()
+ result = package_skill(args.skill_path, args.output_dir)
+
+ sys.exit(0 if result else 1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/skills/skill-creator/scripts/quick_validate.py b/skills/skill-creator/scripts/quick_validate.py
new file mode 100755
index 0000000..5e94dee
--- /dev/null
+++ b/skills/skill-creator/scripts/quick_validate.py
@@ -0,0 +1,164 @@
+#!/usr/bin/env python3
+"""
+Quick validation script for skills.
+
+Validates against DesireCore SKILL.md frontmatter schema.
+Also accepts Claude Code basic format (name + description only).
+"""
+
+import sys
+import re
+from pathlib import Path
+
+try:
+ import yaml
+except ImportError:
+ print("Error: PyYAML is required. Install with: pip install pyyaml")
+ sys.exit(1)
+
+
+# DesireCore 已知的顶层字段集合
+# 来源:lib/schemas/agent/skill-frontmatter.ts 的 properties 定义
+# Schema 设置了 additionalProperties: true,所以未知字段只警告不报错
+KNOWN_PROPERTIES = {
+ # 核心字段
+ 'name', 'description', 'version', 'type', 'requires',
+ 'risk_level', 'status', 'tags', 'metadata',
+ # 功能控制
+ 'disable-model-invocation', 'disable_model_invocation',
+ 'allowed-tools', 'user-invocable', 'argument-hint',
+ 'model', 'context', 'agent',
+ # 高级字段
+ 'error_message', 'skill_package', 'input_schema', 'output_schema',
+ 'market', 'x_desirecore', 'json_output',
+ # Claude Code 兼容字段
+ 'license', 'compatibility',
+}
+
+VALID_TYPES = {'procedural', 'conversational', 'meta'}
+VALID_RISK_LEVELS = {'low', 'medium', 'high'}
+VALID_STATUSES = {'enabled', 'disabled'}
+VALID_CONTEXTS = {'default', 'fork'}
+SEMVER_RE = re.compile(r'^\d+\.\d+\.\d+$')
+KEBAB_RE = re.compile(r'^[a-z0-9][a-z0-9-]*[a-z0-9]$|^[a-z0-9]$')
+
+
+def validate_skill(skill_path):
+ """
+ Validate a skill directory.
+
+ Returns:
+ (valid: bool, errors: list[str], warnings: list[str])
+ """
+ skill_path = Path(skill_path)
+ errors = []
+ warnings = []
+
+ # Check SKILL.md exists
+ skill_md = skill_path / 'SKILL.md'
+ if not skill_md.exists():
+ return False, ["SKILL.md not found"], []
+
+ content = skill_md.read_text()
+ if not content.startswith('---'):
+ return False, ["No YAML frontmatter found (must start with ---)"], []
+
+ # Extract frontmatter
+ match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
+ if not match:
+ return False, ["Invalid frontmatter format (missing closing ---)"], []
+
+ try:
+ frontmatter = yaml.safe_load(match.group(1))
+ if not isinstance(frontmatter, dict):
+ return False, ["Frontmatter must be a YAML dictionary"], []
+ except yaml.YAMLError as e:
+ return False, [f"Invalid YAML: {e}"], []
+
+ # === 必填字段 ===
+ if 'description' not in frontmatter:
+ errors.append("Missing required field: 'description'")
+
+ # === description 质量检查 ===
+ description = frontmatter.get('description', '')
+ if isinstance(description, str):
+ desc_stripped = description.strip()
+ if desc_stripped and len(desc_stripped) < 10:
+ warnings.append("Description is very short — include 'Use when' trigger hints")
+ if len(desc_stripped) > 1024:
+ errors.append(f"Description too long ({len(desc_stripped)} chars, max 1024)")
+ if '<' in desc_stripped or '>' in desc_stripped:
+ warnings.append("Description contains angle brackets (< or >) — may cause parsing issues")
+
+ # === name 格式检查 ===
+ name = frontmatter.get('name', '')
+ if isinstance(name, str) and name.strip():
+ n = name.strip()
+ if len(n) > 64:
+ errors.append(f"Name too long ({len(n)} chars, max 64)")
+ # kebab-case 检查仅当 name 是英文时
+ if re.match(r'^[a-z0-9-]+$', n):
+ if not KEBAB_RE.match(n):
+ warnings.append(f"Name '{n}' starts/ends with hyphen or has consecutive hyphens")
+
+ # === version 格式检查 ===
+ version = frontmatter.get('version')
+ if version is not None and not SEMVER_RE.match(str(version)):
+ warnings.append(f"Version '{version}' is not valid semver (expected x.y.z)")
+
+ # === 枚举字段检查 ===
+ skill_type = frontmatter.get('type')
+ if skill_type is not None and skill_type not in VALID_TYPES:
+ errors.append(f"Invalid type: '{skill_type}'. Must be one of: {', '.join(sorted(VALID_TYPES))}")
+
+ risk = frontmatter.get('risk_level')
+ if risk is not None and risk not in VALID_RISK_LEVELS:
+ errors.append(f"Invalid risk_level: '{risk}'. Must be one of: {', '.join(sorted(VALID_RISK_LEVELS))}")
+
+ status = frontmatter.get('status')
+ if status is not None and status not in VALID_STATUSES:
+ errors.append(f"Invalid status: '{status}'. Must be one of: {', '.join(sorted(VALID_STATUSES))}")
+
+ context = frontmatter.get('context')
+ if context is not None and context not in VALID_CONTEXTS:
+ errors.append(f"Invalid context: '{context}'. Must be one of: {', '.join(sorted(VALID_CONTEXTS))}")
+
+ # === 未知字段警告(不阻断) ===
+ unknown = set(frontmatter.keys()) - KNOWN_PROPERTIES
+ if unknown:
+ warnings.append(f"Unknown fields (will be preserved): {', '.join(sorted(unknown))}")
+
+ valid = len(errors) == 0
+ return valid, errors, warnings
+
+
+def main():
+ if len(sys.argv) != 2:
+ print("Usage: quick_validate.py ")
+ print("\nValidates SKILL.md frontmatter against DesireCore schema.")
+ print("Also accepts Claude Code basic format (name + description).")
+ sys.exit(1)
+
+ skill_path = sys.argv[1]
+ valid, errors, warnings = validate_skill(skill_path)
+
+ if valid and not warnings:
+ print(f"✅ Skill is valid!")
+ elif valid and warnings:
+ print(f"✅ Skill is valid (with warnings):")
+ for w in warnings:
+ print(f" ⚠ {w}")
+ else:
+ print(f"❌ Validation failed:")
+ for e in errors:
+ print(f" ✗ {e}")
+ if warnings:
+ print(f" Warnings:")
+ for w in warnings:
+ print(f" ⚠ {w}")
+
+ sys.exit(0 if valid else 1)
+
+
+if __name__ == "__main__":
+ main()