Architecture
Walkmark is a Tauri 2 desktop app: a Svelte 5 frontend and a Rust backend in one process. Screen capture, AI calls, and file I/O run in Rust; the UI talks to Rust through Tauri commands and events.
High-level flow
Record → frames on disk → edit in UI → Write (AI) → export Markdown/HTML/PDF
- Capture samples a monitor or window, detects meaningful changes, saves PNG frames.
- Storage persists projects as
project.json+frames/*.pngunder app data. - AI runs a two-pass write: outline all frames, then per-step bodies (see AI writing).
- Export renders included steps to Markdown (+ images folder), self-contained HTML, or PDF.
Repository layout
src/ Svelte 5 UI
lib/
store.svelte.ts App state, dialogs, generation progress
api.ts Typed wrappers for Tauri invoke()
components/ Library, editor, settings, export, HUD triggers
src-tauri/src/
lib.rs Command registration, app setup
commands.rs IPC handlers (projects, capture, AI, export)
capture/ Source listing, session, input monitoring, detect
ai/ Prompts, generation orchestration, model catalog
ai/provider/ HTTP clients per provider (gemini, openai, …)
export/ markdown.rs, html.rs, pdf.rs
imaging.rs Resize, encode, burn annotations into frames
storage.rs settings.json, projects, API key files
local.rs Ollama status, model pull/remove
window.rs Main window + recording HUD, global shortcuts
models.rs Shared types and defaults
state.rs AppState (settings, open project, recording session)
Frontend ↔ backend
Commands (request/response)
Examples: list_projects, start_recording, generate, export_document, save_settings.
Defined in commands.rs, invoked from api.ts via @tauri-apps/api/core.
Events (push from Rust)
Examples:
| Event | Purpose |
|---|---|
recording:tick |
Timer, step count, activity meter for HUD |
recording:step |
New frame captured |
recording:stopped |
Session finished |
recording:shortcut |
Global shortcut fired (stop/mark/pause) |
ai:progress |
Write job progress |
ai:step |
Single step finished writing |
ai:done |
Write job complete |
local:pull |
Ollama model download progress |
Subscribed in store.svelte.ts and events.ts.
Capture pipeline
- User picks a CaptureSource (monitor or window) from
xcap. session.rsruns a loop: input events (macOS) + periodic frame diff (detect.rs).- When a step fires, frame is resized to max width from settings and saved as PNG.
project.jsongets a newStepwithframefilename and timestamp.
Manual marks and global shortcuts call the same capture path.
AI pipeline
- Outline pass — all included frame images +
outline_prompt→ title, summary, prerequisites, step titles (JSON schema). - Step pass — for each step: one image + prior step text +
step_prompt→ title + body. - Provider chosen from settings; concurrency from settings (except Ollama = 1).
Prompts live in ai/prompt.rs. Provider-specific HTTP in ai/provider/*.rs.
Export pipeline
- Load project + included steps with rendered frames (annotations applied in
imaging.rs). - Markdown —
.md+images/directory beside it. - HTML — single file, base64 images, inlined CSS.
- PDF —
printpdflayout, A4, page numbers.
Security
- CSP in
tauri.conf.jsonlimits network to provider API hosts + local Ollama. - Asset protocol serves frame PNGs only from
$APPDATA/**. - API keys stored in app data credentials files and OS keychain (
app.walkmark); never uploaded to Walkmark servers.
Adding a provider
- Add variant to
Providerinmodels.rs. - Add catalog entries in
ai/catalog.rs(models, key URL, default base URL). - Implement or reuse HTTP client in
ai/provider/. - Wire
authorize,body,extractinai/provider/mod.rs. - Add provider host to
connect-srcintauri.conf.json. - Add id to
ProviderIdinsrc/lib/types.ts.
See mistral.rs for a recent addition following this pattern.
Tests
pnpm typecheck
cargo test --manifest-path src-tauri/Cargo.toml
tests/wire.rs— provider HTTP against a local stub servertests/live_mistral.rs— optional live test withMISTRAL_API_KEY- Unit tests in
storage.rs,ai/catalog.rs, export helpers