How to navigate the codebase, run the app, and find what you need.
- Node.js 18+ and pnpm
- Rust 1.77.2+ (for the Tauri backend)
- git CLI (required by the git integration features)
If you run the desktop app on Linux, install Tauri's WebKit2GTK 4.1 dependencies first:
- Arch / Manjaro:
sudo pacman -S --needed webkit2gtk-4.1 base-devel curl wget file openssl \ appmenu-gtk-module libappindicator-gtk3 librsvg
- Debian / Ubuntu (22.04+):
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+:
sudo dnf install webkit2gtk4.1-devel openssl-devel curl wget file \ libappindicator-gtk3-devel librsvg2-devel
# 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/)
pnpm playwright:smoke # Curated Playwright core smoke lane (~5 min)
pnpm playwright:regression # Full Playwright regression suitecreate_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.
tolaria/
βββ src/ # React frontend
β βββ main.tsx # Entry point (renders <App />)
β βββ App.tsx # Root component β orchestrates layout + state
β βββ App.css # App shell layout styles
β βββ types.ts # Shared TS types (VaultEntry, Settings, etc.)
β βββ mock-tauri.ts # Mock Tauri layer for browser testing
β βββ theme.json # Editor typography theme configuration
β βββ index.css # Semantic app theme variables + Tailwind setup
β β
β βββ components/ # UI components (~98 files)
β β βββ Sidebar.tsx # Left panel: filters + type groups
β β βββ SidebarParts.tsx # Sidebar subcomponents
β β βββ NoteList.tsx # Second panel: filtered note list
β β βββ NoteItem.tsx # Individual note item
β β βββ PulseView.tsx # Git activity feed (replaces NoteList)
β β βββ Editor.tsx # Third panel: editor orchestration
β β βββ EditorContent.tsx # Editor content area
β β βββ EditorRightPanel.tsx # Right panel toggle
β β βββ editorSchema.tsx # BlockNote schema + wikilink type
β β βββ RawEditorView.tsx # CodeMirror raw editor
β β βββ Inspector.tsx # Fourth panel: metadata + relationships
β β βββ DynamicPropertiesPanel.tsx # Editable frontmatter properties
β β βββ AiPanel.tsx # AI agent panel (selected CLI agent)
β β βββ AiMessage.tsx # Agent message display
β β βββ AiActionCard.tsx # Agent tool action cards
β β βββ AiAgentsOnboardingPrompt.tsx # First-launch AI agent installer prompt
β β βββ 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
β β βββ LinuxTitlebar.tsx # Linux-only custom window chrome + controls
β β βββ LinuxMenuButton.tsx # Linux titlebar menu mirroring app commands
β β βββ CloneVaultModal.tsx # Clone a vault from any git URL
β β βββ AddRemoteModal.tsx # Connect a local-only vault to a remote later
β β βββ ConflictResolverModal.tsx # Git conflict resolution
β β βββ CommitDialog.tsx # Git commit modal
β β βββ 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, ...
β β
β βββ hooks/ # Custom React hooks (~87 files)
β β βββ useVaultLoader.ts # Loads vault entries + content
β β βββ useVaultSwitcher.ts # Multi-vault management
β β βββ useVaultConfig.ts # Per-vault UI settings
β β βββ useNoteActions.ts # Composes creation + rename + frontmatter
β β βββ useNoteCreation.ts # Note/type creation
β β βββ useNoteRename.ts # Note renaming + wikilink updates
β β βββ useAiAgent.ts # Legacy Claude-specific stream helpers reused by the shared agent hook
β β βββ useCliAiAgent.ts # Selected AI agent state + normalized tool tracking
β β βββ useAiAgentsStatus.ts # Claude/Codex availability polling
β β βββ useAiAgentPreferences.ts # Default-agent persistence + cycling
β β βββ 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
β β βββ useUnifiedSearch.ts # Keyword search
β β βββ useNoteSearch.ts # Note search
β β βββ useCommandRegistry.ts # Command palette registry
β β βββ useAppCommands.ts # App-level commands
β β βββ useAppKeyboard.ts # Keyboard shortcuts
β β βββ appCommandCatalog.ts # Shortcut combos + command metadata
β β βββ appCommandDispatcher.ts # Shared shortcut/menu command IDs + dispatch
β β βββ useSettings.ts # App settings
β β βββ useGettingStartedClone.ts # Shared Getting Started clone action
β β βββ useOnboarding.ts # First-launch flow
β β βββ useCodeMirror.ts # CodeMirror raw editor
β β βββ useMcpBridge.ts # MCP WebSocket client
β β βββ useMcpStatus.ts # Explicit external AI tool connection status + connect/disconnect actions
β β βββ useUpdater.ts # In-app updates
β β βββ ...
β β
β βββ utils/ # Pure utility functions (~48 files)
β β βββ wikilinks.ts # Wikilink preprocessing pipeline
β β βββ frontmatter.ts # TypeScript YAML parser
β β βββ platform.ts # Runtime platform + Linux chrome gating helpers
β β βββ ai-agent.ts # Agent stream utilities
β β βββ ai-chat.ts # Token estimation utilities
β β βββ ai-context.ts # Context snapshot builder
β β βββ noteListHelpers.ts # Sorting, filtering, date formatting
β β βββ wikilink.ts # Wikilink resolution
β β βββ 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
β β βββ ...
β β
β βββ lib/
β β βββ aiAgents.ts # Shared agent registry + status helpers
β β βββ appUpdater.ts # Frontend wrapper around channel-aware updater commands
β β βββ releaseChannel.ts # Alpha/stable normalization helpers
β β βββ 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())
β β βββ lib.rs # Tauri setup + command registration
β β βββ commands/ # Tauri command handlers (split into modules)
β β βββ 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
β β β βββ getting_started.rs # Getting Started vault clone orchestration
β β βββ frontmatter/ # Frontmatter module
β β β βββ mod.rs, yaml.rs, ops.rs
β β βββ git/ # Git module
β β β βββ mod.rs, commit.rs, status.rs, history.rs, clone.rs, connect.rs
β β β βββ conflict.rs, remote.rs, pulse.rs
β β βββ telemetry.rs # Sentry init + path scrubber
β β βββ search.rs # Keyword search (walkdir-based)
β β βββ ai_agents.rs # Shared CLI-agent detection + stream adapters
β β βββ claude_cli.rs # Claude CLI subprocess management
β β βββ mcp.rs # MCP server lifecycle + explicit config registration/removal
β β βββ app_updater.rs # Alpha/stable updater endpoint selection
β β βββ settings.rs # App settings persistence
β β βββ vault_config.rs # Per-vault UI config
β β βββ vault_list.rs # Vault list persistence
β β βββ menu.rs # Native macOS menu bar
β βββ icons/ # App icons
β
βββ 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)
βββ tests/smoke/ # Playwright specs (full regression + @smoke subset)
βββ design/ # Per-task design files
βββ demo-vault-v2/ # Curated local QA fixture for native/dev flows
βββ scripts/ # Build/utility scripts
β
βββ package.json # Frontend dependencies + scripts
βββ vite.config.ts # Vite bundler config
βββ tsconfig.json # TypeScript config
βββ playwright.config.ts # Full Playwright regression config
βββ playwright.smoke.config.ts # Curated pre-push Playwright config
βββ ui-design.pen # Master design file
βββ AGENTS.md # Canonical shared instructions for coding agents
βββ CLAUDE.md # Claude Code compatibility shim importing AGENTS.md as an organized Note
βββ docs/ # This documentation
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.pygenerates the larger synthetic vault on demand atgenerated-fixtures/demo-vault-large/for scale/performance experiments. That output is gitignored and should not bloat the normal QA fixture.
| File | Why it matters |
|---|---|
src/App.tsx |
Root component. Shows the 4-panel layout, state flow, and how all features connect. |
src/types.ts |
All shared TypeScript types. Read this first to understand the data model. |
src-tauri/src/commands/ |
Tauri command handlers (split into modules). This is the frontend-backend API surface. |
src-tauri/src/lib.rs |
Tauri setup, command registration, startup tasks, WebSocket bridge lifecycle. |
| File | Why it matters |
|---|---|
src/hooks/useVaultLoader.ts |
How vault data is loaded and managed. The Tauri/mock branching pattern. |
src/hooks/useNoteActions.ts |
Orchestrates note operations: composes useNoteCreation, useNoteRename, frontmatter CRUD, and wikilink navigation. |
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. |
src/components/AddRemoteModal.tsx |
Modal UI for connecting a local-only vault to a compatible remote. |
src/mock-tauri.ts |
Mock data for browser testing. Shows the shape of all Tauri responses. |
| File | Why it matters |
|---|---|
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. |
src-tauri/src/git/ |
All git operations (clone, commit, pull, push, conflicts, pulse, add-remote). |
src-tauri/src/search.rs |
Keyword search β scans vault files with walkdir. |
src-tauri/src/ai_agents.rs |
Shared CLI-agent availability checks, safe-default Codex adapter, and stream normalization. |
src-tauri/src/claude_cli.rs |
Claude CLI subprocess spawning + NDJSON stream parsing. |
src-tauri/src/app_updater.rs |
Desktop updater bridge β selects alpha/stable manifests and streams install progress. |
| File | Why it matters |
|---|---|
src/components/Editor.tsx |
BlockNote setup, breadcrumb bar, diff/raw toggle. |
src/components/SingleEditorView.tsx |
Shared BlockNote shell, Tolaria formatting controllers, and suggestion menus. |
src/components/editorSchema.tsx |
Custom wikilink inline content type definition. |
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. |
src/utils/wikilinks.ts |
Wikilink preprocessing pipeline (markdown β BlockNote). |
src/components/RawEditorView.tsx |
CodeMirror 6 raw markdown editor. |
| File | Why it matters |
|---|---|
src/components/AiPanel.tsx |
AI agent panel β selected CLI agent with tool execution, reasoning, and actions. |
src/hooks/useCliAiAgent.ts |
Agent state: messages, streaming, tool tracking, file detection. |
src/lib/aiAgents.ts |
Supported agent definitions, status normalization, and default-agent helpers. |
src/utils/ai-context.ts |
Context snapshot builder for AI conversations. |
| File | Why it matters |
|---|---|
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). |
| File | Why it matters |
|---|---|
src/hooks/useSettings.ts |
App settings (telemetry, release channel, theme mode, auto-sync interval, default AI agent). |
src/lib/releaseChannel.ts |
Normalizes persisted updater-channel values (stable default, optional alpha). |
src/lib/appUpdater.ts |
Frontend wrapper for channel-aware updater commands. |
src/hooks/useMainWindowSizeConstraints.ts |
Derives the main-window minimum width from the visible panes and asks Tauri to grow back to fit wider layouts. |
src/hooks/useVaultConfig.ts |
Per-vault local UI preferences (zoom, view mode, colors, Inbox columns, explicit organization workflow). |
src/components/SettingsPanel.tsx |
Settings UI for telemetry, release channel, sync interval, default AI agent, and the vault-level explicit organization toggle. |
src/hooks/useUpdater.ts |
In-app updates using the selected alpha/stable feed. |
Every data-fetching operation checks isTauri() and branches:
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.
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.).
type SidebarSelection =
| { kind: 'filter'; filter: SidebarFilter }
| { kind: 'sectionGroup'; type: string }
| { kind: 'folder'; path: string }
| { kind: 'entity'; entry: VaultEntry }
| { kind: 'view'; filename: string }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.
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.
For automated shortcut QA, use the explicit proof path from appCommandCatalog.ts:
window.__laputaTest.triggerShortcutCommand()for deterministic renderer shortcut-event coveragewindow.__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.
# Unit tests (fast, no browser)
pnpm test
# Unit tests with coverage (must pass β₯70%)
pnpm test:coverage
# Rust tests
cargo test
# Rust coverage (must pass β₯85% line coverage)
cargo llvm-cov --manifest-path src-tauri/Cargo.toml --no-clean --fail-under-lines 85
# Playwright core smoke lane (requires dev server)
BASE_URL="http://localhost:5173" pnpm playwright:smoke
# Full Playwright regression suite
BASE_URL="http://localhost:5173" pnpm playwright:regression
# Single Playwright test
BASE_URL="http://localhost:5173" npx playwright test tests/smoke/<slug>.spec.ts- Write the Rust function in the appropriate module (
vault/,git/, etc.) - Add a command handler in
commands/ - Register it in the
generate_handler![]macro inlib.rs - Call it from the frontend via
invoke()in the appropriate hook - Add a mock handler in
mock-tauri.ts
- Create
src/components/MyComponent.tsx - If it needs vault data, receive it as props from the parent
- Wire it into
App.tsxor the relevant parent component - Add a test file
src/components/MyComponent.test.tsx
- Create a type document:
type/mytype.mdwithtype: Typefrontmatter (icon, color, order, etc.) - The sidebar section groups are auto-generated from type documents β no code change needed if
visible: true - Update
CreateNoteDialog.tsxtype options if users should be able to create it from the dialog - Notes of this type are created at the vault root with
type: MyTypein frontmatter β no dedicated folder needed
- Register the command in
useAppCommands.tsvia the command registry - Add a corresponding menu bar item in
menu.rsfor discoverability - If it has a keyboard shortcut, register it in
appCommandCatalog.tswith the canonical command ID, modifier rule, and deterministic QA mode, then wire the matching native menu item inmenu.rsif it should also appear in the menu bar - If its enabled state depends on runtime selection (active note, deleted preview, Git status, etc.), thread that flag through
useMenuEvents.tsandupdate_menu_stateso the native menu enables/disables correctly
- Global app/theme variables: Edit
src/index.css - Editor typography: Edit
src/theme.json
- Agent system prompt: Edit
src/utils/ai-agent.ts(inline system prompt string) - Context building: Edit
src/utils/ai-context.tsfor what data is sent to the agent - Tool action display: Edit
src/components/AiActionCard.tsx - Claude CLI arguments: Edit
src-tauri/src/claude_cli.rs(run_agent_stream()) - Shared agent adapters / Codex args: Edit
src-tauri/src/ai_agents.rs(keep Codex on the normal approval/sandbox path unless you are intentionally designing an advanced mode)