Setup
Requirements
- Node.js 24.15.0 (locked in
.nvmrc; usenvm use) - npm
- Native development targets: macOS arm64, Windows x64
- Do not build or run from an SMB/NAS-mounted path — Electron fails to start on mounted volumes (
icudtl.dat not found) and packaged apps cannot run from them either
macOS
- Xcode Command Line Tools (for native module builds)
- Media component builds (only when rebuilding):
scripts/media-build/darwin-arm64.sh(vcpkg, takes hours)
Windows
- Git, PowerShell
- Visual Studio Build Tools: "Desktop development with C++" workload + Windows SDK (required to compile native module
better-sqlite3) - Inno Setup 6 (required when building the Windows installer package
SerpentSetup.exe):- Recommended (no admin rights required): Fetch
Tools.InnoSetupvia NuGet, extractISCC.exeinto%LOCALAPPDATA%\SerpentTools\inno\tools\; - Official installer: Install official Inno Setup 6 and set environment variable
SERPENT_INNO_TOOLSto the directory containingISCC.exe(or add it to systemPATH); - Not needed if only running dev mode (
npm start) or creating portable builds (npm run package).
- Recommended (no admin rights required): Fetch
- Media component builds (only when rebuilding underlying binaries):
scripts/media-build/win32-x64.ps1(vcpkg)
First build
npm ci --registry=https://registry.npmjs.org
npm run rebuild:native
npm start
rebuild:native compiles better-sqlite3 for Electron's ABI and verifies FTS5. On Windows, do not run a bare @electron/rebuild or node-gyp — machine-wide vcpkg MSBuild integration can link against a non-FTS5 sqlite3.dll; the project script disables it.
Media components
npm ci does not install FFmpeg/ffprobe/OpenImageIO. Without them, normal development and image import still work; video thumbnails/proxies fail with FFMPEG_REQUIRED, and EXR/TGA/complex TIFF need OpenImageIO.
Packaged builds use the controlled media bundle (FFmpeg 8.1 LGPL-only + OpenImageIO 3.1.12.0); gates verify provenance and hashes (bundle-lock.json promotion status + source-lock.json version match). For local development you can point at any trusted FFmpeg via SERPENT_FFMPEG_PATH (needs the required filters/encoders; ffprobe in the same directory; GPL builds are local-dev only):
# macOS
export SERPENT_FFMPEG_PATH="$HOME/tools/ffmpeg/ffmpeg"
npm start
# Windows
$env:SERPENT_FFMPEG_PATH = 'C:\tools\ffmpeg\ffmpeg.exe'
npm start
Quit Serpent completely before retrying (single-instance lock; a second npm start does not replace a running process).
Common commands
npm run lint # ESLint
npm run typecheck # tsc --noEmit
npm run test # unit + worker integration (runs in Electron)
npm run test:unit # unit only
npm run test:worker # worker integration only
npm run test:e2e # Playwright E2E
npm start # development launch
npm run start:multi # two instances
Notes
- Tests run under Electron's ABI (
test:worker/testgo throughrun-vitest-with-electron.mjs); afternpm run package, runnpm run rebuild:nativeto restore the dev native module npm startauto-avoids occupied Vite ports