2026-02-17 13:10:43 +01:00
# Getting Started
How to navigate the codebase, run the app, and find what you need.
## Prerequisites
- **Node.js** 18+ and **pnpm **
- **Rust** 1.77.2+ (for the Tauri backend)
- **git** CLI (required by the git integration features)
2026-04-24 16:25:36 +02:00
### Linux system dependencies
If you run the desktop app on Linux, install Tauri's WebKit2GTK 4.1 dependencies first:
- Arch / Manjaro:
```bash
sudo pacman -S --needed webkit2gtk-4.1 base-devel curl wget file openssl \
appmenu-gtk-module libappindicator-gtk3 librsvg
```
- Debian / Ubuntu (22.04+):
```bash
sudo apt install libwebkit2gtk-4.1-dev build-essential curl wget file \
libxdo-dev libssl-dev libayatana-appindicator3-dev librsvg2-dev \
libsoup-3.0-dev patchelf
```
- Fedora 38+:
```bash
sudo dnf install webkit2gtk4.1-devel openssl-devel curl wget file \
libappindicator-gtk3-devel librsvg2-devel
```
2026-02-17 13:10:43 +01:00
## Quick Start
```bash
# Install dependencies
pnpm install
# Run in browser (no Rust needed — uses mock data)
pnpm dev
# Open http://localhost:5173
# Run with Tauri (full app, requires Rust)
pnpm tauri dev
# Run tests
pnpm test # Vitest unit tests
cargo test # Rust tests (from src-tauri/)
2026-04-07 19:22:11 +02:00
pnpm playwright:smoke # Curated Playwright core smoke lane (~5 min)
pnpm playwright:regression # Full Playwright regression suite
2026-02-17 13:10:43 +01:00
```
2026-04-19 16:18:35 +02:00
## Starter Vaults And Remotes
`create_getting_started_vault` clones the public starter repo and then removes every git remote from the new local copy. That means Getting Started vaults open local-only by default. Users connect a compatible remote later through the bottom-bar `No remote` chip or the command palette, both of which feed the same `AddRemoteModal` and `git_add_remote` backend flow.
2026-02-17 13:10:43 +01:00
## Directory Structure
```
2026-04-12 01:35:34 +02:00
tolaria/
2026-02-17 13:10:43 +01:00
├── src/ # React frontend
│ ├── main.tsx # Entry point (renders <App />)
2026-03-07 04:05:40 +01:00
│ ├── App.tsx # Root component — orchestrates layout + state
2026-02-17 13:10:43 +01:00
│ ├── App.css # App shell layout styles
2026-03-07 04:05:40 +01:00
│ ├── types.ts # Shared TS types (VaultEntry, Settings, etc.)
2026-02-17 13:10:43 +01:00
│ ├── mock-tauri.ts # Mock Tauri layer for browser testing
2026-04-24 22:26:07 +02:00
│ ├── theme.json # Editor typography theme configuration
│ ├── index.css # Semantic app theme variables + Tailwind setup
2026-02-17 13:10:43 +01:00
│ │
2026-03-07 04:05:40 +01:00
│ ├── components/ # UI components (~98 files)
│ │ ├── Sidebar.tsx # Left panel: filters + type groups
│ │ ├── SidebarParts.tsx # Sidebar subcomponents
2026-02-17 13:10:43 +01:00
│ │ ├── NoteList.tsx # Second panel: filtered note list
2026-03-07 04:05:40 +01:00
│ │ ├── NoteItem.tsx # Individual note item
│ │ ├── PulseView.tsx # Git activity feed (replaces NoteList)
2026-03-28 11:03:01 +01:00
│ │ ├── Editor.tsx # Third panel: editor orchestration
2026-03-07 04:05:40 +01:00
│ │ ├── EditorContent.tsx # Editor content area
│ │ ├── EditorRightPanel.tsx # Right panel toggle
│ │ ├── editorSchema.tsx # BlockNote schema + wikilink type
│ │ ├── RawEditorView.tsx # CodeMirror raw editor
2026-02-17 13:10:43 +01:00
│ │ ├── Inspector.tsx # Fourth panel: metadata + relationships
│ │ ├── DynamicPropertiesPanel.tsx # Editable frontmatter properties
2026-04-13 19:37:59 +02:00
│ │ ├── AiPanel.tsx # AI agent panel (selected CLI agent)
2026-03-07 04:05:40 +01:00
│ │ ├── AiMessage.tsx # Agent message display
│ │ ├── AiActionCard.tsx # Agent tool action cards
2026-04-13 19:37:59 +02:00
│ │ ├── AiAgentsOnboardingPrompt.tsx # First-launch AI agent installer prompt
2026-03-07 04:05:40 +01:00
│ │ ├── SearchPanel.tsx # Search interface
│ │ ├── SettingsPanel.tsx # App settings
│ │ ├── StatusBar.tsx # Bottom bar: vault picker + sync
│ │ ├── CommandPalette.tsx # Cmd+K command launcher
│ │ ├── BreadcrumbBar.tsx # Breadcrumb + word count + actions
│ │ ├── WelcomeScreen.tsx # Onboarding screen
2026-04-24 16:25:36 +02:00
│ │ ├── LinuxTitlebar.tsx # Linux-only custom window chrome + controls
│ │ ├── LinuxMenuButton.tsx # Linux titlebar menu mirroring app commands
2026-04-12 17:08:07 +02:00
│ │ ├── CloneVaultModal.tsx # Clone a vault from any git URL
2026-04-19 16:18:35 +02:00
│ │ ├── AddRemoteModal.tsx # Connect a local-only vault to a remote later
2026-03-07 04:05:40 +01:00
│ │ ├── ConflictResolverModal.tsx # Git conflict resolution
2026-02-17 13:10:43 +01:00
│ │ ├── CommitDialog.tsx # Git commit modal
2026-03-07 04:05:40 +01:00
│ │ ├── CreateNoteDialog.tsx # New note modal
│ │ ├── CreateTypeDialog.tsx # New type modal
│ │ ├── UpdateBanner.tsx # In-app update notification
│ │ ├── inspector/ # Inspector sub-panels
│ │ │ ├── BacklinksPanel.tsx
│ │ │ ├── RelationshipsPanel.tsx
│ │ │ ├── GitHistoryPanel.tsx
│ │ │ └── ...
│ │ └── ui/ # shadcn/ui primitives
│ │ ├── button.tsx, dialog.tsx, input.tsx, ...
2026-02-17 13:10:43 +01:00
│ │
2026-04-28 04:20:40 +02:00
│ ├── hooks/ # Custom React hooks (~86 files)
2026-03-07 04:05:40 +01:00
│ │ ├── useVaultLoader.ts # Loads vault entries + content
│ │ ├── useVaultSwitcher.ts # Multi-vault management
│ │ ├── useVaultConfig.ts # Per-vault UI settings
2026-03-16 18:31:33 +01:00
│ │ ├── useNoteActions.ts # Composes creation + rename + frontmatter
2026-04-12 23:14:03 +02:00
│ │ ├── useNoteCreation.ts # Note/type creation
2026-03-16 18:31:33 +01:00
│ │ ├── useNoteRename.ts # Note renaming + wikilink updates
2026-04-28 04:20:40 +02:00
│ │ ├── useCliAiAgent.ts # Selected AI agent state + normalized session pipeline
2026-04-28 03:41:04 +02:00
│ │ ├── useAiAgentsStatus.ts # Claude/Codex/OpenCode/Pi availability polling
2026-04-13 19:37:59 +02:00
│ │ ├── useAiAgentPreferences.ts # Default-agent persistence + cycling
2026-03-07 04:05:40 +01:00
│ │ ├── useAiActivity.ts # MCP UI bridge listener
│ │ ├── useAutoSync.ts # Auto git pull/push
│ │ ├── useConflictResolver.ts # Git conflict handling
│ │ ├── useEditorSave.ts # Auto-save with debounce
│ │ ├── useTheme.ts # Flatten theme.json → CSS vars
refactor: remove QMD semantic indexing — keep keyword search only
Remove the entire QMD search engine (semantic indexing, hybrid search,
vector embeddings) and replace with a simple walkdir-based keyword
search. QMD never worked reliably in production, added bundle bloat,
and showed "Index failed" in the status bar.
What changed:
- Rust: deleted indexing.rs, rewrote search.rs as pure keyword search
- Frontend: removed useIndexing hook, IndexingBadge, hybrid search
- Menu: removed "Reindex Vault" command from palette and menu bar
- Config: removed qmd from bundle resources and build script
- Deleted tools/qmd/ (QMD CLI tool, MCP server, tests)
- Updated docs (ARCHITECTURE, ABSTRACTIONS, GETTING-STARTED)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:18:05 +01:00
│ │ ├── useUnifiedSearch.ts # Keyword search
2026-03-07 04:05:40 +01:00
│ │ ├── useNoteSearch.ts # Note search
│ │ ├── useCommandRegistry.ts # Command palette registry
│ │ ├── useAppCommands.ts # App-level commands
│ │ ├── useAppKeyboard.ts # Keyboard shortcuts
2026-04-11 15:42:53 +02:00
│ │ ├── appCommandCatalog.ts # Shortcut combos + command metadata
2026-04-11 10:39:08 +02:00
│ │ ├── appCommandDispatcher.ts # Shared shortcut/menu command IDs + dispatch
2026-03-07 04:05:40 +01:00
│ │ ├── useSettings.ts # App settings
2026-04-15 14:55:56 +02:00
│ │ ├── useGettingStartedClone.ts # Shared Getting Started clone action
2026-03-07 04:05:40 +01:00
│ │ ├── useOnboarding.ts # First-launch flow
│ │ ├── useCodeMirror.ts # CodeMirror raw editor
│ │ ├── useMcpBridge.ts # MCP WebSocket client
2026-04-22 19:18:52 +02:00
│ │ ├── useMcpStatus.ts # Explicit external AI tool connection status + connect/disconnect actions
2026-03-07 04:05:40 +01:00
│ │ ├── useUpdater.ts # In-app updates
│ │ └── ...
2026-02-17 13:10:43 +01:00
│ │
2026-03-07 04:05:40 +01:00
│ ├── utils/ # Pure utility functions (~48 files)
│ │ ├── wikilinks.ts # Wikilink preprocessing pipeline
│ │ ├── frontmatter.ts # TypeScript YAML parser
2026-04-24 16:25:36 +02:00
│ │ ├── platform.ts # Runtime platform + Linux chrome gating helpers
2026-03-07 04:05:40 +01:00
│ │ ├── ai-agent.ts # Agent stream utilities
2026-03-29 15:05:56 +02:00
│ │ ├── ai-chat.ts # Token estimation utilities
2026-03-07 04:05:40 +01:00
│ │ ├── ai-context.ts # Context snapshot builder
│ │ ├── noteListHelpers.ts # Sorting, filtering, date formatting
2026-03-28 11:03:01 +01:00
│ │ ├── wikilink.ts # Wikilink resolution
2026-03-07 04:05:40 +01:00
│ │ ├── configMigration.ts # localStorage → vault config migration
│ │ ├── iconRegistry.ts # Phosphor icon registry
│ │ ├── propertyTypes.ts # Property type definitions
│ │ ├── vaultListStore.ts # Vault list persistence
│ │ ├── vaultConfigStore.ts # Vault config store
│ │ └── ...
2026-02-17 13:10:43 +01:00
│ │
│ ├── lib/
2026-04-13 19:37:59 +02:00
│ │ ├── aiAgents.ts # Shared agent registry + status helpers
2026-04-12 22:14:53 +02:00
│ │ ├── appUpdater.ts # Frontend wrapper around channel-aware updater commands
2026-04-27 13:06:59 +02:00
│ │ ├── i18n.ts # App-owned localization runtime and locale resolution
│ │ ├── locales/ # JSON locale catalogs (English source + translated locales)
2026-04-12 22:14:53 +02:00
│ │ ├── releaseChannel.ts # Alpha/stable normalization helpers
2026-02-17 13:10:43 +01:00
│ │ └── utils.ts # Tailwind merge + cn() helper
│ │
│ └── test/
│ └── setup.ts # Vitest test environment setup
│
├── src-tauri/ # Rust backend
│ ├── Cargo.toml # Rust dependencies
│ ├── build.rs # Tauri build script
│ ├── tauri.conf.json # Tauri app configuration
│ ├── capabilities/ # Tauri v2 security capabilities
│ ├── src/
│ │ ├── main.rs # Entry point (calls lib::run())
2026-04-12 17:08:07 +02:00
│ │ ├── lib.rs # Tauri setup + command registration
2026-03-28 11:03:01 +01:00
│ │ ├── commands/ # Tauri command handlers (split into modules)
2026-03-07 04:05:40 +01:00
│ │ ├── vault/ # Vault module
│ │ │ ├── mod.rs # Core types, parse_md_file, scan_vault
│ │ │ ├── cache.rs # Git-based incremental caching
│ │ │ ├── parsing.rs # Text processing + title extraction
│ │ │ ├── rename.rs # Rename + cross-vault wikilink update
│ │ │ ├── image.rs # Image attachment saving
│ │ │ ├── migration.rs # Frontmatter migration
2026-04-07 23:28:02 +02:00
│ │ │ └── getting_started.rs # Getting Started vault clone orchestration
2026-03-07 04:05:40 +01:00
│ │ ├── frontmatter/ # Frontmatter module
│ │ │ ├── mod.rs, yaml.rs, ops.rs
│ │ ├── git/ # Git module
2026-04-19 16:18:35 +02:00
│ │ │ ├── mod.rs, commit.rs, status.rs, history.rs, clone.rs, connect.rs
2026-03-07 04:05:40 +01:00
│ │ │ ├── conflict.rs, remote.rs, pulse.rs
2026-03-28 11:03:01 +01:00
│ │ ├── telemetry.rs # Sentry init + path scrubber
refactor: remove QMD semantic indexing — keep keyword search only
Remove the entire QMD search engine (semantic indexing, hybrid search,
vector embeddings) and replace with a simple walkdir-based keyword
search. QMD never worked reliably in production, added bundle bloat,
and showed "Index failed" in the status bar.
What changed:
- Rust: deleted indexing.rs, rewrote search.rs as pure keyword search
- Frontend: removed useIndexing hook, IndexingBadge, hybrid search
- Menu: removed "Reindex Vault" command from palette and menu bar
- Config: removed qmd from bundle resources and build script
- Deleted tools/qmd/ (QMD CLI tool, MCP server, tests)
- Updated docs (ARCHITECTURE, ABSTRACTIONS, GETTING-STARTED)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:18:05 +01:00
│ │ ├── search.rs # Keyword search (walkdir-based)
2026-04-13 19:37:59 +02:00
│ │ ├── ai_agents.rs # Shared CLI-agent detection + stream adapters
2026-03-07 04:05:40 +01:00
│ │ ├── claude_cli.rs # Claude CLI subprocess management
2026-04-28 03:41:04 +02:00
│ │ ├── pi_cli.rs # Pi CLI subprocess management
2026-04-22 19:18:52 +02:00
│ │ ├── mcp.rs # MCP server lifecycle + explicit config registration/removal
2026-04-12 22:14:53 +02:00
│ │ ├── app_updater.rs # Alpha/stable updater endpoint selection
2026-03-07 04:05:40 +01:00
│ │ ├── settings.rs # App settings persistence
│ │ ├── vault_config.rs # Per-vault UI config
│ │ ├── vault_list.rs # Vault list persistence
│ │ └── menu.rs # Native macOS menu bar
2026-02-17 13:10:43 +01:00
│ └── icons/ # App icons
│
2026-03-07 04:05:40 +01:00
├── mcp-server/ # MCP bridge (Node.js)
│ ├── index.js # MCP server entry (stdio, 14 tools)
│ ├── vault.js # Vault file operations
│ ├── ws-bridge.js # WebSocket bridge (ports 9710, 9711)
│ ├── test.js # MCP server tests
│ └── package.json
│
├── e2e/ # Playwright E2E tests (~26 specs)
2026-04-07 19:22:11 +02:00
├── tests/smoke/ # Playwright specs (full regression + @smoke subset)
2026-03-07 04:05:40 +01:00
├── design/ # Per-task design files
2026-04-19 22:26:35 +02:00
├── demo-vault-v2/ # Curated local QA fixture for native/dev flows
2026-03-07 04:05:40 +01:00
├── scripts/ # Build/utility scripts
2026-02-17 13:10:43 +01:00
│
├── package.json # Frontend dependencies + scripts
2026-04-27 13:06:59 +02:00
├── lara.yaml # Lara CLI locale sync configuration
2026-02-17 13:10:43 +01:00
├── vite.config.ts # Vite bundler config
├── tsconfig.json # TypeScript config
2026-04-07 19:22:11 +02:00
├── playwright.config.ts # Full Playwright regression config
├── playwright.smoke.config.ts # Curated pre-push Playwright config
2026-03-07 04:05:40 +01:00
├── ui-design.pen # Master design file
2026-04-14 14:16:55 +02:00
├── AGENTS.md # Canonical shared instructions for coding agents
2026-04-19 17:00:30 +02:00
├── CLAUDE.md # Claude Code compatibility shim importing AGENTS.md as an organized Note
2026-02-17 13:10:43 +01:00
└── docs/ # This documentation
```
## Key Files to Know
2026-04-19 22:26:35 +02:00
### Fixtures
- `demo-vault-v2/` is the small checked-in QA fixture used for native/manual Tolaria flows. It is intentionally curated around a handful of search, relationship, project-navigation, and attachment scenarios.
- `tests/fixtures/test-vault/` is the deterministic Playwright fixture copied into temp directories for isolated integration and smoke tests.
- `python3 scripts/generate_demo_vault.py` generates the larger synthetic vault on demand at `generated-fixtures/demo-vault-large/` for scale/performance experiments. That output is gitignored and should not bloat the normal QA fixture.
2026-02-17 13:10:43 +01:00
### Start here
| File | Why it matters |
|------|---------------|
2026-03-07 04:05:40 +01:00
| `src/App.tsx` | Root component. Shows the 4-panel layout, state flow, and how all features connect. |
2026-02-17 13:10:43 +01:00
| `src/types.ts` | All shared TypeScript types. Read this first to understand the data model. |
2026-03-28 11:03:01 +01:00
| `src-tauri/src/commands/` | Tauri command handlers (split into modules). This is the frontend-backend API surface. |
2026-03-07 04:05:40 +01:00
| `src-tauri/src/lib.rs` | Tauri setup, command registration, startup tasks, WebSocket bridge lifecycle. |
2026-02-17 13:10:43 +01:00
### Data layer
| File | Why it matters |
|------|---------------|
| `src/hooks/useVaultLoader.ts` | How vault data is loaded and managed. The Tauri/mock branching pattern. |
2026-03-16 18:31:33 +01:00
| `src/hooks/useNoteActions.ts` | Orchestrates note operations: composes `useNoteCreation` , `useNoteRename` , frontmatter CRUD, and wikilink navigation. |
2026-04-15 14:55:56 +02:00
| `src/hooks/useVaultSwitcher.ts` | Multi-vault management, vault switching, and persisting cloned vaults in the switcher list. |
| `src/hooks/useGettingStartedClone.ts` | Shared "Clone Getting Started Vault" action for the status bar and command palette. |
2026-04-19 16:18:35 +02:00
| `src/components/AddRemoteModal.tsx` | Modal UI for connecting a local-only vault to a compatible remote. |
2026-02-17 13:10:43 +01:00
| `src/mock-tauri.ts` | Mock data for browser testing. Shows the shape of all Tauri responses. |
### Backend
| File | Why it matters |
|------|---------------|
2026-03-07 04:05:40 +01:00
| `src-tauri/src/vault/mod.rs` | Vault scanning, frontmatter parsing, entity type inference, relationship extraction. |
| `src-tauri/src/vault/cache.rs` | Git-based incremental caching — how large vaults load fast. |
| `src-tauri/src/frontmatter/ops.rs` | YAML manipulation — how properties are updated/deleted in files. |
2026-04-19 16:18:35 +02:00
| `src-tauri/src/git/` | All git operations (clone, commit, pull, push, conflicts, pulse, add-remote). |
refactor: remove QMD semantic indexing — keep keyword search only
Remove the entire QMD search engine (semantic indexing, hybrid search,
vector embeddings) and replace with a simple walkdir-based keyword
search. QMD never worked reliably in production, added bundle bloat,
and showed "Index failed" in the status bar.
What changed:
- Rust: deleted indexing.rs, rewrote search.rs as pure keyword search
- Frontend: removed useIndexing hook, IndexingBadge, hybrid search
- Menu: removed "Reindex Vault" command from palette and menu bar
- Config: removed qmd from bundle resources and build script
- Deleted tools/qmd/ (QMD CLI tool, MCP server, tests)
- Updated docs (ARCHITECTURE, ABSTRACTIONS, GETTING-STARTED)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 16:18:05 +01:00
| `src-tauri/src/search.rs` | Keyword search — scans vault files with walkdir. |
2026-04-28 03:41:04 +02:00
| `src-tauri/src/ai_agents.rs` | Shared CLI-agent availability checks, adapter dispatch, and stream normalization. |
2026-03-07 04:05:40 +01:00
| `src-tauri/src/claude_cli.rs` | Claude CLI subprocess spawning + NDJSON stream parsing. |
2026-04-28 03:41:04 +02:00
| `src-tauri/src/pi_cli.rs` | Pi subprocess spawning through JSON mode and transient MCP adapter config. |
2026-04-12 22:14:53 +02:00
| `src-tauri/src/app_updater.rs` | Desktop updater bridge — selects alpha/stable manifests and streams install progress. |
2026-02-17 13:10:43 +01:00
### Editor
| File | Why it matters |
|------|---------------|
2026-03-28 11:03:01 +01:00
| `src/components/Editor.tsx` | BlockNote setup, breadcrumb bar, diff/raw toggle. |
2026-04-15 22:42:40 +02:00
| `src/components/SingleEditorView.tsx` | Shared BlockNote shell, Tolaria formatting controllers, and suggestion menus. |
2026-03-07 04:05:40 +01:00
| `src/components/editorSchema.tsx` | Custom wikilink inline content type definition. |
2026-04-15 22:42:40 +02:00
| `src/components/tolariaEditorFormatting.tsx` | Markdown-safe formatting toolbar surface for BlockNote. |
| `src/components/tolariaEditorFormattingConfig.ts` | Filters toolbar and slash-menu commands to markdown-roundtrippable actions. |
2026-03-07 04:05:40 +01:00
| `src/utils/wikilinks.ts` | Wikilink preprocessing pipeline (markdown ↔ BlockNote). |
| `src/components/RawEditorView.tsx` | CodeMirror 6 raw markdown editor. |
2026-02-17 13:10:43 +01:00
2026-03-07 04:05:40 +01:00
### AI
2026-02-17 13:10:43 +01:00
| File | Why it matters |
|------|---------------|
2026-04-13 19:37:59 +02:00
| `src/components/AiPanel.tsx` | AI agent panel — selected CLI agent with tool execution, reasoning, and actions. |
2026-04-28 04:20:40 +02:00
| `src/hooks/useCliAiAgent.ts` | Thin React owner for the selected CLI agent session state. |
| `src/lib/aiAgentSession.ts` | Single message/session lifecycle for prompt normalization, history, streaming, and reset behavior. |
| `src/lib/aiAgentFileOperations.ts` | Detects agent-created or modified vault files from normalized tool inputs. |
2026-04-13 19:37:59 +02:00
| `src/lib/aiAgents.ts` | Supported agent definitions, status normalization, and default-agent helpers. |
2026-03-07 04:05:40 +01:00
| `src/utils/ai-context.ts` | Context snapshot builder for AI conversations. |
2026-03-28 11:03:01 +01:00
### Styling
2026-03-07 04:05:40 +01:00
| File | Why it matters |
|------|---------------|
2026-04-24 22:26:07 +02:00
| `src/index.css` | Semantic CSS custom properties for app-owned light/dark themes. |
| `src/theme.json` | Editor-specific typography theme (fonts, headings, lists, code blocks). |
2026-03-07 04:05:40 +01:00
### Settings & Config
| File | Why it matters |
|------|---------------|
2026-04-26 08:18:47 +02:00
| `src/hooks/useSettings.ts` | App settings (telemetry, release channel, theme mode, UI language, auto-sync interval, default AI agent). |
2026-04-12 22:14:53 +02:00
| `src/lib/releaseChannel.ts` | Normalizes persisted updater-channel values (`stable` default, optional `alpha` ). |
| `src/lib/appUpdater.ts` | Frontend wrapper for channel-aware updater commands. |
2026-04-16 05:03:01 +02:00
| `src/hooks/useMainWindowSizeConstraints.ts` | Derives the main-window minimum width from the visible panes and asks Tauri to grow back to fit wider layouts. |
2026-04-10 13:52:39 +02:00
| `src/hooks/useVaultConfig.ts` | Per-vault local UI preferences (zoom, view mode, colors, Inbox columns, explicit organization workflow). |
2026-04-26 08:18:47 +02:00
| `src/components/SettingsPanel.tsx` | Settings UI for telemetry, release channel, sync interval, UI language, default AI agent, and the vault-level explicit organization toggle. |
2026-04-12 22:14:53 +02:00
| `src/hooks/useUpdater.ts` | In-app updates using the selected alpha/stable feed. |
2026-02-17 13:10:43 +01:00
## Architecture Patterns
### Tauri/Mock Branching
Every data-fetching operation checks `isTauri()` and branches:
```typescript
if (isTauri()) {
result = await invoke<T>('command', { args })
} else {
result = await mockInvoke<T>('command', { args })
}
```
This lives in `useVaultLoader.ts` and `useNoteActions.ts` . Components never call Tauri directly.
### Props-Down, Callbacks-Up
2026-03-28 11:03:01 +01:00
No global state management (no Redux, no Context). `App.tsx` owns the state and passes it down as props. Child-to-parent communication uses callback props (`onSelectNote` , etc.).
2026-02-17 13:10:43 +01:00
### Discriminated Unions for Selection State
```typescript
type SidebarSelection =
2026-03-07 04:05:40 +01:00
| { kind: 'filter'; filter: SidebarFilter }
2026-02-17 13:10:43 +01:00
| { kind: 'sectionGroup'; type: string }
2026-04-19 03:37:33 +02:00
| { kind: 'folder'; path: string }
2026-02-17 13:10:43 +01:00
| { kind: 'entity'; entry: VaultEntry }
2026-04-19 03:37:33 +02:00
| { kind: 'view'; filename: string }
2026-02-17 13:10:43 +01:00
```
2026-03-07 04:05:40 +01:00
### Command Registry
2026-04-24 16:25:36 +02:00
`useCommandRegistry` + `useAppCommands` build a centralized command registry. Commands are registered with labels, shortcuts, and handlers. The `CommandPalette` (Cmd+K) fuzzy-searches this registry. Shortcut combos live in `appCommandCatalog.ts` ; real keypresses always flow through `useAppKeyboard` , native menu clicks emit the same command IDs through `useMenuEvents` , and `appCommandDispatcher.ts` suppresses the duplicate native/renderer echo from a single shortcut. On macOS, any browser-reserved chord that WKWebView swallows before that path must also be added to the narrow `tauri-plugin-prevent-default` registration in `src-tauri/src/lib.rs` . On Linux, `LinuxTitlebar.tsx` and `LinuxMenuButton.tsx` reuse the same command IDs through `trigger_menu_command` because the native GTK menu bar is intentionally not mounted. The same shortcut manifest also declares the deterministic QA mode for each shortcut-capable command.
2026-02-17 13:10:43 +01:00
2026-04-07 20:09:04 +02:00
Commands whose availability depends on the current note or Git state must also flow through `update_menu_state` so the native menu stays in sync with the command palette. The deleted-note restore action in Changes view is the reference example: the row opens a deleted diff preview, the command palette exposes "Restore Deleted Note", and the Note menu enables the same action only while that preview is active.
2026-04-27 10:12:13 +02:00
Current-note find/replace is a surface-aware command: editor focus enables "Find in Note" / "Replace in Note" and routes Cmd+F into raw CodeMirror mode; note-list focus enables existing note-list search instead. When adding another focus-dependent command, mirror this pattern with an availability event consumed by `useMenuEvents.ts` and `update_menu_state` .
2026-04-11 19:03:15 +02:00
For automated shortcut QA, use the explicit proof path from `appCommandCatalog.ts` :
- `window.__laputaTest.triggerShortcutCommand()` for deterministic renderer shortcut-event coverage
- `window.__laputaTest.triggerMenuCommand()` for deterministic native menu-command coverage
That browser harness is a deterministic desktop command bridge, not real native accelerator QA. For macOS browser-reserved chords, still perform native QA in the real Tauri app because the webview-init prevent-default layer is only active there. Do not treat flaky synthesized macOS keystrokes as proof that a shortcut works unless you also confirm the visible app behavior.
2026-04-11 10:39:08 +02:00
2026-02-17 13:10:43 +01:00
## Running Tests
```bash
# Unit tests (fast, no browser)
pnpm test
2026-03-07 04:05:40 +01:00
# Unit tests with coverage (must pass ≥70%)
pnpm test:coverage
2026-02-17 13:10:43 +01:00
# Rust tests
2026-03-07 04:05:40 +01:00
cargo test
2026-02-17 13:10:43 +01:00
2026-03-07 04:05:40 +01:00
# Rust coverage (must pass ≥85% line coverage)
cargo llvm-cov --manifest-path src-tauri/Cargo.toml --no-clean --fail-under-lines 85
2026-02-17 13:10:43 +01:00
2026-04-07 19:22:11 +02:00
# Playwright core smoke lane (requires dev server)
2026-03-07 04:05:40 +01:00
BASE_URL="http://localhost:5173" pnpm playwright:smoke
2026-02-17 13:10:43 +01:00
2026-04-07 19:22:11 +02:00
# Full Playwright regression suite
BASE_URL="http://localhost:5173" pnpm playwright:regression
2026-03-07 04:05:40 +01:00
# Single Playwright test
BASE_URL="http://localhost:5173" npx playwright test tests/smoke/<slug>.spec.ts
2026-02-17 13:10:43 +01:00
```
## Common Tasks
### Add a new Tauri command
2026-03-07 04:05:40 +01:00
1. Write the Rust function in the appropriate module (`vault/` , `git/` , etc.)
2026-03-28 11:03:01 +01:00
2. Add a command handler in `commands/`
2026-02-17 13:10:43 +01:00
3. Register it in the `generate_handler![]` macro in `lib.rs`
4. Call it from the frontend via `invoke()` in the appropriate hook
5. Add a mock handler in `mock-tauri.ts`
### Add a new component
1. Create `src/components/MyComponent.tsx`
2. If it needs vault data, receive it as props from the parent
3. Wire it into `App.tsx` or the relevant parent component
4. Add a test file `src/components/MyComponent.test.tsx`
### Add a new entity type
2026-03-15 23:40:47 +01:00
1. Create a type document: `type/mytype.md` with `type: Type` frontmatter (icon, color, order, etc.)
2. The sidebar section groups are auto-generated from type documents — no code change needed if `visible: true`
3. Update `CreateNoteDialog.tsx` type options if users should be able to create it from the dialog
4. Notes of this type are created at the vault root with `type: MyType` in frontmatter — no dedicated folder needed
2026-03-07 04:05:40 +01:00
### Add a command palette entry
1. Register the command in `useAppCommands.ts` via the command registry
2. Add a corresponding menu bar item in `menu.rs` for discoverability
2026-04-11 19:03:15 +02:00
3. If it has a keyboard shortcut, register it in `appCommandCatalog.ts` with the canonical command ID, modifier rule, and deterministic QA mode, then wire the matching native menu item in `menu.rs` if it should also appear in the menu bar
2026-04-07 20:09:04 +02:00
4. If its enabled state depends on runtime selection (active note, deleted preview, Git status, etc.), thread that flag through `useMenuEvents.ts` and `update_menu_state` so the native menu enables/disables correctly
2026-03-07 04:05:40 +01:00
2026-03-28 11:03:01 +01:00
### Modify styling
2026-03-07 04:05:40 +01:00
2026-04-24 22:26:07 +02:00
1. **Global app/theme variables ** : Edit `src/index.css`
2026-03-28 11:03:01 +01:00
2. **Editor typography ** : Edit `src/theme.json`
2026-03-07 04:05:40 +01:00
### Work with the AI agent
1. **Agent system prompt ** : Edit `src/utils/ai-agent.ts` (inline system prompt string)
2. **Context building ** : Edit `src/utils/ai-context.ts` for what data is sent to the agent
3. **Tool action display ** : Edit `src/components/AiActionCard.tsx`
2026-04-27 16:46:32 +02:00
4. **Claude CLI arguments ** : Edit `src-tauri/src/claude_cli.rs` (`run_agent_stream()` ; keep app-managed launches on strict Tolaria MCP config, `acceptEdits` , and the scoped file/search tool list)
2026-04-28 03:41:04 +02:00
5. **Shared agent adapters / Codex/Pi args ** : Edit `src-tauri/src/ai_agents.rs` plus the per-agent adapter modules (keep Codex sandboxed with active-vault `workspace-write` , keep Pi on transient MCP config, and do not use dangerous permission bypasses unless an ADR explicitly designs a new mode)
2026-04-27 17:51:25 +02:00
### Work with external MCP setup
1. **Backend registration/status ** : Edit `src-tauri/src/mcp.rs` ; registration must verify Node.js first, resolve the packaged `mcp-server/` for macOS, Windows, Linux, and AppImage installs, and write an explicit stdio entry with `VAULT_PATH` plus `WS_UI_PORT=9711`
2. **Setup dialog copy/actions ** : Edit `src/components/McpSetupDialog.tsx` ; users should see the Node.js prerequisite and the manual config shape before Tolaria writes third-party config files
3. **Status hook/toasts ** : Edit `src/hooks/useMcpStatus.ts` when setup, reconnect, disconnect, or failure messaging changes