先说背景。我是做 Java 后端的,最近一年多深度使用 AI 编程工具——Claude Code、Cursor 这些天天在写(实测),也用过 Ollama 在本地跑 qwen2.5:7b(实测),所以对"Agent 框架"这个 2026 年最火的方向一直盯得很紧。如果你也在用 AI 编程工具,应该能理解这种感觉:工具再多,真正顺手的就那几个,我用 Claude Code 写后端、用本地模型跑离线任务,各司其职(实测)。dsh 对我来说不是要替换谁,而是想看看官方开源 Agent 框架到底把"智能体该做什么"定义成什么样。
2026 年 8 月 13 日,DeepSeek 官方开源了 DeepSeek Harness(简称 dsh),12 小时 GitHub 星标破 5 万,一周干到 14.7 万(来源:社区教程统计)。这个热度在开源圈相当罕见,我当时的第一反应就是:官方出手做 Agent 框架了,必须看看。
它的一句话定位是 Agent = Model + Harness(来源:官方 README):大模型本身只会生成文字,而 dsh 负责文件系统接入、工具调用、沙箱权限、会话记忆、任务循环这些"让模型动起来"的部分。架构上坚持"一切皆插件"(Everything is a Plugin),模型适配器、工具、UI、甚至 Agent 主循环都可以通过插件树组合替换,底层基于 Cordis 这个可组合框架。
为什么值得关注?2026 年市面上的 Agent 产品,Manus、Operator 这些多是闭源 SaaS,用起来不可控、还贵。而 dsh 是 DeepSeek 官方开源、MIT 协议、架构设计非常工程化。作为程序员,我天然会想:能不能自己 clone 下来编译跑起来,再折腾点别人没有的东西?这篇博客就是我从源码编译到打包成桌面程序的完整记录。
具体到能干什么,dsh 提供两种运行形态(来源:官方文档 + 社区教程):dsh web 起对话式 Web UI,dsh --profile headless "任务文本" 跑一次性任务、执行完打印结果退出,后者对 CI 极其友好。运行模式有四档——标准模式(文件编辑 + Shell + 搜索 + 子 Agent,开箱即用)、PTC 模式(模型生成代码批量编排工具调用,省 token,适合批量爬虫/多文件处理)、极简模式(只留 Shell 和文件编辑器,模型基准测试用)、创造模式(可探查运行时、在线调试插件,插件开发者专用)。推理档位分 low/off、high(默认)、max,官方提示工具链任务约 90% 时间在思考,降档是性价比最高的提速手段(来源:社区教程)。这些能力对于一个刚开源的 v0.1 版本来说,成熟度超出我的预期。
如果你还没系统了解过 AI 工具赛道,建议先看 2026 AI 编程工具与大模型终极指南,建立整体认知。
官方主推的是 npx @deepseek-ai/dsh web 一条命令启动 Web UI(来源:官方 README)。但对想改源码、想二次开发的人来说,必须走源码构建这条路。
环境要求(来源:官方 README + 官方 package.json 的 engines 字段):
^22.19.0 || >=24.0.0,用 nvm 管理版本最省心pnpm@11.7.0源码构建四步走:
git clone https://github.com/deepseek-ai/deepseek-harness.git
cd deepseek-harness
pnpm install
pnpm run build
pnpm dsh web
几点实测注意:
pnpm install 会拉一个巨大的 monorepo 依赖树。这个仓库是 monorepo 结构(apps/ + packages/ + native/),几百个包,首次安装耗时明显,耐心等。pnpm run build 拆成三块:build:lib:host(宿主端)、build:lib:client(客户端)、build:web(前端页面)。如果你只改后端逻辑,可以只跑对应部分,不用每次全量构建。"dsh": "node --import tsx/esm apps/cli/src/bin.ts"。这说明它开发时用 tsx 跑 TypeScript,改完代码重新 build 即可生效,不用先发布 npm 包。如果过程中报错,最常见的就两类(来源:社区安装教程):一是 pnpm install 或 npx 拉不到包,多半是网络问题,换个国内 npm 镜像源再试;二是 dsh web 提示端口被占用,默认就是 3080,换端口启动即可。
首次启动后还要配两样东西才能用(来源:社区安装教程):在 Web UI 的 Settings → Models 里粘贴 DeepSeek API Key(明文存在 ~/.dsh/.credentials.yaml),然后点击 “Choose workspace” 选一个本地项目目录作为 Agent 的操作空间。没选工作区之前,会话输入框是不可用的,这是 dsh 刻意设计的——它不想让你在没有明确操作边界的时候乱跑。
想验证源码构建是否成功,不用非得开 UI——headless 模式更直接:pnpm dsh --profile headless "用一句话介绍你自己",能打印出回复就说明整条链路通了(来源:社区教程)。这个模式对 CI 也很实用,可以把 dsh 接进流水线跑代码检查、批量任务。
另外补一个我个人的想法:dsh 不一定只能接 DeepSeek 的 API——它把模型适配器做成插件,理论上能接任何兼容 OpenAI 协议的模型(来源:官方 README 插件机制)。我本地跑着 Ollama,后面还想试试能不能把 qwen2.5 接进来当后端,彻底免掉 API 费用。这个等模型适配器插件成熟了再验证,先记一笔。
重点来了。很多人以为 14.7 万 star 的项目会有现成的桌面 app,我翻了官方仓库,apps/ 目录下只有 cli 和 web 两个应用,没有 electron、没有 tauri、没有 desktop(来源:官方 GitHub 仓库结构)。
官方设计哲学很明确:Web UI 跑在 localhost:3080,“浏览器就是桌面端”。社区里流传的所谓"DeepSeek Harness 桌面版",基本都是个人用 Electron/Tauri 包的一层壳,非官方产物、不增加任何 Harness 能力、还可能版本滞后(来源:社区搜索结果汇总)。
社区那些桌面壳还有个共同问题:它们大多固定在某个老版本上,而 dsh 是 developer preview,两三周就能变好几轮,包装壳升级不及时,等你发现的时候界面和功能已经跟上游对不上了。与其用别人的壳,不如自己包一个——反正就几十行代码,还能随时跟上游走。这也侧面说明:官方不做桌面端,未必是能力问题,而是取舍——把桌面端这个生态位留给社区和第三方去填。
我作为程序员的看法:官方不做桌面端有其合理性——Web UI 开发效率高、跨平台零成本、热更新方便,还省掉了 Electron 那 100MB+ 的安装包负担。但对一部分人来说,浏览器的体验确实不够"桌面":没有独立窗口、没有任务栏图标、每次都要手动开终端敲 dsh web 再切到浏览器。这时候自己包一层 Electron 壳,价值就出来了。
我的打包思路很简单:官方 dsh web 会起一个 localhost:3080 的 Web 服务,我用 Electron 开一个 BrowserWindow 加载这个地址,窗口关闭时自动清理 dsh 进程。这样得到一个双击即用、带任务栏图标的桌面 app,完全不需要改动 harness 源码。
前置准备,建一个空的 Electron 项目:
mkdir dsh-desktop && cd dsh-desktop
npm init -y
npm install --save-dev electron electron-builder
写 main.js(完整可运行):
const { app, BrowserWindow, shell } = require('electron');
const { spawn } = require('child_process');
const http = require('http');
let win = null;
let dsh = null;
// 后台启动 dsh web 服务
function startDsh() {
dsh = spawn('npx', ['@deepseek-ai/dsh', 'web'], {
stdio: 'ignore',
detached: true,
});
dsh.unref();
}
// 轮询等待 3080 端口就绪,避免窗口白屏
function waitPort(port, cb, retry = 30) {
const req = http.get({ host: '127.0.0.1', port, timeout: 1000 }, (res) => {
res.destroy();
cb();
});
req.on('error', () => retry > 0 && setTimeout(() => waitPort(port, cb, retry - 1), 1000));
req.on('timeout', () => req.destroy());
}
function createWindow() {
win = new BrowserWindow({
width: 1280,
height: 820,
title: 'DeepSeek Harness',
autoHideMenuBar: true,
webPreferences: { contextIsolation: true, nodeIntegration: false },
});
win.loadURL('http://127.0.0.1:3080);
// 外部链接交给系统浏览器打开,避免在 app 里乱跳
win.webContents.setWindowOpenHandler(({ url }) => {
shell.openExternal(url);
return { action: 'deny' };
});
}
app.whenReady().then(() => {
startDsh();
waitPort(3080, createWindow);
});
app.on('window-all-closed', () => {
if (dsh) dsh.kill();
if (process.platform !== 'darwin') app.quit();
});
代码拆解一下(示例,标准 Electron 流程):
spawn('npx', ['@deepseek-ai/dsh', 'web']) 在后台拉起 dsh 服务,detached: true + unref() 让子进程独立于 Electron 生命周期waitPort 每隔 1 秒探测 3080 端口,服务就绪后才创建窗口,这一步是关键——不轮询的话窗口会白屏setWindowOpenHandler 拦截新窗口,外部链接一律丢给系统浏览器,防止在桌面 app 里弹出一堆子窗口三个技术细节值得展开:
第一,安全配置。 webPreferences 里我特意设了 contextIsolation: true 和 nodeIntegration: false。虽然这里加载的是本地受信任的 Web UI,但保持默认安全配置是好习惯——万一以后加载第三方页面,也不至于直接暴露 Node 能力。
第二,为什么不 loadFile 打包静态页面,而是走 localhost:3080 端口? 因为 dsh 的核心是 host 端进程——文件系统、Shell、沙箱权限全跑在服务进程里,UI 只是一个前端壳。你把前端静态化打包了,后端能力就断了。理解"为什么是包 Web UI 而不是打包静态站",是搞懂整个方案的关键。
第三,进程清理。 dsh 进程我用 detached: true 拉起,并在窗口全部关闭时 kill(),避免 Electron 退了还残留一个 3080 端口进程占着,下次启动冲突。
本地先验证:npx electron .,能弹出窗口并加载出 dsh 界面就成功了。确定没问题后,用 electron-builder 打包成安装包,在 package.json 里加 build 字段:
{
"name": "dsh-desktop",
"version": "1.0.0",
"main": "main.js",
"scripts": {
"start": "electron .",
"dist": "electron-builder"
},
"devDependencies": {
"electron": "^33.2.0",
"electron-builder": "^25.1.8"
},
"build": {
"appId": "com.sky.dsh-desktop",
"productName": "DeepSeek Harness",
"files": ["main.js", "package.json"],
"directories": { "output": "release" },
"win": { "target": "nsis" },
"mac": { "target": "dmg" },
"linux": { "target": "AppImage" }
}
}
打包命令:
npx electron-builder --win # Windows NSIS 安装包
npx electron-builder --mac # macOS DMG
npx electron-builder --linux # Linux AppImage
这里要多说一句:我折腾过不少 AI 工具,nanobrowser 评测 里那种开源工具往往把"本地运行"当卖点,而 Qwen 本地 API 开发指南 讲的是本地大模型 API 的坑。dsh 的桌面壳其实和它们是同一类问题:工具跑起来了只算一半,好用才是另一半。
坑 1:Node 版本不够。 官方要求 22+,我之前 nvm 默认还是 18,一跑 pnpm install 直接报 engines 不满足。用 nvm install 22 && nvm use 22 切过去就好了。
坑 2:pnpm 版本不对。 官方锁定 pnpm@11.7.0,我全局的 pnpm 是旧版 9.x,解析 lockfile 报错。corepack enable 之后让仓库自带的 packageManager 字段生效,才装得进去。顺带一提,如果之前装过 pnpm 又想验证版本,pnpm --version 看一眼就明白。
坑 3:首次 build 特别慢。 monorepo 几百个包 + 部分原生模块编译,首次全量构建十几分钟起步。想省时间就只 build 自己改的那一端(host 或 client)。
坑 4:Electron 窗口白屏。 第一次写没做端口探测,窗口先出来、dsh 服务还没起好,一片白。加 waitPort 轮询后解决。这是所有"Electron 包 Web 服务"类项目的通病。还有个隐蔽变体:服务起来了但 API Key 没配,页面会停在设置页而不是白屏——排查时先分清是"服务没起"还是"配置没配",别在错误的坑里打转。
坑 5:打包体积大。 electron-builder 打完的安装包轻松 100MB+。介意体积的可以评估 Tauri(Rust 核心、包小一个数量级),但要装 Rust 工具链,二次集成成本高。我图省事选的 Electron。
坑 6:dsh 升级可能有 breaking change。 developer preview 阶段升级可能改配置格式、插件接口,桌面壳里 npx @deepseek-ai/dsh 会自动拉最新版,建议在 Electron 里固定版本号,别让它悄无声息升级。具体做法是把启动命令写成 npx @deepseek-ai/dsh@0.1.0-rc.6 web 这种带版本号的写法,升级时手动决定,心里有数。
先给观点:dsh 值得每个关注 Agent 框架的开发者上手玩一玩,但官方确实没有桌面端,想要桌面体验就得自己包一层——我用 Electron 大概半小时就搞定了,这个投入是值的。
适合打包桌面端的人:
不适合、直接用 Web UI 的人:
我的建议:先跑 npx @deepseek-ai/dsh web 确认 dsh 适合你的工作流,再决定要不要包桌面壳。别为打包而打包——工具选型这件事,适合你的才是最好的。
最后补一句实话:我前前后后折腾了大概半天——编译一个多小时(大部分时间在等 install 和 build),写 Electron 壳半小时,修白屏和进程残留又花了点时间。整个过程不算轻松,但对一个刚开源的 14.7 万 star 项目来说,文档和架构质量已经算良心了。等它过完 developer preview、API 稳定下来,这个"本地编译 + 桌面壳"的路线会越来越顺,值得持续关注。
本文参考了以下资料,结合博主个人使用经验进行了二次创作:
- GitHub: deepseek-ai/deepseek-harness — README(14.7 万 Star,2026-08 快照)
- 实在智能:DeepSeek Harness 怎么安装?npx 一键安装到源码构建全流程
- 社区搜索结果汇总:官方无桌面端,社区桌面包装壳均为 Electron/Tauri 非官方产物