mateclaw/mateclaw-desktop
Joe0720 e79fb00fec
feat(desktop): support remote lite build mode without bundled JRE/JAR (#417)
* feat(desktop): support remote lite build mode without bundled JRE/JAR

Add a dual packaging mode system controlled by the BUILD_MODE env var:

- **local** (default): Full build bundling JRE + Spring Boot JAR, identical
  to the previous behavior.  Supports both embedded local backend and
  remote server connection.

- **remote** (lite): Omits the ~530 MB JRE/JAR resources, producing an
  installer that is ~81% smaller (97 MB vs 523 MB on macOS arm64).  The
  app only supports connecting to a remote server; the "local" option is
  hidden from the splash connection chooser.

Changes:
- Replace static electron-builder.json with dynamic electron-builder.cjs
  that conditionally includes extraResources based on BUILD_MODE
- Add build mode detection at runtime (checks JAR existence) with graceful
  fallback to remote-only mode
- Add IPC handler app:get-build-mode and expose via preload
- Hide "本地运行" option in splash when running a remote build
- Ignore stale 'local' saved config in remote builds
- Add package scripts: package:mac:local, package:mac:remote, etc.
- Add missing build scripts: build.sh, download-jre.sh, build-all-platforms.sh
- Add no-op afterPack hook (trim-playwright-driver.cjs) placeholder
- Add cross-env devDependency for cross-platform BUILD_MODE support

* feat(desktop): add white-label branding system for build-time rebranding

Add a Vite plugin (scripts/branding.cjs) that replaces hardcoded "MateClaw"
strings at build time, enabling white-label/OEM rebranding without modifying
any source code.

Configuration:
- Edit branding.config.json (name, tagline, team, copyright, appId, githubUrl)
- Or set BRAND_* env vars (BRAND_NAME, BRAND_TAGLINE, BRAND_TEAM, etc.)

Usage:
  # Default build (MateClaw brand)
  npm run package:mac

  # Custom brand via env vars
  BRAND_NAME=MyAI BRAND_TAGLINE="Smart AI Helper" npm run package:mac:remote

  # Or edit branding.config.json and build normally
  npm run package:mac:remote

Replacements applied at build time:
- Brand name (window title, About dialog, error messages, console logs)
- Tagline, team name, copyright line
- GitHub repo/issues URLs
- Logo file path
- electron-builder config (productName, appId, artifactName, dmg title, publish repo)

The branding plugin runs in Vite's transform hook, covering the renderer
(App.vue, index.html), electron main process, and preload script.

Server-coupled strings (H2 database name, Spring Boot property names) are
intentionally NOT replaced to avoid breaking backend compatibility.

---------

Co-authored-by: qiaozhipeng <qiaozhipeng@daojia-inc.com>
2026-06-26 09:29:24 +08:00
..
build feat(desktop): open-source the Electron desktop app (build, electron main/preload, renderer, config) 2026-06-25 16:00:39 +08:00
electron feat(desktop): support remote lite build mode without bundled JRE/JAR (#417) 2026-06-26 09:29:24 +08:00
public/logo feat(desktop): open-source the Electron desktop app (build, electron main/preload, renderer, config) 2026-06-25 16:00:39 +08:00
scripts feat(desktop): support remote lite build mode without bundled JRE/JAR (#417) 2026-06-26 09:29:24 +08:00
src feat(desktop): support remote lite build mode without bundled JRE/JAR (#417) 2026-06-26 09:29:24 +08:00
.env.example feat(desktop): open-source the Electron desktop app (build, electron main/preload, renderer, config) 2026-06-25 16:00:39 +08:00
.gitignore feat(desktop): open-source the Electron desktop app (build, electron main/preload, renderer, config) 2026-06-25 16:00:39 +08:00
branding.config.json feat(desktop): support remote lite build mode without bundled JRE/JAR (#417) 2026-06-26 09:29:24 +08:00
CODESIGNING.md feat(desktop): open-source the Electron desktop app (build, electron main/preload, renderer, config) 2026-06-25 16:00:39 +08:00
electron-builder.cjs feat(desktop): support remote lite build mode without bundled JRE/JAR (#417) 2026-06-26 09:29:24 +08:00
index.html feat(desktop): open-source the Electron desktop app (build, electron main/preload, renderer, config) 2026-06-25 16:00:39 +08:00
package.json feat(desktop): support remote lite build mode without bundled JRE/JAR (#417) 2026-06-26 09:29:24 +08:00
pnpm-lock.yaml feat(desktop): support remote lite build mode without bundled JRE/JAR (#417) 2026-06-26 09:29:24 +08:00
README.md feat(desktop): open-source the Electron desktop app (build, electron main/preload, renderer, config) 2026-06-25 16:00:39 +08:00
RELEASE_NOTES_v1.0.101.md feat(desktop): open-source the Electron desktop app (build, electron main/preload, renderer, config) 2026-06-25 16:00:39 +08:00
tsconfig.json feat(desktop): open-source the Electron desktop app (build, electron main/preload, renderer, config) 2026-06-25 16:00:39 +08:00
tsconfig.node.json feat(desktop): open-source the Electron desktop app (build, electron main/preload, renderer, config) 2026-06-25 16:00:39 +08:00
tsconfig.node.tsbuildinfo feat(desktop): open-source the Electron desktop app (build, electron main/preload, renderer, config) 2026-06-25 16:00:39 +08:00
vite.config.ts feat(desktop): support remote lite build mode without bundled JRE/JAR (#417) 2026-06-26 09:29:24 +08:00

MateClaw Desktop

MateClaw 的桌面客户端,基于 Electron 构建,自动集成 JRE 21 和后端服务,实现双击即用。

架构

Electron Shell
├── Splash Screen (Vue 3)     ← 启动加载界面
├── Bundled JRE 21            ← 自带 Java 运行时
├── mateclaw-server.jar       ← Spring Boot 后端 + Vue 前端
└── BrowserWindow → localhost:18088

启动流程: Electron 启动 → 显示 Splash → 用内置 JRE 启动 JAR → 等待后端就绪 → 加载主界面

快速开始

前置要求

  • Node.js 18+
  • pnpm (前端构建)
  • Maven 3.9+ (后端构建)
  • Java 21+ (仅构建时需要,运行时使用内置 JRE)

开发模式

# 1. 安装依赖
npm install

# 2. 构建后端 JAR包含前端资源
npm run setup:jar

# 3. 下载 JRE当前平台
npm run setup:jre

# 4. 启动开发模式
npm run dev

打包发布

# macOS (.dmg)
npm run package:mac

# Windows (.exe)
npm run package:win

# 全平台
npm run package:all

输出在 release/ 目录。

目录结构

mateclaw-desktop/
├── electron/main/        # Electron 主进程Java 生命周期管理)
├── electron/preload/     # 预加载脚本(安全 IPC 桥接)
├── src/                  # Splash ScreenVue 3 加载页面)
├── build/                # 应用图标和 macOS entitlements
├── scripts/              # 构建脚本
│   ├── download-jre.sh   # 下载 Adoptium JRE 21
│   └── build.sh          # 构建前端 + 后端 JAR
└── resources/            # 运行时资源JRE + JAR不提交到 Git

环境变量

桌面应用不需要任何环境变量就能启动——LLM 供应商 Key 在 UI 里加。

以下是可选的环境变量(桌面应用会继承系统环境):

变量 必须 说明
SERPER_API_KEY Google Serper 搜索 API搜索工具暂未迁到 UI
TAVILY_API_KEY Tavily 搜索 API

💡 DashScope / OpenAI / Anthropic / DeepSeek / Kimi / Ollama 等 LLM 供应商 Key 启动后在「设置 → 模型 → 添加供应商」里粘进去,加密存到本地 H2 数据库。

自动升级

应用内置 electron-updater 自动升级,更新产物托管在 GitHub Releases

升级流程:启动时检查 → Splash Screen 底部通知 → 用户点击下载 → 下载完成点击重启 → 自动停止 Java 后端 → 安装新版本

平台 更新包格式 元数据文件 签名要求
Windows NSIS .exe latest.yml 可选(不签名会触发 SmartScreen
macOS .zip latest-mac.yml 必须签名+公证(否则只能手动 DMG 安装)

发布操作手册

第一步:配置 GitHub Token

electron-builder 使用 github provider需要 GitHub Personal Access Token 来创建 Release 并上传产物。

  1. 前往 https://github.com/settings/tokensGenerate new token (classic)
  2. 勾选 repo 权限(需要完整 repo 访问才能创建 Release
  3. 生成后保存 token
# 设置环境变量(建议写入 ~/.zshrc 或 CI Secret
export GH_TOKEN=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

第二步:版本号管理

每次发布前必须更新 package.json 中的 version 字段。electron-updater 客户端通过对比本地版本号和 latest.yml 中的版本号来判断是否有更新。

# 编辑版本号
cd mateclaw-desktop
vim package.json  # 修改 "version": "1.0.0" → "1.1.0"

版本号遵循 SemVer

  • 修复 bug → 1.0.01.0.1
  • 新功能 → 1.0.01.1.0
  • 破坏性变更 → 1.0.02.0.0

第三步:构建并发布

cd mateclaw-desktop

# 一键构建全平台 + 自动上传到 GitHub Releases
export GH_TOKEN=ghp_xxxxxxxxxxxx
bash scripts/build-all-platforms.sh --all --publish=always

这会自动:

  1. 构建后端 JAR
  2. 下载各平台 JRE
  3. 编译前端
  4. 打包 macOSDMG + ZIP和 WindowsNSIS
  5. 生成 latest.ymllatest-mac.yml
  6. 创建 GitHub Draft Release 并上传所有产物

完成后前往 https://github.com/matevip/mateclaw/releases ,找到 Draft Release

  • 填写 Release Notes更新说明
  • 点击 Publish release 正式发布

也可以仅构建特定平台:

bash scripts/build-all-platforms.sh --mac-only --publish=always   # 仅 macOS
bash scripts/build-all-platforms.sh --win-only --publish=always   # 仅 Windows

第四步(可选):手动发布

如果不想用 --publish=always 自动上传:

# 1. 仅构建,不上传
bash scripts/build-all-platforms.sh --all

# 2. 查看生成的产物
ls -la release/
# 产物包括:
#   MateClaw_1.1.0_arm64.dmg           macOS ARM64 安装包
#   MateClaw_1.1.0_x64.dmg             macOS x64 安装包
#   MateClaw_1.1.0_arm64.zip           macOS ARM64 更新包(升级用)
#   MateClaw_1.1.0_x64.zip             macOS x64 更新包(升级用)
#   MateClaw_1.1.0_x64_Setup.exe       Windows x64 安装包
#   MateClaw_1.1.0_arm64_Setup.exe     Windows ARM64 安装包
#   MateClaw_1.1.0_*.blockmap          差分下载支持文件
#   latest.yml                         Windows 更新元数据
#   latest-mac.yml                     macOS 更新元数据

# 3. 在 GitHub 手动创建 Release
#    Tag: v1.1.0
#    上传 release/ 目录中的所有 .exe .zip .dmg .blockmap .yml 文件

注意latest.ymllatest-mac.yml 必须上传,客户端靠它们检测新版本。


macOS 代码签名与公证

macOS 自动升级必须签名+公证,否则 Gatekeeper 会阻止更新后的应用启动。未签名时 macOS 用户只能手动下载 DMG 安装。

证书创建完整指南:首次配置或证书过期时,参见 CODESIGNING.md(含 CSR 生成、证书创建、.p12 导出、公证配置等完整步骤)。

本地签名构建(推荐)

证书安装到本地钥匙串后,不需要设置 CSC_LINKelectron-builder 会自动发现证书:

# 只需设置公证相关变量
export APPLE_ID=your@apple.id
export APPLE_APP_SPECIFIC_PASSWORD=xxxx-xxxx-xxxx-xxxx   # 在 appleid.apple.com 生成
export APPLE_TEAM_ID=XXXXXXXXXX                           # 10 位团队 ID

bash scripts/build-all-platforms.sh --mac-only --publish=always

electron-builder 会自动完成签名 → 公证 → 装订staple→ 上传。

注意:不要设置 CSC_LINK 环境变量,否则 electron-builder 会创建临时钥匙串,可能导致签名卡死。详见 CODESIGNING.md 故障排查章节。

CI/CD 签名构建

CI 环境无本地钥匙串,需通过 CSC_LINK 指定 .p12 文件Base64 编码存入 GitHub Secret

export CSC_LINK=base64_encoded_p12_content
export CSC_KEY_PASSWORD=your_certificate_password
export APPLE_ID=your@apple.id
export APPLE_APP_SPECIFIC_PASSWORD=xxxx-xxxx-xxxx-xxxx
export APPLE_TEAM_ID=XXXXXXXXXX

bash scripts/build-all-platforms.sh --mac-only --publish=always

公证超时处理

如果公证上传超时(deadlineExceeded),可先跳过公证构建,再用 xcrun notarytool 手动公证:

# 1. 去掉公证变量,仅签名出包
unset APPLE_ID APPLE_APP_SPECIFIC_PASSWORD APPLE_TEAM_ID
bash scripts/build-all-platforms.sh --mac-only

# 2. 手动公证(支持断点续传)
xcrun notarytool submit release/MateClaw_*.zip \
  --apple-id your@apple.id \
  --password "app专用密码" \
  --team-id XXXXXXXXXX \
  --wait

# 3. 装订公证票据
xcrun stapler staple release/MateClaw_*.dmg

跳过签名(开发/测试用)

export CSC_IDENTITY_AUTO_DISCOVERY=false
bash scripts/build-all-platforms.sh --mac-only

Windows 代码签名(可选)

未签名的 Windows 安装包会触发 SmartScreen 警告("Windows 已保护你的电脑"),用户可以点击"仍要运行"。签名可消除此警告。

EV 代码签名证书

推荐使用 EVExtended Validation证书可立即获得 SmartScreen 信誉,无需积累安装量。

证书提供商(参考):

配置

# PFX 文件签名
export WIN_CSC_LINK=/path/to/windows-cert.pfx
export WIN_CSC_KEY_PASSWORD=password

# 或使用 signtool需要硬件 token 的 EV 证书)
# 在 electron-builder.json 的 win 节中配置:
# "signingHashAlgorithms": ["sha256"],
# "sign": "./scripts/sign.js"

CI/CD 自动发布GitHub Actions

以下为 GitHub Actions 完整示例,实现 Git tag 推送时自动构建全平台并发布:

# .github/workflows/release.yml
name: Release Desktop

on:
  push:
    tags:
      - 'v*'  # 推送 v1.0.0 等 tag 时触发

jobs:
  release-mac:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: 21

      - name: Build and publish macOS
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          CSC_LINK: ${{ secrets.MAC_CSC_LINK }}
          CSC_KEY_PASSWORD: ${{ secrets.MAC_CSC_KEY_PASSWORD }}
          APPLE_ID: ${{ secrets.APPLE_ID }}
          APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
          APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
        run: |
          cd mateclaw-desktop
          npm install
          bash scripts/build-all-platforms.sh --mac-only --publish=always          

  release-win:
    runs-on: windows-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: 20

      - uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: 21

      - name: Build and publish Windows
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          cd mateclaw-desktop
          npm install
          bash scripts/build-all-platforms.sh --win-only --publish=always          

配置 CI Secrets

在 GitHub 仓库 → Settings → Secrets and variables → Actions → New repository secret

Secret 名称 说明
MAC_CSC_LINK macOS 签名证书 .p12 的 Base64 编码:base64 -i cert.p12 | tr -d '\n'
MAC_CSC_KEY_PASSWORD .p12 证书密码
APPLE_ID Apple ID 邮箱
APPLE_APP_SPECIFIC_PASSWORD App 专用密码
APPLE_TEAM_ID 10 位开发者团队 ID
GITHUB_TOKEN 自动提供,无需手动配置

发布流程CI 方式)

# 1. 更新版本号
cd mateclaw-desktop
vim package.json  # "version": "1.1.0"

# 2. 提交并打 tag
git add -A && git commit -m "release: v1.1.0"
git tag v1.1.0
git push origin main --tags

# 3. GitHub Actions 自动构建并创建 Draft Release
# 4. 前往 GitHub Releases 确认并发布

本地测试自动升级

方式一:开发模式 + dev-app-update.yml

在开发模式下测试 updater 流程(不需要打包):

# 1. 在 mateclaw-desktop/ 根目录创建 dev-app-update.yml
cat > dev-app-update.yml << 'EOF'
provider: generic
url: http://localhost:8080/
EOF

# 2. 构建一个"新版本"的产物
#    先把 package.json 的 version 改为更高版本(如 9.9.9
#    然后构建:
npm run build
npx electron-builder --mac --publish=never  # 或 --win
#    构建完成后把 version 改回原值

# 3. 启动本地文件服务器
cd release && python3 -m http.server 8080

# 4. 另一个终端启动开发模式
cd mateclaw-desktop && npm run dev
# updater 会从 localhost:8080 检查更新并发现"新版本"

开发模式下 quitAndInstall() 不会真正安装,但可验证检查→发现→下载的完整流程。

方式二:打包后端到端测试(推荐)

# 1. 打包 v1.0.0 并安装到系统
# 2. 修改 package.json version 为 v1.1.0
# 3. 重新构建,产物上传到 GitHub Release或本地服务器
# 4. 启动已安装的 v1.0.0,观察完整升级流程:
#    检查更新 → 发现 v1.1.0 → 下载 → 重启安装

发布检查单

  • package.json 版本号已更新
  • 后端 JAR 已构建(npm run setup:jar
  • 各平台 JRE 已下载
  • npm run build 编译通过
  • GH_TOKEN 环境变量已设置
  • macOS 签名证书环境变量已设置(若需要签名)
  • bash scripts/build-all-platforms.sh --all --publish=always 执行成功
  • GitHub Draft Release 已确认发布
  • 在旧版本应用上验证升级通知正常

技术栈

  • Electron - 桌面应用框架
  • Vite + Vue 3 - Splash Screen 构建
  • electron-builder + electron-updater - 跨平台打包与自动升级
  • Adoptium JRE 21 - 内置 Java 运行时