| name | windows-release |
| description | Build, verify, and publish the Windows desktop build (NSIS installer + latest.yml) to the openmausbot-releases repo. 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-releases.
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 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
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:
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-releases 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:
- It installs per-user with no UAC prompt and launches.
- The chat window renders (not the error page). Server logs land in
%APPDATA%\OpenMausBot\logs\server.log.
- 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.
- 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.
Copy-Item release/OpenMausBot-<version>-setup.exe release/OpenMausBot-setup.exe
gh release upload v<version> --repo milind-soni/openmausbot-releases `
release/OpenMausBot-<version>-setup.exe `
release/OpenMausBot-setup.exe `
release/OpenMausBot-<version>-setup.exe.blockmap `
release/latest.yml
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.