把 mattpocock 的 38 个开源 Skills 装进 DeepSeek Harness
环境:Windows 10 IoT 企业版 LTSC 21H2(19044.7807)· DeepSeek Harness 0.2.1-rc.2 项目:https://github.com/mattpocock/skills(38 个技能,MIT,29.8 万 star) 结果:38 个技能全部被 DSH 识别,实测可用
mattpocock/skills 是 Matt Pocock(Total TypeScript 作者)开源的一套 Agent Skill 技能库,近 30 万 star,现在也在 DSH 社区里很热。
但它有个反直觉的地方:很多人第一反应是去 DSH 的插件市场里搜,搜不到,然后以为装不了。
其实它根本不是插件。本文把整套流程走通,并记录下那些文档里不会写、但你一定会撞上的坑。
一、先搞清楚你装的是什么
mattpocock/skills 不是 DSH 插件,也不能通过插件市场安装。
它是 Agent Skill 格式的技能库——一堆带 YAML 头的 Markdown 文件。这个格式最先是 Anthropic 为 Claude Code 定的,现在 Codex、Gemini CLI、Cursor 等一批 harness 都认。DSH 也认,但它的入口和上面那些不一样。
所以「装到 DSH」这件事,本质是:把符合格式的目录放到 DSH 会去扫的地方。没有安装向导,也不需要。
⚠️ 别在插件市场里硬塞。 如果你把 skills 目录填进 DSH 的「添加插件」对话框,会得到这样的红字:
提示是「该路径不存在或不是有效的插件包」——因为它确实不是插件包,扫描器找的是
package.json,而 skills 目录里只有SKILL.md。这条路是死路,看到这个报错就说明方向错了。
顺带说明一下这个仓库的规模:截至本文写作时,mattpocock/skills 已有 298,777 个 star、25,090 个 fork,是当前 Agent Skill 生态里最热门的项目之一。
二、DSH 的 skill 发现机制
DSH 内核里有三个包负责这件事:
| 包 | 作用 |
|---|---|
@deepseek-ai/dsh-skill |
技能注册表,只管登记 |
@deepseek-ai/dsh-skill-filesystem |
从磁盘扫目录、解析 frontmatter、监听变更 |
@deepseek-ai/dsh-tool-skill |
把扫到的技能渲染成模型能看到的目录 + 给你用的 / 命令 |
dsh-skill-filesystem 会按 rank 从小到大扫这 5 个位置:

选哪一格取决于你想让谁看到:
- 只给这个项目用 → 100 或 200,跟着仓库走,可以提交进 git
- 给这台机器的所有 DSH 会话用 → 400(
~/.dsh/skills),本文选这个 - 同时给 Codex / Claude Code 用 → 500(
~/.agents/skills),跨 harness 通用
我选 400,是因为它用户级、又只属于 DSH,不会污染你其他工具的技能列表。代价是不能跟着项目走。
三、最大的坑:只认「一层深度」
这是整套流程里唯一非直觉、也最容易失败的地方。
扫描器只往下看一层:认 <根目录>/<技能名>/SKILL.md,也认平铺的 <根目录>/<技能名>.md。它刻意不支持 **/SKILL.md 这种递归查找。
而仓库的结构是三层:
skills/engineering/tdd/SKILL.md
└─ 分类 ─┘ └技能┘
把这个目录原样搬进去,结果是 0 个技能被发现,而且不报错——因为对扫描器来说,engineering/ 里没有 SKILL.md,它只是"一个不认识的子目录",跳过。

正确做法是拍平:丢掉 engineering/、productivity/ 这些分类层,让每个技能目录直接挂在一层。分类信息在仓库里只是给人看的组织方式,对 DSH 没有意义(你的 SKILL.md 里的 description 才是模型挑技能的依据)。
技能目录内部可以随便深:references/、scripts/、templates/ 放多深都行,只有 SKILL.md 本身必须在一层。
💡 这是整个安装过程里唯一一个"不报错但完全失败"的地方。 没有红色提示、没有警告,就是 38 个技能变 0 个。如果你按流程走完发现技能面板空着,先回来查这一条。
四、实操步骤
步骤 1:下载仓库
GitHub 页面 → Code → Download ZIP,解压得到 skills-main/skills-main/。
目录里真正有用的是 skills/ 这一层,四个子目录:engineering(20)、productivity(7)、misc(4)、in-progress(7)。deprecated/ 是空的(只剩一个 README),跳过。
仓库里还有个
scripts/link-skills.sh,别用它。作者在文件开头自己写明:「NOTE: This is a dev-only script, intended for use by maintainers of this repo. It is not a supported installer. Modifications to it, or requests for modifications, will not be approved.」
而且它链去的是
~/.claude/skills和~/.agents/skills,不是 DSH 的目录。注释里还额外说明:deprecated/不链(已退役),misc/也不链(保留但很少用、不推荐),in-progress/会链(公开征求意见用的)。
步骤 2:校验(先看清楚再动手)
在动手复制之前先跑一遍校验,确认每个技能的 frontmatter 都合规。原因见下一节——DSH 对格式错误的技能是静默丢弃的。
import os, re, sys, shutil
SRC = r'C:/Users/hek/Downloads/skills-main/skills-main/skills'
DST = r'C:/Users/hek/.dsh/skills'
BUCKETS = ['engineering', 'productivity', 'misc', 'in-progress']
APPLY = '--apply' in sys.argv
KEBAB = re.compile(r'^[a-z0-9]+(?:-[a-z0-9]+)*$')
def frontmatter(path):
text = open(path, encoding='utf-8', errors='replace').read()
if not text.startswith('---'):
return None
end = text.find('\n---', 3)
if end < 0:
return None
data = {}
for line in text[3:end].splitlines():
m = re.match(r'^([A-Za-z0-9_-]+):\s*(.*)$', line)
if m:
data[m.group(1)] = m.group(2).strip()
return data
rows, problems = [], []
for b in BUCKETS:
bdir = os.path.join(SRC, b)
if not os.path.isdir(bdir):
continue
for name in sorted(os.listdir(bdir)):
sdir = os.path.join(bdir, name)
sk = os.path.join(sdir, 'SKILL.md')
if not os.path.isfile(sk):
continue
fm = frontmatter(sk)
if fm is None:
problems.append((b, name, 'no frontmatter')); continue
fname = fm.get('name', '').strip('"\'')
desc = fm.get('description', '').strip('"\'')
if not fname:
problems.append((b, name, 'name 缺失'))
elif not KEBAB.match(fname):
problems.append((b, name, 'name 非 kebab-case: ' + repr(fname)))
if not desc:
problems.append((b, name, 'description 缺失'))
rows.append((b, name, fname))
names = [r[2] for r in rows if r[2]]
dupes = {n for n in names if names.count(n) > 1}
print('发现 %d 个 skill,问题 %d 个,重名 %s' % (len(rows), len(problems), dupes or '无'))
for p in problems:
print(' ', p)
if APPLY:
os.makedirs(DST, exist_ok=True)
for b, n, f in rows:
if not f or f in dupes:
continue
dst = os.path.join(DST, f)
if os.path.exists(dst):
shutil.rmtree(dst)
shutil.copytree(os.path.join(SRC, b, n), dst)
print('已复制 ->', DST)
不加 --apply 是只读校验,加了才写入。
这台机器的结果:
发现 38 个 skill,问题 0 个,重名 无
步骤 3:复制到 ~/.dsh/skills
python install_dsh_skills.py --apply
结果:38 个技能 / 103 个文件 / 440 KB。
我选的是复制目录而不是建符号链接:符号链接的好处是 git pull 后自动更新,坏处是源目录一挪走,技能全部失效且不报错。复制更笨但更可控,更新时重跑一次就行。
📌 上面脚本里的
SRC/DST请按你自己的实际路径改。这台机器的下载目录是C:\Users\hek\Downloads\skills-main\skills-main\skills。
步骤 4:用 DSH 自己的解析器复核(关键一步)
上面那个脚本用的是我自己写的简易 frontmatter 解析器,只能查"像不像"。要查"DSH 收不收",得用 DSH 运行时同一个 YAML 库。
DSH 是 Electron,app.asar 里就带着 yaml 包。把 ELECTRON_RUN_AS_NODE 打开,就能借它的 node 跑一段校验:
const fs = require('fs');
const path = require('path');
const YAML = require('C:/Users/hek/AppData/Local/Programs/DeepSeek Harness/resources/app.asar/dsh/node_modules/yaml');
const KEBAB = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
const BOOLS = ['true','false','yes','no','on','off','1','0'];
function strictBool(v) {
if (typeof v === 'boolean') return v;
if (typeof v === 'string' && BOOLS.includes(v.toLowerCase()))
return ['true','yes','on','1'].includes(v.toLowerCase());
return undefined;
}
for (const name of fs.readdirSync('C:/Users/hek/.dsh/skills').sort()) {
const sk = path.join('C:/Users/hek/.dsh/skills', name, 'SKILL.md');
if (!fs.existsSync(sk)) continue;
const text = fs.readFileSync(sk, 'utf8');
const end = text.indexOf('\n---', 3);
let fm;
try { fm = YAML.parse(text.slice(3, end)); }
catch (e) { console.log('DROP', name, 'YAML 坏了:', e.message); continue; }
if (typeof fm.name !== 'string' || !KEBAB.test(fm.name)) { console.log('DROP', name, 'name 不合规'); continue; }
if (typeof fm.description !== 'string' || !fm.description.trim()) { console.log('DROP', name, '缺 description'); continue; }
const dmi = fm['disable-model-invocation'];
if (dmi !== undefined && strictBool(dmi) === undefined) { console.log('DROP', name, '布尔值不合规'); continue; }
console.log('OK ', name, strictBool(dmi) === true ? '仅用户' : '模型可自动调用');
}
export ELECTRON_RUN_AS_NODE=1
"C:/Users/hek/AppData/Local/Programs/DeepSeek Harness/DeepSeek Harness.exe" validate_skills.js
这台机器的结果:
被丢弃: 0
可被 DSH 识别: 38
💡 这一步值得单独花时间。 脚本里那个
strictBool不是多余的——disable-model-invocation的值如果是'yes'、'on'、'1'这些字符串,DSH 会不会当成 true 解析?自己写的简易正则不一定答得上来。借 DSH 自己的 YAML 库跑一遍,才是真的对齐了运行时的判定标准。
步骤 5:确认 Agent preset 是「标准」
装完没反应,九成是卡在这一步。
DSH 的 skill 能力不是全局开关,是挂在 Agent preset 上的。同一个 App 切到不同 preset,就是完全不同的一套插件:

极简(minimal) 只有 4 个插件——persona + 文件读写 + 压缩 + 常驻 shell,根本没有 skill 插件。在极简模式下,~/.dsh/skills 里放再多东西也没有任何东西去读它。
怎么改:新任务页面的 preset 选择器(或设置页的 preset 卡片)→ 选「标准」。
注意两点:
- 新会话才生效,已有会话保留它创建时的模式——切完要开一个新会话再试
- 怎么确认切成功了:打开
C:\Users\hek\.dsh\profiles\desktop\cordis.patch.yml,看这一行
yaml
- id: agent-preset-registry
name: "@deepseek-ai/dsh-agent-preset-registry"
config:
default: standard
selectedDefault: standard # ← 这里是 standard 才对
步骤 6:验证
不用重启 App(DSH 对这个目录挂了文件监视),但要开新会话。然后点输入框上方的「技能」,应该看到:

列表按名称字母序排列,第一屏就能看到 ask-matt、chief-of-staff、claude-handoff、code-review、codebase-design、diagnosing-bugs。
带「仅用户」徽章的,是模型不会自己用的那批。全部 38 个都在列表里,就算成功。
📌 顺便一提,这 38 个技能按「谁能唤起」正好劈成两半:23 个仅用户调用、15 个模型可自动调用。这个划分不是随意的——仅用户的技能负责编排(管流程、分任务、决定下一步),模型可调的负责纪律(可复用的做事方法)。想深入了解每个技能怎么用,可以看配套的《使用技巧》。
五、排错表
| 现象 | 原因 | 怎么办 |
|---|---|---|
| 技能面板整个不存在 | Agent preset 是「极简」 | 切到「标准」 |
| 面板在、列表几乎为空 | 目录没拍平(还是三级结构) | 看第三节,~/.dsh/skills/<名>/SKILL.md |
| 少了几个特定的技能 | frontmatter 不合规被静默丢弃 | 用步骤 4 的脚本定位具体是哪个、坏在哪 |
| 改了技能内容没变化 | 改了 SKILL.md 正文但没改 frontmatter |
正文是每次加载时重读的,但如果会话已经加载过就该技能,要开新会话 |
| 复制进去后被删了 | 用了符号链接且源目录被移动 | 改用复制 |
| 切了 preset 还是看不到 | 切的是已有会话 | 开新会话 |
| 插件市场里搜不到 | 它本来就不是插件 | 回到第一节 |
六、更新与卸载
更新(仓库有新版时):
# 重新下载解压,然后
python install_dsh_skills.py --apply
脚本会先删同名目录再复制,等于整体覆盖。
💡 也可以用
npx skills@latest add mattpocock/skills走通用安装器——作者在 README 里给「其他 agent 或需要可编辑文件」的场景推荐的就是这条。但那条命令装的是~/.agents/skills(rank 500),不是 DSH 优先扫的 400 目录,DSH 里可能会出现两份。所以本文还是坚持自己拍平到~/.dsh/skills。
卸载单个:直接删 C:\Users\hek\.dsh\skills\<技能名>\,不用重启。
全部卸载:
rm -rf C:/Users/hek/.dsh/skills
给别的 harness 也装一份:把同样的内容复制到 C:\Users\hek\.agents\skills\(那格是跨 harness 通用的,rank 500,DSH 也会扫,优先级低于 ~/.dsh/skills)。
七、一句话总结
DSH 装 skill 没有"安装"这个动作,只有"放到它扫的地方"。 三个词决定成败:找对目录(400 或 500)、拍平一层、preset 是标准。
本文所有结论都来自实测:dsh-skill-filesystem 的官方中文文档、DSH 合成配置的实际内容、以及 38 个技能的逐个校验结果。文中引用的仓库技能数(38)、分类分布(20/7/4/7)、以及「仅用户 23 个 / 模型可调 15 个」的划分,均已按 2026-10-21 的仓库状态重新核对。
