🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI
广告☁️ 云服务器特惠阿里云首购 8 折 · 腾讯云合作特惠
DeepSeek Harness Hub
← 返回列表

liangz2210-lgtm/dsh-openclaude-ecosystem

DeepSeek Harnessspec-screened扫描:中风险在 GitHub 查看 ↗
未验证

运行 DSH web 配置并加载合并后的

尚未跑自动兼容性验证,可查看页面内的依赖与入口分析。 · 最近上游提交 2026/9/16 · 已提供中文文档

在 DeepSeek Harness 上将 OpenClaude 注册为具名子代理提供方:任务图、退出码分类、带自动恢复的停滞看门狗。实验性——尚无真实委托完成。

综合分
29.1
GitHub 分
29.1
用户评分
—
★ Stars
0
周下载量
—
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add liangz2210-lgtm/dsh-openclaude-ecosystem
该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
信任档位:已验证本站已于 0 天前真实安装成功
是什么
dsh 原生插件 · chat
装得上吗
本站已真实安装成功(非静态推断)
安全吗
本站尚未对该插件做风险分级(暂未覆盖,不等同于无风险)
还在维护吗
活跃:最近一次提交在 10 天前

档位由下列信号合成:本站实装验证(真实安装,当前最高到 L4)· 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。下方各区块是它的证据明细。 验证判据与等级说明 →

🟢实装验证通过· 2026/9/25
由本站实装验证器在真实 dsh 环境安装成功,非静态推断。
数据截至 2026/9/24(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

由 DeepSeek 最新模型翻译生成
dsh-openclaude-ecosystem

运行 DSH web 配置并加载合并后的
dsh-openclaude 插件所需的一切,该插件
进而驱动 OpenClaude(NVIDIA NIM,nemotron-3-ultra-550b-a55b)。

状态:实验性,未经证实

在克隆之前请先阅读本节。该插件可以挂载、构建,并通过其自身的测试
套件(57 条断言),但它从未完成过一次真正的委托。

- 1 次真实委托,0 次成功。 唯一一次实际调用(2026-09-11,一个
单文件 HTML 游戏)运行了 62 分钟却毫无产出,随后被外部终止,归类为
OPENCLAUDE_NON_ZERO_EXIT。
- 根本原因不在本插件中。 子进程对其发往 NVIDIA 的 HTTP 请求没有读取
超时,卡在了套接字上。为约束该故障而加入的停滞看门狗(IDLE_TIMEOUT →
自动 --resume,外加 RUNTIME_EXCEEDED 墙钟时间上限)从未针对真实
停滞进行过验证——该故障早于修复。
- 它按设计就是不设防的。 --yolo 被硬编码在 buildInvocation
(executor/openclaude.ts)中,因此被委托的任务会在没有确认步骤的情况下
写入文件并运行命令。请谨慎限定 workdir 的范围。
- 它需要你自己安装的第三方 CLI。 该插件只负责启动 openclaude;它
不持有任何凭据。如果 PATH 上没有该 CLI(或没有可解析的回退方案,见
resolveExecutable),则什么都不会运行。

PLUGIN-STATUS-2026-09-11.md 是那唯一一次委托的完整取证快照,取自进程
记录而非回忆。请将其视为关于当前状况的诚实记录。

使用它

dsh                 # 启动,前台运行;Ctrl-C 停止
dsh bg              # 分离式启动,等待其响应,日志位于 logs/
dsh status          # pid / 端口 / HTTP 健康状态
dsh stop            # 停止它
dsh restart
dsh check           # 预检:组合配置,不启动任何东西
dsh logs 60         # 查看最新后台日志的末尾
dsh where           # 它所依赖的每一条路径

然后打开 http://127.0.0.1:3080。

dsh 是 bin/dsh,从 ~/.local/bin/dsh 符号链接而来(该路径通过
.zshrc 加入 PATH)。它是一个轻量前端——start-dsh.sh 负责实际的启动
以及 arm64-node 防护。

ds 是 dsh 的同义词(.zshrc:alias ds="dsh")。它以前是
cd ~/deepseek-harness && pnpm web,这永远不可能生效:harness 根目录下
没有 web 脚本,因此 pnpm web 会以 Command "web" not found 失败。真正
的入口是 pnpm dsh(tsx 源码 CLI)和 pnpm dev:web(前端开发服务器)。

在 DSH 内部驱动 OpenClaude

该插件在启动时自行挂载——没有启用步骤,没有按对话进行的设置,打开新对话后
也无需重新武装。这些命令注册在命令注册表的全局层中,因此运行实例中的
每个会话都共享它们。只有重启 harness 才会重新挂载该插件。
存在三个命令,而 /openclaude 是你唯一会日常使用的:

/openclaude         将单个临时请求作为单个任务运行
/openclaude tasks/foo.json   运行任务图文件(任何以 .json 结尾的文件)
/openclaude-status           当前图中每个任务的状态
/openclaude-abort            中止运行并终止进行中的 CLI 进程

在输入框中输入 / 会打开命令菜单(UI 通过 commands.list(sessionId) 将自身注册为 '/' 触发源),因此可以选取 /openclaude 而不必手动输入。解析规则是
/^\/([a-z][a-z0-9_-])(?=$|[\t\n\r ])/u,这意味着:

- 该行必须以 / 开头——前面不能有任何文本。
- 名称只能是小写,后面跟一个空格。/openclaude你的需求 和
/OpenClaude … 都无法解析,会作为普通聊天发送给模型。
- 不带参数的裸 /openclaude 可以正常解析,处理程序会回答
Usage: /openclaude 。

命令是一个触发器,而不是一种模式:

- 它不会发送给模型。CommandDefinition.handler 的文档说明其运行方式是“针对接收代理,而不将命令发送给模型”,因此输入它只是一个本地操作,而不是提示词。
- 它不会重新路由后续消息。插件中没有任何东西会挂钩会话;普通聊天永远不会被转发给 OpenClaude。每个任务都需要自己的 /openclaude。
- 各次运行之间不会互相记忆。runRequest() 构建一个单任务图,运行它,然后关闭引擎;上下文来自 workdir 下的文件,通过 collectContext 收集,而从不来自聊天历史。要延续之前的工作,请在请求中重新陈述,或将其写入图 JSON。

workdir 在 cordis.patch.yml 中默认为 .,并相对于启动 dsh 时所在的目录解析——因此请从你希望 OpenClaude 编辑的项目中启动 dsh,而不是从 $HOME 启动。

每次运行都是无人值守且无防护的。 --yolo 被硬编码在
buildInvocation(executor/openclaude.ts:215)中,并且默认不设置任何 permission-mode,因此在写入文件或运行命令之前不会有任何询问。像“删除 X”这样的请求会在没有确认步骤的情况下被执行——请有意地限定 workdir 的范围,如果你想要更严格的模式,请设置 permissionMode。

如果你想让普通消息自动路由到 OpenClaude,那是另一种集成:它需要一个插件目前尚不具备的会话级钩子。

没有澄清步骤,而且这是结构性的

人们期望的工作流——DSH 澄清需求、提出计划,然后将一份确定的简报交给 OpenClaude——并不是这两部分中任何一部分的做法:

- /openclaude  从不分解任何内容。 runRequest 只构建一个任务:title = 前 72 个字符,description = 整个字符串,acceptanceCriteria: [],没有依赖项,然后运行它。这个字符串就是简报。
- LLM 监督者是一个审查者,而不是规划者。 它在……之后运行
尝试之后,看到执行器的报告以及验收结果,然后从五个动作中选择一个。escalate 会把任务标记为已停止——它不会回来问你任何问题。
- 运行过程中没有向你提问的通道。 执行器是无头的
(--print --yolo),并且命令处理器会阻塞直到运行结束。
- DSH 一侧无法行动。 web profile 禁用了 tool-bash、tool-fs、
tool-fs-search、tool-str-replace-editor、plan-mode、tool-subagent、
tool-workflow 等等——在 packages/bundle/web-app/cordis.patch.yml 中有 24 行。
因此对话式 agent 可以与你一起推理,但自己无法读取、写入或运行
任何东西。

因此这两半彼此错位:agent 能规划但不能行动,
插件能行动但不能规划或提问。

获得你真正想要的流程

在对话中完成澄清,然后交给它一个任务图,而不是
一句话。/openclaude .json 是能给你分解、依赖、并行
(maxConcurrency,默认 2)以及每任务重试(maxRetriesPerTask,默认 3)的路径:

{
"tasks": [
{
"id": "t1",
"title": "抽出重试策略",
"description": "把 payments 的 timeout 重试逻辑抽成独立模块,保持现有行为",
"acceptanceCriteria": ["npm test -- payments 通过"],
"priority": 1
},
{
"id": "t2",
"title": "补指数退避与测试",
"description": "在 t1 的模块上加指数退避,最多 3 次,并补单元测试",
"dependencies": ["t1"],
"priority": 1
}
]
}

顶层是数组也可以。除 title 外,字段都是可选的;
description 默认为 title,dependencies 默认为 [],priority 默认为 1,
assignee 默认为 openclaude。由于 agent 没有文件工具,它必须把这个 JSON 作为文本交给你——你自己保存它,然后在从该项目启动的 dsh 中运行 /openclaude tasks/x.json。

这通常不是失败——该命令只在整个运行结束后返回一行摘要。
没有流式输出到对话中,并且
OpenClaude 在处于模型回合中时有意不报告任何内容。日志是唯一诚实的进度视图:

tail -n 1 /.dsh/openclaude/tasks.jsonl     # default storePath

每一行都是一个完整的任务快照;status、attempts[].errorCode 和
haltedReason 会告诉你发生了什么。有用的代码:

| errorCode | 含义 |
| --- | --- |
| OPENCLAUDE_ABORTED | 调用方的信号触发了——一个新命令或一个新对话取消了这个 |
| OPENCLAUDE_IDLE_TIMEOUT | 在 idleTimeoutMs(默认 240 秒)内没有进展。--heartbeat 行是存活信号,不是进展,所以它不会重置这个时钟——子进程还活着,但毫无进展 |
| OPENCLAUDE_RUNTIME_EXCEEDED | 达到了每次尝试的墙钟时间上限 maxRuntimeMs(默认 3600 秒)。这是进度时钟看不到的一种失败:一种不断报告活动的活锁 |
| OPENCLAUDE_CLI_NOT_FOUND | openclaude 无法解析;见下面的损坏符号链接说明 |
| OPENCLAUDE_NON_ZERO_EXIT | CLI 以非零状态退出;真正的退出码在结果中,而不是异常中 |

在不使用 ps(可能受限)的情况下交叉检查存活状态:

lsof -p  | grep cwd                 # OpenClaude 继承的工作目录
pgrep -P                            # openclaude 子进程(如果正在运行)

预期运行会很慢:默认 --max-turns 50。--heartbeat 30s 正是让一次安静的运行与一次死掉的运行可区分开来的东西——但请注意,它只报告存活状态;它并不能换来耐心。一个永远在心跳却什么也不产出的子进程就是卡住了,idleTimeoutMs 会终结它。不要把“它还在心跳”读作“它还在工作”。在 Apple 芯片上的 x64 node(Rosetta)下,它会更慢。

那些默认值属于编排器(/openclaude,idleTimeoutMs 240s)。下面的子代理提供方有它自己的、更长的默认值(900s)——两者是分别配置的。

编排模式 预设:让代理自行委派

上面的命令要求你把工作打包成任务图。另一条路径把决策放进代理内部:一个预设,其 persona 告诉它对每个请求进行分诊、规划、分解,并把工程密集的工作交给子 OpenClaude——同时把澄清、规划、分解和验收留给自己。

它作为用户预设发布,并且是默认预设:

~/.dsh/.agent-presets/delegating/
preset.yml           name: 编排模式, order: 5
agent.cordis.yml     standard 的完整副本,带两处本地修改

这两处修改,仅此而已:

1. persona.config.text 替换为委派策略(来自
DELEGATION-POLICY.md);
2. 在 delegation 组中,将随附但已禁用的
tool-subagent-claude-code 行替换为:

- id: tool-subagent-openclaude
name: '@deepseek-ai/dsh-tool-subagent'
config:
provider: openclaude
toolName: subagent_openclaude
enableRunInBackground: true
maxDepth: provider-managed

因为预设是一份完整组合,而不是补丁,所以 standard 保持原样,两者共存——从预设选择器中任选其一,或修改 ~/.dsh/settings.yaml 中的 agent-presets.default:

agent-presets:
default: delegating      # 或:standard

代理得到的是:subagent_openclaude(默认前台,或通过 run_in_background: true 转为后台 → job_output / job_kill),外加来自 standard 的它自己的 subagent 和 subagent_fork。代理得不到的是:任何查看子进程中间步骤的能力、任何在会话 cwd 之外的 --add-dir,或一个共享对话的子进程——inheritsParentContext 为 false,因此任务简报必须自包含。

提供方在不告知任何人的情况下处理的唯一一种失败是卡住:一个在 idleTimeoutMs 内没有取得任何进展的子进程会被视为挂起,被杀死,并以 --resume  恢复,最多 maxStalledRestarts 次。一个
停滞若仍能到达 agent,就意味着恢复早已耗尽。

“进展”才是关键词,它并不等同于“输出”:OpenClaude 每 30 秒在 stderr 上发送心跳,这些行证明进程还活着,却完全不能说明它是否在工作。把它们当作进展,正是看门狗一开始失效的原因——计时器每 30 秒就被重置,因此一个冻结的子进程永远不会被杀死,而它本应捕获的停滞恰恰是它唯一看不见的情况。这一点在 2026-09-11 被现场观察到:一次委派冻结了一个多小时,其 TCP 连接毫无变化,却被报告为 running。maxRuntimeMs 现在还会对每次尝试额外施加时间上限,以应对无进展规则在结构上无法覆盖的情况——即子进程不断报告活动却毫无进展。

告诉 agent 该能力存在

接好工具行只是其中一半,而且有一段时间我们只有这一半。2026-09-11 的测量显示,在预设正确且 subagent_openclaude 已在目录中的情况下:零次委派调用,而且推理轨迹中从未出现过 subagent、OpenClaude、委派 或 派。

原因在于 harness 有意留下的一个缺口。注册工具和描述工具是两种不同的行为,而 harness 只对它硬编码的那一种形态执行第二种:当 backgroundMode 为 continuable 时,@deepseek-ai/dsh-tool-subagent 会发布一个 tool: 提示词区段。一次性 provider——我们的,以及随附的 claude-code provider 都一样——只能得到一个 schema,别无其他。schema 陈述的是参数,不是能力;其中没有任何内容说明你可以把工程工作交给另一个进程。

因此,provider 在 packages/dsh-openclaude/src/subagent/index.ts 中自行声明:

// order 116.5 is where the harness writes its own "delegate in the background"
// text; 116.6 hitch-hikes onto the same tail-of-prompt attention band without
// demoting anyone.
ctx.systemPrompt.section({
name: tool:${toolName},
order: 116.6,
text: context => tools.get(toolName, context.scope) === undefined ? '' : guidance,
})

116 个字符,它点明的是能力,而不是重述规则——路由标准仍留在 persona 中,只被引用而不被复制。它通过子 fiber(ctx.inject([...]))到达 systemPrompt 和 tools,而不是通过扩大该行的 inject,因为一个挂起的行会把委派工具一起拖垮;并且注册过程容忍同名冲突,而不是让重复项抛出错误导致挂载失败。DELEGATION-POLICY.md §11.1 列出了这四个属性以及每个属性背后的测试。

DELEGATION-POLICY.md §12 涵盖了同一次更新的另一半:对 persona 的六项新增(一个三部分澄清门、一份“绝不询问这些”清单、推荐答案、决策中被拒绝的备选方案、四类验证分类,以及一项空产物禁令),从 1,846 个字符增至 2,726 个字符,借用了
逐句对照 github/spec-kit 的命令提示词,同时我们更强的四个地方——返工循环、监督、红线、子报告契约——保持不变。

什么在哪里

| 路径 | 作用 |
| --- | --- |
| bin/dsh | dsh 命令(start / stop / status / logs / lock recovery) |
| start-dsh.sh | 真正的启动器:验证 arm64 node + harness 树,然后 exec CLI |
| packages/dsh-openclaude/ | 插件:一个包,三个内部模块组 |
| DELEGATION-POLICY.md | 委派策略——也是预设 persona 文本的来源(§11 实测的非委派记录,§11.1 提供方自己的提示词部分,§12 六项 persona 增补) |
| PLAN-agent-plane-delegation.md | A/B 路线分析,保留作为选择 B 的原因记录 |
| PLUGIN-UPDATE-PLAN.md | 本次更新执行的四个批次更新计划,附有它所依据的 Spec Kit 对比 |
| tools/ | 验收脚本:启动真实 profile,挂载预设,对会话日志进行断言(dsh-acceptance-guidance.sh 是当前状态所用的那个) |
| LICENSE | MIT |

下面提到的两个目录是运行时产物,不在本仓库中(.gitignore 排除了它们):logs/(dsh bg 输出,每次启动一个文件)和 backups/(带日期的本地快照,每个都有 MANIFEST.md 和恢复命令)。发布时有意省略了它们——这些快照在废弃的测试脚本中携带了一个有效的 API key,而且两者对读者都没有价值。

DSH 侧的接线是四个文件,都在本仓库之外:

- ~/.dsh/profiles/web/package.json — dsh.profile.bundles,必须以 dsh-openclaude 结尾
- ~/.dsh/profiles/web/cordis.patch.yml — profile 补丁层
- ~/.dsh/profiles/web/node_modules/dsh-openclaude — 指回 packages/ 的符号链接
- ~/.dsh/.agent-presets/delegating/ — 编排模式 预设(persona + 工具行)
- ~/.dsh/settings.yaml — agent-presets.default: delegating
- ~/.openclaude.json — 保存 NVIDIA key 和默认模型的 env 块

bundle 链承载全部八个 bundle。 2026-09-11,一次精简处理短暂移除了 @liustack/modlens、dsh-vision-router、dsh-find-plugin 和 @anysearch/anysearch-dsh,将工具目录从 46 个削减到 16 个;当天即回滚。DELEGATION-POLICY.md §11 保留了这些测量数据作为该实验的记录,并说明了为何回滚。这次往返每个方向只花了一行,因为 dsh.profile.bundles 中的条目只控制挂载——这些包从未从 node_modules/ 中卸载。精简处理原本要解决的问题,当天就以相反的方式解决了(添加能力声明,不删除任何东西)——见下文 §11.1。

回滚还恢复了 attachment-local 的图片限制(20MiB / 100MP / 10000px),这些限制由 dsh-vision-router 从其自身的 bundle 补丁中贡献。因此 profile 的 cordis.patch.yml 恢复为不携带任何 attachment-local
行,而且它应该保持这样:profile 补丁层是在 bundles 之后 组合的,并且会替换整个 config 块,而不是合并进去,所以手写的一行会抹掉 maxImageDimension——这正是 bundle 自己的注释所警告的陷阱。

不要删除或移动这个目录:profile 通过那个符号链接加载插件,所以链接一旦损坏,整个 profile 在启动时就会挂掉。预设是 ~/.dsh/ 下的一个单独副本,所以编辑它不会影响这个仓库——反过来也一样:重新构建插件不会更新已经复制过去的预设。

注意事项

- 首次启动很慢(这里实测 5 秒到 167 秒):开销在于挂载其他 bundles,而不是这个插件。dsh bg 最多等待 DSH_START_TIMEOUT(300 秒)。
- 一个 dsh 在持有 settings writer 锁时被杀掉,会留下 ~/.dsh/settings.yaml.lock,并阻塞下一次启动;当记录的 pid 已不存在时,dsh 会自动清除它。
- 环境变量覆盖:DSH_PORT、DSH_START_TIMEOUT、DSH_NODE、DSH_HARNESS_DIR、DSH_ECOSYSTEM_DIR。
- ~/.homebrew/bin/openclaude 曾是一个指向 ~/openclaude/bin/openclaude 的损坏符号链接(一个被删除的克隆),这导致在 shell 中直接运行 openclaude 会失败,而插件却仍然可用——resolveExecutable 会跳过那些 accessSync(X_OK) 失败的符号链接,并回退到 ~/.homebrew/Cellar/node/*/lib/node_modules/@gitlawb/openclaude/bin/。现已重新指向 ../Cellar/node/26.4.0/bin/openclaude(版本 0.30.0)。如果 openclaude 再次消失,请先检查那个链接,再查其他任何东西。

上游仓库有新提交时邮件通知你(每天最多一封,无更新不打扰),随时一键退订。

💬 加入社群

插件用法、部署报错、新插件第一时间同步——群里问,比一个人翻文档快。

DPharness QQ 群二维码,QQ 扫码进群
QQ 扫码进群
DPharness 飞书群二维码,飞书扫码进群
飞书扫码进群