🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

桌面工作台 Caxson/dsh-gui

DeepSeek Harnessv0.0.1
Caxson75 天前有提交已提供中文文档扫描:高危

在 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 仓库。
预览分享卡片长什么样 ↓Caxson/dsh-gui
分享 · DeepSeek Harness Hub
Caxson/dsh-gui

在 macOS 桌面窗口里运行 DSH 会话与工具

这是你的仓库?认领条目

回到顶部