16 KiB
Build and release targets
Use stable Rust, Node 24 LTS, Python 3.11+, Git, CMake, and a native C/C++ toolchain. Python provisions the pinned Google runtime and model; inference runs in a native process. Default Rust tests do not download model assets.
Windows needs Visual Studio C++ build tools, a Windows SDK, and WebView2. Linux desktop builds need WebKitGTK 4.1 development libraries; macOS needs Xcode command-line tools. Follow the Tauri prerequisites. Headless Linux CLI/worker builds do not need WebKitGTK or a display server.
macOS runtime preparation embeds Metal kernel sources and inspects the static worker's Apple dependencies before staging. See macOS runtime for the prepared workflow and explicitly unexecuted native checks. Headless builds still need a C/C++ compiler, linker, CMake, and Rust: SQLite, USearch, NumKong, and the Google worker contain native code.
Windows CPU development
Run from the repository root. Building the worker clones a pinned llama.cpp revision and verifies/applies its memory patch. Model provisioning explicitly uses the network and verifies both Google assets, approximately 865 MB total. The Python CMake package is needed only when CMake is absent from PATH.
python -m pip install cmake
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
python tools/embeddinggemma2/download.py
$env:SEARCHI_FORCE_CPU = '1'
$env:SEARCHI_GEMMA_MODEL_DIR = (Resolve-Path .searchi/models/embeddinggemma2).Path
$env:SEARCHI_GEMMA_WORKER = (Resolve-Path .searchi/runtime/cpu/Release/searchi-gemma-worker.exe).Path
cargo fmt --all --check
cargo clippy --workspace --all-targets --locked -- -D warnings
cargo test --workspace --locked
cargo test -p searchi-semantic --test gemma_cpu -- --ignored --nocapture
cargo test -p searchi-service --test google_cpu -- --ignored --nocapture
cargo test -p searchi-service --lib google_cpu_preserves -- --ignored --nocapture
The explicit internal CPU worker uses the static MSVC CRT on Windows; normal
auto builds use the shared runtime described below. Staging verifies a complete
candidate resource directory, then swaps it into place under a process lock.
Its recovery journal restores an interrupted swap on the next invocation;
failed restoration retains the previous backup. Existing unrelated fonts and
media resources are preserved. Fault-injected process interruption is tested;
power-loss durability is not certified. Add
--bundle-model to staging for an offline model bundle after downloading;
otherwise desktop setup provisions verified models on first launch. Search
itself performs no network inference or downloads. The worker now uses the verified media projector for genuine image/audio embeddings. The FFmpeg script stages verified standalone decoders and their notices.
The desktop is a standalone Cargo workspace and needs separate validation:
cargo test --manifest-path apps/desktop/src-tauri/Cargo.toml --locked
Set-Location apps/desktop
npm ci
npm run format:check
npm test
npm run build
$env:WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS = '--disable-gpu --disable-accelerated-video-decode'
npm run tauri -- dev
Every Windows VM inference/rendering test must stay CPU only. Production
supports --backend auto|metal|vulkan|cuda builds with CPU fallback; do not
exercise those acceleration backends in this VM. Their execution and failure
recovery require validation on the corresponding release hardware.
Isolated native desktop validation
Set SEARCHI_DATA_DIR to an absolute directory to isolate the desktop's
settings and index for release QA or portable use. Normal launches use the OS
app-data directory. Invalid overrides fail startup instead of falling back to
the user's regular data. Model downloads still use the configured model
directory or managed cache, so isolated tests should also configure a verified
fixture model directory in their own settings.
$env:SEARCHI_DATA_DIR = 'C:\searchi-qa-data'
$env:SEARCHI_FORCE_CPU = '1'
$env:WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS = '--disable-gpu --disable-accelerated-video-decode'
Extract and launch the entire Release archive outside the source checkout. Direct Cargo release builds must embed the frontend:
cargo build --manifest-path apps/desktop/src-tauri/Cargo.toml --release --features custom-protocol --locked
The crate rejects Release compilation without this feature; the Tauri build
CLI also needs --features custom-protocol explicitly for this crate. A
development-server URL is not a release gate.
Record native window interaction separately from process startup, browser
screenshots and worker inference; those are different release gates.
Headless Linux Google search
These are the current script and CLI interfaces, not evidence of an executed
Linux release. On a native Linux build host with Vulkan development libraries
and glslc, run from the repository root:
On Ubuntu 24.04, the native worker build prerequisites are build-essential,
cmake, git, pkg-config, libvulkan-dev, glslc, and spirv-headers.
The last package supplies the SPIR-V CMake configuration required by the pinned
Vulkan backend. These build tools do not enable GPU execution in tests.
python3 tools/embeddinggemma2/build_runtime.py --backend auto --jobs 2
python3 tools/embeddinggemma2/download.py
python3 tools/media-runtime/provision.py
cargo build --release -p searchi-cli --locked
./target/release/searchi index --db searchi.sqlite --root /path/to/documents
./target/release/searchi embed --db searchi.sqlite --model-dir .searchi/models/embeddinggemma2 --embedding-worker .searchi/runtime/auto/searchi-gemma-worker --ffmpeg .searchi/media-runtime/bin/ffmpeg --ffprobe .searchi/media-runtime/bin/ffprobe --cpu-threads 1
./target/release/searchi search --db searchi.sqlite 'supplier cancellation terms' --model-dir .searchi/models/embeddinggemma2 --embedding-worker .searchi/runtime/auto/searchi-gemma-worker --cpu-threads 1
embed builds document, image, video and audio/music vectors by default. Use
--text-only explicitly to omit media. Default media indexing needs paired
FFmpeg/FFprobe paths or packaged helpers beside the installed CLI.
This normal worker detects usable acceleration and falls back to CPU. Internal
CPU-only model tests may use --backend cpu and SEARCHI_FORCE_CPU=1; those
test artifacts are not a separate distribution edition.
Linux headless archive validation
The Linux x86-64 normal worker layout includes baseline and optimized CPU modules, an optional Vulkan module and adjacent core libraries. The builder audits ELF dependencies and origin-relative lookup before writing a hashed runtime inventory. ARM and other distribution/ABI combinations remain separate release gates.
After building the normal worker, release CLI and pinned media helpers, prepare an unsigned headless development candidate:
python3 tools/package_linux.py
python3 tools/package_linux.py --compression xz
python3 tools/embeddinggemma2/linux_smoke.py --worker .searchi/runtime/auto/searchi-gemma-worker --models .searchi/models/embeddinggemma2 --output .searchi/packages/linux-worker-smoke.json
python3 tools/embeddinggemma2/linux_smoke.py --worker .searchi/runtime/auto/searchi-gemma-worker --models .searchi/models/embeddinggemma2 --output .searchi/packages/linux-baseline-smoke.json --baseline
The packager accepts explicit --executable, --runtime, --media and
--llama-license paths when builds use separate target/cache directories.
It packages only approved runtime files, pinned decoders and notices, with
normalized archive metadata, executable modes and per-file checksums. It
excludes model caches and user indexes/settings. The smoke checks copy the
runtime outside its build tree and run genuine Google code inference on CPU;
the baseline check omits optimized CPU modules from its temporary extraction.
They do not exercise GPU providers or certify older physical CPUs, installers
or desktop behavior. Archive extraction and installed CLI search must also
be verified before a release gate is closed.
The default archive uses gzip; --compression xz produces .tar.xz with the
same normalized TAR members, file checksums and executable modes. XZ uses the
standard library's preset 6. The extraction smoke accepts either format. A
smaller download does not change runtime behavior or ABI requirements.
Always use the current normal runtime directory, not a copied historical
desktop staging cache. A valid old checksum inventory alone does not prove
compatibility with the current foreground query protocol. Before packaging,
exercise actual query-role inference with the selected worker; then run the
full extracted archive smoke. A legacy worker lacking --role query can build
document vectors while failing foreground search. The archive smoke retains
captured CLI error output when a command exits unsuccessfully.
Normal runtime inventories now include build-input provenance. Rebuild the normal runtime before staging historical caches; source changes invalidate their inventory even if the stored file checksums are valid. See runtime provenance for scope and actual validation.
The optional Linux missing-loader check requires explicit root execution and util-linux mount namespaces/chroot. It never escalates privileges and verifies a private namespace before creating an isolated filesystem:
sudo python3 tools/embeddinggemma2/linux_loader_smoke.py --worker .searchi/runtime/auto/searchi-gemma-worker --models .searchi/models/embeddinggemma2 --output .searchi/packages/linux-missing-loader.json
It runs automatic device selection with no forced-CPU override, but contains no Vulkan loader, driver configuration or GPU devices, so only CPU inference can execute. This is distinct from testing an actual GPU or recovering device loss.
searchi setup --model-dir PATH is an alternative verified model-provisioning
command. It provisions model assets, not the native worker. Package the worker
separately and pass its path to headless embedding/search. Each short-lived CLI
search starts a model process; the desktop retains a prewarmed query worker.
Cross-compilation and native release matrix
Normal distribution worker builds and staging default to auto: Metal on
macOS, Vulkan on Windows/Linux, with CPU fallback in the same application.
Users do not choose a CPU/GPU edition or rebuild for their graphics card.
Windows/Linux build machines need the Vulkan SDK including glslc. Windows
x64 provisioning now downloads the pinned, checksum-verified official SDK into
the workspace using copy-only mode; it does not install drivers or change the
system environment. Linux builders provision their distro's Vulkan development
tools. Missing required tools fail release preparation rather than omitting GPU.
The compilation SDK is not an end-user requirement. Explicit --backend cpu
commands in the VM development sections are internal test configurations.
The shared Rust engine/service has no GUI dependency. Install a destination
Rust target with rustup target add TARGET, then build using
cargo build -p searchi-cli --target TARGET --locked. This also requires the
target C/C++ toolchain, linker, and SDK for bundled SQLite and the vector index.
The separate native Google worker must be compiled for the same destination;
installing a Rust target does not cross-compile it. The current Python runtime
script configures the host toolchain; it does not expose a CMake cross-toolchain
file interface. Record each verified host/target pair before claiming support.
| Release host | Intended artifacts | Remaining validation |
|---|---|---|
| Windows | Windows CLI, worker, desktop installer | Installer, upgrade, signing, GPU hardware |
| macOS | Apple Silicon/Intel CLI, worker, desktop bundle | Native builds, architecture parity, Metal, notarization |
| Linux | CLI, worker, desktop packages | Native builds, distribution ABI, webview, acceleration |
Use native runners for dependable desktop releases. Platform webviews, packaging tools, SDKs, and signing impose additional constraints. macOS signing/notarization requires Apple tooling and credentials. See the Tauri Windows installer cross-build caveats.
CI and packaging gates
Windows archive for source installations
Stage the normal hardware-detecting worker and media helpers, then build an embedded-frontend desktop binary and collect its runtime files:
python tools/embeddinggemma2/build_runtime.py --backend auto --jobs 2
python tools/embeddinggemma2/stage_runtime.py --backend auto
python tools/media-runtime/provision.py --stage
Set-Location apps/desktop
npm run tauri -- build --features custom-protocol --no-bundle
Set-Location ../..
python tools/package_windows.py
To include the CLI and read-only MCP server in this source archive:
cargo build --release -p searchi-cli --locked
python tools/package_windows.py --cli target/release/searchi.exe
The additional binary is named searchi-cli.exe; searchi.exe remains the
desktop launcher. Its model cache and database must be selected explicitly,
as described in agent integration. This option does not
add the CLI to the already published v0.1.0 installer.
The generated .searchi/packages/searchi-windows.zip contains the desktop,
matching-architecture Google worker, FFmpeg/FFprobe and notices. It excludes
model caches, local settings and indexes. PACKAGE.json records SHA-256 for
each included file. Extract the entire archive before launching searchi.exe.
First launch uses normal verified model setup. WebView2 remains a Windows
prerequisite. The normal x64 archive ships unchanged Microsoft release CRT
DLLs with their redistribution notice; Visual Studio is not required to run it.
The Windows archive includes baseline and optimized CPU modules, selected
using CPU and OS capabilities, and
the verified Vulkan loader DLL and its license; GPU availability is detected at
runtime, with CPU fallback. The SDK is used only to compile the app.
All runtime DLLs are listed by size and SHA-256 in runtime-libraries.json.
Packaging also verifies the original pinned decoder ZIP and compares staged
FFmpeg/FFprobe, notices and manifest against it. Keep that verified archive in
.searchi/media-runtime while preparing the package; changed staged helpers
or notices are rejected before replacing a previous archive.
Staging and packaging reject missing or changed listed dependencies before
replacing output. CPU-only VM smoke tests can also omit optimized modules to
exercise the packaged baseline; this does not certify older physical hardware.
This is an unsigned development archive, not a production installer. Native launch, clean-machine dependencies, upgrades and signatures must still be verified. The packager rejects mixed architectures and preserves a previous archive if validation fails. It does not certify GPU dependency packaging.
CI status and installer gates
Gitea Actions are disabled for this repository at the owner's request after repeated failure emails (2026-10-12). Existing workflows remain as references: GitHub defines native OS matrices; Gitea targets its available Ubuntu runner. A workflow declaration does not prove a platform was tested; Linux/macOS gates remain open until actual job evidence exists. Current workflow checks do not certify the separately built Google worker or execute downloaded-model tests automatically.
Desktop bundles remain disabled during development. Before enabling release installers, stage the target worker, retain dependency/model notices, verify clean-machine launch and setup, run native Google smoke tests, and complete upgrade/migration, signatures, and rollback checks. Optional offline bundles need both verified model files. See semantic bounds and evidence for current corpus, localization, and performance limitations. Keep signing keys, repository tokens, and model credentials outside source control. FFmpeg provisioning supports manifest-pinned Windows/Linux x86-64 and ARM64 artifacts; Windows and Linux x86-64 startup and CPU decoding have executed here; other architectures and macOS decoder packaging remain gates. See media runtime provenance and measured media limitations.