在本机跑 Agent 运行时,手机远程审批与托管会话
30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/8/28 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
该插件未发布到 npm,按作者文档从 GitHub 源安装即可(静态检查只覆盖 npm 路径,不代表插件不可用)。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add harness-home/harness-ai-desktop该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)
状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:需留意
是什么
dsh 原生插件 · market
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 68 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
⚠︎ 实装验证未通过(unsupported_dep_spec · 2026/10/19) ——可能是验证环境差异,装前建议到 GitHub 仓库确认最近更新与 issue。
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查需源码安装仓库 package.json 标记 private,未发布到 npm,需从源码安装
展开查看检查明细 ↓
以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。
✗npm 包harness-ai-desktop(未发布到 npm,仅可源码安装)
✓Node 引擎要求 ^22.19.0 || >=24.0.0 · 基线 Node 22.19 满足
✓dsh CLI 依赖要求 catalog:dsh · 最新 0.2.1-rc.2 兼容
✓入口文件main/exports/bin 已声明
源码安装时若 pnpm 拦截 prepare 脚本,按其提示在 pnpm-workspace.yaml 的 allowBuilds 中放行后重跑。
验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/20 04:29:58
🔴 安全扫描发现高危能力自动 · 静态分析源码
v2.7.0🔴 扫描:高危尚无人工评估
静态扫描发现安装期即执行代码,或命令参数由运行时变量拼接(参数来源无法静态判定,从严处理)。
安装时即执行脚本可执行外部命令读写/删除本地文件读取剪贴板或密钥环境变量发起外部网络请求
查看扫描证据(共 47 处,展示前 47 条)
- 执行外部命令来自配置/变量scripts/install-electron.mjs:12
const result = spawnSync(process.execPath, [installer], { stdio: 'inherit' }) - 读取本地文件plugins/windows-pwsh-sandbox/src/index.ts:28
return candidates.find(candidate => existsSync(candidate)) - 发起网络请求scripts/acceptance.mjs:16
const res = await fetch(`${BASE}/api/${method}`, { - 发起网络请求scripts/acceptance.mjs:27
const res = await fetch(`${BASE}/api/respond`, { - 读取密钥环境变量scripts/acceptance.mjs:88
if (!process.env.DSKEY) fail('DSKEY env var missing') - 读取密钥环境变量scripts/acceptance.mjs:89
await call('credentials.set', { ref: 'DEEPSEEK_API_KEY', value: process.env.DSKEY }) - 发起网络请求scripts/app-click.mjs:12
const targets = await (await fetch(`http://127.0.0.1:${port}/json/list`)).json() - 读取本地文件scripts/app-eval.mjs:13
const expression = args[0] === '--file' ? readFileSync(args[1], 'utf8') : args.join(' ') - 发起网络请求scripts/app-eval.mjs:15
const targets = await (await fetch(`http://127.0.0.1:${port}/json/list`)).json() - 读取本地文件scripts/gen-notices.mjs:24
return existsSync(join(dir, 'package.json')) ? dir : undefined - 读取本地文件scripts/gen-notices.mjs:44
const queue = Object.keys(JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')).dependencies ?? {}) - 读取本地文件scripts/gen-notices.mjs:62
const manifest = JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')) - 写入本地文件scripts/gen-notices.mjs:86
writeFileSync(join(root, 'THIRD_PARTY_NOTICES.md'), `# Third-Party Notices - 写入本地文件scripts/generate-icon.mjs:244
mkdirSync(out, { recursive: true }) - 写入本地文件scripts/generate-icon.mjs:245
writeFileSync(join(out, 'icon.png'), renderPng(256)) - 写入本地文件scripts/generate-icon.mjs:246
writeFileSync(join(out, 'icon.ico'), renderIco([16, 24, 32, 48, 64, 128, 256])) - 读取本地文件scripts/runtime-closure.mjs:15
return existsSync(path) ? JSON.parse(readFileSync(path, 'utf8')) : undefined - 读取本地文件scripts/runtime-closure.mjs:15
return existsSync(path) ? JSON.parse(readFileSync(path, 'utf8')) : undefined - 读取本地文件scripts/runtime-closure.mjs:19
const app = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')) - 读取本地文件scripts/runtime-closure.mjs:40
const declared = new Set(Object.keys(JSON.parse(readFileSync(join(root, 'package.json'), 'utf8')).dependencies ?? {})) - 读取本地文件scripts/set-dsh-version.mjs:43
const content = readFileSync(workspaceFile, 'utf8') - 写入本地文件scripts/set-dsh-version.mjs:67
writeFileSync(workspaceFile, lines.join('\n')) - 读取本地文件scripts/smoke-packaged.mjs:14
if (!existsSync(join(unpacked, exeName))) { - 删除本地文件递归scripts/smoke-packaged.mjs:20
rmSync(stage, { recursive: true, force: true }) - 写入本地文件scripts/smoke-packaged.mjs:21
mkdirSync(stage, { recursive: true }) - 执行外部命令来自配置/变量scripts/smoke-packaged.mjs:25
const child = spawn(join(stage, exeName), [], { stdio: ['ignore', 'pipe', 'pipe'] }) - 发起网络请求scripts/smoke-packaged.mjs:37
const res = await fetch(`http://127.0.0.1:${String(port)}/`, { signal: AbortSignal.timeout(2000) }) - 发起网络请求scripts/smoke-packaged.mjs:53
const bundle = await fetch(`http://127.0.0.1:${String(endpoint.port)}/plugins/@harness-ai/${plugin}/client.js`) - 删除本地文件递归scripts/smoke-packaged.mjs:64
rmSync(stage, { recursive: true, force: true, maxRetries: 10, retryDelay: 500 }) - 读取本地文件scripts/smoke.mjs:18
if (!existsSync(command)) { - 执行外部命令来自配置/变量scripts/smoke.mjs:23
const child = spawn(command, args, { stdio: ['ignore', 'pipe', 'pipe'] }) - 发起网络请求scripts/smoke.mjs:31
const response = await fetch(`http://127.0.0.1:${String(port)}/`, { signal: AbortSignal.timeout(2000) }) - 发起网络请求scripts/smoke.mjs:58
const bundle = await fetch(`http://127.0.0.1:${String(endpoint.port)}/plugins/@harness-ai/harness-brand/client.js`) - 读取本地文件src/main/crash.ts:62
return readdirSync(dumpDir()).filter((name) => name.endsWith('.dmp')).length - 读取本地文件src/main/crash.ts:71
const parsed: unknown = JSON.parse(readFileSync(markerPath(), 'utf8')) - 写入本地文件src/main/crash.ts:114
mkdirSync(app.getPath('userData'), { recursive: true }) - 写入本地文件src/main/crash.ts:115
writeFileSync(markerPath(), JSON.stringify(marker), 'utf8') - 读取本地文件src/main/crash.ts:128
if (existsSync(markerPath())) rmSync(markerPath()) - 删除本地文件src/main/crash.ts:128
if (existsSync(markerPath())) rmSync(markerPath()) - 写入本地文件src/main/log.ts:21
mkdirSync(dir, { recursive: true }) - 写入本地文件src/main/log.ts:24
if (statSync(file).size > MAX_LOG_BYTES) renameSync(file, join(dir, 'main.previous.log')) - 读取本地文件src/main/log.ts:24
if (statSync(file).size > MAX_LOG_BYTES) renameSync(file, join(dir, 'main.previous.log')) - 写入本地文件src/main/log.ts:28
stream = createWriteStream(file, { flags: 'a' }) - 读取本地文件src/main/runtime-config.ts:158
if (existsSync(path)) return readFileSync(path, 'utf8') - 读取本地文件src/main/runtime-config.ts:158
if (existsSync(path)) return readFileSync(path, 'utf8') - 读取本地文件src/main/updater.ts:150
if (!existsSync(path)) return undefined - 读取本地文件src/main/updater.ts:152
return readFileSync(path, 'utf8')
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 全包扫描 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis@deepseek-ai/cordis-plugin-group@deepseek-ai/cordis-plugin-include@deepseek-ai/cordis-plugin-loader@deepseek-ai/cordis-plugin-timer@deepseek-ai/dsh@deepseek-ai/dsh-anonymous-user-id@deepseek-ai/dsh-app-boot@deepseek-ai/dsh-atomic-write@deepseek-ai/dsh-authorization@deepseek-ai/dsh-base@deepseek-ai/dsh-bash-local给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
功能亮点
- 本机启动智能体运行时
- 手机远程审批
- 托管会话
Harness AI 桌面客户端——Electron 应用,在回环地址上以进程内方式启动 DeepSeek Harness(dsh)智能体运行时,支持托管会话、远程审批和带门槛的插件市场。
README
由 DeepSeek 最新模型翻译生成English · 简体中文
工作原理 · 功能 · 安全模型 · 构建 · 发版 · 目录结构 · 路线图
harness-ai-desktop 是 Harness AI 的桌面客户端:基于 DeepSeek Harness(dsh)的类 Codex / Claude Code 桌面 Agent 工作台。
Agent 运行时跑在这个应用里、跑在你自己的机器上——就在 Electron 主进程内,只绑定回环地址,不开放任何入站端口。客户端补上的是运行时本身不提供的部分:账号、能跟到手机上的托管会话、远程审批,以及一个前置了供应链闸门的插件市场。
[!IMPORTANT]
开发者预览。 上游运行时处于 developer preview,官方明示会有破坏性变更;本客户端以固定版本跟随。安装包发布在 Releases 页——未做代码签名,每次发布都附 SHA-256 供核对——也可以从源码构建。
展开完整文档(README 剩余 1 节)
English · 简体中文 工作原理 · 功能 · 安全模型 · 构建 · 发版 · 目录结构 · 路线图 harness-ai-desktop 是 Harness AI 的桌面客户端:基于 DeepSeek Harness(dsh)的类 Codex / Claude Code 桌面 Agent 工作台。 Agent 运行时跑在这个应用里、跑在你自己的机器上——就在 Electron 主进程内,只绑定回环地址,不开放任何入站端口。客户端补上的是运行时本身不提供的部分:账号、能跟到手机上的托管会话、远程审批,以及一个前置了供应链闸门的插件市场。 [!IMPORTANT] 开发者预览。 上游运行时处于 developer preview,官方明示会有破坏性变更;本客户端以固定版本跟随。安装包发布在 Releases 页——未做代码签名,每次发布都附 SHA-256 供核对——也可以从源码构建。 工作原理 flowchart LR subgraph machine["你的机器"] direction TB ui["内嵌 dsh Web UI+ Harness AI 插件"] main["Electron 主进程"] dsh["dsh 运行时(同进程)127.0.0.1:43110"] files["工作区文件 · 凭据 · 会话日志"] main --> dsh ui dsh dsh --> files end main -.->|"只出不进"| server["harness-ai-server账号 · 托管会话 · 市场目录"] server -.-> phone["harness-ai-app查看 · 回答 · 审批"] dsh -.->|"密钥取自本机凭据存储"| model["模型服务"] 支撑这张图的三条性质: 1. 运行时不在回环之外监听。 手机端能看到的一切,都是这个客户端主动向外推送的结果;没有任何连接是拨进来的。 2. 壳只经一层窄适配(HarnessAdapter)对接运行时,经本地 /api 对接托管服务,不碰 dsh 内部实现——这样升级上游是改版本号,而不是重写。 3. 我们自己的功能也是插件。 品牌、账号面板、市场面板、原生目录选择器、Windows 沙箱执行器都是叠加在上游 profile 上的 Cordis 插件,用的是和第三方插件同一套扩展机制。 功能 运行时托管 | 同进程启动 | 用官方 bundle 分层组合出桌面 profile,在 Electron 主进程内启动 dsh Host——没有子运行时,也不需要第二个 Node。 | | 回环绑定 | 绑定 127.0.0.1:43110;端口被占用则顺延到下一个空闲端口,最多探测 20 次。 | | 版本钉死 | 所有 @deepseek-ai/ 依赖统一走 pnpm catalog,升级上游是一行改动(pnpm dsh:version),而不是逐条改三十个依赖。 | | Electron 宿主修复 | 上游有两处用 process.execPath 拉起 Node,在 Electron 下等于再开一个应用实例*。两处都在接缝上修好:原生目录选择器 worker 走 child_process 注入,Windows ACL PowerShell 沙箱执行器走 trampoline。 | 账号、托管会话与远程控制 | 登录 | 应用内登录;每台设备有独立身份,可在服务端吊销。 | | 会话托管 | 本地会话事件镜像到 harness-ai-server,同一段对话可在手机端查看并接续。 | | 上传前脱敏 | 密钥形状的字符串在上传之前遮蔽;工作目录命中 denylist 的会话根本不同步;大块字节不走事件通道。 | | 附件 | Agent 产出的图片按内容寻址(sha256:…),走独立通道排在事件之后上传,按账号去重并受服务端配额约束。 | | 远程审批与指令 | 越出工作区的工具调用会先发起审批而不是直接执行——在桌面前处理,或者在手机上处理。桌面离线期间发来的指令由服务端暂存,重连即投递。 | 插件市场与供应链闸门 运行时的权限体系管的是工具调用,不是插件带来的代码。所以所有防线都前移到安装之前: - 每个目录条目上的风险标记:安装期脚本、原生构建、无来源证明、无许可证、低采用率、新包。 - 每次安装前的告知闸门——包括网页经 harness-ai://install?listing= 交接过来的安装——明说插件拥有与客户端相同的访问权限。 - 写入任何文件之前,回注册表复核完整性摘要:目录记录的 integrity 必须仍然对得上。这一步补的正是版本号钉死补不上的洞——同一个版本号可以被重新发布,字节已经变了。 - 显式写出 --ignore-scripts,不依赖某个可能被改动的配置文件。 - 安装完成后扫描实际能力并回报:网络访问、写文件、原生模块。 - 安装日志:每次改动前先把 profile manifest 原文入日志,失败或崩溃后整份还原——只还原 manifest 文本,不删 node_modules。 可靠性 单实例锁 · 上次运行的崩溃审计 · 脱敏后的文件日志 · 系统托盘 · 启动失败时的恢复页(重试 / 打开日志 / 退出) · 以及一个按进度而不是按墙钟计时的启动看门狗(20 秒无进度 / 180 秒绝对上限),免得把慢机器当成卡死。 应用更新 客户端在启动后不久检查一次新版本,之后每 6 小时一次,发现后在后台下载,过程在托盘里可见。绝不背着用户安装。 下载完成时会问你一次: | 选择 | 会发生什么 | | 立即重启并安装 | 马上重启进入新版本。 | | 稍后 | 保留更新,下次退出时装上。 | | 取消 | 保留已下载的文件,但不再自动安装。托盘里随时可以手动装。 | 关掉这个窗口等同于「取消」。你自己发起的检查一定会给答复,包括「已是最新」。 安全模型 | 红线 | 保证 | | 只走回环 | 运行时绑定 127.0.0.1。没有任何入站连接能到达你的机器——服务端不能,手机也不能。 | | 模型密钥不出本机 | API Key 存在本机的 dsh 凭据存储里,永不上传。 | | 上传前脱敏 | 遮蔽与工作目录 denylist 都在客户端执行,被过滤掉的内容托管服务根本收不到。 | | 审批必须显式 | 越出工作区的动作需要人来回答,且每个决定都可审计。 | | 安装必须告知 | 没有闸门就不会安装;网页只能交接一个目录 id,指定不了包名和版本。 | 发现安全问题请看 SECURITY.md。 安装后的配置 有些设置属于网络环境而不属于某个人,改错了也不该重新出一版客户端。这类设置放在安装目录下、与 Harness AI.exe 同级的 harness-ai.config.json 里。改完重启客户端,日志里的 config: plugin registry … 会写明实际生效的值。 | 键 | 默认值 | 用途 | | pluginRegistry | https://registry.npmjs.org/ | 插件市场解析和下载插件所用的 npm registry。公共 registry 慢或不可达时,改指向它的镜像即可,例如 https://registry.npmmirror.com/。 | | serverUrl | https://api.harnessai.io | 本客户端登录、同步托管会话所连的服务端。自托管部署改成自己的地址即可——自己跑服务端不需要自己出一版客户端。 | 指向镜像不会降低市场的门槛:完整性复核会从当前配置的这个 registry 读取,也就是从 tarball 真正会被下载的地方读——镜像给出的字节与目录记录的不一致就直接拒绝,而不是照单全收。但它必须是公共 registry 的镜像:一个用同样的包名提供自家包的私有 registry 过不了这道校验。 文件写坏了也不会让客户端起不来:该值被丢弃、原因进日志、回落到默认值。HARNESS_PLUGIN_REGISTRY 环境变量可以对单次运行覆盖文件里的值。应用更新会把这个文件重写回随包默认值,更新后需要重新改一遍。 从源码构建 前置条件 —— Node ^22.19.0 || >=24、pnpm 11、Windows x64(目前唯一的打包目标),以及一个 DeepSeek API Key(凡是要接模型的环节都需要)。 与移动端、服务端共用的线上契约以 @harness-ai/contracts 从 npm 获取,所以直接克隆本仓库就能装依赖、能构建,不需要工作区里的其它仓库。 pnpm install # postinstall 拉取 Electron 二进制 pnpm typecheck pnpm test # 146 项单测,离线 pnpm dev # 先构建仓内插件,再启动壳 | 命令 | 作用 | | pnpm dev | 生成图标 → 构建仓内插件 → electron-vite dev。 | | pnpm build | main / preload / renderer 与插件的生产构建。 | | pnpm typecheck | tsc --noEmit,必须零错误。 | | pnpm test | Vitest 单测——刻意保持离线且快。 | | pnpm test:e2e | 需要网络或真实 registry 的验证:插件安装、托管附件全链路。 | | pnpm dist:win | 产出 NSIS 安装包到 dist/,前置第三方声明闸门与 afterPack 硬校验。 | | pnpm smoke:packaged | 启动打包产物,断言回环端点、运行时页面与品牌插件。 | | pnpm dsh:version | 一步把所有钉死的 dsh 依赖切到新的上游版本。 | 完整发版清单(含人工步骤)见 docs/acceptance.md。 发版 每次 push 与 PR 都会在 Windows 上跑一遍类型检查、单测与生产构建——客户端实际发布的平台。 发版由 tag 驱动。推一个 v 标签会跑同一道闸门,打出 NSIS 安装包,并连同应用内更新器要读的 latest.yml 与 blockmap 一起发布: git tag v0.1.5 && git push origin v0.1.5 标签必须与 package.json 里的 version 一致,且 CHANGELOG.md 里必须有对应版本的条目——两项都在开始构建之前检查,那段条目会直接成为发布说明。安装包未做代码签名——SmartScreen 会告警,发布说明里带了 SHA-256 供核对。 目录结构 src/main/ Electron 主进程:启动、托盘、更新、崩溃审计、日志、深链 harness/ dsh 接缝——适配层、启动、托管桥、市场与安装闸门 account/ 账号服务与设备身份 src/preload/ 上下文隔离的渲染进程桥 src/renderer/ 包住内嵌运行时 UI 的壳 src/shared/ i18n(en-US / zh-CN)与壳 API 类型 plugins/ brand/ 运行时 UI 内的产品标识(托盘、主题、侧栏) account-ui/ 登录与设备面板 market-ui/ 插件市场面板、风险标记与安装闸门 electron-directory-picker/ 原生工作区选择器 windows-pwsh-sandbox/ Windows ACL 沙箱执行器(已适配 Electron 宿主) scripts/ 图标生成、打包校验、冒烟与验收驱动脚本 路线图 | ✅ 已完成 | 同进程运行时托管 · 账号与设备身份 · 托管会话同步 · 附件同步 · 远程审批与指令排队 · 带安装闸门的插件市场 · Windows 打包 | | 🚧 进行中 | 稳定的更新源——发布物已带 latest.yml,但 feed 地址在分发位置定下来之前仍是占位 | | 📋 计划中 | macOS 打包与代码签名 · 若确有必要,在同一层适配下接入第二种 harness | 参与贡献 欢迎提 issue 和 PR,请先读 CONTRIBUTING.md:提交约定、源码全英文规则,以及涉及上游行为的改动应当如何分级(先插件,补丁层放最后)。 致谢 构建于 DeepSeek Harness(MIT)与 Cordis 之上。打包产物的第三方声明在发版时生成到 THIRD_PARTY_NOTICES.md。 许可 MIT © harness-home
预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
harness-home/harness-ai-desktop
在本机跑 Agent 运行时,手机远程审批与托管会话
相关插件 · 市场 / 管理
插件精选列表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
这是你的仓库?认领条目