在 macOS 桌面窗口里运行 DSH 会话与工具
32.5/100
综合分
3
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/9/27 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
自动兼容检查未通过:要求 dsh 0.1.0-rc.6,而最新版为 0.2.1-rc.2。以下命令仍可尝试,但可能失败。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add Caxson/dsh-gui该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · market
装得上吗
静态安装检查未通过,可能需要源码安装
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 75 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装要求 dsh 0.1.0-rc.6,而最新版为 0.2.1-rc.2
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✓npm 包dsh-gui @ 0.0.1
✓Node 引擎未声明 engines.node
✗dsh CLI 依赖要求 0.1.0-rc.6 · 最新 0.2.1-rc.2 不兼容
✓入口文件main/exports/bin 已声明
源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/19 20:26:35
🔴 安全扫描发现高危能力自动 · 静态分析源码
v2.7.0🔴 扫描:高危尚无人工评估
静态扫描发现安装期即执行代码,或命令参数由运行时变量拼接(参数来源无法静态判定,从严处理)。
安装时即执行脚本可执行外部命令读写/删除本地文件读取剪贴板或密钥环境变量写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 132 处,展示前 114 条)
- 写入本地文件src/main.js:230
writeFileSync(panelPrefPath(), JSON.stringify({ panelVisible })); - 读取本地文件src/main.js:254
const raw = readFileSync(panelPrefPath(), 'utf8'); - 发起网络请求src/main.js:268
const res = await fetch(`${engineUrl}${path}`, { - 发起网络请求src/main.js:291
const res = await fetch( - 读取本地文件src/main.js:340
const saved = JSON.parse(readFileSync(themePrefPath(), 'utf8')); - 写入本地文件src/main.js:412
writeFileSync(themePrefPath(), JSON.stringify({ id: id === FOLLOW_SYSTEM ? FOLLOW_SYSTEM : theme.id })); - 发起网络请求src/main.js:439
const res = await fetch( - 发起网络请求src/main.js:456
const res = await fetch(`${engineUrl}/dsh-gui/browser/shot`, { cache: 'no-store' }); - 发起网络请求src/main.js:468
const res = await fetch(`${engineUrl}/dsh-gui/state`, { cache: 'no-store' }); - 发起网络请求src/main.js:492
const res = await fetch(`${engineUrl}/dsh-gui/sidechat`, { - 写入剪贴板src/main.js:665
clipboard.writeText(text); - 读取本地文件src/main.js:681
if (!existsSync(resolved)) return { ok: false, reason: 'missing' }; - 读取本地文件src/main.js:702
if (!existsSync(resolved)) return { ok: false, reason: 'missing' }; - 读取本地文件src/main.js:735
if (existsSync(cliHome)) return cliHome; - 读取本地文件src/main.js:742
if (existsSync(settingsFile)) return; - 写入本地文件src/main.js:743
mkdirSync(dshHome, { recursive: true }); - 写入本地文件src/main.js:744
writeFileSync( - 写入本地文件src/main.js:768
mkdirSync(presetDir, { recursive: true }); - 写入本地文件src/main.js:769
writeFileSync( - 执行外部命令来自配置/变量src/main.js:828
const child = spawn(process.execPath, args, { - 写入剪贴板src/main.js:914
if (payload) clipboard.writeText(payload); - 读取剪贴板src/main.js:1224
const clipboardBefore = clipboard.readText(); - 写入剪贴板src/main.js:1225
clipboard.writeText('SMOKE_CLIPBOARD_UNSET'); - 读取剪贴板src/main.js:1230
const clipped = clipboard.readText(); - 写入剪贴板src/main.js:1231
clipboard.writeText(clipboardBefore); - 写入本地文件scripts/vendor-panel.js:12
fs.mkdirSync(VENDOR, { recursive: true }); - 读取本地文件scripts/vendor-panel.js:21
if (!fs.existsSync(from)) { - 写入本地文件scripts/vendor-panel.js:25
fs.copyFileSync(from, to); - 读取本地文件src/chromium.js:42
return existsSync(bundled) ? bundled : userDir(app); - 读取本地文件src/chromium.js:51
if (!existsSync(browsersPath)) return false; - 读取本地文件src/chromium.js:53
return readdirSync(browsersPath) - 读取本地文件src/chromium.js:55
.some((name) => existsSync(join(browsersPath, name, 'INSTALLATION_COMPLETE'))); - 执行外部命令来自配置/变量src/chromium.js:85
const child = spawn(process.execPath, [cli, 'install', 'chromium'], { - 读取本地文件src/mobile-pairing.js:39
if (!existsSync(file)) return OFF; - 读取本地文件src/mobile-pairing.js:41
const raw = JSON.parse(readFileSync(file, 'utf8')); - 写入本地文件src/mobile-pairing.js:55
writeFileSync(file, JSON.stringify(state, null, 2), { mode: 0o600 }); - 写入本地文件src/mobile-pairing.js:59
chmodSync(file, 0o600); - 读取本地文件bridge/filetree.js:35
const realRoot = await realpath(root); - 读取本地文件bridge/filetree.js:39
real = await realpath(candidate); - 读取本地文件bridge/filetree.js:62
dirents = await readdir(dir, { withFileTypes: true }); - 读取本地文件bridge/filetree.js:87
const st = await stat(full); - 读取本地文件bridge/filetree.js:95
size = (await stat(full)).size; - 启用终端会话(PTY)bridge/index.js:103
proc = pty.spawn(DEFAULT_SHELL, [], { - 读取本地文件import/index.mjs:64
return statSync(path) - 读取本地文件import/index.mjs:74
entries = readdirSync(dir, { withFileTypes: true }) - 读取本地文件import/index.mjs:121
raw = readFileSync(path, 'utf8') - 读取本地文件import/index.mjs:145
const head = readFileSync(path, 'utf8').split('\n', 1)[0] - 读取本地文件import/index.mjs:161
raw = readFileSync(path, 'utf8') - 读取本地文件import/index.mjs:179
if (cwd !== '' && existsSync(cwd)) return cwd - 发起网络请求import/lib/client.js:163
var res = await fetch('/dsh-gui/import/summarize', { - 发起网络请求import/lib/client.js:207
fetch('/dsh-gui/import/sessions', { cache: 'no-store' }) - 发起网络请求market/index.mjs:86
return fetch(url, { ...options, dispatcher: new ProxyAgent(proxy) }) - 发起网络请求market/index.mjs:91
return fetch(url, options) - 执行外部命令固定命令market/index.mjs:231
if (!spawnSync('pnpm', ['--version']).error) return env - 执行外部命令固定命令market/index.mjs:232
const corepack = spawnSync('corepack', ['--version']) - 写入本地文件market/index.mjs:238
writeFileSync(shim, '#!/bin/sh\nexec corepack pnpm "$@"\n') - 写入本地文件market/index.mjs:239
chmodSync(shim, 0o755) - 执行外部命令来自配置/变量market/index.mjs:254
const child = spawn(process.execPath, [binJs, 'plugin', '--profile', 'web', 'add', spec], { - 发起网络请求market/lib/client.js:209
fetch('/api/market/installed', { cache: 'no-store' }) - 发起网络请求market/lib/client.js:222
fetch(url, { cache: 'no-store' }) - 发起网络请求market/lib/client.js:240
fetch('/api/market/install', { - 发起网络请求market/lib/hub.mjs:34
return fetch(url, { ...options, dispatcher: new ProxyAgent(proxy) }) - 发起网络请求market/lib/hub.mjs:39
return fetch(url, options) - 发起网络请求market/lib/hub.mjs:51
return host.endsWith('.cn') ? fetch(url, { signal }) : proxiedFetch(url, { signal }) - 读取本地文件scripts/build-site.mjs:44
const feeds = readdirSync(dir).filter((f) => /^latest.*\.ya?ml$/i.test(f)) - 读取本地文件scripts/build-site.mjs:47
const m = /^version: *(.+)$/m.exec(readFileSync(join(dir, f), 'utf8')) - 读取本地文件scripts/build-site.mjs:64
if (!jsonPath || !existsSync(jsonPath)) return [] - 读取本地文件scripts/build-site.mjs:67
raw = JSON.parse(readFileSync(jsonPath, 'utf8')) - 读取本地文件scripts/build-site.mjs:99
const files = readdirSync(dir) - 读取本地文件scripts/build-site.mjs:108
const page = readFileSync(join(ROOT, 'site', 'index.html'), 'utf8') - 写入本地文件scripts/build-site.mjs:113
mkdirSync(outDir, { recursive: true }) - 写入本地文件scripts/build-site.mjs:114
writeFileSync(outPath, baked) - 写入本地文件scripts/build-site.mjs:125
writeFileSync( - 读取本地文件scripts/make-icon.js:24
if (!fs.existsSync(SOURCE_IMAGE)) { - 写入本地文件scripts/make-icon.js:159
fs.mkdirSync(ASSETS, { recursive: true }); - 写入本地文件scripts/make-icon.js:160
fs.writeFileSync(pngPath, encodePng(SIZE, SIZE, px)); - 写入本地文件scripts/make-icon.js:164
fs.mkdirSync(ASSETS, { recursive: true }); - 执行外部命令固定命令scripts/make-icon.js:165
execFileSync('python3', [path.join(__dirname, 'process-icon.py'), SOURCE_IMAGE, pngPath], { - 写入本地文件scripts/make-icon.js:171
fs.mkdirSync(BUILD, { recursive: true }); - 删除本地文件scripts/make-icon.js:173
fs.rmSync(iconset, { recursive: true, force: true }); - 写入本地文件scripts/make-icon.js:174
fs.mkdirSync(iconset, { recursive: true }); - 执行外部命令固定命令scripts/make-icon.js:188
execFileSync('sips', ['-z', String(s), String(s), pngPath, '--out', path.join(iconset, name)], { - 写入本地文件scripts/make-icon.js:192
fs.copyFileSync(pngPath, path.join(iconset, 'icon_512x512@2x.png')); - 执行外部命令固定命令scripts/make-icon.js:193
execFileSync('iconutil', ['-c', 'icns', iconset, '-o', path.join(BUILD, 'icon.icns')], { - 读取本地文件scripts/merge-mac-feed.mjs:41
const feeds = inputs.map((p) => parse(readFileSync(p, 'utf8'))) - 写入本地文件scripts/merge-mac-feed.mjs:75
writeFileSync(out, lines.join('\n') + '\n') - 执行外部命令来自配置/变量scripts/smoke.mjs:48
const child = spawn(electron, ['.'], { cwd: ROOT, env, stdio: ['ignore', 'pipe', 'pipe'] }) - 读取本地文件scripts/verify-docs-consistency.mjs:36
return readFileSync(join(ROOT, rel), 'utf8') - 读取本地文件scripts/verify-docs-consistency.mjs:142
existsSync(join(ROOT, 'LICENSE')) && /MIT License/.test(read('LICENSE')), - 发起网络请求scripts/verify-downloads.mjs:46
const res = await fetch(url, { method: 'HEAD', redirect: 'follow' }) - 读取本地文件scripts/verify-downloads.mjs:56
if (!dir || !existsSync(dir)) { - 读取本地文件scripts/verify-downloads.mjs:63
for (const name of readdirSync(dir)) { - 读取本地文件scripts/verify-downloads.mjs:65
if (statSync(full).isDirectory()) continue - 读取本地文件scripts/verify-downloads.mjs:66
onDisk.set(dashed(name), statSync(full).size) - 读取本地文件scripts/verify-downloads.mjs:72
const feeds = readdirSync(dir).filter((f) => FEED_RE.test(f)) - 读取本地文件scripts/verify-downloads.mjs:76
for (const { url, size } of parseFeed(readFileSync(join(dir, feed), 'utf8'))) { - 执行外部命令固定命令scripts/verify-ios-client.mjs:43
const compile = spawnSync( - 删除本地文件递归scripts/verify-ios-client.mjs:56
rmSync(scratch, { recursive: true, force: true }) - 执行外部命令来自配置/变量scripts/verify-ios-client.mjs:62
const relay = spawn(process.execPath, [join(ROOT, 'mobile', 'relay.mjs'), '--port', String(PORT)], { - 执行外部命令来自配置/变量scripts/verify-ios-client.mjs:109
const child = spawn(binary, [SECRET, RELAY_URL], { stdio: 'inherit' }) - 删除本地文件递归scripts/verify-ios-client.mjs:122
rmSync(scratch, { recursive: true, force: true }) - 执行外部命令来自配置/变量scripts/verify-mobile-link.mjs:65
const relay = spawn(process.execPath, [join(ROOT, 'mobile', 'relay.mjs'), '--port', String(PORT)], { - 执行外部命令来自配置/变量scripts/verify-mobile-relay.mjs:46
const relay = spawn(process.execPath, [join(ROOT, 'mobile', 'relay.mjs'), '--port', String(PORT)], { - 执行外部命令来自配置/变量scripts/verify-mobile-relay.mjs:159
const capped = spawn( - 读取本地文件scripts/verify-package.mjs:41
if (!existsSync(binary)) { - 删除本地文件递归scripts/verify-package.mjs:59
rmSync(scratch, { recursive: true, force: true, maxRetries: 5, retryDelay: 200 }) - 执行外部命令来自配置/变量scripts/verify-package.mjs:78
const child = spawn(binary, [], { - 读取本地文件scripts/verify-runtime-closure.mjs:41
return JSON.parse(readFileSync(join(ROOT, rel), 'utf8')) - 读取本地文件scripts/verify-shell-status.mjs:29
runInNewContext(readFileSync(join(ROOT, 'shell', 'client.js'), 'utf8'), sandbox) - 发起网络请求shell/client.js:101
const res = await fetch(STATE_URL, { cache: "no-store" }); - 读取本地文件src/themes/index.js:139
for (const theme of JSON.parse(readFileSync(BUILTIN_PATH, 'utf8')).themes) add(theme, 'built-in'); - 读取本地文件src/themes/index.js:146
if (userDir && existsSync(userDir)) { - 读取本地文件src/themes/index.js:147
for (const file of readdirSync(userDir)) { - 读取本地文件src/themes/index.js:150
add(JSON.parse(readFileSync(join(userDir, file), 'utf8')), file);
扫描于 2026/11/3(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis-plugin-group@deepseek-ai/dsh@deepseek-ai/dsh-anonymous-user-id@deepseek-ai/dsh-atomic-write@deepseek-ai/dsh-bash-local@deepseek-ai/dsh-code-runtime@deepseek-ai/dsh-compaction@deepseek-ai/dsh-fs@deepseek-ai/dsh-invariants@deepseek-ai/dsh-output-retention@deepseek-ai/dsh-sandbox@deepseek-ai/dsh-scope给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 运行DSH会话
- 运行DSH工具
- Mac桌面图形界面
DeepSeek Harness 的 Mac 桌面图形界面
README
由 DeepSeek 最新模型翻译生成Dsh GUI
一个面向 DeepSeek Harness (DSH) 的 Codex 风格桌面应用——优先支持 macOS(Apple Silicon + Intel,已签名并公证),同时提供 Windows 构建版本。
DSH 引擎是内核;本应用是其上的插件层——不 fork,不修改引擎。官方 @deepseek-ai/dsh 包按原样打包,并以无头方式启动(dsh web,仅回环地址,随机端口);桌面行为通过 DSH 自身的插件/补丁系统注入。
一个 Codex 风格的 macOS 桌面客户端,内核是官方 DeepSeek Harness (DSH)。
不重新发明引擎——App 只是 DSH 之上的「插件层」。
展开完整文档(README 剩余 1 节)
Dsh GUI 一个面向 DeepSeek Harness (DSH) 的 Codex 风格桌面应用——优先支持 macOS(Apple Silicon + Intel,已签名并公证),同时提供 Windows 构建版本。 DSH 引擎是内核;本应用是其上的插件层——不 fork,不修改引擎。官方 @deepseek-ai/dsh 包按原样打包,并以无头方式启动(dsh web,仅回环地址,随机端口);桌面行为通过 DSH 自身的插件/补丁系统注入。 一个 Codex 风格的 macOS 桌面客户端,内核是官方 DeepSeek Harness (DSH)。 不重新发明引擎——App 只是 DSH 之上的「插件层」。 特性 / Features - 🖥️ 原生 macOS 窗口,深色 Codex 风格;完整 DSH 能力(多会话、工具调用、工作区、Goal、子代理) - 📋 Codex 式右侧面板(Cmd+B 呼出,默认隐藏;浏览器式多标签,可新建/关闭/弹出为独立窗口): - 终端 — 与 agent 共享同一个 PTY(agent 跑的每条命令实时可见),可再开多个本地终端标签(⌘T) - 改动 — 改动按文件聚合成卡片,真·逐行 diff(LCS + 上下文折叠)、+N/−N 统计、展开/收起(⌘P) - 文件树 — 工作区目录树,按需逐层展开,生成目录默认折叠(⌘E) - 浏览器 — agent 驱动的无头 Chromium 实时画面 + 搜索/抓取活动流(Chromium 不随包分发,首次打开该标签时按提示下载,优先走国内镜像;下载后随用户数据保留,不会被更新覆盖) - 侧边聊天 — 临时轻量聊天(⌥⌘S),流式回复,关闭应用即消失,不打扰主会话 - 🔌 桌面行为全部以 DSH 插件(profile patch overlay)实现:bridge/(活动采集 + 共享 PTY + terminal_send 工具)、browser/(实时浏览器) - 🔒 引擎只绑定 127.0.0.1,外部链接自动走系统浏览器 - 🔄 自动更新默认走国内 CDN 镜像(大陆下载更快更稳);DSH_GUI_UPDATE_URL=github 可切回 GitHub Releases,或填任意自建镜像地址 安装 / Install macOS 提供 Apple Silicon (arm64) 与 Intel (x64) 两个版本,请按芯片选择; Windows 提供安装版与免安装版(x64)。 macOS 提供 Apple Silicon (arm64) 与 Intel (x64) 版本;Windows 提供安装版与免安装版(x64)。 Windows 版尚未经过真机验证,也未做代码签名——首次运行 SmartScreen 会提示,点「更多信息 → 仍要运行」即可。欢迎反馈问题。 Windows 构建版尚未在真机上验证,且未签名; SmartScreen 会在首次运行时警告——选择「更多信息 → 仍要运行」。 1. 从下载页(自动识别系统与芯片,其他平台的包也在同一处列出)或 Releases 下载对应的 Dsh-GUI--arm64.dmg / Dsh-GUI--x64.dmg; Windows 为 Dsh-GUI-Setup--x64.exe(安装版)或 Dsh-GUI-Portable--x64.exe(免安装版) 2. 双击打开,把 Dsh GUI 拖进「应用程序」 3. 首次打开:Gatekeeper 会弹一次确认框,点「打开」即可(见下方说明) 4. 打开后进入 设置 → 模型 填入 DeepSeek(或任意 OpenAI 兼容)API Key,开聊 数据目录:机器上已有 ~/.dsh(用过 dsh CLI / dsh web)时直接复用它——会话、模型、插件与命令行侧完全同步;没有才使用 ~/Library/Application Support/Dsh GUI/dsh-home。DSH_GUI_HOME 环境变量可覆盖。 首次打开被 Gatekeeper 拦住了? 签名与公证已接入发布流程:仓库配置了 Developer ID 证书与公证凭证时, CI 产出的就是已签名并公证的包,首次打开只会弹一次「来自互联网的 App」确认框,点「打开」即可。 如果你下载到的是未签名的构建(凭证缺失时 CI 会降级产出),macOS 会把它统一报成「已损坏,无法打开」——这不是文件真的损坏,执行一次即可: xattr -cr "/Applications/Dsh GUI.app" 签名与公证已接入发布流程:当签名凭证存在时,CI 会产出已签名并公证的构建,macOS 只会显示一次性的「应用从互联网下载」提示。如果你拿到的是未签名的构建(凭证缺失时 CI 会降级为未签名), Gatekeeper 会将其报告为“已损坏”——上面的一次性 xattr -cr 会清除隔离标记。 开发 / Development npm install # postinstall 会 vendor 面板依赖 npm start # 开发运行 npm run smoke # 端到端冒烟:引擎启动 + 面板 PTY + 布局探针 npm run dist # 构建 dmg + zip(发版产物) npm run dist:unsigned # 无证书时的本地构建 架构速览: src/main.js Electron 主进程:引擎拉起、窗口/面板布局、更新 src/panel/ 右侧面板(终端 xterm / 文件 diff / 浏览器) bridge/ DSH 插件:活动采集、共享 PTY、terminal_send 工具 browser/ DSH 插件:agent 可驱动的无头 Chromium + 画面流 plugins/desktop.patch.yml 挂到 web profile 的 loader patch 覆盖层 发版 / Release package.json 改版本号 → 打 vX.Y.Z tag 推送到 GitHub,Actions 云构建自动发版:依赖闭包 + 文档一致性校验 → macOS dmg + zip(arm64 与 x64 各自在对应架构的 runner 上构建)与 Windows 安装版 + 免安装版 → Apple Developer ID 签名 + 公证(仅 macOS)→ 挂到 GitHub Releases 并同步 OSS 镜像,老用户自动更新;大陆用户可用 DSH_GUI_UPDATE_URL 指向镜像源。 未配置签名 secrets 时(如 fork),构建自动退回未签名版——功能不受影响,只是首次打开需右键 →「打开」。 Releases 在 GitHub Actions 上构建,使用 Developer ID 签名 + 公证;如果没有签名 secrets,工作流会自动回退到未签名产物。 License MIT © Caxson. DSH engine © DeepSeek — 见官方 deepseek-harness 仓库。
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
Caxson/dsh-gui
在 macOS 桌面窗口里运行 DSH 会话与工具
相关插件 · 市场 / 管理
插件精选列表awesome-dsh-plugin/awesome-dsh-plugin
DeepSeek Harness(dsh)插件精选列表
★ 22,225未汉化DSH
73.6
新词雷达zhuyansen/new-term-radar
new-term-radar新词雷达
★ 2,049已汉化MCP
72.8
插件生态导航0xsline/awesome-deepseek-harness
安装 贡献指南 DeepSeek Docs 公开插件目录 Issues
★ 1,188已汉化DSH
72.6
技能注册中心iflytek/skillhub
企业级开源智能体技能注册中心——发布、发现并管理组织内可复用的技能包。
★ 5,370已汉化DSH
71.9
插件市场目录imsai-sh/awesome-deepseek-harness-plugins
面向 DeepSeek Harnessdsh生态的社区插件目录,共收录 13941 个插件含 PR 收录与…
★ 355已汉化DSH
71.8
插件精选清单Anil-matcha/awesome-dsh-plugin
DeepSeek Harnessdsh精选指南——DeepSeek…
★ 1,013已汉化DSH
71.7
这是你的仓库?认领条目