Build and verify the Windows desktop build (NSIS installer + latest.yml) for the canonical OpenMausBot release and its legacy updater mirror. Use when cutting a release, shipping a new version to Windows users, or when a Windows user reports they are stuck on an old version. Windows only — does not cover the macOS dmg/notarization flow.
4,081 stars
0 votes
0 copies
0 views
Added October 4, 2026
ai-agentsrustgoswiftshellnodeazuregit
Works with
cli
Security analysis
A96/100
mediumInstalls packages at runtime which could introduce malicious dependencies
Installs into .claude/skills of the current project.
Are you the author of Windows Release?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/milind-soni-windows-release)
---
name: windows-release
description: Build and verify the Windows desktop build (NSIS installer + latest.yml) for the canonical OpenMausBot release and its legacy updater mirror. Use when cutting a release, shipping a new version to Windows users, or when a Windows user reports they are stuck on an old version. Windows only — does not cover the macOS dmg/notarization flow.
---
# Windows release
Ships `OpenMausBot-<version>-setup.exe` and its update feed to
[milind-soni/OpenMausBot](https://github.com/milind-soni/OpenMausBot/releases).
The unified release workflow mirrors the same bytes to the legacy releases
repository for apps installed before the updater migration.
**Scope: Windows only.** The macOS build is a separate flow (dmg + notarytool +
staple) that must run on a Mac. This skill never touches mac artifacts — but see
[Every release ships both](#every-release-ships-both) before you finish.
## Preconditions
- **Run on Windows.** NSIS packaging from macOS needs Wine; don't.
- **Node 24+** (`package.json` `engines`). Node 23 builds fine but pnpm warns on
every step and CI runs 24 — don't debug a runtime oddity on the wrong major.
- **pnpm** via `corepack pnpm`. If `corepack enable` fails with EPERM (no admin),
drop a `pnpm.cmd` shim containing `@echo off` / `corepack pnpm %*` somewhere on
PATH — `package:win` chains `pnpm build && …` and needs bare `pnpm` to resolve.
## 1. Version
Bump `version` in `package.json`. It must match the tag on the GitHub release you
upload to, and it becomes the version electron-updater compares against.
## 2. Build
```powershell
pnpm install
pnpm typecheck
pnpm package:win
```
`package:win` deliberately omits `build:speech` — the dictation helper is a signed
macOS Swift binary and has no Windows counterpart.
Output in `release/`:
| File | Purpose |
|---|---|
| `OpenMausBot-<version>-setup.exe` | the installer |
| `latest.yml` | **the update feed** — see step 4 |
| `OpenMausBot-<version>-setup.exe.blockmap` | differential updates |
| `OpenMausBot-<version>-x64.zip` | portable, not used by the updater |
## 3. Verify before uploading
Three things silently produce a broken app if wrong. Check all three:
```powershell
Test-Path release\win-unpacked\resources\server\index.js # harness server
Test-Path release\win-unpacked\resources\ui\index.html # built UI
Get-Content release\win-unpacked\resources\app-update.yml # feed config
```
- Missing `server/index.js` → `utilityProcess.fork` fails → the 🐭 "Couldn't start
the bot server" page.
- Missing `ui/index.html` → server has nothing to serve → black window.
- `app-update.yml` must point at `milind-soni/OpenMausBot` and, while the
build is unsigned, **must not contain `publisherName`** — electron-updater would
reject every update as untrusted.
Then smoke-test the installer itself. Run it, and confirm:
1. It installs per-user with no UAC prompt and launches.
2. The chat window renders (not the error page). Server logs land in
`%APPDATA%\OpenMausBot\logs\server.log`.
3. The model picker lists at least one provider — this exercises the `.cmd`-shim
resolution in `server/procs.ts`, which only ever runs for real on Windows.
4. No update popup appears on launch. Background check failures are silent by
design; a popup here means that regressed.
## 4. Publish
Upload to the **same tag** as the macOS release for that version, so one release
carries both platforms.
```powershell
Copy-Item release/OpenMausBot-<version>-setup.exe release/OpenMausBot-setup.exe
gh release upload v<version> --repo milind-soni/OpenMausBot `
release/OpenMausBot-<version>-setup.exe `
release/OpenMausBot-setup.exe `
release/OpenMausBot-<version>-setup.exe.blockmap `
release/latest.yml
```
Prefer the repository's **Release** workflow, which builds all platforms from
one pinned commit and mirrors the complete, byte-identical asset set safely.
If this emergency manual path is used, the same four files must also be attached
to the matching draft in `milind-soni/openmausbot-releases`; never replace the
bytes of an already-published asset.
Both names are required, for different consumers:
- **`OpenMausBot-<version>-setup.exe`** is what `latest.yml` references by name and
sha512. The auto-updater downloads exactly this.
- **`OpenMausBot-setup.exe`** is a byte-identical copy that gives the README's
`/releases/latest/download/OpenMausBot-setup.exe` button a stable URL. This
mirrors `OpenMausBot.dmg` sitting beside `OpenMausBot-<version>.dmg`.
### latest.yml is not optional
Without it every installed Windows app 404s on check and stays on its version
forever. It is generated by `package:win` even under `--publish never`.
**Never hand-edit it or carry one forward from a previous build.** It pins the
installer's sha512; a mismatch makes the updater download and then reject the
update, which looks like "updates silently do nothing".
## Every release ships both
A version that exists on macOS but not on this release is a Windows user stuck on
old code with no signal that anything is wrong — the updater reports "up to date"
because `latest.yml` still describes the older build.
So: **whenever a new version goes out, this flow runs too.** If Windows can't ship
for some reason, don't publish the mac-only release under a new version tag either
— or accept that Windows is knowingly frozen and say so in the release notes.
Because the two builds must run on two machines, the tag is the join point: cut the
release, attach mac artifacts from the Mac, attach Windows artifacts from here.
## Known: the build is unsigned
No certificate is configured, so SmartScreen shows "unknown publisher" and users
click **More info → Run anyway**. The README documents this. Auto-update still
works *because* it's unsigned (no `publisherName` to verify against).
If signing is added later, it goes under `win.signtoolOptions` or
`win.azureSignOptions` in `electron-builder.yml` — electron-builder 26 nests these;
there is no top-level `win.certificateFile`. Once signed, keep the certificate
subject stable forever, or list both old and new in `publisherName`; changing it
strands every already-installed user.