dsh-launcher
macOS 程序坞一键启动 DeepSeek Harness (DSH) 的快捷启动器 / One-click DSH launcher for macOS Dock
- Stars
- 0
- Language
- Shell
- Created
- Aug 22, 2026
- Updated
- Aug 22, 2026
Introduction
DSH Launcher
中文 | English
在 macOS 程序坞 (Dock) 中一键启动 DeepSeek Harness (DSH) 的快捷启动器。
点击程序坞图标即可: 检测 DSH 服务 → 未运行则后台启动 dsh web → 等就绪后自动打开浏览器。已在运行时则直接打开浏览器, 不会重复启动服务。
特性
- 🖱️ 程序坞一键启动: 原生
.app包, 拖入 Dock 常驻, 点击即用 - 🌐 全局启动: 安装即注册 macOS LaunchAgent —— 登录自启、崩溃自动重启, DSH 后台常驻随时可用
- ⚡ 幂等: 服务已在运行就直接开浏览器, 不重复拉起
- 🔍 Finder 环境兼容: 显式定位
dsh/node(npx 缓存、Homebrew、nvm 等路径自动探测) - 🛑 安全停止: 通过 PID 文件只停自己拉起的实例, 不误伤手动启动的进程
- 📋 日志可查:
~/Library/Logs/DSH/dsh.log(服务日志:dsh-service.log) - 📦 一键安装/卸载: 支持
git clone或curl | bash - 🤖 CI 自动打包: 打 tag 即自动构建
.app并发布到 GitHub Release
快速开始
方式一: 远程一键安装
curl -fsSL https://raw.githubusercontent.com/YunlongL-byte/dsh-launcher/main/install.sh | bash
方式二: 克隆后安装
git clone https://github.com/YunlongL-byte/dsh-launcher.git
cd dsh-launcher
./install.sh
方式三: 下载 Release
到 Releases 下载 DSH-Launcher-macos.zip, 解压后运行其中的 install.sh(或直接把 DSH Launcher.app 拖进 ~/Applications)。
使用
- 打开 Finder →
~/Applications, 把 DSH Launcher 拖到程序坞 - 点击程序坞图标即可启动 DSH 并打开浏览器
- 停止服务: 双击
DSH Stop.command, 或终端执行:
"$HOME/Applications/DSH Launcher.app/Contents/MacOS/DSH" --stop
其他入口:
| 入口 | 作用 |
|---|---|
DSH.command | 双击在终端里启动 |
DSH Stop.command | 双击停止 |
DSH Launcher.app ... --status | 打印运行状态(含全局服务状态) |
DSH Launcher.app ... --install-service | 安装全局服务(登录自启 + 崩溃自动重启) |
DSH Launcher.app ... --uninstall-service | 卸载全局服务 |
DSH Launcher.app ... --start-service | 重新启用已安装的服务 |
全局启动 (登录自启)
install.sh 默认会把 DSH 注册为 macOS LaunchAgent(~/Library/LaunchAgents/local.dsh.launcher.plist), 实现全局启动:
- 🖥️ 登录自启: 开机登录后自动在后台运行
dsh web, 无需手动点击 - 🔄 崩溃自动重启: 服务异常退出后 launchd 自动拉起(端口被其他实例占用时平稳退出, 不会重启循环)
- 🌍 随时可用: 浏览器直接访问
http://127.0.0.1:3080, 或点程序坞图标打开
服务管理(终端执行):
L="$HOME/Applications/DSH Launcher.app/Contents/MacOS/DSH"
"$L" --install-service # 安装并启用全局服务(安装时默认执行)
"$L" --start-service # 重新启用(例如 --stop 之后)
"$L" --stop # 停止: 停用服务 + 停止一次性实例
"$L" --uninstall-service # 彻底移除服务(下次登录不再自启)
"$L" --status # 查看服务与实例状态
说明:
--stop在服务模式下会停用服务(本次生效), 但保留 plist, 下次登录仍会自启; 要彻底关闭自启用--uninstall-service。跳过全局服务安装:
DSH_SKIP_SERVICE=1 ./install.sh。
工作原理
点击启动
├─ 探测 http://127.0.0.1:3080 是否已运行
│ ├─ 是 → open 打开浏览器, 结束
│ └─ 否 → 已装全局服务? → launchctl kickstart 拉起服务
│ └─ 未装服务 → nohup 后台一次性启动: node <dsh> web
│ → 轮询等待服务就绪 (最多 90s)
│ → open 打开浏览器
开机登录 → launchd 加载 LaunchAgent → dsh-launch.sh --serve
├─ 端口已被占用 → 平稳退出 (不冲突, 不重启循环)
└─ 端口空闲 → 前台运行 node <dsh> web (崩溃时 launchd 自动重启)
- PID 管理: 一次性启动时把进程 PID 写入
~/Library/Logs/DSH/dsh.pid; 全局服务模式由 launchd 管理 - 可执行文件定位:
PATH→~/.npm/_npx/*/node_modules/.bin/dsh→ Homebrew → nvm - 端口/命令可调: 通过环境变量
DSH_URL、DSH_OPEN、DSH_LOG_DIR覆盖默认值 - 全局服务: LaunchAgent
local.dsh.launcher指向dsh-launch.sh --serve,RunAtLoad+KeepAlive(SuccessfulExit=false)实现自启与崩溃重启
目录结构
dsh-launcher/
├── install.sh # 一键安装 (支持 curl | bash, 默认注册全局服务)
├── uninstall.sh # 卸载 (含移除全局服务)
├── src/
│ └── dsh-launch.sh # 核心脚本: 启动/停止/状态/全局服务 (App 的实质内容)
├── scripts/
│ ├── build-app.sh # 构建 .app + .command 到 dist/ (本地与 CI 共用)
│ └── make-icon.py # 生成应用图标 (python3 + pillow)
├── assets/
│ └── dsh-icon.png # 图标源图
└── .github/workflows/
└── release.yml # 打 tag 自动构建并发布 Release
开发
# 构建到 dist/ (需要 python3 + pillow; 图标已提交, 无需重绘)
bash scripts/build-app.sh
# 重新生成图标
python3 scripts/make-icon.py assets/dsh-icon.png
发布新版本
git tag v1.0.0
git push origin v1.0.0
GitHub Actions 会在 macOS runner 上自动构建并发布 DSH-Launcher-macos.zip 到 Release。
常见问题 (FAQ)
Q: 启动报 "找不到 dsh 命令"?
先手动执行一次 npx -y @deepseek-ai/dsh 确认 DSH 可用, 再点击启动器。
Q: 想用别的端口或浏览器?
DSH_URL=http://127.0.0.1:9999 DSH_OPEN='open -a "Google Chrome"' "$HOME/Applications/DSH Launcher.app/Contents/MacOS/DSH"
Q: 服务启动失败?
查看日志: cat ~/Library/Logs/DSH/dsh.log, 全局服务模式看 dsh-service.log 与 dsh-service.error.log。
Q: 如何临时停用全局自启(之后还能恢复)?
"$HOME/Applications/DSH Launcher.app/Contents/MacOS/DSH" --stop
# 恢复:
"$HOME/Applications/DSH Launcher.app/Contents/MacOS/DSH" --start-service
Q: 如何彻底关闭登录自启?
"$HOME/Applications/DSH Launcher.app/Contents/MacOS/DSH" --uninstall-service
Q: 如何完全卸载?
./uninstall.sh
# 如需连日志一起删除:
rm -rf ~/Library/Logs/DSH
许可
MIT © YunlongL-byte