Architecture
rScoop is a Tauri 2 app. Rust backend, SolidJS frontend, talking to each other over Tauri’s IPC bridge.
Rust backend
The backend lives in src-tauri/src/. Here’s how it’s organized:
lib.rsis the entry point. Wires up all Tauri plugins, resolves the Scoop root path, and creates the sharedAppState(cached packages, Scoop directory).commands/has 30+ Tauri commands grouped by domain: search, install, update, uninstall, buckets, doctor, VirusTotal, settings, shims, cache, version switching, profile export/import, and more. These are what the frontend calls.cold_start.rsruns on first launch to preload Scoop metadata. Emitscold-start-finishedandscoop-readyevents that the frontend waits for before rendering.- Execra is the runtime used for long-running jobs. It provides process execution, streamed output, cancellation, and structured outcomes for Scoop jobs, cleanup, update flows, and VirusTotal scans.
utils.rshas shared helpers for parsing manifests, caching bucket metadata, resolving Scoop state, and working with shims/shortcuts.tray.rsbuilds the system tray menu from installed Scoop apps. Extracts real exe icons, supports pinning/hiding apps, and handles show/hide operations.scheduler.rsis the background loop for auto-updating buckets and packages on a configurable interval. Persists across restarts.operations.rsmanages the install/update/uninstall queue. Operations run in the background via Tokio tasks, streaming progress to the frontend throughtauri-plugin-log. The queue is FIFO; queued items can be cancelled individually.
SolidJS frontend
The frontend lives in src/. Four pages plus settings, each with its own components:
App.tsxis the root component. Listens for backend lifecycle events, manages the update banner, handles routing.pages/contains SearchPage, InstalledPage, BucketPage, DoctorPage, SettingsPage.hooks/wraps Tauri command calls.useInstalledPackageshandles refreshes,useBucketSearchdoes paginated discovery,usePackageOperationsorchestrates install/update flows.stores/holds reactive state shared across components. Installed packages cache, held packages, settings, operations queue state.components/page/mirrors the page structure. Each page has its own subfolder of components.
How data flows
- User clicks something (e.g. “Install”).
- A hook calls the matching Rust command via
@tauri-apps/api/core.invoke. - The Rust command either delegates the core package action to Scoop through Execra or handles the task natively in Rust. Search indexing, manifest parsing, cache cleanup, doctor checks, shim inspection, profiles, bucket metadata, scheduling, and UI-facing state are rScoop logic, while package install/update/uninstall behavior stays with Scoop.
- The hook updates SolidJS signals/stores, which re-renders the UI. Completion triggers follow-up refreshes (e.g. reloading the package list).
Profile export & import
The commands/profile.rs module handles serializing and restoring a user’s rScoop + Scoop setup:
- Export: Gathers installed apps, buckets, held packages, Scoop global config, and rScoop preferences. Each group is optional, and the frontend picks which to include. Output is a versioned JSON document.
- Import: Parses the JSON leniently (unknown fields ignored, malformed entries skipped), then applies the selected groups in order: rScoop settings → Scoop config → bucket cloning → app installs (queued into the operations system) → holds. Import only adds or updates data; it does not uninstall anything.
- The frontend has its own Export Profile and Import Profile modals that preview the file, let you pick groups, and show warnings before applying.
Caching
- In-memory: installed packages and bucket metadata are cached in
AppStateto avoid hammering Scoop on every render. Invalidated by a fingerprint check (did the apps directory change?). - On-disk: the expanded bucket search index is saved locally so discovery works offline. You control when to refresh it.
- localStorage: view preferences (selected tab, layout mode) persist across restarts via
createStoredSignal.