awesome-dsh-plugin 插件收录指南:从 YAML 投稿到 CI 评审的完整实战手册

  • 知识库
  • DeepSeek
  • dsh-plugin

【免费下载链接】awesome-dsh-plugin

A curated list of plugins for DeepSeek Harness (dsh) · DeepSeek Harness 插件精选列表

项目地址: https://gitcode.com/gh_mirrors/aw/awesome-dsh-plugin
点击查看 免费下载

awesome-dsh-plugin 是 DeepSeek Harness(dsh)插件精选列表,其最大的设计特点是两个 README 全部由脚本从数据源生成:所有列表数据存放在 data/plugins/ 目录下,每个插件对应一个 YAML 文件,投稿即提交这一个文件。本文围绕 contributing.md 展开,结合仓库内真实脚本源码,完整讲解插件收录的格式规范、硬性门槛、CI 自动检查、人工评审要点、截图与 npm 发布等全流程,读完即可按规范提交一个「一次通过」的插件 PR。

为什么 README 不能手改:数据与展示分离的架构

投稿的第一条铁律是:不要手工编辑 README.md 与 README.zh.md。列表的真实数据源是 data/plugins/*.yml,两个 README 由 scripts/generate-readme.mjs 在 PR 合并后于 main 分支自动重新生成,投稿者不需要运行任何命令。

这一设计在源码层面有明确支撑:历史教训是「所有人往同一分类的同一位置追加」导致合并一个 PR 就撞掉下一个,而独立文件永不冲突。生成器在 scripts/lib/entries.mjs 中定义了 PLUGINS_DIR = 'data/plugins',并在 scripts/generate-readme.mjs 中通过 <!-- BEGIN TOC --> / <!-- END TOC -->、<!-- BEGIN PLUGINS --> / <!-- END PLUGINS --> 两对标记块重写 README,标记块之外的内容(徽章、引言、免责声明)保持手工维护。

如果你只想预览自己那一行的效果,本地重新生成是允许的,提交生成结果也照样接受,但结果必须与数据源一致:

npm ci
node scripts/generate-readme.mjs

CI 侧的校验在 scripts/generate-readme.mjs:--check 模式会比较 README 与数据源是否同步,同时做「双向集合校验」——README 中出现的 URL 必须全部在 data/plugins/ 有对应文件(防走私条目),数据源声明的 URL 必须全部出现在 README 中(防缺失条目)。另外该脚本还会检查 contributing.md 中的分类列表是否与代码里的 CAT_IDS 一致(scripts/generate-readme.mjs),防止文档漂移。

一个插件一个文件:YAML 条目格式详解

投稿就是一个 PR 添加一个文件,文件名按仓库名规则生成:data/plugins/<owner>__<repo>.yml。最小示例:

url: https://github.com/owner/repo        # 必须与仓库完全一致
name: owner/repo                          # 列表中显示的链接文字
category: ui                              # 见下方分类列表
description:
  en: One-line description ending with a period.
  zh: 一句话描述,以句号结尾。   # 可选,维护者会补

必填与可选字段

  • description.en 是唯一必填项。写不了中文就不写 zh,维护者会补上——缺翻译是维护者的工作,不是插件被打回的理由。
  • zh 字段如果写了但为空字符串,同样会被校验拒绝(提示「omit the key instead」),见 scripts/lib/entries.mjs。
  • 描述必须是单行(不能含换行符),并且只能使用仓库实际渲染的语言 en / zh。源码中 LOCALE_CODES = ['en', 'zh']、BASE_LOCALE = 'en'(scripts/lib/entries.mjs),历史上曾有两个条目带着 ja 键进入 main,站点根本不渲染它——现在校验会直接拒绝多余的语言键(scripts/lib/entries.mjs)。

⚠️ 描述中含冒号必须加引号

描述内容里出现 :(半角冒号加空格)时,YAML 会把它解析成嵌套键导致解析失败,必须加引号:

description:
  en: 'Vision toolkit: OCR, grounding and pixel diff.'   # ✅ 加引号
  zh: '识图工具包:OCR、定位与像素比对。'                    # 中文全角冒号无此问题,加引号也无妨
  en: Vision toolkit: OCR, grounding and pixel diff.     # ❌ 解析失败

scripts/lib/entries.mjs 专门为这种最常见的投稿错误写了诊断:当 YAML 解析失败时,会从文件里定位 en:/zh: 行,自动判断是否属于「含 : 未加引号」,并在报错信息中直接给出修正后的那一行,让投稿者十秒钟内就能修好。

可用的 category 取值

agi ui usage theme model identity session memory tools wsl browser vision voice docs skill workflow git notify dev security remote market fun

这组取值不是固定不变的。scripts/lib/entries.mjs 中的 CAT_IDS 是规范顺序来源,驱动着 README 分区顺序、站点排序与 sitemap;validateEntries 会校验 category 必须属于该集合(scripts/lib/entries.mjs)。分类体系本身会随增长而拆分:usage、vision、security、browser、git、docs、remote、voice 都是在 tools、ui、dev 大到没人能扫完之后从中拆出来的。

monorepo 子包:URL 指向子目录

如果插件位于 monorepo 子包,url 指向子目录,name 用 owner/repo#subname 形式:

url: https://github.com/owner/repo/tree/main/packages/my-plugin
name: owner/repo#my-plugin

文件名随之变为 owner__repo--packages-my-plugin.yml。slug 生成规则在 scripts/lib/entries.mjs 的 slugFor() 中实现:https://github.com/o/r → o__r,.../tree/main/packages/x → o__r--packages-x。校验会强制文件名与 URL 一一对应(scripts/lib/entries.mjs),如果文件名不匹配,generate-readme.mjs 会提示期望的文件名。

硬性要求:什么样的插件才能收录

1. 必须声明 dsh.bundle manifest

仓库的 package.json 必须声明 dsh.bundle(monorepo 根包或子包声明亦可),这是它能通过 dsh plugin add 安装的前提。最常见的被拒原因是只声明了 dsh.client——那只是带浏览器 UI 的标记,单独声明不可安装。完整示例:

{
  "dsh": {
    "bundle": { "patch": "./cordis.patch.yml" },   // ← 必须
    "client": { "platform": "web" }                // 仅带前端 UI 时需要
  }
}

同时仓库根目录要放一个 cordis.patch.yml:

- insert:
    - id: your-plugin-id
      name: your-package-name

CI 侧的检测在 scripts/check-submission.mjs 的 scanTree() 中:它递归拉取仓库 git tree,枚举最多 MAX_TREE_PKGS = 40 个 package.json(scripts/check-submission.mjs),逐一看是否含 dsh.bundle。有两类特殊拒绝:

  • 只声明 dsh.client:报 "declares only dsh.client — that alone is not installable"(scripts/check-submission.mjs)。
  • 仓库本身就是 DSH:deepseek-ai/deepseek-harness 及三个官方包(@deepseek-ai/dsh-base、@deepseek-ai/dsh-web-app、@deepseek-ai/dsh-headless)会被按身份拒绝——把产品本身列进产品的插件列表是每个访客都能识别的错误条目(scripts/check-submission.mjs)。

此外,如果条目指向仓库根而根 manifest 没有 bundle、但子目录里有,gate 会精确指出应改成的子包 URL、name 和文件名(scripts/check-submission.mjs),因为安装命令是按条目 URL 生成的,指向根目录会「装了个寂寞」。

2. 仓库创建满 1 天

没有提交数门槛(历史上 MIN_COMMITS = 10 在 2026-09-03 被移除,见 #4196)——提交数衡量的是开发习惯而非质量,squash-merge 的仓库主历史很短,而 git commit --allow-empty 十秒就能凑数。1 天年龄门槛的意义是过滤「PR 前几分钟才建好」的一次性仓库,且时间无法伪造。源码 MIN_AGE_DAYS = 1(scripts/check-submission.mjs)。

如果你暂时没达标,什么都不用做:gate 的错误信息会明确告诉你「无需重新提交、无需 push、无需 close 再 reopen」,因为 regate.yml 每六小时自动重跑,年龄达标后 verdict 会自动变绿(scripts/check-submission.mjs)。

3. 其余硬性要求

  • 仓库需有真实可用的代码:占位仓库、纯 README 仓库、空壳不收。
  • 项目处于活跃维护状态:定期扫描会标记仓库消失、已归档或长期停更的条目。这一机制实现在 scripts/scan-decay.mjs:每周扫描会标记 gone(404)、archived、dormant(DORMANT_MONTHS = 6 个月无推送)、subpath-gone(子目录已移动)、unbundled(dsh.bundle 被移除)五类信号,汇总到跟踪 issue 由人工确认后移除。扫描只标记、绝不自动删除。
  • 为仓库添加 dsh-plugin topic。
  • 描述只说功能,不带营销词。
  • 描述必须属实:描述会被当作对插件的声明并与代码核对。写「46 个工具、六大领域」,就应有 46 个工具和六个领域;提到某个命令或 API,它就应该存在。夸大是让一个本来不错的插件被打回的主要原因。
  • 选贴合插件实际做的事的分类,而不是你希望它出现在哪里;选得不够准的,维护者会直接改,不会打回。

字段白名单:条目文件只允许这些键

scripts/lib/entries.mjs 定义了条目文件的全部合法键:url、name、category、description、tarball(file 是读取时自动附加的)。任何未知键都会被拒绝,理由是「没人读的字段放在文件里看似权威实则虚假」。历史上四个条目曾积累过 npm: 键,而没有任何代码读取它——npm 映射是从 registry 自动采集的,见下文 npm 一节。

收录如何评审:CI 是前置条件,不是结论

CI 通过只代表形式正确——manifest、仓库年龄、格式、README 能否重新生成。CI 无法判断插件是否名副其实、分类是否贴切、是否与已有条目重复。合并前维护者会实际阅读目标仓库。评审看八点:

  1. 代码是否与条目声明一致——包括描述里的数字与 API 名称。
  2. 分类是否合理——不会有人因分类被打回,维护者发现更贴切的会直接改。
  3. 是否真实可用的代码,而非占位或空壳。
  4. 是否已被现有条目覆盖——两个插件做同一件事时先来者保留位置,但这只是平局排序,不是既得利益。停止维护、有恶意行为、有明显缺陷的条目会被移除;分叉也可以被收录,只要它维护得更好或确实做了新东西。规则不是先来后到,规则是谁更好。
  5. 源码中是否有可疑之处——混淆代码、凭据外传、异常的安装期行为。注意:收录不等于安全审查,这只是常识性检查,不是审计。
  6. PR 是否动了与它无关的条目——更新某个插件的 PR 不该改写另一个插件的描述。这曾两次蒙混过关(#1348:检测两条描述共享 40+ 字符连续文本的「串扰指纹」(RUN = 40,scripts/check-bleed.mjs),同属一个作者的兄弟插件自动跳过。它作为评审信号而非 gate 强制执行,因为相似插件确实会被相似地描述。
  7. 是不是纯聚合包——内容只有依赖清单、自己不带行为的聚合包不单独收录:收插件,不收聚合包。聚合包可以继续存在、用户也可以继续装,只是不占一行(一行只指向别的行没有增量信息,还会重复计数)。但聚合包自己做事——合成配置、提供设置界面、运行时协调——那就是插件,按普通标准审。
  8. 依赖是否指向原作者——聚合包的依赖必须解析到原作者的仓库或其发布的 npm 包。把别人插件重新上传到自己账号下再依赖副本的,不予收录:副本没有 fork 关系、没有署名、也没有上游。

反馈以 PR 评论给出,明确指出要改什么。因描述不准确被打回不是对插件本身的否定——改好那一行即可收录。更新自己的条目时只改自己那一条:手工编辑 README 是事故高发区,列表增长让行号移位,改动容易落到邻居身上。

一个 PR 最多 3 条

一个 PR 最多添加 3 条条目,超过会被 CI 拒绝并要求拆分。这是有数据支撑的决策,不是拍脑袋:定下余量时,最近 100 个已合并 PR 中 92 个加 1 条、8 个加 2 条;2026-09-24 重新统计,最近 100 个新增条目的 PR 中 88 个加 1 条、3 个加 2 条、9 个加 3 条。留这个余量是为了一种确实需要它的情形:monorepo 多个子包各自是独立可安装的插件。

评审投稿意味着读插件源码并把描述每一句话对着代码核一遍,这是逐条工作量,不因打包而变少——127 条的 PR 不是一次投稿,而是 127 次投稿套了件外衣,诚实的结果是没一条会被认真读完。实现见 scripts/check-submission.mjs 的 MAX_ENTRIES_PER_PR = 3,且该检查在任何网络请求之前执行(scripts/check-submission.mjs),避免为一个注定被拒的 PR 烧掉 API 配额。

如果多个插件都是你的,除了拆分还要挑:提交那些「如果只能留几个你会留下的」,而不是所有能跑的。读者打开一个分类需要的是「这些都值得一看」,而不是「这里面有几个值得一看」。

CI 会检查什么:四步流水线

每个 PR 依次运行四步检查(实现在 scripts/check-submission.mjs 与 scripts/generate-readme.mjs):

  1. Entry count——每个 PR 最多 3 条,最先检查,早于任何网络请求。
  2. dsh.bundle——从仓库 package.json 读取(根包,或 packages/ · plugins/ · apps/ 子包);只声明 dsh.client 会失败。实际遍历时并发度为 6(CONCURRENCY = 6),需要 GITHUB_TOKEN(匿名配额 60/小时/IP 远不够,见 scripts/check-submission.mjs)。
  3. Repo age——上面说的 1 天年龄门槛。
  4. awesome-lint 与站点构建——双语一致性、分隔符、日期、截图。

若某步失败会明确说改什么,在同一分支上推送修复即可,无需重开 PR。两个值得一提的实现细节:

  • 重试语义:GitHub 的 403 同时对应「权限不足」与「请求过频」两种无关问题,gate 只对 rate-limit 型 403 重试,且按 GitHub 要求的 retry-after 等待(scripts/check-submission.mjs),并有单次 75 秒、总计 150 秒的双预算上限——无限退避本身也是一场故障。
  • 未验证 ≠ 通过:incomplete 结果绝不阻塞,但会单独报告「哪些条目未经过完整检查」,因为一个分不清「通过」与「没跑过」的 gate 比没有 gate 更糟(scripts/check-submission.mjs)。

截图规范:screenshots.json

插件市场(如 dsh-market 的详情页)可以像 App Store 一样展示插件截图。在你的仓库里声明:在 package.json 旁边放一个 screenshots.json(monorepo 条目放在对应子目录里),列出 1-8 张图片路径:

// <your repo>/screenshots.json
[
 "assets/screenshot-1.png",
 "assets/screenshot-2.png"
]

路径相对于该文件本身,指向你仓库里已有的图片。{"screenshots": [...]} 同样可用。规则:

  • 1 到 8 张。
  • 绝对 URL 也可接受,但必须是 GitHub 托管的 https(raw.githubusercontent.com、user-images.githubusercontent.com、camo.githubusercontent.com、github.com attachments)——出于用户隐私考虑,第三方图床被拒绝。
  • 相对路径不能跳出插件目录(不能以 / 开头,不能含 ..)。
  • 不声明也没关系:市场会从你的 README 自动抽取,声明只是让你能控制展示的顺序与内容。

为什么放自己仓库:换截图推自己的仓库即可生效,不用提 PR、不用等维护者;相对路径在你自己仓库里改名会立刻坏掉,而写死在列表仓库的绝对 URL 只会静默腐烂——已发布的 773 张截图里有 41 张就是这样变成 404 的;没有人会动你的文件,截图投稿之间不再互相冲突。

旧条目(此约定之前收录的)截图仍记录在本仓库的 data/screenshots.json,照常生效——仓库没声明时就读它。它是有终点的回退而非第二个存放地:一旦仓库声明了自己的 screenshots.json,那边多余的键会被清理,文件清空后删除。不要再往里面加新的键。

推荐实践:让安装体验更好

以下三项均不影响收录,但能显著改善用户安装体验:

1. 发布 npm 包

  • 发布 npm 后,预构建安装可跳过 allowBuilds 构建授权步骤。
  • 已发布包的 repository 字段必须指回本列表收录的那个仓库,否则两者不关联——这是刻意的,防止包挂到未认领它的仓库上。
  • 不需要通知:映射会从 registry 自动采集。实现见 scripts/probe-npm.mjs:读取仓库 package.json 的 name,去 registry 查 packument,只有当包的 repository 字段指回同一 GitHub 仓库时才接受(防名称抢注);结果缓存到 data/npm-map.json。
  • 在 yml 里手写 npm: 键会被校验拒绝(见上文字段白名单)。
  • 没有 npm 包也完全不影响收录,只是市场里没有下载量数字。

2. 提供预构建 tarball

不发 npm 的话,可以把预构建 tarball 附加到 GitHub Release,用可选的 tarball: 字段指向它,市场会优先展示它而不是源码构建命令。如果仓库根本无法从源码安装,这一项是必需的。

tarball: https://github.com/owner/repo/releases/latest/download/your-plugin.tgz

必须是 GitHub Release 托管的 https .tgz。校验实现在 scripts/lib/entries.mjs 的 tarballProblem():只允许 github.com、objects.githubusercontent.com、release-assets.githubusercontent.com 三个主机,且 URL 必须落在 /releases/ 路径下、以 .tgz 或 .tar.gz 结尾。

⚠️ latest/download/ 的陷阱:latest 在请求时解析,但文件名是照字面取的。如果资产名带版本号,链接提交当天有效,下次发版就 404——而且没人察觉。要么让资产名不带版本,要么钉住 release tag:

# 钉住 tag —— 永不腐烂,文件名带版本号在此处是正常写法
tarball: https://github.com/owner/repo/releases/download/v1.2.0/your-plugin-1.2.0.tgz

3. peerDependencies 的预发布分支陷阱

官方 @deepseek-ai/* 包请用 peerDependencies 声明,但不带显式预发布分支的 peer 范围会静默排除 harness 的所有预发布构建。node-semver 只有当范围里某个比较符与该版本的 major.minor.patch 元组完全一致、且自身带预发布标签时,才会放行预发布版本:

// ❌ 看似很宽,实则静默排除所有 0.1.0-* 预发布
"peerDependencies": { "@deepseek-ai/dsh-tools": ">=0.0.1-rc.1 <0.2.0" }

// ✅ 在 0.1.0 元组上显式加预发布分支
"peerDependencies": { "@deepseek-ai/dsh-tools": ">=0.0.1-rc.1 <0.1.0 || >=0.1.0-rc.1 <0.2.0-0" }

否则用户 npm install 时会遇到 ERESOLVE,还得手工绕行。

主题与皮肤:专属分类与一键安装

Themes & Appearance(主题与外观) 分类下的条目会自动进入 dsh-market 插件市场的主题 Tab,用户可一键安装、切换、卸载——主题/皮肤类插件务必放这个分类,不要放 UI 增强。支持 monorepo 子包:直接链接子目录,如 https://github.com/owner/repo/tree/main/packages/my-theme。

移除与更新

修正描述、调整分类、移除失效项目的 PR 同样欢迎。核心原则始终是:编辑你自己的 data/plugins/<owner>__<repo>.yml,然后重新生成,而不是手改 README。合并后网站自动重建,无需改动其他文件。

最后值得记住的是:这个列表的维护者不是插件好坏的裁判。收录与否不代表对作品的评价——有很多优秀软件永远不会出现在这里,而出现在这里也仅仅说明它符合规则。这些规则只为一件事存在:让打开这个页面的人,装上他挑中的插件后,它确实做描述里写的那件事。

  • 知识库
  • DeepSeek
  • dsh-plugin

【免费下载链接】awesome-dsh-plugin

A curated list of plugins for DeepSeek Harness (dsh) · DeepSeek Harness 插件精选列表

项目地址: https://gitcode.com/gh_mirrors/aw/awesome-dsh-plugin
点击查看 免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值