## Summary One download per need, with fewer duplicate or unused assets: | | Before | After | |---|---|---| | **Linux Electron** | portable `tar.gz` | **`.deb`** | | **Linux Tauri** | `.deb` + AppImage | **AppImage** (self-updating) | | **Windows Tauri** | ZIP wrapping the installer + the same installer as `.exe` | **`.exe`** only | | **Updater signatures** | `latest.json` + separate `.sig` assets | **`latest.json` only** | ### Linux: Electron deb, Tauri AppImage - The Electron deb installs as root, so electron-builder's post-install script gives Chromium's `chrome-sandbox` the `root:root` ownership and `4755` mode that a user-extracted archive cannot. Electron starts **with its sandbox** and without any manual step. This fixes #541 properly. - The package is named `codenomad` and **conflicts with / replaces** the former Tauri deb (`code-nomad`). Both ship `/usr/share/applications/CodeNomad.desktop`, so without this, installing over an existing Tauri deb would fail on the shared file. - The deb declares Electron's full runtime closure. electron-builder's default `Depends` omit `libgbm1` and ALSA, which previously arrived only through Recommends. ALSA is declared as `libasound2t64 | libasound2`, because `libasound2` is a multi-provider virtual package on Ubuntu 24.04. - Debian versions: dev builds (`<stable>-dev-<date>-<sha>`) become `<stable>+dev.<date>.<HHMMSS commit time>.<sha>`, so they install as upgrades after their stable base and in order on the same day; other prereleases keep electron-builder's `~`, which sorts before the release. The workflow rewrites the control `Version` with `dpkg-deb` when it differs; PR and stable builds rewrite a copy to a synthetic dev version and check that fields, files, modes, owners and control members are preserved. - Tauri Linux builds only the AppImage (`tauri build --bundles appimage`). - No unused electron-updater metadata is generated (`publish: null`). ### Windows: installer only - The Tauri NSIS installer is published directly as `CodeNomad-Tauri-windows-x64-<version>.exe`. It is also the signed updater payload, so signed builds upload it once. - The ZIP that wrapped the same installer is no longer published. - The WinGet automation defaults now point to the `.exe`. ### Updater signatures - The updater reads each signature from `latest.json`, never from a `.sig` asset. Staging still verifies every signature and its trusted comment and records it in the receipt, and publication still requires every payload's uploaded digest to match. - Releases no longer carry `.sig` assets, and staging deletes any left on a rebuilt tag by older builds. Rebuilt tags also delete obsolete Electron `tar.gz`, Tauri deb and Windows ZIP assets. ### Docs - **README:** shows the deb and AppImage commands. The AppImage uses the static type2 runtime, so it needs no `libfuse2`; `--appimage-extract-and-run` covers environments without FUSE. The Wayland/NVIDIA command now targets the AppImage. - **BUILD.md, `TAURI_UPDATER.md` and the WinGet guide** describe the new formats. ## Migration note Installing the Electron deb over a Tauri deb switches the app from Tauri to Electron: - `code-nomad` and `codenomad-tauri` are removed, and the launcher becomes `CodeNomad`; - server configuration is shared, but desktop window state is not migrated. Tauri deb users never had in-app updates, so the release notes should say this. The AppImage is their Tauri option. ## Validation - **Electron deb packaging (CI):** checks package, conflicts, replaces and version metadata, the contents, the post-install `chmod 4755` step, the resources/asar smoke checks and `ldd`. - **Electron deb install (CI):** installs on Ubuntu 24.04 **without recommends**, so `ldd` proves the declared `Depends` are enough. It installs over a stand-in `code-nomad` package, then checks that the old package was replaced, the owner of the desktop entry, `/usr/bin/CodeNomad`, `chrome-sandbox` `root:root 4755` and shared libraries. - **Version mapping:** the mapping, the ordering against stable, later releases and same-day builds, and both repack branches were checked with dpkg 1.22.6 on Ubuntu 24.04. The repack keeps the control fields and root ownership. - **Dependencies:** every declared dependency resolves on Ubuntu 24.04, either as a real package or through its t64 provider. - **Updater scripts:** `updater-artifacts.test.mjs` passes, including signature-in-manifest publication with no staged `.sig`. - **Workflow:** the YAML parses. - **Independent review:** no blocker. The major finding (missing deb dependencies) and the minor ones (dev version ordering, stale BUILD.md and README command, unchecked exit codes, unused updater metadata) are addressed. ## Follow-ups outside this PR - **WinGet:** the `WINGET_WINDOWS_ASSET_NAME_TEMPLATE` repository variable still pins the `.zip` name and overrides the new default. Before the next stable release: - update it to `.exe`, or delete it; - check that the automated `winget-pkgs` PR declares a direct `nullsoft` installer without the old ZIP fields, and correct it if not. Until then, a stable release's WinGet job waits for the ZIP and fails without side effects. - **Ubuntu desktop trial:** test the Electron deb on a real Ubuntu desktop.
7.2 KiB
Building CodeNomad Binaries
This guide explains how to build distributable binaries for CodeNomad.
Prerequisites
- Bun - Package manager and runtime
- Node.js 24 LTS - Use the exact release pinned in
.node-versionfor builds and tests - Electron Builder - Installed via devDependencies
Bundled server runtime
Both Tauri and Electron ship a separate Node.js executable for the CodeNomad
server. scripts/prepare-node-runtime.cjs reads the same .node-version pin as
CI, downloads the official target archive, and verifies its SHA-256 before
packaging. Only the executable is bundled, not npm or Corepack. Updating this
pin does not update Electron's internal Node/Chromium, WebView2, the system Node
installation, or the independently managed OpenCode daemon.
For a runtime update, run the server and desktop tests with the pinned Node,
then rebuild and smoke-test the packaged applications on Windows, macOS, and
Linux. Check the upstream Node platform requirements before changing the pin;
Node 24 requires macOS 13.5 or later. Keep both desktop bundle minimum versions
aligned. Keep the version exact rather than resolving latest or lts/* at
build time so release inputs remain reproducible.
Quick Start
All commands now run inside the workspace packages. From the repo root you can target the Electron app package directly:
npm run build --workspace @neuralnomads/codenomad-electron-app
Build for Current Platform (macOS default)
bun run build:binaries
This builds for macOS (Universal - Intel + Apple Silicon) by default.
Platform-Specific Builds
macOS
# Universal (Intel + Apple Silicon) - Recommended
bun run build:mac
# Intel only (x64)
bun run build:mac-x64
# Apple Silicon only (ARM64)
bun run build:mac-arm64
Output formats: .dmg, .zip
Windows
# x64 (64-bit Intel/AMD)
bun run build:win
# ARM64 (Windows on ARM)
bun run build:win-arm64
Output formats: .exe (NSIS installer), .zip
Linux
# Electron Debian package (x64)
npm run build:linux --workspace @neuralnomads/codenomad-electron-app
# Tauri AppImage (x64)
npm exec --workspace @codenomad/tauri-app -- tauri build --bundles appimage
Release formats: Electron .deb installer and self-updating Tauri .AppImage.
Build All Platforms
bun run build:all
⚠️ Note: Cross-platform builds may have limitations. Build on the target platform for best results.
Build Process
The build script performs these steps:
- Build @neuralnomads/codenomad → Produces the CLI
dist/bundle (also rebuilds the UI assets it serves) - Compile TypeScript + bundle with Vite → Electron main, preload, and renderer output in
dist/ - Package with electron-builder → Platform-specific binaries
Output
Build artifacts are generated in package-specific output directories:
packages/electron-app/release/
└── CodeNomad-Electron-linux-amd64-0.18.0.deb
packages/tauri-app/target/release/bundle/appimage/
└── CodeNomad_0.18.0_amd64.AppImage
File Naming Convention
CodeNomad-Electron-{os}-{arch}-{version}.{ext}
CodeNomad-Tauri-{os}-{arch}-{version}.{ext}
- version: From package.json (e.g.,
0.18.0) - os:
macos,windows,linux - arch:
x64,arm64,universal - ext:
zip,exe,app.tar.gz,deb,AppImage
Electron names deb architectures the Debian way (amd64) and Tauri keeps its native bundle filenames. CI renames both to the convention above when preparing release assets.
Platform Requirements
macOS
- Build on: macOS 13.5+ with the required Xcode tools (CI uses macOS 15)
- Run on: macOS 13.5+ (Intel and Apple Silicon; required by bundled Node 24)
- Code signing: Optional (recommended for distribution)
Windows
- Build on: Windows 10+, macOS, or Linux
- Run on: Windows 10+
- Code signing: Optional (recommended for distribution)
Linux
- Build on: Linux x64
- Electron deb: built and installation-tested on Ubuntu 24.04; its post-install step gives
chrome-sandboxthe root ownership and 4755 mode Chromium's sandbox requires, and it replaces the former Tauri deb (code-nomad) - Tauri AppImage: built and tested on Ubuntu 24.04; older distributions are not yet guaranteed
Troubleshooting
Build fails on macOS
# Install Xcode Command Line Tools
xcode-select --install
Build fails on Linux
Install the Electron and Tauri build dependencies documented by their upstream projects. Release builds currently target Linux x64 and produce an Electron Debian package plus a Tauri AppImage.
"electron-builder not found"
# Install dependencies
bun install
Build is slow
- Use platform-specific builds instead of
build:all - Close other applications to free up resources
- Use SSD for faster I/O
Development vs Production
Development:
bun run dev # Hot reload, no packaging
Production:
bun run build:binaries # Full build + packaging
CI/CD Integration
Example GitHub Actions workflow:
name: Build Binaries
on:
push:
tags:
- "v*"
jobs:
build-mac:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
- uses: oven-sh/setup-bun@v1
- run: bun install
- run: bun run build:mac
build-win:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- uses: oven-sh/setup-bun@v1
- run: bun install
- run: bun run build:win
build-linux:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: oven-sh/setup-bun@v1
- run: bun install
- run: bun run build:linux
Advanced Configuration
Edit package.json → build section to customize:
- App icon
- Code signing
- Installer options
- File associations
- Auto-update settings
See electron-builder docs for details.
Brand Assets
images/CodeNomad-Icon.png— primary asset for in-app logo placements and the 1024×1024 master icon used to generate packaged app icons
To update the binaries:
- Run
node scripts/generate-icons.js images/CodeNomad-Icon.png electron/resourcesto round the corners and emit freshicon.icns,icon.ico, andicon.pngfiles. - (Optional) Pass
--radiusto tweak the corner curvature or--nameto change the filename prefix. - If you prefer manual control, export
images/CodeNomad-Icon.pngwith your tool of choice and place the generated files inelectron/resources/.
Clean Build
Remove previous builds:
rm -rf release/ dist/
bun run build:binaries
FAQ
Q: Can I build for Windows on macOS?
A: Yes, but native binaries (e.g., DMG) require the target OS.
Q: How large are the binaries?
A: Approximately 100-150 MB (includes Electron runtime).
Q: Do I need code signing?
A: Not required, but recommended for public distribution to avoid security warnings.
Q: How do I update the version?
A: Update version in package.json, then rebuild.
Support
For issues or questions:
- Check electron-builder documentation
- Open an issue in the repository
- Review existing build logs in
release/