Architecture
Surface UIs, protocol, server, engine, session files — five layers top to bottom.
Architecture
Five layers: surface UIs / protocol / server / engine / session files.
↓ data flow: user input → engine → events → UI
Event model
27 events form the full vocabulary (24 durable / 3 live-only), each carrying three attributes:
- durable
- 24 types. Persisted to JSONL, replayable to rebuild the UI
- live
- 3 delta types. Never persisted, gone after a reconnect
- surface
- 2 types. The model-visible surface — always in model history
The two "projections" differ: each surface folds the event stream into UI state with the same applyEvent reducer, while the engine-side Projector projects model context (surface events → LlmMessage). The protocol layer is runtime code, not type definitions. New events follow the new-event-type flow: type definition → zod schema → classification → reducer unit test → engine emit → doc sync.
Four surfaces
Shared @spark/protocol, platform specifics adapted per surface.
- Web
The primary interactive surface, full feature coverage
React 19 · Vite 7 · Tailwind CSS v4
- Desktop
Local shell, system integration and shortcuts
Electron sidecar · embedded server
- CLI
Terminal-native experience, keyboard only
Ink 7 · Node.js 24
- Mobile
Session viewing and light interaction on mobile
Expo + RN · Taro 4 mini app
Data location
Session data persists as append-only JSONL on the local filesystem — no external database.
# Session data location (packages/engine/src/session/store.ts)
~/.spark/sessions/<cwd-munged>-<sha1-8>/<ISO-timestamp>_<sessionId>.jsonl
# Format: append-only JSONL
# Line 0 is the header (sparkVersion / cwd / createdAt / model)
# Each following line is one event envelope, seq == file line number
# Append-only, never rewritten — the full decision chain is preserved
# Replay = reduce line by line from the top → rebuild the full UI state