dsh-skill-center
Browse, preview and install public Agent Skills from inside the DSH web GUI, aggregating five sources (claudeskills.info, skillsmp.com, the awesome-claude-skills repository list, the official anthropics/skills repo, and skill packs shipped by installed DSH plugins). Skills install pinned to a commit
Install
dsh plugin --profile web add dsh-skill-center
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
技能中心 · dsh-skill-center
一个 DeepSeek Harness 插件,在侧边栏里搜技能,看清了再装。
dsh plugin --profile <你的 profile> add dsh-skill-center
装上之后侧边栏底部会多出一个「技能中心」按钮:
 · 
占名、缺件、不完整、名字不合法:四种坏法各配自己的后果与选项 · 扫描 35 个别的 agent 技能目录,把 DSH 看不见的技能导进来
 · 
装完之后的状态:来路、更新检查、调用开关、回收站 · 颜色全走 --dsw-alias-* 令牌,没有第二套样式表
面板分三块。发现聚合 5 个来源的技能目录,能按中英文关键词搜,也能按分类和 star 排序。已安装直接读你本机的 ~/.dsh/skills,把每个技能的来源、文件数和校验结果列出来,并且可以就地开关(关掉不等于删掉,见下面「关掉一个技能」),还能告诉你每个技能被模型调用过几次。本机扫的是 35 个别家 agent 的目录,把 DSH 看不见的技能导进来。
想看清楚再动手就进详情页:仓库目录树、SKILL.md 原文、逐个文件预览。确认后写到 ~/.dsh/skills/<name>/,harness 的 chokidar 立刻侦测得到,不用重启。
侧边栏按钮、shell.overlay 抽屉、设置页里的内联分区,三个入口共用同一份状态。
装得上,不等于 harness 会认它
这个插件大部分代码在处理这两者之间的落差。
装之前先告诉你它会怎么坏
检查 · 不做的话会怎样
frontmatter 体检 · name 不合法(PDF-Processing、my_pdf_tool)的技能会被 harness 静默跳过。装完看起来成功,列表里什么都没有。面板会直说「照现在这样装上去,DSH 会直接忽略它」;能一键改写 name: 行的就改,缺 frontmatter 或缺 description 的拒绝安装,不装作成功
完整性 · 一次 429 或超时会让仓库遍历半途而废。技能看起来干净,缺的却是它自己让模型去跑的脚本。详情页标出「完整 / 部分」,并列出停止取回的原因和条数
引用缺件 · SKILL.md 里 ` scripts/build.py 或 [schema](references/schema.md)` 指向的文件如果不在取回的目录里,会被列出来。这类问题只在模型第一次真用它时才爆,而且爆在别人的任务中间
同名冲突 · 目标名字已被占用时不静默覆盖,也不静默加 -2。两种做法都是你事后才发现的性质。三个选项连后果一起摆出来:覆盖(先把现有版本完整挪进 .backup/)、改名装为 pdf-2、跳过。默认永远是不动现有的那个
装下来的就是那一次提交
安装读的是 commit,不是分支名:
一次请求 api.github.com/repos/{owner}/{repo}/commits/{branch} → 拿到 commit SHA
一次请求 codeload.github.com/{owner}/{repo}/tar.gz/{sha} → 整棵树,不可变
分支名是可变引用,commit 是不可变引用。raw.githubusercontent.com 对分支名有 max-age=300 的 CDN 缓存,所以「刚才看是这版、五分钟后装下来是上一版」是可能的;按 SHA 取,缓存命中永远是对的。本项目自己撞过这个坑:推完 README 立刻校验,读到的还是上一版。
详情页会写它是哪一版:「上游版本 8ca22db · 最后提交 2026-09-25」。问不到版本时(匿名 API 配额是 60 次/小时)它会明说「没能问到上游版本,这次抓的是分支当前内容」,而不是假装钉住了。
两条抓取路径都按 commit 读。主路径是一次 codeload 归档,归档不可达时回落到逐文件抓取,但回落也读那个 commit。否则回执上会写着一个它从没读过的版本,下一次更新检查就会拿错东西去比。只有连 commit 都问不到才读分支,那种情况下回执不写版本,界面也照实说。
一次请求拿整棵树,不是每个文件一次:80 个文件就是 80 次请求,也更容易在中途失败。读过的 commit 只下载一次,键就是 commit,所以这条缓存永远不会过期,也不需要失效:换个版本就是换了个键,不是这个键下的旧值。
二进制文件不再被写坏。旧路径把所有内容按 UTF-8 解,技能里的 PNG / PDF 会被静默损坏;现在按字节判断,非文本走 base64 存盘。解 tar.gz 是手写的约 60 行,用 Node 自带的 zlib,运行时依赖仍然是 0。
装完之后看得见的状态
每个装过的技能都记住自己来自哪个源、哪个仓库、哪条路径、哪个 commit,列表里直接显示。
更新检查分两步。先问分支现在的 commit,和记录里的一样就到此为止,一个文件都不用下,而且结论是确定的(同一个 commit 命名同一棵树)。不一样才去取那一版,算整棵树的哈希:
- 树也一样 → 最新,同时把记录里的 commit 前移,下次检查又变回一次小请求
- 树不一样 → 有更新
这里和旧行为最实质的差别是哈希的范围:从只算 SKILL.md 变成整棵树,所以上游改一行 scripts/*.py 也瞒不过去,而这恰恰是技能最常被修的地方。拿不到版本信息时会降级成只比 SKILL.md,并在结果里标出这次的结论只覆盖了文档(depth: document)。
删除是移进 .trash/ 而不是抹掉,并弹出可撤销提示。被删的技能连同它的来路记录一起进桶,恢复后仍是「受管理」的技能。同名覆盖时,上一版完整保留在 <root>/.backup/<name>-<时间戳>/。
.trash 与 .backup 都带点前缀,是刻意的:harness 靠「目录里直接含 SKILL.md」判定技能,所以它两个都看不见,不会被当成技能列出来。
安装
已发布到 npm:dsh-skill-center
dsh plugin --profile <你的 profile> add dsh-skill-center
包名会从 npm 上解析,和你装任何别的 DSH 插件是同一条路。桌面版自带 CLI 的路径随安装位置变化,
Windows 上在 <安装目录>\resources\runtime\cli\bin\dsh.cmd。
刚发版的那 24 小时里,请把版本号写上:
dsh plugin --profile <你的 profile> add dsh-skill-center@0.4.0
pnpm 11 自带一个发版冷却期(内置的 minimumReleaseAge,默认 24 小时,不写在任何配置文件里,
pnpm config get minimumReleaseAge 返回 undefined)。在这段时间里裸包名不会解析到 latest,
而是解析到窗口之外最新的那一版,然后把这个范围写进 profile 的 package.json。所以 0.4.0 发布后
跑上面第一条命令,装到的其实是 0.2.2——命令成功、输出干净、没有任何提示。写出版本号就绕开了,
--config.minimumReleaseAge=0 也可以。这条是实测出来的,不是推测:docs/probe-npm-install.mjs
一直打印「陌生人装得上」,直到有人去看它到底装到了哪一版——它装的是 0.2.2。
想改用源码(要改代码、或想跑本仓库里那套检查):
git clone https://github.com/tuoLuoSuan/dsh-skill-center.git dsh plugin --profile <你的 profile> add "<仓库路径>"
--profile desktop 会被普通 CLI 拒绝(`profile "desktop" is managed exclusively by
the Electron application`)。要让桌面版自己的 profile 生效,得用上面那条 Electron 附带的
dsh.cmd,或者直接在应用内的插件管理界面里添加。
只要 profile 的 package.json 里 dsh.profile.bundles 有了本插件,且 cordis.patch.yml
是纯 insert(本仓库就是),就能热挂载,不需要重启。此后客户端代码改动同样热重载(刷新页面即可);
lib/ 下的宿主代码改动仍需要重启。
本包没有任何运行时依赖:dependencies 是空的,装下去的就是 lib/、client/、locale/
和两个清单文件,23 个文件、115.9 kB 打包(解开 383.7 kB)。对 @deepseek-ai/dsh 的依赖写在
peerDependencies 里(>=0.2.0-rc.2)并标了 optional。它是一道版本门禁,不是要去安装的
东西:DSH 读这个字段判断插件和当前运行时兼不兼容,pnpm 则因为 optional 不会去装第二份宿主。
怎么确认装上了
插件本身会告诉你它有没有活着,不用去翻日志:
1. 侧边栏底部多出一个「技能中心」按钮(注册在 sidebar.footer.action 槽)。
2. 点开抽屉后,左下角「发现」标签页里的来源轨应当列出 5 个来源。如果它报「宿主代码还是旧版本」,说明宿主那一半没加载。lib/ 是宿主代码,加完插件要重启一次 DeepSeek Harness;之后改 client/ 就只需要刷新页面。
3. 面板底部的条数必须是实时数。这个数来自 GET /dsh-skill-center/api/sources,不写死。看到 0 或者一直转圈,那是上游没连上,不是装错了。在浏览器里直接开 http://127.0.0.1:<端口>/dsh-skill-center/api/sources 就能看到原始 JSON 和真实错误。
0.2.0-rc.2 上验证过。更低版本会被上面那道版本门禁拦住(见「兼容性」)。
配置
在 profile 的插件配置里可选地提供:
键 · 默认值 · 说明
dshHome · $DSH_HOME 或 ~/.dsh · 技能根目录的父目录
cacheDir · <dshHome>/skill-center/cache · 上游响应缓存
trustedHosts · [] · 反代/隧道场景下额外放行的 Host
skillsmpApiKey · 空 · 提高 skillsmp 的每日配额
agentHome · 真实 OS home · 其他 agent 技能目录的父目录(测试用覆盖项)
关掉一个技能,但别把它删掉
「已安装」那一页每个技能右边有一个开关:关掉之后技能还在原处、还能读、还能再打开,
只是模型不会再看到它。列表按来源分组,每组标题右边还有一个总开关(全组启用 / 全组禁用),
关掉的技能挂一个 已禁用 标签,页头汇一个总数。
开关改的是技能自己 frontmatter 里的 disable-model-invocation——就是宿主真正读的那个字段,
不是把文件改名或搬走。这么选换来三件事:
- 技能待在原地,所以列表还列得出来、正文还打得开;改回来只是删掉一行,文档逐字节回到原样。
- 对一个不是本插件装的技能一样能用。
- 技能目录在 git 仓库里时,改名会显示成一次删除,改一行不会。
写入是逐字节编辑 frontmatter 那一段(setFrontmatterFlag),不是把 YAML 解析出来再重新序列化:
手写的注释、缩进、键顺序都留着。docs/probe-toggle.mjs 问的正是这件事,而且问三遍——
翻过去是不是宿主认的那个「关」、翻回来是不是原来那份字节、以及一份它改不了的文档
是不是被拒绝而不是写坏。
改不动的会被拒绝,并且说出是哪个字段:frontmatter 里用了宿主不认的旧写法时,
宿主是整份丢掉这个技能的,那么给它写开关就等于报告了一次谁也看不见的变化。
只在三个根上生效:~/.dsh/skills、<工作区>/.dsh/skills、<工作区>/.agents/skills。
其他 agent 的技能目录(~/.claude/skills 等)只读。
请求里 `enab
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::7,最后更新 2026-10-10