Skill(技能)元数据 struct + 发现与加载系统。
Skill 是通过 SKILL.md 文件定义的领域知识片段,Agent 在启动时自动发现并按需注入到系统提示词。
SKILL.md 文件格式
---
name: elixir-testing
description: Elixir 项目测试最佳实践
allowed_tools: # 可选,限制 Skill 激活时 Agent 可用工具
- read_file
- grep
- shell
---
## 测试规范
- 使用 ExUnit,describe 按功能分组
- Mock 外部服务,不 Mock 内部模块
...两级目录
- 项目级:
.cmdc/skills/— 项目特定,优先级高于全局 - 全局级:
~/.cmdc/skills/— 所有项目通用
同名 Skill 以项目级为准(覆盖全局)。
Skill Identity(.skill_id sidecar)
每个 Skill 目录可包含 .skill_id 文件,存储该 Skill 的持久唯一标识。
discover/1 首次发现时自动生成(格式 {name}__imp_{uuid8}),后续读取已有值。
此 ID 可供外部系统(如 cmdc_skill_engine)追踪版本、进化谱系等。
使用示例
# 发现所有 Skills
skills = CMDC.Skill.discover(["./skills", "~/.cmdc/skills"])
# 加载完整内容
{:ok, skill_with_content} = CMDC.Skill.load(skill)
# 生成系统提示词注入片段(仅 name + description,不含完整内容)
snippet = CMDC.Skill.to_prompt_snippet(skills)
Summary
Functions
在给定目录列表中发现所有 SKILL.md 文件,返回解析后的 %Skill{} 列表。
按名称查找 Skill,未找到返回 nil。
按 skill_id 查找 Skill,未找到返回 nil。
加载单个 Skill 的完整内容(包含 SKILL.md 正文部分)。
生成系统提示词注入片段(仅 name + description 列表,不含完整内容)。
写入(或覆盖)Skill 目录下的 .skill_id sidecar 文件。
Types
Functions
在给定目录列表中发现所有 SKILL.md 文件,返回解析后的 %Skill{} 列表。
目录列表按优先级从低到高排列(后面的覆盖前面的同名 Skill)。
示例
skills = CMDC.Skill.discover(["~/.cmdc/skills", "./.cmdc/skills"])
# => [%CMDC.Skill{name: "elixir-testing", ...}, ...]
按名称查找 Skill,未找到返回 nil。
按 skill_id 查找 Skill,未找到返回 nil。
加载单个 Skill 的完整内容(包含 SKILL.md 正文部分)。
如果 Skill 已有 :content,直接返回;否则从文件重新读取。
示例
{:ok, loaded} = CMDC.Skill.load(skill)
loaded.content # => "## 测试规范..."
生成系统提示词注入片段(仅 name + description 列表,不含完整内容)。
供 Agent 启动时注入到系统提示词,引导 LLM 了解可用的 Skills。 LLM 可在需要时通过工具加载完整内容。
示例
snippet = CMDC.Skill.to_prompt_snippet(skills)
# =>
# ## 可用 Skills
#
# - **elixir-testing**: Elixir 项目测试最佳实践
# - **git-workflow**: Git 工作流约定
写入(或覆盖)Skill 目录下的 .skill_id sidecar 文件。
供外部系统(如 cmdc_skill_engine)在 FIX/DERIVED/CAPTURED 进化后 更新 Skill 身份标识。