从零到打包发布,踩过的坑比写的代码多。
大家好,今天想跟大家分享一下这两天我做的一个小工具——OpenClaw 一键安装器。
起因很简单。OpenClaw 是一个很不错的 AI 聊天工具,但它的安装依赖 Node.js、npm、Git 这些环境,对于不熟悉命令行的朋友来说,6光是配环境就能劝退一大半人。
我就想,能不能做一个桌面小程序,把检测、下载、安装、配置全部自动化,用户双击一下就完事?
说干就干。
技术选型
GUI 框架我选了 CustomTkinter,基于 tkinter 的现代 UI 库,跨平台,颜值还过得去。
打包用 PyInstaller,--onefile --windowed 一个 exe 搞定。
项目结构很简单:主界面 main.py、环境检测 checker.py、依赖安装 installer.py、OpenClaw 安装 openclaw_setup.py,再加一个工具函数文件 utils.py。
五个 Python 文件,分工明确。
第一天:Windows 版
第一天先把 Windows 版跑通了。
环境检测部分,需要检查操作系统版本、Node.js 版本(要求 ≥22.19)、npm、Git、网络连通性、OpenClaw 是否已安装。
每项检测返回一个 CheckResult 对象,包含名称、状态、版本、提示信息和修复动作。
GUI 布局上踩了不少坑。
第一个坑:窗口高度不够
620px 的窗口,控件一多底部按钮就被挤出去了,改到 720px 才显示完整。
第二个坑:日志区域膨胀
fill="both", expand=True 把按钮栏直接顶飞了,改成 fill="x" 就好了。
第三个坑:颜色代码
我用了 #ffffffcc 这种 8 位带透明度的 hex,tkinter 根本不支持,最后改成 #cccccc。
第四个坑:进度条颜色
一开始用了红色(accent 龙虾红),结果用户说看着像出错,赶紧改成蓝色 #3498db,"进行中"的感觉对了。
最得意的是离线打包方案。国内网络连 GitHub 经常超时,我就把 Node.js 的 msi 安装包(32MB)和 Git 安装包(68MB)直接打进 exe 里,打包后 116MB,但完全离线可用。
installer.py 优先读内置文件,找不到才在线下载,保留了后备逻辑。
还做了一个测试模式——通过环境变量 OPENCLAW_TEST_MISSING=npm,node,git 可以模拟组件未安装,方便调试而不用真的卸载 Node.js。
第二天:Mac 版
第二天说做 Mac 版。
本以为照搬就行,结果发现差异还挺大的。
Windows 上用注册表管理 PATH,Mac 上得写 ~/.zshrc。
Windows 用 where 找命令,Mac 用 which。
Windows 弹终端窗口用 cmd /c start,Mac 用 osascript 调 AppleScript。
Windows 管理员权限用 UAC 提权,Mac 用 sudo。
安装器方面,Windows 版内置 msi/exe,Mac 版内置 pkg。Node.js 的 Mac 安装命令是 sudo installer -pkg xxx.pkg -target /。
Git 更简单——macOS 大多预装了 Xcode Command Line Tools,自带 Git,检测到已存在就直接跳过。
字体也得换。Windows 用「微软雅黑」,Mac 上换成「Helvetica Neue」,等宽字体从 Consolas 换成 Menlo。
整体来说,Mac 版的代码结构和 Windows 版一模一样,就是底层实现换了平台 API。
这也证明了当时分文件写的决定是对的——逻辑和平台解耦,移植起来很顺畅。
打包方面,Mac 用 --onedir --windowed 生成 .app bundle,内置安装包用 --add-data="bundled:bundled"(注意 Mac 用冒号分隔,Windows 用分号)。
为了方便分发,还写了一个 build.sh 一键构建脚本,自动下载 Node.js 离线包、安装依赖、打包 .app,傻瓜式操作。
收获
这两天做下来,最大的感受是:跨平台的难点不在逻辑,在细节。
两个版本的核心逻辑几乎一模一样,但 PATH 管理、权限提升、终端弹窗、文件格式这些"脏活累活"才是真正费时间的地方。
如果你也想做跨平台桌面工具,建议从一开始就抽象好平台层——把 utils.py 写好,上层代码就能复用 80%。
项目已经放到 GitHub 上了,感兴趣的朋友可以看看。
有问题欢迎留言交流!