npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@andykwok/dsh-desktop

v0.3.2

Published

A Go + WebView2 desktop shell for the DeepSeek Harness Web UI (dsh web). Prebuilt Windows x64 binary bundled in the package; no install script and no runtime download needed.

Readme

dsh-desktop

DeepSeek Harness(dsh web)的 Windows 桌面壳(Go + WebView2)——把 DSH Web UI 装进原生窗口, 而不是丢进浏览器标签页。可作 DSH 插件 bundle 发布,在插件市场(dshmarket)被发现,通过 dsh plugin 或 npm 一键安装、更新。

License: MIT Go Platform GitHub release npm


演示

占位:主窗口加载 DSH Web UI、加载态/错误态示意。


是什么 / 为什么

dsh-desktop 是 dsh web(默认 http://127.0.0.1:3080)的壳,只做这几件事:

  • 内嵌渲染:WebView2 加载 DSH Web UI。
  • 服务生命周期:探测并静默启动/复用/停止 dsh web 后端。
  • 实例认人:识别端口占用者(监听 PID / 镜像路径 / 命令行),只复用与停止本壳自己启动的实例。
  • 单实例防重:重复启动时激活已有窗口并退出。
  • 打包体验:console 子系统构建(GUI 启动时隐藏控制台)+ DeepSeek 图标 + 内嵌 loading/error/token 页。

为什么值得用:相比直接 dsh web 在浏览器开标签页,本壳给你一个独立的原生窗口、 单实例(不会重复弹窗/堆积标签页)、默认复用已在跑的服务(二次启动更快),且 GUI 启动时不闪黑色控制台。 同时它对不属于自己的进程零伤害:端口被占不会去"抢"或杀掉占用者,而是换端口;关窗时也只停 归属可证的实例(见实例识别与安全边界)。

边界:它不承载任何 Harness 逻辑——/api 的执行/读写库、workflow 等能力全部由 dsh 负责,本壳只负责把 Web UI 包进 Windows 窗口。

需求与设计见产品 PRD(V1.2)与技术设计。


目录


环境要求

| 场景 | 需要什么 | | :-- | :-- | | 终端用户(下载 EXE) | Windows 10 (1803+) / Windows 11;WebView2 Evergreen 运行时(Win11 预装,Win10 需装) | | 运行时(任何场景) | 全局安装 dsh(npm i -g @deepseek-ai/dsh),且 node、dsh 均在 PATH | | 构建者(从源码) | 额外需要 Go 1.21+(含 CGO)+ GCC/mingw-w64;重建图标时才需要 Node + sharp |


安装与更新

1. GitHub Releases 直接下载(终端用户推荐)

到 Releases 下载 dsh-desktop-win-x64.exe,双击即可。该 EXE 内置自更新:

.\dsh-desktop.exe --check-update   # 检查是否有新版本(输出到控制台)
.\dsh-desktop.exe --update         # 下载并应用,退出(不弹窗体;请重新运行以使用新版本)

说明:这两个命令是纯 CLI 命令,结果直接输出到控制台(stdout/stderr),并同时写入 %LOCALAPPDATA%\dsh-desktop\dsh-desktop.log,不再弹出原生提示框,也不弹窗体。

控制台同步:该 EXE 用控制台子系统构建(不再用 -H=windowsgui),所以 --version/ --check-update/--update 在 PowerShell/cmd 中会像普通命令一样同步等待并内联输出,无副作用。

GUI 启动:不带这些 flag 启动时,程序会 ShowWindow(SW_HIDE) 隐藏双击产生的控制台窗口 (双击有极短暂的黑框闪现);从已有终端(PowerShell/cmd)启动 GUI 时会复用该终端控制台, PowerShell 会阻塞直到窗体关闭,或在已有实例时激活现有窗体并快速退出。

2. npm / dsh plugin(插件市场发现与一键管理)

本项目是 DSH 插件 bundle(npm 包,package.json 声明了 dsh.bundle),可被插件市场 (dshmarket 等)发现并一键安装:

# 通过 npm 全局安装
npm i -g @andykwok/dsh-desktop
dsh-desktop

# 通过 dsh 插件系统安装到某个 profile(会初始化/复用该 profile)
dsh plugin --profile web add github:andykwokatgithub/dsh-desktop

更新:

npm update -g @andykwok/dsh-desktop   # npm 途径
dsh plugin --profile web update          # dsh 插件途径(自动激活升到新版本的 bundle)

注:dsh plugin add github:... 会安装 git 源并运行包的脚本;pnpm 可能要求先在 profile 的 pnpm-workspace.yaml 的 allowBuilds 里放行本包,命令失败时按 pnpm 提示操作即可。 npm 途径安装后,命令是 dsh-desktop(不带 .exe),没有 install 脚本——预编译 EXE 已内置, 首次运行 dsh-desktop 时自动拷贝到 %LOCALAPPDATA%\dsh-desktop\dsh-desktop.exe(不在 PATH)并启动, 不联网。

3. 从源码构建(贡献者)

见构建。


快速上手

# 通过 npm / dsh plugin 安装后,命令是 dsh-desktop(不带 .exe):
dsh-desktop

# 直接使用从 GitHub 下载或本地构建的 EXE:
.\dsh-desktop.exe

npm 安装后,真正的二进制在 C:\Users\<你>\AppData\Local\dsh-desktop\dsh-desktop.exe,并不在 PATH 上;dsh-desktop 命令会把它拷贝到位并启动。想直接双击/引用它,可用上面这个路径。

典型场景:

  • 冷启动(服务未跑):自动 dsh web --no-open 拉起服务,先显示加载态,健康后再跳转 UI。
  • 热启动(服务已在跑,且是本壳启动的):健康校验通过后直接复用,快速进入(≤3s)。
  • 认证失效自愈(自有实例的 cookie 失效/过期):自动停掉该自有实例并以新 token 重新拉起, 不把用户留在 401 页面上;非本壳实例不会被停,只转 token 输入页。
  • 附着别人的实例(端口上是你自己 dsh web 起的实例):先按持久化 cookie 直接进入;若取不到 验证(cookie 失效/过期)则显示 token 输入页——把 dsh web 打印的整条认证 URL(或裸 token) 粘进去即可附着,也可以点"改用本应用自己的实例"在 ≥10000 端口自建一个。
  • 端口被别的进程占用(非 dsh):不动占用者,自动在 10000-65535 里挑一个空闲端口自建, 占用者身份写入日志。
  • 重复启动(窗口已存在):激活已有窗口并置顶(即使最小化),新进程立即退出。

所有交互(加载/错误/token/更新询问)都由窗口内的本地 HTML 页承载,由 Bind 桥接回调 Go。 参数/配置错误一律走控制台(stderr,exit code 2,同时写入 %LOCALAPPDATA%\dsh-desktop\dsh-desktop.log),不弹原生对话框——参数写错的人一定是在终端/shortcut 里发起的,错误就该留在他看的那个终端里。原生 MessageBox 只保留给窗口创建前的非命令行失败 (单实例/建窗),窗口创建之后的错误一律显示在页面上(错误原因可注入、可重试)。


配置

命令行 flags(--url --host --port --command --stop-on-exit --devtools --context-menu --startup-timeout --poll-ms --width --height --title --version --check-update --update):

| Flag | 默认值 | 说明 | | :-- | :-- | :-- | | --url | (空,自动派生) | 可选覆盖:要附着的 DSH Web UI 地址,可携带启动 token(--url "http://127.0.0.1:34567/?token=…")。未显式给 --host/--port 时,URL 的 host/port 会被采纳;若与显式 --host/--port 冲突则报错。URL 必须含显式端口 | | --host | 127.0.0.1 | 健康探测与 spawn 的绑定 host(校验阶段即拒绝 0.0.0.0) | | --port | 3080 | dsh web 的监听端口(1-65535);被非 dsh 进程占用时自动改用 10000-65535 的空闲端口 | | --command | web | 要 spawn 的 dsh 子命令(web = --profile web 别名) | | --stop-on-exit | false | 关闭窗口时是否同时停止 dsh 服务(默认保留,二次启动更快)。只停本壳自己的、归属可证的实例(含本壳上一次运行启动的实例);附着或他人启动的实例永不停止 | | --devtools | false | 开启 WebView2 开发者工具(安全默认:关闭) | | --context-menu | true | 保留 WebView2 默认右键菜单(默认开启;如需禁用传 --context-menu=false) | | --startup-timeout | 30 | 等待服务就绪的超时(秒,须>0) | | --poll-ms | 500 | 健康校验轮询间隔(毫秒,须>0) | | --width | 1200 | 窗口宽度(须>0) | | --height | 800 | 窗口高度(须>0) | | --title | DeepSeek Harness Desktop {version} | 窗口标题(仅用于显示;单实例定位不依赖标题)。默认带 {version} 占位符,展开为运行时版本(如 DeepSeek Harness Desktop 0.3.2);自定义标题不含占位符时原样显示,需要显示版本就自己写上 {version} | | --version | false | 打印版本并退出 | | --check-update | false | 检查 GitHub Releases 是否有新版本并退出 | | --update | false | 下载并应用最新版本,然后退出 |

参数校验:--host/--port/--width/--height/--startup-timeout/--poll-ms/--url 在启动前做语义校验, 值非法即在控制台报错并退出(exit code 2,写入 %LOCALAPPDATA%\dsh-desktop\dsh-desktop.log), 既不弹原生对话框、也不开窗口。错误只打印一次且跟随系统语言(中文/英文),未知 flag 会附带 最接近的建议,随后是该语言的用法,例如:

$ dsh-desktop --updaetg
配置错误: 未知参数 --updaetg(是否想用 --update?)
用法: dsh-desktop [选项]

选项:
  --check-update            检查 GitHub Releases 是否有新版本并退出
  --command                要启动的 dsh 子命令 (web)  (默认 web)
  ...

同类消息还有 参数 --port 的取值 "abc" 无效、参数 --port 缺少取值、参数 --port 必须在 1-65535 之间, 当前为 70000 等;英文系统下分别是 unknown flag --updaetg (did you mean --update?)、 invalid value "abc" for flag --port、flag --port needs an argument、--port must be between 1 and 65535, got 70000。 规范写法为双横杠 --flag;Go 的 flag 包同时兼容单横杠 -flag 输入。

--help 文案跟随系统语言:优先取 LC_ALL/LC_MESSAGES/LANG,未设置时回退 Windows 用户界面 语言(GetUserDefaultUILanguage)——中文系统显示中文,其他显示英文。--check-update/--update 的控制台输出同样如此。


实例识别与安全边界

本壳对"端口上的 dsh 是谁起的"分三层判定,结论决定它复用、附着还是避让:

| 层 | 判据 | 命中后的行为 | | :-- | :-- | :-- | | L1 归属记录 | %LOCALAPPDATA%\dsh-desktop\web-endpoint.json:spawnerPid(本壳 spawn 的 cmd.exe 包装器)是本壳直接子进程或仍以记录中的启动时间在运行 ⇒ 肯定是本壳启动的;listenerPid + 进程启动时间(±1s)仍与当前监听者一致也判定为本壳启动的 | 健康则直接复用(带持久化 cookie) | | L2 强证据 | 监听 PID 的命令行含 @deepseek-ai\dsh/deepseek-harness/dsh web/…\dsh\lib\bin.js 等强关键字 | 健康则先按 cookie 附着;取不到验证转 token 输入页 | | L3 弱证据 | 裸 dsh、--port <该端口> 这类弱关键字(本壳自身的 dsh-desktop.exe --port … 也会命中) | 不足以判定为 dsh,只作参考 |

判定与终止的安全约定:

  • 监听者身份来自 Win32 API(GetExtendedTcpTable(TCP_TABLE_OWNER_PID_LISTENER) 取监听 PID、 QueryFullProcessImageNameW 取镜像、NtQueryInformationProcess 取命令行),不解析 netstat 文本、 不 spawn PowerShell/CIM;HTTP 侧认 dsh 的认证边界(200/303,或 401 + 认证栅栏文案), 不是"只看 200"。
  • 终止进程必须有证明:--stop-on-exit 与认证栅栏自愈都走 service.StopOwned。归属是一条血脉, 不是单个 PID:主目标是本壳 spawn 的 cmd.exe 包装器进程树(spawnerPid)——它随实例终生存在, taskkill /T 能连带干掉当前真正服务端口的进程(哪怕服务进程换了 PID、记录里的监听 PID 已过期); 记录中的监听 PID 作为第二目标。终止前必须有证明:包装器是本壳的直接子进程(本次启动),或它仍以 记录中的启动时间在运行(上一次启动,跨会话可证);监听 PID 则以"记录中的启动时间仍一致"为证。 证明不成立就放弃终止并如实记日志——但绝不假装成功:端口上仍有实例而无法证明归属时报 ErrNotOwned,实例已退出则记"无需停止"(宁可不杀,也不误杀)。
  • 任何分支都不终止端口占用者:端口被别人占用时只换端口,不做抢占或清理。
  • token 是凭据:只在页面 → Go → Navigate(?token=…) 之间于内存流转,不落盘、不入日志; 日志只记 host:port 与占用者身份。

构建

推荐(也会内嵌 DeepSeek 图标):

.\build.ps1

或直接构建(默认即 console 子系统,无需 -H=windowsgui):

go build -o dsh-desktop.exe .

版本号可通过 build.ps1 -Version X.Y.Z 或 -ldflags 注入:

.\build.ps1 -Version 1.2.3
go run . -version   # -> dsh-desktop 1.2.3

构建形态:出于让 CLI 命令在 PowerShell/cmd 中同步输出等考量,EXE 用 console 子系统构建 (不再用 -H=windowsgui)。GUI 运行时 main.hideConsole() 会隐藏双击产生的控制台窗口(有极短的 黑框闪现);从已有终端启动 GUI 时复用该终端控制台,PowerShell 会阻塞直到窗体关闭。 参数错误在 hideConsole() 之前就打印并退出,所以终端里一定看得到,不会弹对话框。 webview_go 依赖 CGO,需要本机 Windows + GCC;不能跨平台交叉编译。 运行 dsh-desktop.exe 会真的拉起 dsh web,不要在无 DSH 环境时盲目运行;验证请用 go run . -version 或单测。

应用图标

  • assets/deepseek.ico(16–256px)、assets/deepseek-256.png。
  • tools/make-icon.mjs 用 sharp 从官方 SVG 重新生成 ICO。
  • rsrc_windows_amd64.syso 内嵌图标;build.ps1 在 ICO 更新时自动用 github.com/akavel/rsrc 重建。

目录结构

main.go                         入口(配置→单实例→建窗→启动决策:复用/附着/token/自建;含自更新命令)
internal/appdir/                %LOCALAPPDATA%\dsh-desktop 状态目录(日志/端点记录)
internal/config/                运行配置与 flag;Version 常量;系统语言检测(中文/英文文案)
internal/service/               服务探测/spawn/生命周期;端点归属记录;回退端口;token 解析与校验
internal/procinfo/              端口占用者识别:监听 PID/镜像路径/命令行 + DSH 关键字匹配(纯 Win32)
internal/singleinstance/        互斥体+原生窗口类+激活消息+Win32 封装
internal/update/                GitHub Releases 自更新(校验+下载+应用)
internal/webview/               安全脚本/外链交接/认证栅栏探测 + 页面 Bind 桥接
internal/ui/                    go:embed 的 loading/error/token 页
bin/                            npm 启动器
scripts/fetch-exe.mjs           下载并校验预编译 EXE(npm postinstall)
cordis.patch.yml                DSH bundle patch 层(市场/插件系统识别)
assets/                         应用图标
tools/make-icon.mjs             用 SVG 重新生成 .ico
rsrc_windows_amd64.syso         嵌入图标的资源对象
build.ps1                       一键构建
.github/workflows/              CI 与发版流水线
docs/                           PRD + 技术设计 + 发布指南

贡献与安全

  • 贡献:环境要求、开发命令与提交约定见CONTRIBUTING.md。
  • 安全:漏报私报方式、下载/更新校验与品牌资产关注点见SECURITY.md。
  • 变更日志:见CHANGELOG.md(Keep a Changelog + 语义化版本)。

许可与商标

MIT License(详见LICENSE)。项目内置的 DeepSeek 鲸鱼图标及其品牌元素属于 DeepSeek 方,本许可不授予商标/Logo/品牌资产使用权,相关使用需另行取得品牌方许可。


文档