跳过主要内容
全部文章
教程

从 GitHub 安装 DeepSeek Harness 插件

dsh plugin add github:owner/repo 到底做了什么:源码与构建产物的区别、pnpm 10+ 强制的 allowBuilds 提示、commit 锁定,以及构建失败时怎么办。

目前大多数 DeepSeek Harness 插件是以 GitHub 仓库的形式存在,而不是已发布的 npm 包——这是一个非常年轻、快速演进中的生态,不是每个作者都走到了发布 npm 这一步。安装方式是 dsh plugin --profile <name> add github:owner/repo,但这条命令拉取的是源码,不是构建产物,这意味着你第一次用这种方式安装一个 TypeScript 插件时,大概率会碰到一个权限提示。下面讲清楚这个提示到底意味着什么,以及如何安全地处理它。

命令

dsh plugin --profile web add github:owner/repo

你也可以指定具体的引用,而不是默认分支:

dsh plugin --profile web add github:owner/repo#a1b2c3d

这条命令之所以能这样用,是因为 dsh plugin add 只是 pnpm add 的一层薄转发——pnpm 的 git 依赖解析支持什么,dsh 就支持什么。#a1b2c3d 后缀会锁定到一个精确的 commit SHA(你也可以用分支名或 tag 名,但真正能锁死代码的是 commit SHA)。

为什么 GitHub 安装和 npm 安装不一样

一个发布到 npm 的插件自带构建产物——装完就能直接跑。相比之下,一个来自 GitHub 的插件,pnpm 拿到的是这个仓库的源码。如果这个插件是用 TypeScript 写的,且仓库里没有直接提交编译好的 lib/ 目录,那么这份源码在 dsh 能加载它之前,就需要先被构建一次。

插件作者通常用 package.json 里的 prepare 脚本来处理这件事——这是一个 pnpm 在 git 来源的包被拉取之后自动运行的钩子,用来把源码编译成 dsh 实际会加载的产物。

allowBuilds 提示

这是最容易让人卡住的一点:pnpm 10 及以上版本默认会拦截 git 依赖上的 prepare 脚本执行。 你第一次 add 一个需要构建步骤的 GitHub 来源插件时,安装会失败,pnpm 会提示你去 profile 的 pnpm-workspace.yaml 里显式放行:

allowBuilds:
  dsh-hello-plugin: true

这不是一个 bug 或配置错误——这是 pnpm 默认安全姿态的正常工作方式,dsh 也没有覆盖它。dsh 官方文档对你加上这一行时到底同意了什么说得很直接:

这个放行等价于:允许该包的代码在你机器上、于安装期执行,且脱离 agent 运行时的任何沙箱保护。只应该允许你信任其源码的包,并且要锁定到具体的 commit。

这句话值得读两遍。allowBuilds: true 会在 pnpm install 期间,在你机器上执行该包里的任意代码,而且是在 dsh 自己的运行时沙箱(只读、workspace-write,或 danger-full-access——详见我们的权限与沙箱指南)能覆盖到任何东西之前。一个恶意的 prepare 脚本不受 agent 本身受到的任何约束限制,它就是以你的用户身份运行,和其他任何 npm 安装期脚本没有区别。

由此可以得出两条实操规则:

  1. 只对你真正看过源码的包放行 allowBuilds: true,或者来自你已经信任的作者/组织。
  2. 务必配合锁定 commit 一起使用。 在一个没有锁定的 github:owner/repo 上开着 allowBuilds: true,意味着上游对该分支后续的一次推送,会在你下次重装或更新时改变你机器上实际运行的代码——而你并没有批准任何新东西。

如果你想完全避开这个提示

优先选择已经发布到 npm、自带构建产物的插件(如果有的话)。这样不会有 prepare 脚本运行,也不需要做 allowBuilds 的决策,而且安装通常更快,因为省去了编译步骤。这也是 dsh 官方文档里对插件作者推荐的路径——发布到 npm,而不是依赖 git 安装。

如果你想要的插件只通过 GitHub 分发,在 add 之前先看看它的 README;维护得好的插件通常会说明是否需要 allowBuilds,并给出你可以直接粘贴的那段 YAML。

放行之后构建仍然失败

授予构建权限并不保证构建一定成功。如果放行了构建之后 add 仍然失败,可以检查这几点:

  • 缺少 prepare 脚本。 如果仓库确实没有带 lib/ 目录,也没有一个 prepare 脚本去生成它,安装会成功,但插件在这个 profile 下次启动时会报"找不到模块"一类的错误而加载失败。这是插件本身的编写缺口,不是你在安装侧能修的问题。
  • 构建工具链不匹配。 有些仓库假定了一个特定的构建环境(某个特定 Node 版本、某种 monorepo 构建编排器),而这个环境和一次普通的 pnpm add 运行时不一致。这会表现为构建步骤本身抛错,而不是权限拦截。
  • monorepo 里路径不对。 如果插件位于一个更大仓库的子目录下,而不是仓库根目录,单纯的 github:owner/repo 无法解析到正确的 package.json。查一下插件自己的安装说明,确认正确的说明符格式。

关于 pnpm 找不到、缺 lib/ 这类场景更完整的排障参考,见DeepSeek Harness 插件安装错误与修复

一个更安全的默认流程

把上面这些拼起来,这是一个从 GitHub(而非 npm)安装任意插件时比较合理的顺序:

# 1. 先读仓库——package.json、cordis.patch.yml、插件的入口文件
#    (具体该看什么,见我们的插件安全清单)

# 2. 安装时锁定到你已经审查过的某个 commit
dsh plugin --profile web add github:owner/repo#a1b2c3d

# 3. 如果被提示,只对这一个具体包放行构建
#    (编辑 profile 目录下的 pnpm-workspace.yaml)

# 4. 确认实际生效了什么
dsh --profile web --dump-config

第 4 步比看起来更重要——这是确认插件的配置补丁真的按你预期生效的唯一方法,我们在如何更新和卸载插件那篇里对此有更详细的说明。

FAQ

所有 GitHub 来源的插件都会触发 allowBuilds 提示吗?

不会——只有需要构建步骤(通常是没有提交 lib/ 目录的 TypeScript 源码)且声明了 prepare 脚本的插件才会触发。一个以纯 JavaScript 分发、不需要构建步骤的插件不会触发它。

allowBuilds 是 dsh 专属的机制吗?

不是,这是 pnpm 10+ 的特性。dsh 没有新增或修改这个行为——dsh plugin add 是直接转发给 pnpm 的,所以 pnpm 自己的默认保护措施对任何 git 依赖都一视同仁地生效。

我能锁定到 tag 或分支,而不是 commit SHA 吗?

语法上可以——github:owner/repo#maingithub:owner/repo#v1.2.0 都能用。但只有 commit SHA 是不可变的。分支名会移动,tag 从技术上讲也可能被仓库所有者强制改指向,所以只有 commit SHA 这种锁定方式才能保证你运行的就是你审查过的那份精确代码。

pnpm-workspace.yaml 里加 allowBuilds 条目应该编辑哪个文件?

在 profile 自己的目录下($DSH_HOME/profiles/<name>/pnpm-workspace.yaml),不是某个全局的 dsh 设置。每个 profile 都独立管理自己的放行列表。

如果我想要的插件没有写明 GitHub 安装路径怎么办?

先检查它的 package.json 里有没有 dsh 字段,确认它到底是不是一个真实的 dsh 插件——见我们如何寻找 DeepSeek Harness 插件那篇——然后针对它的仓库 URL 使用标准的 github:owner/repo 说明符即可。

下一步

插件装好之后,看如何更新和卸载 DeepSeek Harness 插件了解后续维护。如果安装过程中出了问题,我们的安装错误与修复和更全面的排障参考覆盖了最常见的失败情形。在给任何你还不信任的作者的插件放行安装之前,先过一遍插件安全清单