@zhijianren/dsh-skills-manager
v0.1.24
Published
跨工具(Cursor / WorkBuddy / Claude Code 等)的 SKILL.md 技能管理器与 Rules 规则管理器(含远程规则导入),TypeScript 零运行时依赖实现
Maintainers
Readme
dsh-skills-manager
跨工具(Cursor / WorkBuddy / Claude Code / Gemini CLI / GitHub Copilot 等 24 个)的 SKILL.md 技能管理器,使用 TypeScript 实现,零运行时依赖(仅用 Node 内置模块,Node.js ≥ 20)。
参考 MichengAI/dsh-skills-manager 的功能模型,将其从「单一 DeepSeek Harness 插件」泛化为「可读取任意 AI 编码助手技能目录的通用管理器」,并同时提供 dsh (DeepSeek Harness) 的 Cordis 插件入口。
特性
- 跨工具技能目录:默认管理用户级(
~/.cursor/skills、~/.workbuddy/skills、~/.claude/skills)与当前项目目录下 24 个支持 SKILL.md 的编辑器技能目录(见「支持矩阵」)。 - 解析
SKILL.md:frontmatter(name / description / 调用策略)→ 结构化模型,bundle(<name>/SKILL.md)与 flat(<name>.md)双形态。 - 完整管理能力:列出 / 查看 / 启用 / 停用 / 删除 / 导入;对可写目录生效,只读目录仅查看。
- 可扩展:配置文件、环境变量、CLI
--tool/--root/--cwd均可增删或覆盖工具目录。 - dsh 插件:HTTP 管理后端 + 真实技能 provider(agent 可直接发现并调用)+ 项目级
/skills斜杠命令 + 设置页技能面板(中英双语)。 - 独立可视化面板:
skillmgr web在本地回环端口启动浏览器管理页(无需 dsh 环境)。 - Markdown 预览:
skillmgr view <rootKey> <name>直接查看技能 SKILL.md 内容;Web 面板每个技能行提供「预览」按钮,弹窗内渲染 markdown(标题/列表/代码/表格/引用等,零外部依赖);GET /api/dsh-skills-manager/skill同时返回原始文本与渲染后 HTML。 - 排障日志:CLI
--verbose、dsh 宿主 logger([dsh-skills-manager]前缀)、库 APIlogger回调三层覆盖(见「排障日志」)。
支持矩阵(24 个 SKILL.md 编辑器)
| 工具 key | 用户级目录 | 项目级目录 | 说明 |
| --- | --- | --- | --- |
| cursor | ~/.cursor/skills | .cursor/skills | Cursor |
| workbuddy | ~/.workbuddy/skills | .workbuddy/skills | WorkBuddy |
| cc | ~/.claude/skills | .claude/skills | Claude Code |
| gemini | — | .gemini/skills | Gemini CLI(workspace skills) |
| windsurf | — | .windsurf/skills | Windsurf / Cascade |
| roo | — | .roo/skills | Roo Code |
| opencode | — | .opencode/skills | OpenCode |
| cline | — | .cline/skills | Cline |
| agents | — | .agents/skills | Agent Skills 开放标准(Gemini/Windsurf/Roo/OpenCode/Claude Code 等均兼容) |
| github-copilot | — | .github/skills | GitHub Copilot |
| codex | — | .codex/skills | OpenAI Codex |
| continue | — | .continue/skills | Continue |
| amazon-q | — | .amazonq/skills | Amazon Q |
| kimi | — | .kimi/skills | Kimi CLI |
| qwen | — | .qwen/skills | Qwen Code |
| trae | — | .trae/skills | Trae |
| lingma | — | .lingma/skills | Lingma |
| kiro | — | .kiro/skills | Kiro |
| aide | — | .aide/skills | Aide |
| cosine | — | .cosine/skills | Cosine |
| bolt | — | .bolt/skills | Bolt.new |
| claude-dev | — | .claude-dev/skills | Claude.dev |
| based | — | .based/skills | BasedHardware Agent |
| val-town | — | .val-town/skills | Val Town Agent |
目录约定来源:核心 6 个(gemini / windsurf / roo / opencode / cline / agents)按官方文档核实;其余按社区维护的 SKILL.md 支持矩阵(vercel-labs/skills、OpenSpec 工具对比表)。 除
cursor/workbuddy/cc外的工具仅参与项目级探测(不产生用户级根,避免skillmgr list输出噪音);如需管理它们的用户级技能,通过配置文件自行添加roots。
作用域与去重
- 三类作用域:local(用户级可写)、shared(全局只读)、project(当前项目目录,纳入版本控制,可写)。
- 根目录按绝对路径去重:同一路径只保留最 specific 的根(
project < local < shared)——避免~/.workbuddy/skills同时被探测为本地根和项目根时,同名技能被注册两次导致 dsh 忽略其一。
安全边界(移植并保留)
| 能力 | 说明 |
| --- | --- |
| 列出 / 查看 | 扫描各根目录,解析 SKILL.md,展示名称、形态、说明、模型/手动调用状态 |
| 启用 / 停用 | 在 SKILL.md frontmatter 增删 disable-model-invocation / user-invocable,同时控制模型与手动调用入口(非破坏性) |
| 删除 | 仅对可写根,删除整个技能条目,需二次确认 |
| 导入 | 导入单目录 / 单 .md / 批量目录;先复制到临时副本再替换,覆盖前备份旧版本,符号链接一律拒绝 |
| 只读保护 | shared 作用域根目录只允许查看,启停/删除/导入均被拒绝 |
- 技能名只允许单个普通路径段,目录穿越名称被拒绝(
entryPath)。 - 导入来源若与目标目录重叠(相同/包含/被包含),拒绝导入,避免误删自身来源。
- 导入内容递归拒绝符号链接,不会把目标目录外的文件带入技能目录。
- 写入采用「临时副本 + rename」原子替换;覆盖导入先备份旧条目,失败回滚。
安装与构建
npm install @zhijianren/dsh-skills-manager # 作为依赖安装
# 或从源码构建:
git clone https://gitee.com/xuyi-emb/dsh-skills-manager
cd dsh-skills-manager
npm install # 安装 typescript 等 devDependencies
npm run build # 编译到 dist/
npm test # 运行全部测试(node --test)运行时无需任何第三方依赖,Node.js ≥ 20 即可。作为 dsh 插件时,
@deepseek-ai/cordis与react由宿主提供(peerDependencies)。
命令行用法
# 列出全部工具的技能(可按工具/作用域/启停状态筛选)
skillmgr list
skillmgr list --tool workbuddy --enabled
skillmgr list --scope project --json
# 仅查看当前项目目录下的项目级 skills(跨工具,可按 --cwd 指定其他项目)
skillmgr project
skillmgr project --cwd /path/to/project --json
# 查看已配置的技能根目录
skillmgr roots
# 查看单个技能详情
skillmgr get workbuddy mao-retro-tool
skillmgr get cursor:project design-before-implement
# 预览技能 SKILL.md 内容(markdown)
skillmgr view workbuddy mao-retro-tool # 输出正文(已去 frontmatter)
skillmgr view workbuddy mao-retro-tool --raw # 输出完整文件(含 frontmatter)
skillmgr view workbuddy mao-retro-tool --html # 生成自包含 HTML 预览并用浏览器打开
skillmgr view workbuddy mao-retro-tool --json # 结构化输出 { raw, body }
# 启用 / 停用 / 删除(删除需确认,可用 --yes 跳过)
skillmgr enable workbuddy mao-retro-tool
skillmgr disable workbuddy mao-retro-tool
skillmgr delete workbuddy old-skill --yes
# 导入:单目录、单 .md、或含多个子目录的批量目录
skillmgr import ./my-skill --tool workbuddy
skillmgr import ./skills-bundle --tool cursor --overwrite
skillmgr import ./skills-bundle --tool cc --dry-run # 预检,不写入
# 浏览器可视化管理面板(默认 http://127.0.0.1:8787)
skillmgr web
skillmgr web --port 9000 --cwd /path/to/project # 换端口 / 指定项目<rootKey>即skillmgr roots输出的第一列(如cursor、workbuddy:project)。- 所有命令支持
--verbose:输出根探测/扫描排障日志到 stderr(不污染 stdout)。
可视化 Web 管理面板
skillmgr web 在本地回环地址启动一个自包含的管理页面(无任何前端依赖):
skillmgr web # 打开 http://127.0.0.1:8787页面能力:
- 跨工具技能分组展示(本地 / 只读 / 项目 徽标,可写状态,目录路径),随系统深浅色主题自适应。
- 实时搜索与目录筛选;顶部统计总数 / 已启用数。
- 每个技能行提供「预览」按钮:弹窗内渲染 SKILL.md 的 markdown(标题 / 列表 / 代码块 / 表格 / 引用等),无需离开页面即可查看技能内容。
- 对可写目录内技能一键启用 / 停用;删除需弹窗二次确认;只读目录不显示操作按钮。
- 导入:填写源路径 → 选择目标目录(可写下拉)→ dry-run 预检(展示待导入 / 冲突 / 失败明细)→ 按「跳过 / 覆盖」策略正式导入。
- 服务只绑定
127.0.0.1;所有写操作带x-dsh-skills-manager: 1标记头,防止本机浏览器被跨站页面诱导篡改技能。
导入需要填写本机绝对路径(浏览器受安全限制无法读取本地文件路径);dsh 设置页内的 client 面板则可通过宿主原生目录选择器直接选目录。 该服务复用与 dsh 插件完全相同的
/api/dsh-skills-manager/*后端与安全校验,--tool / --root / --cwd / 配置文件选项均适用。
扩展工具目录
- 环境变量:
SKILLS_MANAGER_<TOOL>_DIR覆盖某工具的 local 路径,例如SKILLS_MANAGER_CC_DIR=~/.config/claude/skills。 - 配置文件(默认
~/.config/dsh-skills-manager/config.json,或SKILLS_MANAGER_CONFIG指定):
配置中为工具设置{ "tools": [ { "key": "cursor", "label": "Cursor", "roots": [{ "scope": "local", "path": "~/.cursor/skills" }] }, { "key": "workbuddy", "label": "WorkBuddy", "roots": [ { "scope": "local", "path": "~/.workbuddy/skills" }, { "scope": "shared", "path": "~/.workbuddy/plugins/cache", "mutable": false } ] }, { "key": "cc", "label": "Claude Code", "roots": [{ "scope": "local", "path": "~/.claude/skills" }] }, { "key": "gemini", "label": "Gemini CLI", "roots": [{ "scope": "local", "path": "~/.gemini/skills" }], "projectDir": ".gemini/skills" } ] }projectDir即可让其参与项目级探测。 - CLI 一次性根:
skillmgr list --root /abs/path/to/skills(归入custom工具,可写)。 - 项目级跨工具技能:自动探测各工具子目录,存在即作为
project作用域根加入(key 形如cursor:project);可用--cwd <路径>指定其他项目。项目级目录可写、纳入版本控制。完整目录见「支持矩阵」。
排障日志
技能「没扫到 / 没注入」时,先看日志再下结论:
- CLI:任何命令加
--verbose,日志输出到 stderr:skillmgr project --verbose # [skillmgr:info] project probe: cwd=/path/to/project # [skillmgr:info] project probe: cursor -> /path/to/project/.cursor/skills (found) # [skillmgr:info] project probe: workbuddy -> .../.workbuddy/skills (missing, skip) # [skillmgr:info] roots resolved: 4 个根 [...] # [skillmgr:info] scanned cursor:project: 7 个技能 [...] # [skillmgr:info] dedupe by path: 5 → 4(同一路径保留 scope 最 specific 的根) - dsh 插件:日志走宿主 logger,前缀
[dsh-skills-manager]:apply: cwd=<...> (process.cwd 回退)—— 插件用的项目根provider.list(cwd=<工作区>): <rootKey> (<scope>) -> N 个技能—— 每个根注入 dsh 的技能数(含被 kebab 规则跳过的计数),cwd 应为当前工作区而非 dsh 启动目录/skills: cwd=<...> (来源: agent 推断|options.cwd|process.cwd 回退)—— 斜杠命令的项目根
- 库调用:
resolveRoots/SkillsManager的 options 支持logger(level, message)回调,缺省静默。
常见结论速查:cwd 未提供 的 warn 说明项目根没传进(应回退 process.cwd());(missing, skip) 说明该目录确实不存在;scanned 行直接显示每个根扫出几个技能;dedupe by path 说明有路径重复被合并。
dsh web 没有日志出口?
dsh web 默认插件树不含 console logger exporter(cordis logger 无输出目标,日志被静默丢弃)。两种解法:
- 装官方日志插件:
dsh plugin --profile web add @deepseek-ai/cordis-plugin-logger-console,并在~/.dsh/cordis.patch.yml写入:
重启- insert: - id: logger-console name: "@deepseek-ai/cordis-plugin-logger-console"dsh web后插件日志输出到启动终端。 - 本地插件(免安装 npm 包):把
ctx.logger.exporter()的 console 出口写成一个小.mjs插件(import用绝对路径指向@deepseek-ai/cordis),经~/.dsh/cordis.patch.yml挂载。级别语义:error=0 / info=1 / warn=2 / debug=3,exporter 阈值需 ≥ 想看到的级别(levels: { default: 3 }看全部)。
作为 dsh (DeepSeek Harness) Cordis 插件使用
src/plugin.ts 导出标准 Cordis 插件形态(apply(ctx, options)),把上面全部管理能力接入 dsh 宿主:
安装(开箱即用):
dsh plugin --profile web add @zhijianren/dsh-skills-manager(或本地构建后dsh plugin add <仓库路径>)。安装后 dsh 自动 reconcile:检测到本包声明dsh.bundle.patch即把它加入 profile 的dsh.profile.bundles层栈,随后dsh restart web,设置页即出现「技能」菜单。已手动
npm install的用户:v0.1.3 起包携带dsh.bundle声明,跑一次dsh plugin --profile web install(触发 reconcile)即会自动加入 bundles;或直接编辑~/.dsh/profiles/web/package.json,在dsh.profile.bundles数组追加"@zhijianren/dsh-skills-manager"后dsh restart web。依赖声明:
inject = ["webServer", "skills", "commands"],宿主按拓扑就绪后调用apply。HTTP 管理后端(挂载于
/api/dsh-skills-manager):| 方法 | 路径 | 说明 | | --- | --- | --- | | GET / HEAD |
/state| 返回全部根目录与技能({ ok: true, data: RootWithSkills[] }) | | POST |/enable| body{ root, name }| | POST |/disable| body{ root, name }| | POST |/delete| body{ root, name }| | POST |/import| body{ source, root?, conflict?, dryRun? },root缺省取第一个可写根 |安全边界(与参考实现一致):全部请求先校验 loopback Host(防 DNS rebinding);写接口额外要求
x-dsh-skills-manager: 1头与application/json(防跨站预检)。技能目录联动:写操作成功后调用
ctx.skillsprovider 的invalidate(),并ctx.emit("commands/change")/ctx.emit("skills/change")刷新 dsh 技能菜单与目录缓存。插件配置:
apply(ctx, { tools, extraRoots, configFile, cwd, logFile }),语义与 CLI/库完全一致;logFile可选,写操作审计日志。
把跨工具技能接入 dsh agent(可被 skill 工具调用)
插件通过 ctx.skills.registerProvider 注册名为 dsh-skills-manager 的真实技能 provider:
- 按工作区动态发现(list):dsh 调用
provider.list(options)时传入当前工作区的 cwd,provider 用它动态解析项目根——在哪个 workspace 会话,就能看到哪个项目目录下的 skills(cwd 回退process.cwd())。每个技能映射为 dsh 的SkillCandidate(kebab-case 名、description、modelInvocable/userInvocable、source、rank);非 kebab 名自动跳过。 - 加载(get):按候选读取
SKILL.md,剥离 frontmatter 后返回正文content——与dsh-skill-filesystem的 frontmatter 契约一致(disable-model-invocation/user-invocable)。 - rank / source 与官方一致:项目级
project-dsh(100)、用户级user-dsh(400)、共享只读bundled(600);根目录按 path 去重后每个技能只注册一次,避免同目录既当本地又当项目级时被 dsh 忽略其一。 - 可见性闭环:设置面板 / CLI 的启用/停用直接改写 frontmatter 调用策略 → provider 输出的
invocation随之变化 →invalidate()+skills/change刷新目录 → dsh 的skill工具(isModelInvocable)只对已启用技能放行。面板里停用某个技能,agent 立刻无法再调用它。
这样 24 个跨工具目录里的技能无需复制到 ~/.dsh/skills,agent 即可在会话技能目录中发现并调用(正文经 renderSkillContent 注入模型)。
项目层面的斜杠命令 /skills
在 dsh 工作区(当前项目)聊天框中可直接管理 skills:
/skills—— 列出当前项目 cwd 下可写目录的所有技能及其启停状态(按 root 分组,markdown 表格)/skills enable <rootKey> <name>—— 启用技能(直接修改 SKILL.md frontmatter 调用策略)/skills disable <rootKey> <name>—— 停用技能/skills delete <rootKey> <name>—— 删除技能(仅可写根)/skills view <rootKey> <name>—— 预览技能 SKILL.md 正文(在聊天框内直接查看 markdown 内容)
handler 优先从 invocation.agent 推断当前工作区 cwd(向下兼容 options.cwd / process.cwd()),无需手动指定项目路径;写操作完成后通过 invalidate() + skills/change 事件实时刷新 agent 技能目录。
client 端 Web UI
src/client/client.cjs 是 dsh 客户端插件(挂到设置页 settings.section 槽),复用同一套 /api/dsh-skills-manager/* 后端:
- 功能:跨工具技能分组展示(带 local / shared / project 作用域徽标)、搜索与目录筛选、启用/停用、删除(二次确认)、导入(拖放或原生文件/目录选择,dry-run 预检 + 同名覆盖确认 + 可写目录下拉选择导入目标)。
- 依赖声明:
inject = ["slots", "workspaces", "locale"],宿主注入ctx后向settings.section注册面板;React 由宿主提供(peerDependencyreact ^18.2.0)。 - 双语:内置 zh/en 词典(102 键对齐),随宿主语言切换。
- 双模式单文件:浏览器经
window.__ModuleLoader__.load({ id, factory })加载;Node 环境直接require("dsh-skills-manager/client")可取纯函数(filterSkills/parseApiResponse/translateError等)做零依赖测试。
node --test test/client.test.cjs # client 纯函数测试程序化接入示例:
import { apply } from "@zhijianren/dsh-skills-manager/plugin";
// 由 dsh 宿主注入 ctx(真实 ctx 是 CordisContextLike 的超集)
export function apply(ctx, options) {
return import("@zhijianren/dsh-skills-manager/plugin").then((m) => m.apply(ctx, options));
}作为库使用
import { SkillsManager, resolveRoots, parseSkillDoc, projectSkills } from "@zhijianren/dsh-skills-manager";
const mgr = new SkillsManager(); // 默认读取用户级 + 当前项目(cwd)下的全部跨工具目录
const roots = await mgr.listSkills(); // RootWithSkills[]
// 只看当前项目目录下的 skills(跨工具,仅 project 作用域)
const projRoots = await mgr.listProjectSkills(); // 或便捷函数 projectSkills({ cwd })
const projMeta = await mgr.getProjectRoots(); // 仅 project 根元数据
// 排障日志(可选,缺省静默)
const mgr2 = new SkillsManager({ cwd, logger: (level, msg) => console.log(`[skillmgr:${level}] ${msg}`) });
await mgr.setSkillEnabled("workbuddy", "mao-retro-tool", false);
await mgr.importSkill("/path/to/skill", "workbuddy", { conflict: "skip" });目录结构
src/
types.ts 类型定义(含 SkillLogger)
paths.ts 路径解析与安全校验(防穿越 / 拒绝符号链接)
parser.ts SKILL.md frontmatter 解析与调用策略改写
scanner.ts 扫描技能根、定位条目(支持 logger 回调)
tools.ts 工具注册表(24 个 SKILL.md 编辑器,按 path 去重,支持扩展)
manager.ts 管理核心:list/get/enable/disable/delete/import
plugin.ts dsh (DeepSeek Harness) Cordis 插件入口:apply(ctx, options)
web-server.ts 独立可视化服务:skillmgr web(复用 plugin 路由)
ui.ts 可视化管理页面(自包含 HTML,vanilla JS)
cli.ts 命令行入口
index.ts 公共 API(含 ./plugin 导出)
client/
client.cjs dsh 客户端 Web UI(设置页技能面板,双模式单文件)
test/
core.test.ts 核心测试(node:test)
project.test.ts 项目级跨工具扫描/去重/日志测试
plugin.test.ts Cordis 插件形态测试(mock ctx,含 provider 工作区注入)
web.test.ts 可视化服务测试(页面/API/安全校验)
client.test.cjs client 纯函数测试(词典/过滤/解析/翻译)变更记录
| 版本 | 内容 |
| --- | --- |
| v0.1.24 (N5 UI) | dsh 设置面板的「规则」分区隐藏项目级 rule(scope=project),仅展示用户级/共享级;摘要附"项目级 X 条随项目自动加载"提示;项目级规则由项目本地管理(编辑文件/.state.json),不再在 dsh 全局设置中启停/删除;注入管道照常按 cwd 加载项目级规则到消息上下文;ui.ts(独立 Web 面板)+ client.cjs(dsh 设置页插件)同步过滤 |
| v0.1.22 (N3) | 规则管理面:RulesManager 写操作(setRuleEnabled 改写 mdc frontmatter disabled / 纯 Markdown 走 .dsh/rules/.state.json 禁用名单、deleteRule、importRule 原子导入)+ skillmgr rules 子命令(list/get/view/enable/disable/delete/import)+ /rules 斜杠命令 + HTTP API(rules/state/rule/preview/enable/disable/delete/import,沿用 loopback + 标记头安全校验)+ Web 面板「规则」标签页(ui.ts 技能/规则双 tab、client.cjs 设置页新增 RulesSection 分区,均含触发模式徽标/启停/删除/预览/导入)+ 修复禁用规则仍被注入的 bug |
| v0.1.21 (N2) | dsh 规则注入管道:主路径 ctx.systemPrompt.section 聚合段落(agent/pre-step 异步预计算 + section 同步读取,order 200)+ agent/request waterfall 回退(systemPrompt 不可用时注入 system 消息)+ rules 只读 skills provider(rule- 前缀,agent 可按需检索)+ 会话事件文件集合收集 + cwd 动态切换;现有 provider 测试适配双 provider |
| v0.1.20 (N1) | 新增规则匹配引擎:微型 glob matcher(* / ** / ? / ! 否定,Cursor 语义)+ 四种触发模式注入判定 + RulesManager 核心 API(per-file mtime 缓存、L3 就近排序、16KiB 阈值保护、## Rule: 注入块渲染)+ 单测 |
| v0.1.19 (N0) | 新增跨工具 Rules 基础能力(方案见 docs/rule-features-plan.md):规则根探测(L1 项目根 AGENTS.md/CLAUDE.md + L2 工具规则目录 + L3 子目录嵌套就近锚点)+ mdc/纯 Markdown/Claude 格式解析 + Cursor 四种触发模式推导(always/globs/agent/manual)+ listRules/resolveRuleRoots 公共 API + 单测 |
| v0.1.17 | 支持 markdown 预览 skill.md 内容:skillmgr view(正文/--raw/--html/--json)、Web 面板「预览」弹窗、GET /skill 接口(返回渲染后 HTML)、/skills view 子命令;新增零依赖 renderMarkdown |
| v0.1.16 | 扩展工具项目探测跳过等于 ~/<home>/<projectDir> 的路径(如 ~/.codex/skills),不再误标为用户级 |
| v0.1.15 | 去重优先级调整为保留显式声明(local>project),修正 home 用户级目录被误标项目级 |
| v0.1.14 | 支持全部 24 个 SKILL.md 编辑器;README 全面重写;dsh web 日志出口 |
| v0.1.13 | 根目录按 path 去重(同一路径只保留最 specific 的根,消除重复加载) |
| v0.1.12 | skill provider 按 dsh 工作区 cwd 动态注入项目级技能 |
| v0.1.11 | 排障日志:CLI --verbose + 插件 [dsh-skills-manager] 前缀日志 + 库 logger 回调 |
| v0.1.10 | /skills 与 provider 的 cwd 回退 process.cwd()(修复项目技能未列出) |
| v0.1.8 | 新增 skillmgr project 命令、listProjectSkills()/projectSkills()、6 个扩展工具探测 |
| ≤ v0.1.7 | 跨工具基础能力(见 Git 历史) |
许可证
MIT
