1.2 装到哪个目录:六层优先级与选择决策
六层发现优先级
DeepSeek Harness 的本地技能提供方按 rank 顺序扫描若干根目录。官方给出的完整表如下,rank 数字越小越优先:
| Rank | 来源标识 | 根目录 | 典型用途 |
|---|---|---|---|
| 100 | project-dsh |
<projectRoot>/.dsh/skills |
只属于这个项目的技能 |
| 200 | project-agents |
<projectRoot>/.agents/skills |
项目级、跨 agent 工具通用的技能 |
| 300 | custom |
Config.customSkillDirs |
部署方指定的自定义目录 |
| 400 | user-dsh |
<dshHome>/skills |
你个人的全局技能 |
| 500 | user-agents |
<agentsHome>/skills |
个人级、跨工具通用技能 |
| 600 | bundled |
Config.bundledSkillDir |
随包分发的技能 |
两点说明。其一,bundled 层只有在配置了 Config.bundledSkillDir 时才参与扫描。其二,SkillSource 的完整取值里还有一个 runtime,它与本地文件扫描的六个根不是一回事,不会以上表任何一行的形式出现。
“层”到底是什么
优先级表里的 rank 只是决胜规则之一。官方的结构是“宿主 + 按 scope 的分层”:
- 宿主行与 repository 插件落入全局层;
- 由 agent preset 常驻组合挂载的插件落入该 preset 的层;
- 提供方名称在每层内唯一,而非进程级唯一。
读取时把全局层与所观察 scope 的链合并。所以“层”回答的是“这次读取站在哪个 scope 上看”,rank 回答的是“同一层内谁先谁后”。两件事别混:换 scope 换的是层,同层之内才轮到 rank 说话。
项目根目录怎么定
这里的“项目根目录”有明确定义:包含 .git 的最近祖先目录,找不到时退化为当前工作目录。技能的作用域跟着 git 仓库边界走,这在多仓库工作区里非常重要。
细节上还有三条:
其一,git 根目录是向上探测的。 当 ctx.fs 可用时,查找 .git 的动作通过文件系统服务完成,因此远程或沙箱工作区不会回退到宿主机文件系统边界。你在容器里打开一个仓库,技能解析依然以仓库根为准。
其二,用户级 DSH 根目录会跳过 .system 子目录。 这是平台的保留区域,不要往里放自己的东西。
其三,本地提供方不会合成内置系统 skill。 想随包分发技能,部署方应通过 bundled 根目录或专用提供方提供,而不是指望本地目录里凭空多出系统技能。
举个多仓库工作区的例子:你在 platform/apps/web 子目录里打开 harness,而 .git 在 platform/ 根上,那么项目级技能根就是 platform/.dsh/skills,不是 platform/apps/web/.dsh/skills。想只在单个子应用范围内生效,得换能被识别的位置或走 custom 层——这是“作用域跟着 git 边界走”的直接后果。
怎么选:一张决策表
面对一个新技能,按这个顺序问自己:
| 你的情况 | 放哪 | 理由 |
|---|---|---|
| 这技能只对当前项目有意义 | <projectRoot>/.dsh/skills |
随仓库走,clone 即得 |
| 团队共享,且用多种 agent 工具 | <projectRoot>/.agents/skills |
跨工具通用层 |
| 我想让所有项目都能用 | <dshHome>/skills |
个人全局 |
| 我用多个 agent 工具,想共用一套 | <agentsHome>/skills |
个人跨工具层 |
| 我是部署方,要统一下发 | customSkillDirs |
集中管控 |
提醒:把技能提交进项目仓库前,确认里面没有公司敏感信息。skill 是纯文本,
git log会记住你删掉的一切。
两个项目层、两个用户层,差别在哪
同样是本地四层,分两对:
| 层 | 归属 | 作用范围 |
|---|---|---|
.dsh/skills |
DeepSeek Harness 专属约定 | 只在 harness 工作流里生效 |
.agents/skills |
跨 agent 工具通用约定 | 同作用域内共享给多种工具 |
判断标准很简单:这技能有没有用到 harness 特有的能力。用到了,放 .dsh 层,放进 .agents 层反而可能让别的工具误解它的适用范围;没用到、就是一套通用工作方法,放 .agents 层,让团队里用不同工具的人都能受益。项目对、用户对,再按作用域选。
custom 与 bundled:部署方的两个抓手
最后两层不是给个人日常用的,是给部署方用的:
custom(rank 300)通过Config.customSkillDirs把任意目录拉进扫描范围,适合企业内网统一维护一套技能库,各团队指向同一份目录;bundled(rank 600)通过Config.bundledSkillDir提供随包分发的技能,优先级最低,是官方技能族(如 Office 族)进入目录的正规入口。
普通使用者一般不用碰这两层,但要知道它们存在——公司统一下发的技能突然出现或消失时,先问部署方改了哪一层。
重名了怎么办:两层裁决规则
多目录共存,重名几乎必然发生。规则分两层,配三个实例。
跨层:近者胜。 读取时把全局层与观察 scope 的链合并,最近层的条目直接赢得重名 skill。项目级(rank 100)无条件覆盖用户级(rank 400)。
实例一:
~/.dsh/skills/code-review/ (rank 400,用户全局)
./.dsh/skills/code-review/ (rank 100,项目级)
→ 在仓库内工作:项目级胜出
→ 在仓库外工作:用户级生效
同层内:依次比三样。 rank → 提供方顺序 → 本地顺序;摘要按名称排序。
实例二(同层比 rank):
全局层内同时存在 project-dsh 与 project-agents 两个来源的同名技能
→ rank 100 的 project-dsh 赢,rank 200 的 project-agents 让位
实例三(rank 相同,比提供方顺序):
同一层内两个提供方给出同名技能时(一般来自部署方把多个目录配进同一来源桶)
→ 按提供方注册顺序决胜;同一提供方内部再按本地扫描顺序决胜
这个设计非常实用:你可以在用户级放一份“通用代码评审技能”,再在某个严格项目里放一份“本公司代码评审技能”覆盖它,互不干扰,且不需要任何条件判断语法。
变更会实时生效吗
会。本地提供方通过 Chokidar 监视根目录,覆盖三类变化:
| 监听对象 | 变化类型 |
|---|---|
| 直属 bundle 与平铺条目 | 添加、移除 |
| 直属 skill 条目 | 内容变更 |
面向模型的 write 与 edit 观测 |
目标路径与目录相关时,同步让提供方目录失效 |
注意“直属”二字的含金量:bundle 下的资源文件变更不属于目录变更。改 references/checklist.md 不会触发技能目录失效——它本来就在按需加载的路径上,不需要刷新目录。
对缺失的根目录,watcher 会从最近的现有祖先开始,逐个跟踪缺失的路径段,直至 Chokidar 可以附加。所以 .dsh/skills 还不存在时先把它建好,watcher 才能尽早盯上。
watcher 自身失败只会让当前观测不完整,但不会把本来可读的技能藏起来;项目作用域 watcher 使用按配置设限的 LRU。绝大多数情况下,改完 SKILL.md 保存,下一次读取就能看到新内容,不需要重启。
skills/change 事件:不带 diff
提供方和运行时变更会发出不带过滤条件的 skills/change 失效事件。两个要点:
- 事件不携带 diff——它只广播“有变化”,不说变了什么;
- 消费方因此要用自身的查找选项重新获取
snapshot(),而不是试图从事件里推增量。
这对写代码的人重要,对使用者只意味一件事:变更通知是广播式的,任何监听方都会重新拉取,你手动改的文件不会因为“事件被过滤掉”而看不见。
另外,发现缓存以解析后的 scope 链为键:重设 scope 父级(如空会话重组)无需注册表变更,即可被下一次读取看到——换 scope 不用重启。
一个容易踩的坑
嵌套递归的 **/SKILL.md 发现不受支持。 技能目录下再套一层含 SKILL.md 的子目录,内层那个不会被发现。
skills/
├── outer-skill/
│ ├── SKILL.md # ✅ 会被发现
│ └── inner/
│ └── SKILL.md # ❌ 不会被发现
需要多个技能就平铺多个目录,不要嵌套。
小结
- 六层优先级:项目
.dsh→ 项目.agents→ custom → 用户.dsh→ 用户.agents→ bundled。 - 项目根 = 最近的含
.git祖先目录;远程与沙箱工作区不回退宿主边界。 .system是保留区;本地提供方不合成内置系统技能。- 跨层重名近者赢,同层比 rank → 提供方顺序 → 本地顺序。
- 监听只看直属变化;
skills/change不带 diff,消费方重新snapshot()。 - 不支持
**/SKILL.md递归发现,技能要平铺。
延伸阅读
- 官方子系统参考:skill 子系统
- 本书后续:1.3 三种装法与装后验证
- 相关机制:DeepSeek Harness 作用域与作用域注册
