DeepSeek Harness Hub
← 返回列表

macOS 原生窗口barisuraz/dsh-mac

DeepSeek Harnessspec-screened在 GitHub 查看 ↗
未验证

在独立原生窗口中运行智能体网页界面,隔离浏览器配置

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

为 DeepSeek Harness 网页 GUI 打造的原生 macOS 窗口——无需浏览器,无需 Chrome,无需重新实现

综合分
30.3
GitHub 分
30.3
用户评分
★ Stars
1
周下载量
安装插件(需先安装 dsh CLI 引擎:npm install -g @deepseek-ai/dsh)
dsh plugin --profile web add barisuraz/dsh-mac
该插件未发布到 npm,走 GitHub 源安装(pnpm 若拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑)
数据截至 2026/9/16(元数据每日更新 · 实装验证按队列轮转,单条结论的验证时间见上方)
用户评分
还没有人投票,来当第一个
订阅周报,不错过优质插件更新
每周一封 · 高评分插件 + 新用户活动

README

dsh-mac

一个用于 DeepSeek Harness 的原生 macOS 应用。它在自己的窗口中运行真正的 DSH Web UI,因此你的智能体不会与你的个人浏览共享浏览器配置文件、会话或键盘快捷键。

它会启动 dsh web,等待其开始监听,在 WKWebView 中显示 GUI,并在你退出时停止服务器。

应用窗口

安装

一条命令即可。它会下载最新版本,校验其校验和与签名,将应用放入 /Applications,信任它,并打开它:

curl -fsSL https://raw.githubusercontent.com/barisuraz/dsh-mac/main/install.sh | sh

或者手动操作:从 Releases 打开 dsh-mac-.dmg,将应用拖入 Applications,然后自行清除隔离标记:

xattr -dr com.apple.quarantine "/Applications/DeepSeek Harness.app"

之所以需要该标记,是因为该构建采用临时签名而非公证签名,而公证需要付费的 Apple Developer 账户。从源码构建则完全无需此步骤。

install.sh 会读取三个可选变量:DSH_INSTALL_DIR、DSH_VERSION(例如 v1.2 这样的标签)以及 DSH_NO_OPEN。

要求

- macOS 13 或更高版本
- Node 和 npm,用于获取 harness

无需先安装 DSH;参见首次运行。

或者从源码构建

需要 Xcode Command Line Tools(xcode-select --install)。

git clone https://github.com/barisuraz/dsh-mac
cd dsh-mac
./build.sh
cp -R "build/DeepSeek Harness.app" /Applications/

build.sh 不会下载任何内容,只需几秒钟。

build/ 下的 bundle 是构建产物,而不是你使用的应用——请将其复制到
/Applications 并启动那个副本。build.sh 会标记该目录,以便 Spotlight
忽略它;若不这样做,这个散落的 bundle 会被索引为第二个
"DeepSeek Harness",并在 Spotlight 和 Launchpad 中显示为重复项。如果已经
注册了一个,请将其删除并注销该游离路径:

rm -rf "build/DeepSeek Harness.app"
lsregister -u "$PWD/build/DeepSeek Harness.app"

其中 lsregister 为
/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister。
之后重启 Dock(killall Dock),以便 Launchpad 重建其列表。

它是什么

一个 Swift 文件。它是一个外壳,而非分支:没有 harness 逻辑,没有重新实现的 UI,没有 DSH 配置、API 或插件接口。窗口中的一切都是上游 DSH,因此新的 harness 功能一经发布就会立即出现。

它不是聊天客户端。它不调用任何模型 API,不存储任何对话,也不管理任何凭据。

更新

DSH 处于开发者预览阶段且不断变化,因此该应用会在每次启动时更新它,就像 Android 的 A/B 系统更新那样。它会保留两份副本,更新只会写入空闲的那一份:

slot a ── running now          new versions install into the idle slot,
槽位 b ── 已知可用的回退版本   绝不会覆盖你正在使用的副本

1. 首选槽位启动并显示你的 GUI。不会等待任何下载。
2. 当正在运行的版本稳定运行一分钟后,最新版本会被安装到另一个槽位。
3. 该副本会以一个临时端口启动,并且必须先能提供 UI 服务,才会被信任。
4. 下次启动时它就会成为你的版本,而它所替换的那个版本则保留为回退版本。

如果新版本有问题,应用会自行恢复并说明情况:

- 它无法启动。 在它成为你正在运行的版本之前就被捕获并丢弃。
- 它启动了但不断崩溃。 三次提前退出后,应用停止重试,将其标记为损坏,并切换回去。

无论哪种情况,都会有一张卡片说明失败的版本、你当前所在的版本,以及原因。警告会一直保留,直到被关闭;进度通知则会淡出。

回滚通知 启动失败的版本不会被再次下载 —— ⌘U 会清除该状态并重试,而 Reinstall Harness… 会重建空闲槽位。

两个副本各占约 600 MB,另外应用还会在 ~/Library/Application Support/DeepSeekHarness 下保留一个仅供自己使用的 npm 缓存。你自己的 npm 缓存不受影响。

首次运行

你无需自己安装 DSH。如果不存在任何 harness,首次启动会安装一个并提供服务。如果你已经有一个,则会立即使用该副本 —— 首次启动和你习惯的一样快 —— 同时会在后台配置一个受管理的槽位。无论哪种情况,你现有的设置都会保持原样。

行为

你现有的 harness 不受影响。 如果端口 3080 被占用,应用会向操作系统请求一个空闲端口,而不是去争抢它。

没有任何东西会在应用退出后残留。 服务器在一个 supervisor 下运行,即使应用被强制终止,它也会将其关闭,因此不会有孤立的 node 进程占用端口。

会话会延续。 应用使用与命令行相同的 ~/.dsh,因此现有的会话、工作区和凭据都会直接出现,无需迁移。

存储是独立的。 webview 使用应用自己的容器,因此 cookie 和本地存储绝不会与 Chrome 或 Safari 混在一起。

配置

全部为可选,从环境变量读取,因此请从终端启动以使用它们。

| 变量 | 默认值 | 含义 |
| --- | --- | --- |
| DSH_WRAPPER_PORT | 3080 | 首选端口;如果被占用,则回退到操作系统分配的端口。 |
| DSH_MANAGED | 1 | 设为 0 可跳过槽位和更新,并使用 dsh 解析到的任何内容。 |
| DSH_NO_AUTO_UPDATE | 0 | 设为 1 可保留槽位,但启动时绝不获取更新。 |
| DSH_NO_SYSTEM_DSH | 0 | 设为 1 可忽略 PATH 上的任何 harness,仅使用受管理的槽位。 |
| DSH_SLOT_VERSION | 最新 | 将槽位固定到某个版本,而不是跟踪最新版本。 |
| DSH_BIN | 自动检测 | dsh 可执行文件的显式路径。 |
| DSH_APP_SUPPORT | ~/Library/Application Support/DeepSeekHarness | 槽位和更新状态所在的位置。 |
| DSH_WRAPPER_LOG | ~/Library/Logs/DeepSeekHarness/wrapper.log | 诊断信息的写入位置。 |
DSH_HOME 以及你的其余 DSH 环境会原样继承。

键盘

| 快捷键 | 操作 |
| --- | --- |
| ⌘R | 重新加载 GUI |
| ⇧⌘R | 重启 harness |
| ⌘U | 检查 Harness 更新 |
| ⌘+ / ⌘- / ⌘0 | 缩放 |
| ⌘Q | 退出并停止 harness |

维护

任何包装器的风险都在于上游发生变化而包装器随之腐坏,因此这个包装器始终只与单一契约耦合:

1. 能够解析到一个 dsh 可执行文件,
2. dsh web --no-open --port N 在回环地址上提供 GUI 服务,
3. 它打印一个携带 token 参数的回环 URL。

第 3 条是一行日志,而非有文档记载的接口,因此当它发生偏移时,--test-parser 和 --check-contract 会大声失败。CI 在每次推送时以及每周运行这两项,将上游变更转化为一次红色构建,并指出损坏的是哪一条契约,而不是一个永远加载不出来的窗口。

诊断

APP="/Applications/DeepSeek Harness.app/Contents/MacOS/DeepSeekHarness"

"$APP" --selftest          # 它解析到了什么
"$APP" --install-harness   # 将一个 harness 拉取到槽位中,无头模式
"$APP" --check-contract    # 启动一个真实的 harness 并验证契约
"$APP" --screenshot out.png --notice rollback   # 将窗口渲染为 PNG

./tools/test-ab.sh         # 恢复,针对故意损坏的 harness
./tools/test-repair.sh     # 会话日志修复,针对合成日志

恢复一个被插件弄成无法加载的会话(见下文)。
python3 tools/repair-sessions.py  --type

单元测试运行器不在发布构建中——--test-parser 等在那里会以退出码 2 退出。构建一个包含它们的版本:

DSH_BUILD_DIR=build-tests DSH_BUILD_TESTS=1 ./build.sh
BIN="build-tests/DeepSeek Harness.app/Contents/MacOS/DeepSeekHarness"

"$BIN" --test-parser       # 就绪行解析器,包括拒绝情况
"$BIN" --test-update       # A/B 槽位与崩溃循环检测
"$BIN" --test-notice       # 通知卡片渲染
"$BIN" --test-concurrency  # 状态锁与 healthCheck,在真实线程下

--test-concurrency 是需要密切关注的那个:它从多个线程同时驱动更新路径,这是让其中的竞态变得可见的唯一方式。

恢复无法加载的会话

包含 harness 不认识的事件类型的会话日志会被直接拒绝,除非该事件携带标记 ignorable: true。这一检查是刻意的:静默跳过塑造重建过程的事件,会导致恢复出一个微妙地错误的会话。

陷阱在于仓库外的插件。harness 的已知类型目录是在仓库内生成的,因此插件自己的事件类型从构造上就在其之外,而 Session.append() 没有给插件任何设置该标记的方式。因此,一个追加了此类事件的插件会写出一个任何 harness 都无法重新打开的日志——包括写出它的那个 harness,因为 append 在写入时不进行校验。该故障只会在下一次打开该会话时出现:

会话“...”包含此 harness 未知且未标记为可忽略的事件类型“/event-name”(seq 18);拒绝解释该日志

tools/repair-sessions.py 将指定的事件类型标记为可跳过,以便日志能够再次加载。它只会处理你明确指定的事件类型——绝不猜测,因为将某个事件标记为可忽略会告诉所有未来的读取者丢弃它,这对于请求记录是安全的,但对于任何会影响会话的内容则不安全。它会在 ~/.dsh/session-format-repairs/ 下保留每个原始文件的副本,并且在某个 harness 仍持有该会话打开时拒绝运行,因为该 harness 会在下一次刷新时覆盖修复结果。

python3 tools/repair-sessions.py \
~/.dsh/sessions///session.v3.jsonl.zstd \
--type /

更好的修复方式在插件一侧:停止写入该事件。在修复之前,请先确认该事件在插件源码中是信息性的。

安全性

该 harness 在回环 URL 后面运行本地代码执行,而应用尊重这一边界:

- 只会加载 127.0.0.1 或 localhost 上携带 token 的 http URL,并且解析器会针对非回环输入进行测试。
- token 从 harness 的输出中读取,仅使用一次,并在所有诊断信息中脱敏。
- DSH 拒绝绑定 0.0.0.0,本应用不会改变这一点。
- 指向其他站点的链接会在你的默认浏览器中打开,而不是在 harness 窗口中。
- 安装使用应用自己的缓存运行 npm install。不会全局安装任何内容,也不会修改任何 shell 配置文件。
- DSH 处于开发者预览阶段。请审查你在自己机器上运行的任何内容。

项目布局

Sources/main.swift          整个应用:窗口、启动器、监督器、槽位、诊断
(HarnessLifecycle 决定运行什么;AppDelegate 绘制它)
install.sh                  下载并安装的一行命令
build.sh                    编译、组装、图标并签名该 bundle
tools/package.sh            构建发布磁盘映像并通过挂载来验证它
tools/make-dmg.sh           磁盘映像本身
tools/notarize.sh           对发布构建进行签名、公证并装订
tools/test-ab.sh            端到端更新与恢复测试
tools/repair-sessions.py    将信息性插件事件标记为可忽略,以便其日志能够加载
tools/test-repair.sh        针对修复工具的重写及其拒绝行为的测试
tools/known-event-types.json  此构建所知的 harness 事件目录
tools/make-icon.swift       图标,按每种所需尺寸以矢量方式绘制
docs/                       截图,由应用自身渲染

发布版本

构建默认采用 ad-hoc 签名,本地副本所需的仅此而已。要让其他人无需经过隔离步骤即可打开发布版本,必须使用 Developer ID Application 证书签名并由 Apple 公证,这需要付费的 Apple Developer 账户。
build.sh 始终启用强化运行时,因此你在本地测试的内容就是会被公证的内容:

xcrun notarytool store-credentials "dsh-mac" \
--apple-id "you@example.com" --team-id "YOURTEAMID" --password "app-specific-password"

DSH_SIGN_IDENTITY="Developer ID Application: Your Name (YOURTEAMID)" ./tools/notarize.sh

该脚本会进行构建,如果签名不是 Developer ID、未启用强化运行时或未加时间戳,则拒绝继续,然后对应用和磁盘映像两者进行公证并装订,确认 Gatekeeper 接受每一个。它会留下 build/dsh-mac-.dmg 以供上传。设置详情见 tools/notarize.sh 的头部。

仅提交磁盘映像会对其中的应用进行公证,但只有磁盘映像会带有装订票据,而 install.sh 会将应用复制到 /Applications,在那里它会单独接受评估。两者都经过公证,因此每个产物都是自给自足的。

该应用不需要任何权利例外:强化运行时限制是按二进制文件生效的,而它会将 node 和 zsh 作为独立进程启动。

许可证

MIT,见 LICENSE。

该应用图标使用 DeepSeek 鲸鱼标志,解析自 DSH 在其 Web 前端中附带的矢量资源。该标志属于 DeepSeek,仅用于标识该应用运行的内容;如果你以其他名称重新分发此应用,请替换它。与 DeepSeek 无关联,也未获其认可。

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

💬 加入 DPharness 群聊

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

点击加入 QQ 群
DPharness 群聊二维码,手机 QQ 扫码进群
扫码进群