--- name: Dev launcher and scripts type: architecture-map-page slice: 05-core-storage-hotkey-build last_verified: 2026/05/09 --- # Dev launcher and scripts > **Where you are:** [Architecture map](../README.md) → [Core, Storage, Hotkey, Build](README.md) → Dev launcher and scripts **Plain English summary.** Two ways to start Magnotia in development. `run.sh` is the bespoke launcher that starts Vite first and then Tauri (avoiding a Tauri-spawned-second-Vite mess). The `package.json` scripts are the canonical npm-run interface — the same scripts CI uses for the frontend gate. ## At a glance - Files: `run.sh` (636 bytes, +x), `package.json` (1,211 bytes), `package-lock.json` (109 KB). - External tools: `npm`, `npx`, `curl`, `bash` (run.sh); the Node toolchain (package.json scripts). - Consumers: `run.sh` is invoked by Jake on his Monolith. The `package.json` scripts are invoked by both CI (`npm run build`) and developers (`npm run dev`). ## `run.sh` — the local launcher ```bash #!/usr/bin/env bash # Magnotia dev launcher. Starts Vite first, waits for it to bind port 1420, # then runs Tauri without triggering a second Vite instance. # For performance testing use: npm run tauri build set -euo pipefail cd "$(dirname "$0")" export LIBCLANG_PATH=/usr/lib64/llvm21/lib64 printf 'Starting Vite dev server...\n' >&2 npm run dev:frontend & VITE_PID=$! until curl -sf http://localhost:1420 > /dev/null 2>&1; do sleep 0.5; done printf 'Vite ready. Launching Tauri...\n' >&2 cleanup() { kill "$VITE_PID" 2>/dev/null || true } trap cleanup EXIT INT TERM npx tauri dev --config '{"build":{"beforeDevCommand":""}}' ``` ### Why this exists The default `npm run tauri dev` invokes `tauri dev`, which honours `beforeDevCommand` from `tauri.conf.json` and spawns its own Vite. If Vite is already running (eg during interactive iteration), you get two instances racing for port 1420. The launcher solves it by starting Vite explicitly and disabling Tauri's spawn via `--config '{"build":{"beforeDevCommand":""}}'`. ### Steps 1. `set -euo pipefail` — early exit on any command failure or unset variable. 2. `cd "$(dirname "$0")"` — anchor to the repo root. 3. **Hard-codes `LIBCLANG_PATH=/usr/lib64/llvm21/lib64`** — Fedora 41 default LLVM 21 path. **Breaks on Debian / Ubuntu / macOS.** Worth softening to `LIBCLANG_PATH=${LIBCLANG_PATH:-/usr/lib64/llvm21/lib64}` so a developer-set value wins. 4. Spawn `npm run dev:frontend &`; capture PID in `VITE_PID`. 5. Poll `curl -sf http://localhost:1420` every 500 ms until 200 OK. 6. Trap `EXIT INT TERM` to kill the Vite process group on script exit. 7. `npx tauri dev` with `beforeDevCommand` disabled. ### `LIBCLANG_PATH` rationale Bindgen (pulled by `whisper-rs-sys` and `llama-cpp-sys-2`) needs a `libclang.so` at build time. On Fedora's LLVM 21 packaging, the canonical location is `/usr/lib64/llvm21/lib64`. On Debian-family the path is `/usr/lib/llvm-N/lib`; on macOS Homebrew it's `$(brew --prefix llvm)/lib`. The hard-coded value means a clean `git clone` on a non-Fedora machine fails the first build until the developer sets `LIBCLANG_PATH` themselves. ## `package.json` — npm scripts and deps ### Scripts ```json "scripts": { "dev": "npm run dev:frontend", "dev:frontend": "svelte-kit sync && vite dev", "build": "vite build", "preview": "vite preview", "check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json", "check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch", "tauri": "tauri" } ``` - `npm run dev` — frontend only (no Tauri). Useful for pure-UI iteration. - `npm run build` — Vite production build. CI gate. - `npm run check` — `svelte-check` against `jsconfig.json`. CI gate. - `npm run tauri` — passthrough. `npm run tauri dev`, `npm run tauri build`, etc. ### Runtime dependencies - `@tauri-apps/api 2.10.1` — JS bridge to Tauri commands. - `@tauri-apps/plugin-autostart 2.5.1` — autostart on boot. - `@tauri-apps/plugin-dialog 2.7.1` — native file dialogs. - `@tauri-apps/plugin-global-shortcut 2.3.1` — non-Linux hotkey backend (Linux uses our own `magnotia-hotkey` crate, slice 5). - `@tauri-apps/plugin-notification 2.3.3` — toast notifications. - `@tauri-apps/plugin-opener 2.x` — open external URLs. - `@chenglou/pretext 0.0.5` — stylable text preview. - `lucide-svelte 0.577.0` — icon set. - `svelte-i18n 4.0.1` — i18n. ### Dev dependencies - `@sveltejs/kit 2.58.0` + `@sveltejs/adapter-static 3.0.10` + `@sveltejs/vite-plugin-svelte 5.0.0`. - `@tailwindcss/vite 4.2.1` + `tailwindcss 4.2.1` (Tailwind v4, Vite-plugin-driven, no PostCSS config). - `@tauri-apps/cli 2.x`. - `svelte 5.0.0`, `svelte-check 4.0.0`, `typescript 5.6.2`, `vite 6.4.2`. ## Watch-outs - **`run.sh` `LIBCLANG_PATH` is Fedora-specific.** A new developer on Ubuntu / macOS hits a build failure on first run and has to either edit `run.sh` or pre-set the env var. Worth the conditional default. - **No `dev:fullstack` script.** The Tauri dev path goes through `npx tauri dev` (or `run.sh`), not through an npm script. A `npm run dev:fullstack` shortcut would make discovery easier. - **Tailwind v4 is in flight.** Major version, no PostCSS config. Cross-link to slice 1 for the consumed surface. - **`@tauri-apps/api` is pinned to `2.10.1` (no caret).** Intentional because Tauri's JS bridge can shift behaviour subtly between minors. Pinned ensures we test what we ship. - **Plugin versions are caret-ranged.** Compatible-change updates land transparently. `npm audit` (CI) catches advisories. ## See also - [Workspace Cargo.toml](workspace-cargo.md) - [Frontend build config (vite.config, svelte.config, jsconfig)](frontend-build-config.md) - [CI pipeline](ci-pipeline.md) — invokes `npm run build` and `svelte-check`. - [Slice 1 frontend](../01-frontend/README.md) — consumer of every `@tauri-apps/*` runtime dep.