Skill 系统
Skill 是 Agent Spaces 提供给 Agent 复用的「能力封装」机制。每个 Skill 是一段 Markdown 提示词(外加可选的脚本、模板等辅助文件),用来在特定场景下调整或约束 Agent 的行为模式——例如强制先做头脑风暴再写代码、以 TDD 方式工作、或进入超压缩的「caveman」沟通模式。Skill 与 Agent 解耦:你在全局 Skill 库中维护 Skill 内容,再把它们按需绑定到一个或多个 Agent 预设上。
什么是 Skill?
一个 Skill 在磁盘上对应 ~/.agent-spaces-data/skills/<skill-name>/ 目录,其中核心文件是 SKILL.md。该文件由 YAML frontmatter + Markdown 正文组成。系统解析时只识别两个字段(见 packages/server/src/services/skill.ts 中的 parseFrontmatter):
name— Skill 的标识符,决定落地的目录名description— 一句话描述,用于在管理界面区分用途
frontmatter 之外是给 Agent 阅读的 Markdown 正文,可以包含触发条件、规则、步骤、约束(例如 <HARD-GATE> 标签)等任意内容。Skill 目录下还可以放脚本(scripts/)、模板(templates/)、参考文档等辅助文件,这些文件不会自动注入 Agent,但可以在 Skill 正文中引用、或通过文件接口单独读取。
抽样自
packages/templates/skills/caveman/SKILL.md、grill-me/SKILL.md、superpowers/brainstorming/SKILL.md,三者均采用name+description双字段 frontmatter。
内置 Skill 库
项目随包附带一组内置 Skill 模板,位于 packages/templates/skills/。当前内置约 20+ 个 Skill,按 8 个顶级类别组织(以实际目录为准):
| 类别 | 代表性 Skill |
|---|---|
superpowers(14 个) | brainstorming、writing-plans、executing-plans、test-driven-development、systematic-debugging、subagent-driven-development、requesting-code-review、receiving-code-review、dispatching-parallel-agents、using-git-worktrees、finishing-a-development-branch、verification-before-completion、using-superpowers、writing-skills |
tdd(6 篇) | SKILL.md + deep-modules、interface-design、mocking、refactoring、tests 等专题文档 |
planning-with-files | planning-with-files-zh(含 scripts/ 与 templates/ 子目录) |
improve-codebase-architecture | SKILL.md + DEEPENING、HTML-REPORT、INTERFACE-DESIGN、LANGUAGE 专题 |
| 单文件类 | caveman、grill-me、handoff、to-prd |
superpowers 是最大的一组,覆盖了从需求澄清、计划撰写、TDD 执行、调试、代码评审、并行 Agent 调度到分支收尾的一整套「超能力」工作流;tdd 与 improve-codebase-architecture 则是多文件 Skill 的范例,演示如何在 Skill 目录中组织配套的子文档。
模板库根目录的 index.json 为部分 Skill 维护了 id / group / path / md5 / updatedAt 索引(当前仅覆盖 superpowers 与 planning-with-files 两组),供 Skill Store 列表与增量同步使用。
Skill Store 导入
内置 Skill 不会自动出现在用户的 Skill 库中,需要从 Skill Store 导入。导入本质是把模板目录复制到数据目录 ~/.agent-spaces-data/skills/<skill-name>/。
支持以下导入方式(对应 SDK sdk.skills.* 与路由 /api/skills/*):
- 从 Store 导入 —
POST /api/skills/import-store,body{ path, group }。path形如superpowers/brainstorming,后端在多个候选位置查找模板目录(含public/skills/、packages/agents/skills/等),找到后整体cpSync复制,并在_meta.json中记录分组。对应 SDKsdk.skills.importStore(path, group)。 - 批量导入 —
POST /api/skills/import-batch,body{ items: [{ name, content, group }] },按 frontmattername逐个落地。对应sdk.skills.importBatch(items)。 - 单文件导入 —
POST /api/skills/import,body{ filename, content, group }。 - 从 Git 仓库导入 —
POST /api/skills/import-git,body{ url },后端git clone到临时目录后扫描其中的 Skill 文件,返回解析出的{ name, content }列表。对应sdk.skills.importGit(url)。
Skill Store 的整体浏览与安装入口详见 Agent Store。
Agent 如何绑定 Skill
Skill 与 Agent 预设是多对多关系:一个 Skill 可绑给多个 Agent,一个 Agent 可绑多个 Skill。绑定关系记录在 Agent 预设的 skills?: string[] 字段中(类型定义见 packages/shared/src/types/workspace.ts:76 的 AgentConfig)。数组元素是 Skill 名(兼容带 .md 后缀的旧写法,后端解析时会自动 replace(/\.md$/i, ''))。
在 Agent 设置界面勾选要启用的 Skill 后,系统会把这些 Skill 同步到该 Agent 的私有目录 ~/.agent-spaces-data/agent-templates/<agentId>/skills/<skill-name>/,供运行时加载。
同步检查与一键同步
因为 Skill 库中的内容可能被编辑更新,而各 Agent 私有副本可能滞后,后端提供差异同步接口:
GET /api/skills/sync-check— 遍历所有 Agent,比较其绑定的每个 Skill 的全局副本SKILL.mdmtime 与 Agent 私有副本 mtime,返回需要同步的列表SkillSyncItem[](字段:agentId、agentName、skillName、globalMtime、agentMtime)。若 Agent 私有副本缺失,agentMtime为空字符串。对应sdk.skills.syncCheck()。POST /api/skills/sync— body{ items: [{ agentId, skillName }] },把指定的全局 Skill 目录整体cpSync覆盖到对应 Agent 私有目录(含删除遗留的旧扁平.md文件),返回实际同步条数{ synced }。对应sdk.skills.sync(items)。
listSkills() 在返回每个 Skill 信息时,也会附带 boundAgents 字段({ id, name, avatarUrl }),列出当前绑定了该 Skill 的所有 Agent 预设,便于在前端管理界面直观查看绑定关系。
自定义 Skill 创建
1. 在 Skill 管理界面新建
进入「设置 → Skills」页面(/settings/skills,组件 SkillsDialog 的 standalone 模式),可新建 Skill。系统按 frontmatter 中的 name 字段决定目录名(经 sanitizeFolderName 净化,仅保留 [a-zA-Z0-9._-],空格等转为 -),写入 <name>/SKILL.md。
2. 编辑内容
新建或选中已有 Skill 后,可直接在编辑器中改写 SKILL.md 内容并保存:
- 更新主文件 —
PUT /api/skills/:name,body{ content },对应sdk.skills.save(name, content)。 - 列出 Skill 内文件 —
GET /api/skills/:name/files,递归返回目录树(跳过_前缀与.DS_Store),每项含name、path、isDirectory。对应sdk.skills.listFiles(name)。 - 读 / 写辅助文件 —
GET/PUT /api/skills/:name/files/{*filePath},对应sdk.skills.getFile(name, path)/saveFile(name, path, content)。后端做了路径穿越防护(fullPath.startsWith(join(skillsDir, name)))。 - 在文件管理器中打开 —
POST /api/skills/:name/reveal,按平台调用open(macOS)/explorer(Windows)/xdg-open(Linux)打开 Skill 目录。对应sdk.skills.reveal(name)。
3. 收藏与分组
- 收藏 —
POST /api/skills/:name/favorite,切换收藏态,返回{ favorited }。收藏列表持久化在_meta.json的favorites数组中。对应sdk.skills.toggleFavorite(name)。 - 分组 — 导入时通过
group参数指定,记录在_meta.json的groups映射中,前端可按分组归类展示。
4. 删除
DELETE /api/skills/:name,递归删除整个 Skill 目录,并清理 _meta.json 中对应的 favorites 与 groups 条目。对应 sdk.skills.delete_(name)。
数据布局
~/.agent-spaces-data/
├── skills/ # 全局 Skill 库
│ ├── _meta.json # { favorites: string[], groups: Record<name, group> }
│ ├── caveman/
│ │ └── SKILL.md
│ ├── superpowers/
│ │ └── brainstorming/
│ │ ├── SKILL.md
│ │ └── scripts/ # 可选辅助文件
│ └── ...
└── agent-templates/
└── <agentId>/
└── skills/ # 该 Agent 私有的 Skill 副本(由 sync 写入)
└── <skill-name>/
└── SKILL.md
旧版的扁平 .md 文件会在 listSkills() 调用时由 migrateFlatFiles() 自动迁移为 <name>/SKILL.md 目录结构。
REST API 汇总
| 方法 | 路径 | 用途 |
|---|---|---|
| GET | /api/skills | 列出全部 Skill(含 boundAgents) |
| PUT | /api/skills/:name | 更新 SKILL.md 内容 |
| DELETE | /api/skills/:name | 删除整个 Skill 目录 |
| POST | /api/skills/:name/favorite | 切换收藏 |
| GET | /api/skills/:name/files | 列出 Skill 内文件树 |
| GET | /api/skills/:name/files/{*filePath} | 读取 Skill 内某文件 |
| PUT | /api/skills/:name/files/{*filePath} | 写入 Skill 内某文件 |
| POST | /api/skills/:name/reveal | 在系统文件管理器中打开 |
| POST | /api/skills/import | 单文件导入 |
| POST | /api/skills/import-batch | 批量导入 |
| POST | /api/skills/import-store | 从内置 Skill Store 导入 |
| POST | /api/skills/import-git | 从 Git 仓库导入 |
| GET | /api/skills/sync-check | 检查 Agent Skill 副本与全局库的差异 |
| POST | /api/skills/sync | 一键同步指定 Skill 到对应 Agent |
所有 Skill 接口均挂载在 packages/server/src/routes/skill.ts,受全局 Bearer Token 鉴权保护。
WebSocket 事件
Skill 系统当前未定义专用的 WebSocket 事件——Skill 的增删改不通过 WS 广播。前端在执行写操作后通过 SDK 返回值或重新拉取 GET /api/skills 刷新列表。