Skip to content

dsh-skills-manager

Verified

@amahayuuri/dsh-skills-manager · v0.4.1 · MIT · Web UI

在 DSH 桌面端侧边栏管理 Skills:从仓库、压缩包或图形化选择的文件夹导入,按 DSH 规则校验并查重安装,查看来源并导出为 ZIP 分享。

Install

dsh plugin add @amahayuuri/dsh-skills-manager

Confirm the layer applied with dsh --profile default --dump-config — see the install guide.

Source

Tags

Creators

Readme

@amahayuuri/dsh-skills-manager

给 DeepSeek Harness 桌面端 / Web 端加一个 Skills 管理页:侧边栏多一个 Skills 入口,点进去就能从 Git 仓库、压缩包、.md 文件或图形化选择的文件夹导入 skill,并按需启用、停用、查看、导出、删除。

当前版本 0.4.1,只在 DSH 0.2.1-rc.2 上实际测试过。运行时依赖全部由桌面端提供(peerDependencies):@deepseek-ai/cordis 4.0.5、@deepseek-ai/dsh-host-webserver 0.2.1-rc.2、@deepseek-ai/dsh-client-locale 0.2.1-rc.2、react 18.2.0。

兼容性声明:package.json 的 engines.dsh 为 >=0.2.1-rc.2,不设上限。DSH 有 engines.dsh 时只按它判断插件是否兼容(不再看 peerDependencies),因此 DSH 升级后本插件不会被拦截;但新版 DSH 若改动了本插件依赖的接口,插件仍可能无法正常工作,遇到问题请反馈。

「选择文件夹」用的是 DSH 的 uiWorkspace 服务(pickDirectory(): Promise<string | null>,0.2.1-rc.2 上由 dsh-client-ui-workspace 提供,取消时返回 null);取不到时回退到旧版的 workspaces 服务,两者都没有 pickDirectory 才隐藏按钮。

功能

  • 侧边栏入口:在「插件」旁注册 Skills 图标(sidebar.panellist,id amahayuuri-dsh-skills-manager),点击进入独立整页面板(main slot,key amahayuuri-dsh-skills-manager),不占用会话。
  • 三种添加方式,先检测再安装
    • 仓库地址:支持 https://、ssh://、git@host:owner/repo.git,也支持 GitHub / GitLab 的 /tree/<ref>/<子目录> 链接。ref 里带 / 时用 git ls-remote --heads --tags 取最长匹配;git 不可用时退回「第一段就是 ref」。GitHub 优先下载 codeload 归档(/zip/<ref>),失败再浅克隆(带 --branch <ref>)。
    • 本地路径:可以点「选择文件」(zip / 7z / rar / tar.gz 等压缩包,或 .md)、点「选择文件夹」(含 SKILL.md 的目录),也可以手动填写路径。选择后自动检测,不会直接安装。
    • 检测结果列出全部 skill(名称、说明、适用场景、相对路径、是否可被 DSH 加载、是否已安装);勾选后安装,不是全部导入。
  • 按 DSH 规则校验:name 与 description 必须存在,且 name 必须匹配 /^[a-z0-9]+(?:-[a-z0-9]+)*$/。不满足的候选项标记「DSH 不会加载」并说明原因,默认不勾选,安装时一律跳过。
  • 查重与覆盖更新:查重只有一套规则——把候选名称按 slugify 归一后与已安装条目比较(同一函数也用于搜索结果与安装跳过,必要时再用原目录名兜底),因此「Changelog Generator」这类写法也会命中 changelog-generator,界面显示「已安装」与安装时跳过 / 需要覆盖的判定始终一致。安装前在托管根(含 .disabled)查重,命中时默认跳过并提示「已安装同名 skill:」。候选与搜索结果都会显示 installedId,可用「覆盖更新」整体替换(先复制到 <DSH_HOME>/.dsh-skills-staging 再整体换入,保留原来的启用/停用状态;单文件 skill 的旧 .md 先改名到备份,换入失败会改名移回)。同名但来自别的来源时,界面会标「同名已安装」并注明原来源(本地来源只显示末两级路径,完整路径在鼠标悬停的 title 里),避免覆盖时静默替换。
  • 自定义名称:必须符合 kebab 规则,否则拒绝;安装时会改写复制后 SKILL.md 顶层 frontmatter 的 name 行(没有就插入),其余内容保持原样,目录名等于该名称,来源记录里带 renamedFrom。
  • 图形化 Find Skills:工具栏「查找 Skill」搜索 skills.sh。
    • 打开时不联网安装任何东西,只读取并显示 find-skills 的本地状态;需要时可点「安装 find-skills(供会话中的模型使用)」,二次确认后才从 vercel-labs/skills 安装。
    • 搜索不依赖 find-skills。结果逐条展示说明、来源仓库与安装量。
    • 点「安装」走检测流程(仓库地址 https://github.com/<source>,并把 skills.sh 的 skillId 作为 wanted 传给 /inspect):只预选 slugify(目录名) 或 slugify(frontmatter name) 恰好等于 slugify(skillId) 的候选;没有精确匹配就列出全部候选、都不勾选。仓库里的 skill 超过 200 个时,/inspect 带 wanted 只保留命中的候选(不带 wanted 的普通「添加 Skill」仍报「过多」)。确认前可展开 SKILL.md 预览,再执行安装。
  • 列表与来源标注:每条 skill 都显示来源——仓库地址(可点击)、本地路径、上传文件名(显示「上传:xxx.zip」),没有来源记录的既有 skill 标注「未记录来源」。符号链接 / junction 形态的 skill 照常列出并标「链接」。
  • 导出 / 导入:详情页可把 skill 导出为 .zip(含 SKILL.md 与随附文件);其他人在「添加 Skill → 本地路径」选择该 .zip 即可导入。
  • 管理:启用 / 停用开关、详情预览(SKILL.md 原文 + 来源 + 安装时间 + 路径 + 可见性)、永久删除(危险样式按钮 + 二次确认,删除进行中对话框不可关闭)。
  • 只读展示:~/.agents/skills 里的 skill 一并列出,但标注「只读」,不提供改动操作。
  • 实时生效:写盘后 dsh-skill-filesystem 的 watcher 会让新 skill 立刻进入会话目录,无需重启 DSH。

安装

三种方式,任选一种:

  1. 在 DSH 的「插件 → 添加插件」里输入包名 @amahayuuri/dsh-skills-manager(DSH 会用 pnpm 从 npm registry 安装)。
  2. 命令行:
dsh plugin --profile desktop add @amahayuuri/dsh-skills-manager
  1. 本地开发用 link::
dsh plugin --profile desktop add "link:E:/path/to/amahayuuri-dsh-skills-manager"

注意:卸载以 link: 方式安装的插件时,DSH(底层 pnpm)可能会清空 link 指向的源码目录(本机实测出现过)。卸载前请先提交代码;只想暂时停用时,用插件详情页的开关即可,不要卸载。

安装后确认 profile 的 package.json 里 dsh.profile.bundles 已包含 @amahayuuri/dsh-skills-manager(dsh plugin add 会处理),DSH 会通过 HMR 自动重组,无需重启。

卸载:

dsh plugin --profile desktop remove @amahayuuri/dsh-skills-manager

并把它从 dsh.profile.bundles 中移除。

说明:本插件与 npm 上同名的 dsh-skills-manager(作者 xichun123,仓库 Xichun123/dsh-skills-manager)没有任何关系,也不是它的分支或续作;请按上面的新包名安装,避免装错。

如何更新

DSH 的「添加插件」会拒绝重复安装同名插件(提示已安装),第三方插件也不会显示「可更新」按钮,所以更新需要先卸载再重新安装:

  1. 在 DSH 的「插件」里打开 @amahayuuri/dsh-skills-manager 的详情页,点「卸载」。
  2. 在「添加插件」里重新输入 @amahayuuri/dsh-skills-manager,会自动安装最新版本,不需要加 @latest。

注意事项:

  • 已安装的 skill 不受影响:它们位于 <DSH_HOME>/skills,与插件本体分开存放,卸载、重装插件都不会删除。
  • DSH 默认使用国内镜像源(npmmirror),新版本发布后通常需要几分钟才能同步。如果装到的还是旧版本,稍等几分钟再重装,或在「添加插件」对话框里把安装源切换为官方源。
  • 当前安装的版本可以在插件详情页的「当前版本」处查看。

从旧版 link 安装迁移

旧版本是以 dsh-skills-manager 这个包名用 link: 装进 profile 的。迁移步骤:

  1. 先在 DSH 的插件管理里移除 dsh-skills-manager(或执行 dsh plugin --profile desktop remove dsh-skills-manager)。移除 link 安装前请先提交源码,原因见「安装」一节的注意事项。
  2. 再按新包名 @amahayuuri/dsh-skills-manager 安装(见上一节)。
  3. 已安装的 skill 不受影响:仍然位于 <DSH_HOME>/skills,.dsh-skills-source.json、.disabled 状态与 <DSH_HOME>/.dsh-skills-staging 的路径和格式都没有变化,照常识别、启停和删除。

存储布局

所有内容都放在 DSH 用户 skill 根 <DSH_HOME>/skills(默认 ~/.dsh/skills):

<root>/<id>/SKILL.md              已启用的目录型 skill
<root>/<id>.md                    已启用的单文件 skill(只识别既有文件)
<root>/.disabled/<id>/SKILL.md    已停用的目录型 skill
<root>/.disabled/<id>.md          已停用的单文件 skill
<root>/<id>/.dsh-skills-source.json  安装来源记录(DSH 不读取它)
<DSH_HOME>/.dsh-skills-staging/   安装暂存与覆盖备份(不在 DSH 的扫描范围内,启动时清空)

停用是把条目移动到 .disabled/:dsh-skill-filesystem 只扫描根目录一层,因此停用的 skill 不会被任何会话发现,重新启用只是原子重命名。本插件安装的 skill 一律写成目录型(即使来源是单个 .md),便于统一启停;对既有的单文件 skill,启用/停用同样只在 <root>/<id>.md 与 <root>/.disabled/<id>.md 之间移动。

安装暂存目录与覆盖备份放在 <DSH_HOME>/.dsh-skills-staging/,不放在 skills 根里:dsh-skill-filesystem 扫描 skill 时不会跳过点开头的目录,根目录下的 .dsh-skills-tmp-* 里的 SKILL.md 会被当成同名 skill 加载,而插件列表又隐藏点开头的条目。暂存目录与 skills 根同盘,rename 仍是原子的;启动时会清空它,并顺手清掉旧版本留在 skills 根与 .disabled 里的 .dsh-skills-tmp-*。

安装位置与来源标记

  • 通过本插件安装的 skill(包括「查找 Skill」里安装的结果)一律复制到 <DSH_HOME>/skills,属于本插件管理,可启停、删除、导出。
  • 只有物理位于 ~/.agents/skills 的 skill 才显示「外部」,放在「其他来源」里只读展示;本插件不会把 skill 安装到那里。
  • 「查找 Skill」顶部的 find-skills 状态只说明查找工具本身是否可用;它是否位于外部目录不影响安装结果目录。
  • 其他工具放进 <DSH_HOME>/skills 的 skill 同样算本插件管理,不会被标成「外部」;缺少来源记录时显示「本地(未记录来源)」。
来源标记 含义
仓库 由本插件从 Git 仓库安装
本地 由本插件从本地路径或压缩包安装
上传 由页面上传文件安装(记录原始文件名)
外部 位于 ~/.agents/skills,只读
未记录来源 位于 <DSH_HOME>/skills,但没有 .dsh-skills-source.json,仍可管理

项目级 .dsh/skills、.agents/skills 不在本插件列表中。

HTTP 接口

宿主半区挂载在 /amahayuuri-dsh-skills-manager/api(同源,供页面使用):

方法 路径 说明
GET /list 已启用 / 已停用 / 其他来源;条目含 scope(managed / agents)、linked、loadable、problems
GET /doc?id=<id>&scope=<managed|agents> SKILL.md 正文
GET /export?id=<id>&scope=<managed|agents> 导出该 skill 为 .zip
POST /inspect { source: 'repo' | 'local', value, wanted? },返回 token 与候选项(含 loadable、problems、installedId);候选超过 200 个且带 wanted(skills.sh 的 skillId)时只保留 slug 命中的候选
POST /inspect-file?name=<文件名> 请求体为压缩包 / .md 原始字节,content-type: application/octet-stream + x-amahayuuri-dsh-skills-manager: 1
POST /preview { token, key },返回该候选项的 SKILL.md 原文(最多 200 KB)
POST /install { token, keys, name?, replace? },只安装选中的候选项;replace: true 覆盖更新
POST /add 兼容旧接口:检测并安装全部候选项(不可加载的一律跳过)
POST /toggle { id, enabled }
POST /remove { id }
GET /find/status find-skills 是否可用(只读)
POST /find/ensure 本地没有 find-skills 时安装(只在用户明确确认后调用)
GET /find/search?q=<关键词>&limit=<n> 通过 skills.sh 搜索并补全说明;结果含 installedId
GET /ping 健康检查

/find/install 已删除:安装统一走 /inspect → /preview → /install。

检测结果在宿主内存里保留 15 分钟(仓库内容暂存于系统临时目录),超时由每分钟执行一次的定时清理释放;卸载插件时定时器与全部临时目录一并释放。启动时还会清理系统临时目录里超过 1 小时、前缀为 dsh-skills-scan-、dsh-skills-zip-、dsh-skills-archive-、dsh-skills-upload-、dsh-skill-find-、dsh-find-skills- 的残留目录,并清空 <DSH_HOME>/.dsh-skills-staging、清掉 skills 根与 .disabled 里遗留的 .dsh-skills-tmp-*。

安全说明

  • 统一 guard:所有路由在分发前检查 Host、Origin、Sec-Fetch-Site。
    • Host 只接受 localhost、127.0.0.1、[::1] 或 IP 字面量,其它域名一律 403(阻断 DNS rebinding)。
    • 带 Origin 时必须等于 http://<Host> 或 https://<Host>,否则 403。
    • 带 Sec-Fetch-Site 时只允许 same-origin / none,否则 403。
    • JSON 类 POST 的 content-type 必须是 application/json;/inspect-file 必须是 application/octet-stream 且带 x-amahayuuri-dsh-skills-manager: 1(强制跨域请求先过预检)。不符合返回 415。
    • 所有响应带 x-content-type-options: nosniff。
  • 这些路由由 DSH WebServer 直接提供,不经过 /api 的登录校验;WebServer 的 host 可以配成 0.0.0.0,此时同局域网内能访问该端口的客户端也会命中上面的 guard(Host 白名单会挡住非 IP/非 localhost 的域名)。请在可信机器上使用。
  • 参数错误返回 400,找不到返回 404,guard 拒绝返回 403 / 415,其它异常返回 500 并在宿主日志里记录堆栈。
  • ZIP 只在内存里解析,但有限制:条目数 ≤ 5000;每个条目先校验声明的 size / compressedSize(不越界、单文件 ≤ 100 MB),再用 inflateRawSync(payload, { maxOutputLength: size }) 解压;累计解压总量 ZIP 导入 ≤ 100 MB、仓库归档 ≤ 300 MB;解压后校验 CRC32;遇到 ZIP64 标记(0xFFFFFFFF)直接报「不支持 ZIP64」。本地 ZIP 先 stat 检查体积再 readFile;ZIP 条目里的绝对路径、盘符和 .. 一律拒绝。
  • 7z / rar / tar.* 交给系统工具:Windows 上优先用 %SystemRoot%\System32\tar.exe(避免 PATH 里的 GNU tar 把 C: 当远程主机),工作目录设为压缩包所在目录,-f 只传文件名;每次尝试前清空并重建目标目录,只接受退出码 0,超时一律视为失败。7z 调用带空密码(-p),避免加密包等待输入,加密包直接提示「不支持加密压缩包」。
  • 解压后安全校验:用 lstat 遍历目标目录,符号链接 / 硬链接 / junction(重解析点)一律删除并在结果里报告数量;每个条目的 realpath 仍在目标目录内(越界即删)。链接只按 lstat().isSymbolicLink() 判断,不再用「realpath 与路径本身是否相同」——TEMP 或 DSH_HOME 含 8.3 短名(如 C:\Users\ADMINI~1)时那个判据会把每个普通目录都当成链接。累计解压后总量 ≤ 300 MB、文件数 ≤ 5000,超限整体拒绝并清理目录。
  • 上传:只接受 zip / 7z / rar / tar.gz 等常见压缩包或 .md;先校验扩展名(不合法直接 400,不读请求体),再边读边写进临时文件并累计大小,上限 45 MB(全插件唯一口径,ZIP 分支也用同一个常量),超限立即中止并删除;同时最多处理 2 个上传,超出返回 429。
  • inspect / inspect-file / add 只会把内容复制进 <DSH_HOME>/skills;id 与检测 token 都经过校验。已存在条目的 id 只做路径安全校验(不含 / \、非 ./..、长度 ≤ 255、dirname(join(root, id)) === root),新生成的 id 才用 VALID_ID 规则。
  • 符号链接 / junction 形态的 skill:列出与启停都只操作链接本身;删除前用 lstat 确认,只删链接,绝不递归删除链接指向的目标。复制 skill 时用 lstat 跳过符号链接,并在安装结果里报告跳过数量。
  • GitHub 仓库通过 https://codeload.github.com/<owner>/<repo>/zip/<ref> 下载归档(压缩后上限 80 MB);失败才回退到 git clone --depth 1 --branch <ref>,并设置 GIT_TERMINAL_PROMPT=0 避免卡住等待凭据。
  • 网络访问范围:Find Skills 会访问 https://www.skills.sh(搜索 API 与详情页),安装时访问 https://codeload.github.com、https://github.com,以及 git ls-remote / git clone 指向的仓库地址(含 git@ 形式)。不会执行搜索结果里的任何内容。
  • 导出时跳过 .git、node_modules 和来源记录文件,避免把本机绝对路径带给其他人;大小上限 40 MB。
  • 删除只作用于本插件管理的根目录;其他来源(~/.agents/skills)只读。

已知限制

  • 只管理 <DSH_HOME>/skills;项目级 .dsh/skills、.agents/skills 不在此处增删。
  • 仓库安装是「检测 → 复制」,不是持续同步;更新需要重新安装或用「覆盖更新」。
  • Find Skills 依赖 skills.sh 的公开搜索接口;说明取自详情页的 og:description,可能被站点截断。非 GitHub 来源(如 well-known)只展示说明与链接,不支持一键安装。
  • 7z / rar / tar.* 依赖系统解压工具,不支持加密压缩包;Linux 上如果只有 GNU tar,需要另装 7z 或 unrar,或先手动解压再选择文件夹。压缩包里的符号链接在没有创建权限的环境(Windows 非管理员、未开启开发者模式)下会让解压工具直接失败,此时提示「压缩包含符号链接,当前系统无权创建;请手动解压后选择文件夹」,不再误导为缺 7-Zip。
  • ZIP64 格式的压缩包不支持,需要先转成普通 ZIP。
  • 导出的 .zip 只含 skill 本体;导入后来源记为本地压缩包路径或「上传:<原文件名>」。
  • 停用只改变本地发现,不修改 skill 自身的 frontmatter(disable-model-invocation 等仍由 skill 作者控制)。
  • 安装后的 skill 是否可被调用,仍取决于 DSH 的 skill 发现规则与会话预设;frontmatter 不合规的 skill 会被 DSH 忽略,界面会提前提示。