This guide is for building Stave locally or contributing changes. If you want to install and use the app, start with the root README and the Install Guide.
- Read AGENTS.md first. It contains repo-specific workflow rules, guardrails, and contribution constraints.
- Runtime: Bun
- Node.js: >= 20. Node 22 LTS is recommended, and the repo pins a version in
.nvmrc. - Native build toolchain:
- macOS: Xcode Command Line Tools (
xcode-select --install) - Linux:
build-essential - Windows: Visual Studio Build Tools 2022 with the Desktop development with C++ workload and Python
- macOS: Xcode Command Line Tools (
- Optional provider setup:
claude auth logincodex login
- Optional language servers:
typescript-language-serverfor TypeScript and JavaScript LSP supportpyright-langserverorbasedpyright-langserverfor Python LSP support
- Bun
- TypeScript
- React 19 + Vite
- Electron + electron-vite
- Tailwind CSS v4
- Monaco Editor
- SQLite via
better-sqlite3 - Playwright
bun installbun install automatically runs a postinstall hook that patches better-sqlite3 for Electron 41 compatibility and rebuilds both better-sqlite3 and node-pty against Electron's ABI.
If you need a web-only install that skips the native Electron rebuild step, use:
SKIP_ELECTRON_REBUILD=1 bun install# Web renderer only
bun run dev
# Browser renderer + local dev bridge server
bun run dev:all
# Electron desktop app
bun run dev:desktop
# Electron desktop app with polling file watching
bun run dev:desktop:pollUse the smallest relevant check set for the change, then run the full gate before opening a PR when appropriate.
bun run typecheckbun testbun run buildbun run build:desktopbun run test:ci
Primary local packaged run:
bun run run:desktop:packagedPackaged run with a timestamped log file:
bun run run:desktop:packaged:loggedPackage targets:
bun run package:desktop:dir
bun run package:linux:dir
bun run package:linux:appimage
bun run package:linux:debIf native modules become out of sync, rebuild them manually:
bun run rebuild:electron-depsbetter-sqlite3 and node-pty are native modules. They are compiled for the host Node.js ABI during install, but Stave runs inside Electron, which ships its own Node runtime and ABI. The repo therefore patches better-sqlite3 for Electron 41 and rebuilds both modules for the installed Electron version.
- Use Conventional Commits for commit messages.
- Keep the root README focused on overview plus common install and setup paths, and move deep technical detail into
docs/. - Use
bunx --buninstead ofnpx. - Run the relevant validation commands before opening a PR.
- For high-risk surfaces such as UI theme tokens, terminal runtime behavior, IPC schemas, Zustand selectors, and React effect or observer logic, follow the guardrails in AGENTS.md.
| Symptom | Likely cause | Fix |
|---|---|---|
NODE_MODULE_VERSION mismatch on launch |
Native modules were compiled for host Node, not Electron | bun run rebuild:electron-deps |
| App crashes or freezes on first persist | Electron rebuild or better-sqlite3 patch did not apply correctly |
bun run rebuild:electron-deps |
Patch signature not found during rebuild |
better-sqlite3 version changed or node_modules is corrupted |
bun install && bun run rebuild:electron-deps |
Build fails with node-gyp errors |
Missing C++ toolchain | Install the platform toolchain listed above, then reinstall |
| macOS repeatedly asks for Desktop, Documents, or Downloads access in development | Electron dev builds change identity frequently, which invalidates stored TCC grants | Grant access in System Settings -> Privacy & Security -> Files and Folders -> Stave, or validate the behavior in a packaged build |
src/renderer app, Zustand store, chat UI, editor surfaces, and client bridgeselectron/Electron main process, preload bridge, provider runtimes, persistence, and IPC handlersserver/browser-only dev bridge serverdocs/stable product, architecture, and developer documentationtests/unit and end-to-end coverage
Good starting points: