Windows: ship-ready build with repair and uninstall flows#16
Open
HKTITAN wants to merge 2 commits into
Open
Conversation
…ll flows
Brings the existing dist:win pipeline up to ship quality on Windows and
adds first-class repair / uninstall affordances:
- main.ts: use os.homedir() with USERPROFILE fallback in
resolvePaperclipHome() so the ~/.paperclip reuse check works on Windows
(process.env.HOME is empty there).
- main.ts: short-circuit resolveShellPath() on win32 to avoid the unix
shell -lc 'echo $PATH' probe (no behavior change, less log noise).
- main.ts: Help menu gains "Open Application Logs",
"Reset Local Data (Repair)..." and (Windows-only)
"Uninstall Paperclip..." entries that confirm, kill the embedded
server, wipe user data and either relaunch or hand off to the NSIS
uninstaller.
- electron-builder.yml: NSIS receives a custom include with an
"also delete user data" prompt covering %APPDATA%/Paperclip,
%LOCALAPPDATA%/Paperclip and %USERPROFILE%/.paperclip; suppressed
during silent updater runs via ${isUpdated}. Adds desktop +
start-menu shortcuts, stable Paperclip-Desktop-Setup-* /
Paperclip-Desktop-Portable-* artifact names, and
differentialPackage for delta updates.
- package.json: declare pnpm.onlyBuiltDependencies so
@embedded-postgres/windows-x64, electron and sharp run their
postinstall scripts under pnpm 10.
- .gitignore: ignore build/ui-staging/ scratch dir produced by
build-ui.mjs when @paperclipai/ui isn't on npm.
Verified end-to-end on Windows 11: pnpm dist:win produces signed-eligible
NSIS + portable installers (~179MB), the unpacked binary boots embedded
Postgres 18.1, applies all 75 migrations, listens on 127.0.0.1:3100, and
serves the UI. All 29 connection tests pass.
…rver logs The most common Windows install failure was 'Server did not start within 60000ms' but on a clean Windows machine with antivirus scanning every binary, embedded-postgres initdb + 75 migrations regularly takes 90-180s. The error dialog also gave the user no actionable information. This commit fixes both: - SERVER_STARTUP_TIMEOUT_MS: 60s -> 300s. Covers cold-start + initdb + full migration run on Windows 11 with Defender enabled. - validateServerEnvironment(): pre-flight check for the bundled node.exe, the server bundle entrypoint, and write access to ~/.paperclip. Each failure produces a structured dialog that names the missing path and suggests a remediation (antivirus, reinstall, permissions/OneDrive). - tailInnerServerLog(): the bundled @paperclipai/server uses pino with a file destination so its real boot progress and crash traces never hit stdout. We now tail ~/.paperclip/instances/default/logs/server.log and feed lines into the same boot-progress UI + the error dialog tail. - 'Server failed to start' / 'Server crashed during startup' dialogs now include the last 2KB of that log instead of 'did not start in time'. - findNodeBinary(): use R_OK instead of X_OK on Windows (X_OK is just R_OK there); fall back to os.homedir() instead of process.env.HOME; skip the NVM scan on Windows. - windowsHide: true on spawn so the bundled node.exe doesn't flash a console window on every boot. - Distinct 'Applying migrations...' progress step so users on slow disks see motion during the long initdb wait. Also refreshes docs/prds/windows-release.md to record the Open Questions this PR resolved (portable shipped alongside NSIS, per-user install, bundled-node-only runtime, opt-in ~/.paperclip reuse) and adds a new docs/development/windows-troubleshooting.md mapping each pre-flight dialog title to its likely cause and fix. No behavior change on macOS or Linux. Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings the existing
dist:winpipeline up to ship quality on Windows and adds first-class repair, uninstall, and boot-failure diagnostics affordances. Verified end-to-end on Windows 11 —pnpm dist:winproduces working NSIS + portable installers and the unpacked binary boots embedded Postgres + the UI on127.0.0.1:3100.This PR is two commits:
feat(windows): production-ready Windows build with repair and uninstall flows— packaging hardening + Help-menu affordancesfix(windows): extend boot timeout, add install pre-flight, surface server logs— runtime reliability + supportabilityChanges
Windows runtime fixes (
src/main.ts)resolvePaperclipHome()now usesos.homedir()withUSERPROFILEfallback. The previousprocess.env.HOMEis empty on Windows, which broke the~/.paperclipreuse check (it would join an empty string and end up checking a relative path).resolveShellPath()short-circuits onwin32to avoid the unix$SHELL -lc 'echo $PATH'probe. Previously this just failed silently in the try/catch — now it's explicit.findNodeBinary()usesR_OKinstead ofX_OKon Windows (whereX_OKis justR_OKanyway), usesos.homedir()properly, and skips the NVM directory scan onwin32.startServer()spawns withwindowsHide: trueso the bundlednode.exeno longer flashes a console window on every boot.detached: !isWindows— never detached on Windows because there are no process groups there and orphaned postgres children would survive parent crashes.Boot reliability + diagnostics
SERVER_STARTUP_TIMEOUT_MS: 60s → 300s. This was the single most common Windows install failure. On a clean Windows 11 machine with Defender enabled, embedded-postgresinitdb+ 75 schema migrations regularly takes 90–180s. The old 60s deadline timed out users in the middle of a successful boot.validateServerEnvironment()pre-flight. Before spawning, we verify (a) the bundlednode.exeexists and is readable, (b) the server bundle entrypoint exists, and (c)~/.paperclip(oruserData) is writable via a write-probe. Each failure produces a structured dialog that names the exact missing path and suggests a fix (antivirus quarantine, reinstall, OneDrive sync conflict, permissions).tailInnerServerLog(). The bundled@paperclipai/serveruses pino with a file destination, so almost nothing useful reaches the spawned child's stdout. We now poll-tail~/.paperclip/instances/default/logs/server.logand feed lines into both the boot-progress UI and the error-dialog tail.initdbwait.In-app repair / logs / uninstall
New Help menu entries:
%APPDATA%/Paperclipin Explorer.userData+~/.paperclip, and relaunches the app.NSIS uninstaller polish (
build/installer.nsh,electron-builder.yml)%APPDATA%/Paperclip,%LOCALAPPDATA%/Paperclip, and%USERPROFILE%/.paperclip. Defaults to No and is suppressed during silent updater self-replace via${isUpdated}so updates don't accidentally wipe data.Paperclip-Desktop-Setup-${version}.exeandPaperclip-Desktop-Portable-${version}.exe(the priorPaperclip Desktop Setup 3.2.0.exehad spaces, which is awkward for download URLs and CI scripts).differentialPackage: truefor delta updates on the NSIS channel.Documentation
docs/prds/windows-release.md— converted the Open Questions section into a Resolved Decisions subsection that records what the PR actually shipped (portable alongside NSIS, per-user install, bundled-node-only runtime, opt-in~/.paperclipreuse, repair/uninstall affordances). Slimmer remaining Open Questions list now focuses on signing, EV vs OV, and MSI/Store.docs/development/windows-troubleshooting.md(new) — support-oriented guide covering log locations, the repair and uninstall flows, and a table mapping each pre-flight error dialog title to its likely cause and fix.Build hygiene
package.jsondeclarespnpm.onlyBuiltDependenciesfor@embedded-postgres/windows-x64,electron, andsharp. Under pnpm 10 their postinstall scripts are blocked by default; this whitelists them sopnpm installproduces a working tree without manualpnpm approve-builds..gitignoreignoresbuild/ui-staging/(scratch dir created bybuild-ui.mjswhile@paperclipai/uiisn't on npm).Auto-update
Already wired via
electron-updaterandpublish: githubinelectron-builder.yml; no changes needed. The artifact-name change keepslatest.ymlin the same path, so existing update channels keep working once a Windows release is cut. The portable channel is intentionally update-free.Test plan
pnpm test:connections— 29/29 pass on Windowspnpm build— clean (tscstrict mode)pnpm dist:win— produces NSIS installer (~179 MB) + portable (~178 MB) +latest.yml+.blockmapfindNodeBinary()resolves the bundlednode-bin/node.exeandextraResourcespacks the win-x64 server bundle correctlynode.exe→ "Bundled Node.js runtime is missing" dialog with correct path; chmod-removed write on%USERPROFILE%\.paperclip→ "Local data directory is not writable" dialogHelp → Reset Local Dataconfirms, stops postgres, wipes data, relaunches successfullyHelp → Uninstall Paperclipshows confirm, then NSIS prompts for "also delete user data" and respects the choicerelease.ymlworkflow only needs the Azure Artifact Signing secrets documented indocs/development/windows-signing-guide.mdto start producing signed buildsNotes
process.platform === "win32"and the existing tests still pass.release.ymlworkflow already has abuild-windowsjob — this PR makes the artifacts it produces ready to ship.