A desktop TTRPG GM assistant. Load your own rulebook PDFs, take structured notes, and query an AI agent that answers with source citations.
No cloud dependency, no subscription — the LLM backend is configurable at setup: use a cloud API (OpenAI, Anthropic, OpenRouter) or run locally via Ollama.
- PDF Ingestion — Import TTRPG sourcebooks, rules references, and lore. Extracts text with chapter/section structure preserved.
- RAG Query — Ask your GM questions in natural language. Every answer cites the source page and chunk.
- Structured Notes — Organise campaigns with entities, relationships, and session logs.
- Configurable AI — Bring your own LLM (OpenAI, Anthropic, Ollama) and embedding model.
- Local-First — All data stays on your machine. No accounts, no telemetry.
┌────────────────────────────────────┐
│ Tauri Shell (Desktop UI) │
│ ┌──────────────┐ ┌─────────────┐ │
│ │ Svelte 5 │◄─┤ Tauri IPC │ │
│ │ Frontend │ │ (commands + │ │
│ │ │ │ events) │ │
│ └──────────────┘ └───────┬─────┘ │
├────────────────────────────┼───────┤
│ Rust Backend │ │
│ ┌─────────────────────────▼─────┐ │
│ │ Service Layer │ │
│ │ LlmProvider · VectorStore · │ │
│ │ BlobStore (all via traits) │ │
│ └─────────────────┬─────────────┘ │
│ ┌─────────────────▼─────────────┐ │
│ │ SurrealDB (relational + │ │
│ │ vector + graph, embedded) │ │
│ └───────────────────────────────┘ │
└────────────────────────────────────┘
All external dependencies are behind Rust traits (Arc<dyn LlmProvider>, Arc<dyn VectorStore>, Arc<dyn BlobStore>), making the service layer testable and portable to a server deployment later.
| Tool | Version | Note |
|---|---|---|
| Rust | ≥ 1.95 | Managed by mise |
| Node.js | ≥ 24 | Managed by mise; pinned to LTS in mise.toml |
| pnpm | ≥ 11 | Managed by mise |
| Tauri | ≥ 2.11 | CLI bundled via pnpm; system deps listed below |
This project uses mise to manage tool versions (defined in mise.toml).
# Install mise (macOS / Linux)
curl https://mise.run | sh
# Or via Homebrew: brew install mise
# Activate mise in your shell (add to ~/.zshrc / ~/.bashrc)
eval "$(mise activate)"
# Install all project tools (Rust, Node.js, pnpm)
cd chronacle
mise installNote: Node.js, pnpm, and Rust are pinned per-project by
mise.tomland installed with a singlemise installcommand. No need for rustup, nvm, or npm-ginstalls.
- macOS: Xcode Command Line Tools (
xcode-select --install) - Linux:
libwebkit2gtk-4.1-dev,libgtk-3-dev,libayatana-appindicator3-dev,librsvg2-dev,libssl-dev - Windows: WebView2 (included in Windows 11 / 10 with latest updates)
For full details, see the Tauri prerequisites guide.
# Clone the repository
git clone https://github.com/nunico/chronacle.git
cd chronacle
# Install frontend dependencies (installs the workspace; apps/desktop is a pnpm workspace package)
pnpm install
# Run in development mode (hot-reload frontend + persistent RocksDB backend)
pnpm -C apps/desktop tauri dev --features rocksdb
# Alternatively: mise run dev (uses the same rocksdb feature)
# Build a production release
pnpm -C apps/desktop exec tauri build --features rocksdb
# Alternatively: mise run build (uses the same rocksdb feature)cargo build --workspace # Build all workspace crates
cargo fmt --all && cargo fmt --all --check # Format / check formatting
cargo clippy --workspace --all-targets --all-features -- -D warnings
cargo test --workspace # Unit + integration tests
cargo test -p <crate> -- --nocapture <name> # Single test in a specific crate
cargo llvm-cov --workspace --html # Coverage report (HTML)
cargo audit # Security audit
cargo deny check # License + dependency checkThe workspace's default SurrealDB feature is memory-only, which keeps normal backend builds and
tests fast. Enable the desktop crate's rocksdb feature only when exercising the persistent app
runtime, for example:
cargo test -p Chronacle --features rocksdb --test rocksdb_persistencepnpm -C apps/desktop dev # Vite dev server (standalone)
pnpm -C apps/desktop typecheck # TypeScript type checking
pnpm -C apps/desktop lint # ESLint
pnpm -C apps/desktop test:run # Vitest (CI mode)
pnpm -C apps/desktop test:coverage # With coverage
scripts/ci/acceptance.sh # Playwright backend acceptance testspnpm -C apps/desktop tauri dev --features rocksdb # Dev with persistence
pnpm -C apps/desktop exec tauri build --features rocksdb # Production bundleCI and local validation share three named repository scripts:
scripts/ci/backend-quality.sh— Rust formatting, Clippy, workspace tests, andcargo denyscripts/ci/frontend-quality.sh— Svelte checks, ESLint, and Vitestscripts/ci/acceptance.sh— Playwright backend acceptance tests
Before creating a Chronacle pull request, run the authoritative PR gate successfully from the repository root:
scripts/ci/local-pr.shThis builds the Docker pr-gate target and runs the same three scripts as the pull-request jobs.
BuildKit caches Cargo data, build output, Playwright Chromium, and a shared pnpm store across the
frontend and acceptance stages. The local PR gate intentionally excludes merge-only coverage and
release builds, and the separate real-app tauri-driver UI E2E workflow.
chronacle/
├── Cargo.toml # Workspace root: members = ["crates/*", "apps/desktop/src-tauri"]
├── crates/
│ ├── chronacle-core/ # Dependency traits + DTOs (LlmProvider, VectorStore, BlobStore, EmbeddingProvider)
│ ├── chronacle-db/ # SurrealQL schema + run_migrations
│ ├── chronacle-providers/# Concrete provider impls (SurrealDB, fastembed, OpenAI/Anthropic/Ollama LLM)
│ ├── chronacle-ingestion/# PDF extraction, chunking, ingestion pipeline
│ ├── chronacle-extraction/# Entity extraction, wikilink resolution
│ ├── chronacle-retrieval/ # RAG agent service (chat + cited answers)
│ └── chronacle-domain/ # Campaign, session, collection, custom-provider CRUD
├── apps/
│ └── desktop/ # Svelte frontend + Tauri shell
│ ├── src/ # Svelte 5 + TypeScript frontend
│ ├── src-tauri/ # Rust Tauri backend (commands, AppState, settings_service)
│ │ └── tests/ # Rust integration tests + fixtures
│ ├── tests/e2e/ # Playwright backend E2E + tauri-driver UI E2E
│ ├── package.json
│ └── vite.config.ts
├── docs/ # Architecture docs and ADRs
└── package.json # pnpm workspace root (minimal)
| Layer | Technology |
|---|---|
| Shell | Tauri 2 (Rust + WebView) |
| Frontend | Svelte 5 + TypeScript + Vite |
| Backend | Rust |
| Storage | SurrealDB (embedded, RocksDB) |
| Embeddings | fastembed-rs (local) |
| LLM | OpenAI / Anthropic / Ollama (configurable via traits) |
| pdfium-render |
Copyright © 2026-present Nico Nußbaum.
Code: Licensed under the GNU Affero General Public License v3.0 — see LICENSE.
Brand Assets: The project name "Chronacle", its logos, icons, and trade dress are not covered by the AGPL. They may not be used in modified or redistributed versions without explicit permission. See LICENSE-EXCEPTION.md.
Forks must remove or replace all Brand Assets.