Gemma Chat - (For Windows, Linux, Raspberry Pi): Ollama backend + installers - #28
Gemma Chat - (For Windows, Linux, Raspberry Pi): Ollama backend + installers#28revdarkness wants to merge 6 commits into
Conversation
Initial v0.1.0-win.1 fork release. Replaces the macOS / Apple Silicon MLX-LM
backend with a thin Ollama HTTP client so the app runs on Windows (and
Linux) against any local Ollama daemon.
Backend
- Delete src/main/mlx.ts (Python venv + mlx-lm subprocess manager)
- Add src/main/ollama.ts (HTTP client: locateOllama, pullModel with
streaming progress, warmModel, listLocalModels, chatStream over
/v1/chat/completions). Honors OLLAMA_HOST env var.
- Rewire src/main/index.ts: ensureOllamaRunning() replaces
ensureMLXRunning(); error message points users to ollama.com/download.
Shared types
- AVAILABLE_MODELS now uses gemma3:{1b,4b,12b,27b} Ollama tags.
- DEFAULT_MODEL = gemma3:4b.
- SetupStage retains 'starting-mlx' as a stable IPC name (now means
"warm model into memory") so the renderer StageList keeps working.
Platform glue
- workspace.ts wsRunBash: PowerShell on Windows, /bin/bash elsewhere.
GEMMA_SHELL=bash opt-out for Git Bash users. Deny list extended with
Windows-side destructive patterns (format c:, rd /s /q c:, etc.).
- main/index.ts createWindow: titleBarStyle/vibrancy/trafficLights only
applied on darwin; standard window frame on Win/Linux. Icon now picks
build/icon.ico on win32, build/icon.png otherwise.
- tools.ts: User-Agent now matches the host OS.
- before-quit: stop the workspace HTTP server but leave Ollama (it's a
shared system service).
Build
- electron-builder.yml: add win/nsis x64 target. Installer is
per-machine-optional, opt-in install dir, desktop + start-menu
shortcuts.
- build/icon.ico generated from build/icon.png via png-to-ico.
- package.json: dist:win + dist:mac convenience scripts, updated
description, version 0.1.0-win.1.
Docs
- README rewritten for Windows: Ollama install path, Gemma 3 model
table, npm run dist:win, OLLAMA_HOST + GEMMA_SHELL env vars,
v0.2 llama.cpp roadmap note. Credit to @ammaar for original work.
Supply-chain audit (npm install + npm audit + lockfile/lifecycle
review): no integrity or registry-source issues, all 6 install hooks
belong to legitimate maintainers (electron, esbuild, fsevents,
onnxruntime-node, protobufjs, sharp). 15 advisories are routine
electron + electron-builder transitive noise, addressable later via
electron 42 / electron-builder 26 upgrades.
Typecheck and electron-vite build both pass clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two findings from local Windows smoke-test:
1. Electron 34's embedded Node 20.19 crashes in cjsPreparseModuleExports
when an ESM main process imports the CJS `electron` module. Symptom:
"TypeError: Cannot read properties of undefined (reading 'exports')"
at node:internal/modules/esm/translators on app start. Root cause is
package.json having "type":"module" (needed for the renderer) combined
with the .js extension on the main bundle making Node treat it as ESM.
Fix: force the main + preload bundles to emit as CommonJS with a .cjs
extension via rollup output.format='cjs'. Renderer is untouched (still
ESM, still uses React 19 + Vite as before). Updates:
- electron.vite.config.ts: rollupOptions.output for main + preload
- package.json: "main" -> "./out/main/index.cjs"
- src/main/index.ts: preload path -> "../preload/index.cjs"
2. Ollama now ships `gemma4:latest` (8B Q4_K_M, 9.6 GB). Promote it to
the recommended default since the upstream repo was named for Gemma 4
and the original macOS/MLX path targeted Gemma 4 specifically. The
gemma3:* tags remain as smaller alternatives.
Both fixes verified against gemma4:latest via curl smoke-tests on the
OpenAI-compatible /v1/chat/completions endpoint (non-streaming returns
clean JSON; streaming returns "data: {...}\n\n" SSE blocks ending with
"data: [DONE]" — matches the chatStream() parser shape exactly).
Note (not in code): if you hit this same "cannot read properties of
undefined" crash on a fresh Windows install and the CJS fix doesn't help,
check `echo %ELECTRON_RUN_AS_NODE%` — if set to 1, Electron skips its
native bootstrap and runs as plain Node, which makes require('electron')
return a path string. Common in shells configured for older Electron
tooling or some MCP setups. Unset it for development.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Smoke-tested locally on Windows 11 + Node 20.19. Two follow-up commits pushed to
Verified end-to-end against Happy to split the CJS fix into its own PR if you'd prefer it land independently of the Windows port — it benefits any Node 20.19+ user, including the macOS path. |
Also updated the GitHub repo About / description to mention Windows. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
electron-builder.yml - New `linux` block: AppImage (x64) + .deb (x64, arm64) - arm64 .deb is the right artifact for Raspberry Pi 5 / Pi 4 64-bit OS - .deb declares libnotify4 + libxtst6 + libnss3 runtime deps; Ollama itself is not an apt dep (install separately from ollama.com) - desktop file metadata: Utility category, StartupNotify, MIME handler package.json - New scripts: `dist:linux`, `dist:linux:arm64` README - "Building the Installer" now covers Windows + Linux side-by-side - New Raspberry Pi note: gemma3:1b or gemma4:cloud (Ollama Turbo) are the right model choices on Pi; local gemma4 8B is too slow even on Pi 5 16 GB. The Ollama HTTP client doesn't care whether the model is :cloud or local — it just hits OLLAMA_HOST. - Roadmap updated: removed "Linux build target" (done), added pre-built release artifacts + OLLAMA_API_KEY as next-up items. Source code untouched. The same ollama.ts client works on Windows, Linux, and Mac without conditional logic — only the build target + install instructions differ per platform. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
.github/workflows/release.yml builds installers for all platforms when a vX.Y.Z tag is pushed, then publishes them to a GitHub Release. Matrix: - windows-latest -> dist:win -> NSIS .exe (x64) - ubuntu-latest -> dist:linux -> AppImage (x64) + .deb (x64, arm64) - macos-latest -> dist:mac -> DMG (arm64) Triggers: - push tag v*.*.* -> build + release - workflow_dispatch -> build only (no release; for sanity-checking) Notable choices: - Node 20 (Electron 34's embedded runtime); npm ci for reproducible installs - Typecheck runs before build in every matrix slot — catches type regressions before we ship binaries - electron-builder invoked with `--publish never`; the release job in the second stage does the publishing via softprops/action-gh-release, which handles attach + release-notes generation - CSC_IDENTITY_AUTO_DISCOVERY=false to keep electron-builder from trying to find non-existent signing identities on macOS - Concurrency: cancel-in-progress: false on release.yml so concurrent tag pushes don't race each other and produce half-published releases - artifact retention: 14 days (workflow_dispatch debug builds expire; released artifacts live on the Release page indefinitely) README: new "Pre-built Releases" section above the Roadmap pointing users at the Releases page. Roadmap dropped the "pre-built artifacts" item (done), added code-signing as the next-up item. To cut the first release after this lands: `git tag v0.1.0-win.1 && git push origin v0.1.0-win.1`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
electron-builder's FPM-based .deb packager rejects a bare-string author
with "Please specify author 'email' in the application package.json".
NSIS and DMG packagers don't care. Promote `author` to the object form
{ name, email } using the GitHub noreply email as a no-PII placeholder.
Verified Win + Mac builds succeeded in the dry run (run 26002493516);
this is the only change needed to unblock the Linux matrix slot.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Adds first-class Windows support by replacing the MLX-LM backend with a thin Ollama HTTP client. Mac/MLX path is left untouched in spirit (and could be reintroduced behind a platform check), but this PR is scoped as a Windows-only release line tagged
v0.1.0-win.1.src/main/mlx.ts(Python venv +mlx_lm.serversubprocess manager)src/main/ollama.ts— locate/pull/warm + chat-stream client. Uses Ollama's OpenAI-compatible/v1/chat/completionsso the SSE parser is identical to the original. HonorsOLLAMA_HOSTenv var.src/shared/types.ts—AVAILABLE_MODELSnow usesgemma3:{1b,4b,12b,27b}Ollama tags;DEFAULT_MODEL = gemma3:4bsrc/main/workspace.ts—wsRunBashruns PowerShell on Windows (GEMMA_SHELL=bashopt-out for Git Bash users); deny list extended for Windows destructive patternssrc/main/index.ts— mac-onlyBrowserWindowoptions (titleBarStyle,vibrancy,trafficLightPosition) now guarded byprocess.platform === 'darwin'; icon picks.icoon win32electron-builder.yml— addedwin+nsisx64 target with desktop/start-menu shortcutsbuild/icon.icogenerated from existingicon.pngviapng-to-icopackage.json—dist:win/dist:macconvenience scripts; description updatedThe window-frame and shell choices are platform-conditional, so reintroducing the MLX backend on darwin in a future PR would be additive — none of the mac-only chrome was removed unconditionally.
Why Ollama instead of MLX
MLX is Apple-only. Ollama runs natively on Windows, ships its own GPU acceleration (CUDA / ROCm preview), and exposes the same OpenAI-compatible chat surface the original MLX server already targeted, so the chat-streaming code carried over with zero changes. It also removes the Python venv bootstrap entirely, which is the biggest source of first-run friction on Windows.
A v0.2 will add an optional bundled llama.cpp backend so users don't need to install Ollama separately.
Test plan
npm run typecheck(node + web) passes on Windows 11npm run build(electron-vite) passesnpm run dist:winproducesdist/gemma-chat-0.1.0-win.1-setup.exe(NSIS, x64) — local smokeSupply-chain note
Ran
npm audit+ lockfile-integrity scan + install-hook review on the fork: lockfile is clean (663/663 entries withsha512-SRI hashes, all fromregistry.npmjs.org), six lifecycle scripts present and all attributable to known maintainers (electron, esbuild, fsevents, onnxruntime-node, protobufjs warning-only, sharp). The 15 audit advisories are routine electron 34 / electron-builder 25 transitive noise, addressable vianpm audit fix --forceto bump electron → 42 / electron-builder → 26.Credits
All original design, UX, agent loop, XML tool protocol, live-streaming write logic, and overall product taste are @ammaarreshi's. This PR is a mechanical port for the Windows side and a credit/link added to the README. Happy to split into smaller commits, drop the README changes, or reshape this as a Linux+Windows PR with a runtime backend switch if you'd rather — your call.
🤖 Generated with Claude Code