Searchi desktop
This Tauri 2 shell calls the same Rust core as the CLI and the real Google EmbeddingGemma 2 service. It provides folder indexing, native folder selection, progressive filename/content/semantic search, folder/extension/size/date/media-duration filters, keyboard navigation, escaped text and scoped image/audio/video previews, native open/reveal actions, persisted selected folders/resource settings, and a global shortcut. There are no mocked results or embeddings. Watchers and release installers remain roadmap work.
Develop
Install Node.js 24 LTS, Rust stable, and the platform prerequisites documented at https://v2.tauri.app/start/prerequisites/. Windows requires MSVC build tools and WebView2; Linux requires WebKitGTK and system development packages; macOS requires Xcode command line tools.
Before launching from a checkout, build and stage both native helpers from the repository root. These explicit setup commands access the network and verify pinned artifacts; they do not install tools globally:
python tools/embeddinggemma2/build_runtime.py --backend cpu --jobs 2
python tools/embeddinggemma2/stage_runtime.py --backend cpu
python tools/media-runtime/provision.py --stage
The decoder manifest currently has Windows/Linux x86-64 and ARM64 artifacts;
a vetted macOS decoder package remains a release gate. Build cpu in the
Windows VM. Production acceleration requires separate platform/hardware QA.
cd apps/desktop
npm ci
npm run build
npm run tauri dev
npm run dev previews layout in a browser but cannot index or search files. The app reports this limitation explicitly. Press Ctrl+K (Cmd+K on macOS) to focus search; arrow keys navigate results. Choose a folder through the native dialog or enter an absolute path. Open/reveal commands canonicalize the path, verify it is a current file, and require exact membership in the index. The webview has no general opener or filesystem capability. Page/paragraph source locations are displayed when supplied by the core; opening at that exact location is future work.
Ctrl+Shift+Space shows and focuses the running app on Windows/Linux; Shift+Cmd+Space does so on macOS. Registration failures appear under Folders & resources rather than preventing startup. Wayland sessions explicitly report the shortcut as unsupported; launcher access remains available. Registration uses the official Tauri global shortcut plugin. Closing the app exits it; background tray lifecycle is not implemented.
Selected roots and the CPU thread budget are stored in versioned settings.json beside the index. Writes use an atomic temporary-file replacement; invalid values never overwrite previous settings. Missing files use defaults, while corrupted/unsupported settings fail explicitly. Selected roots may remain listed while disconnected and are reindexed only on user request. The CPU budget defaults to one and is limited to eight. Indexing uses one worker; CPU inference respects the saved budget.
The desktop index is stored in the platform app-data directory under dev.searchi.desktop. Search uses a cached core reader while indexing runs on a separate blocking worker; a guard limits this shell to one indexing job at a time. Production inference automatically selects supported acceleration with CPU fallback. All model testing on the Windows VM must remain CPU only.
Automatic local semantic search
On first launch, the native app downloads and verifies the pinned Google model artifacts (310 MB text model plus 555 MB media projector, approximately 865 MB total) into app-managed storage and prepares the packaged embedding worker. No model paths, runtime paths, or terminal setup are required. The UI shows native download bytes, verification/warming states, the actual worker device, and explicit errors with a retry control. The first download requires network access; file extraction, embeddings, and queries stay local.
After a folder is indexed, unified document/media semantic indexing starts automatically when the model and packaged media helpers are ready. Images use actual pixels; video frames and full primary-stream audio windows use the Google media projector. Audio/music files also retain artist/title metadata for keyword retrieval. The UI reports unavailable decoder/runtime support and per-file failures while keeping text search available. Existing keyword results stay searchable during setup/indexing. Progress is indeterminate during embedding because the native command does not expose a chunk completion count. Failed automatic builds retry only after a changed index/status revision or an explicit rebuild, avoiding repeated failure loops. Status polls run once per second while setup/indexing/warming is active and stop when idle.
Each query captures one immutable filter snapshot. Keyword results appear first; real hybrid results follow after the query settles. src/search-state.ts bounds each lane to one active native request and one latest pending request, discards old revisions, and retries a busy request at most once. Escape clears both pending lanes and their timers; already-running native work finishes without changing cleared results. Hybrid updates preserve the selected file and keyboard focus where possible.
Run the async-state tests with Node.js 24 or newer:
node --test tests/search-state.test.mjs
For Windows VM UI testing, disable WebView2 GPU rendering as well, before starting Tauri in PowerShell:
$env:WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS = '--disable-gpu --disable-accelerated-video-decode'
$env:SEARCHI_FORCE_CPU = '1'
npm.cmd run tauri dev
Desktop design
The compact launcher follows the selected first visual direction with the searchi brand palette: blue #2563FF, dark #0B0F14, light #F8FAFC, lowercase wordmark, and “Find what matters. Locally.” Native operating-system window chrome remains native. The right pane shows real extracted passages and source locations, without invented PDF pagination or confidence scores.
Inter Variable is bundled locally with system font fallbacks. All interface icons come from Microsoft Fluent UI System Icons; no runtime CDN requests are made. Light/dark themes follow the operating system. Brief 120–160 ms opacity/transform motion respects reduced-motion settings, and forced-colors mode retains borders and focus visibility. Keyed result rows preserve selected files, keyboard focus, and scroll position during hybrid updates. Settings, filters, and model details use compact disclosures; errors open model details so recovery controls stay accessible.
Distributed notices are included in public/licenses/ and src-tauri/resources/licenses/: Inter SIL Open Font License, Microsoft Fluent icons MIT license. These are the actual upstream notices, not summaries.
Visual fidelity remains subject to native screenshot QA. Compilation and state tests alone do not verify visual appearance.
Verification and packaging
npm run build checks strict TypeScript and creates production frontend assets. npm run tauri build -- --no-bundle compiles the native shell when platform prerequisites are installed. Installer bundling is intentionally disabled until release icons, signing and native platform checks are complete. Native Windows, macOS, and Linux checks must be recorded separately; a frontend build does not prove the native shell works.
Media preview and quality
The result pane renders images and audio/video controls through Tauri's scoped asset protocol. Native preparation verifies the selected path belongs to a current indexed file before exposing it. There is no general filesystem access or local HTTP server. Players use metadata preload, never autoplay, and seek matched millisecond timestamps after metadata loads. Selection changes and Escape pause/unload playback; stale preparation responses cannot replace the current preview. Unsupported WebView codecs show an Open file fallback.
Opening the default application does not guarantee exact-location navigation. Preview seeking uses the returned window/frame start, which may differ from the actual utterance. The independent media quality report records real file recall, speech alignment failures, music hard negatives and unmet no-answer handling. Genuine multimodal support is implemented; production quality and native playback/visual interaction QA remain open gates.
Performance details
Normal results show the actual native search duration and latest result-display latency from input. The Performance details checkbox in Settings is opt-in and captured per request. Its expandable panel separates input debounce, intentional semantic delay, pending-lane queue, failed attempts and bounded retry wait, invocation time, native stage hierarchy and synchronous result DOM updates. First response and hybrid-final latency are distinct; keyword-only results do not claim semantic completion. Native spans use a command-relative clock and nested or parallel spans must not be summed. Invocation minus native total is explicitly an estimated transport/serialization/scheduling residual, not an exact IPC cost. DOM update timings do not claim actual screen paint or deferred media loading.
The local clipboard report excludes queries, paths, filenames, snippets and error strings. It captures available model/device/thread/runtime context without guessing missing values. Histories are bounded and dropped counts remain visible. Clipboard failure is explicit; no diagnostic telemetry is uploaded.
Reproducible documentation capture
The optional loopback harness in tools/desktop-capture serves this production-built
frontend against the actual shared Rust search engine and local Google model.
Browser activation requires explicit ?capture=1, a loopback HTTP origin and a
ready readme-capture bootstrap with an ephemeral nonce. Read-only search/status
commands use authenticated same-origin requests; indexed media uses restricted
fixture URLs. Indexing, dialogs, external opening and resource-setting mutations
are disabled. Ordinary browser previews remain disconnected and native Tauri
invocations/media URLs retain their existing implementation.
These documentation images show browser-rendered application content backed by real engine queries. They do not establish native OS chrome, global shortcuts, native playback or desktop interaction QA. The harness returns no mocked search results or replayed model output.