How the `install_sidestore_operation` Flow Works in iloader
The install_sidestore_operation flow is a three-stage pipeline—download, install, and pairing—that coordinates between a TypeScript frontend definition, a generic operation runner, and a Rust backend command to deploy SideStore onto iOS devices while streaming real-time progress events.
The install_sidestore_operation command serves as the primary deployment mechanism in the nab138/iloader repository for installing SideStore (and optionally LiveContainer) onto connected iOS hardware. This architecture separates concerns into a declarative UI layer, a generic orchestration handler, and a native Rust implementation that performs the actual sideloading work while emitting state updates through Tauri’s event system.
Frontend Operation Definition
The flow begins with a static configuration object defined in src/components/operations.ts. This Operation interface declares the metadata and sequential steps that the UI will render during execution.
export const installSideStoreOperation: Operation = {
id: "install_sidestore",
titleKey: "operations.install_sidestore_title",
successTitleKey: "operations.install_sidestore_success_title",
successMessageKey: "operations.install_sidestore_success_message",
steps: [
{ id: "download", titleKey: "operations.install_sidestore_step_download" },
{ id: "install", titleKey: "operations.install_sidestore_step_install" },
{ id: "pairing", titleKey: "operations.install_sidestore_step_pairing" },
],
};
This object enumerates the three discrete phases—download, install, and pairing—that map directly to the backend’s execution stages. The id field "install_sidestore" serves as the root identifier for both the event channel name and the Tauri command invocation.
Orchestrating the Flow with startOperation
When a user initiates installation, the frontend invokes the generic startOperation utility located in src/App.tsx. This function establishes the state management and event listening infrastructure before delegating to the Rust backend.
The orchestration follows three distinct phases:
- State Initialization – Resets the operation state to track started, completed, and failed steps.
- Event Listener Registration – Subscribes to Tauri events on the channel
operation_install_sidestoreusinglisten<OperationUpdate>(). - Command Invocation – Calls
invoke("install_sidestore_operation", params)to trigger the Rust routine.
<button
onClick={() => {
if (!ensuredLoggedIn() || !ensureSelectedDevice()) return;
startOperation(installSideStoreOperation, {
nightly: false,
liveContainer: false,
}).catch(e => console.error(e));
}}
>
{t("app.sidestore_stable")}
</button>
The startOperation handler accepts an InstallParams object containing boolean flags for nightly (determining which IPA variant to download) and liveContainer (controlling whether to bundle LiveContainer). These parameters pass through to the Rust command unchanged.
Backend Command Implementation in Rust
The actual work occurs in src-tauri/src/sideload.rs within the async function install_sidestore_operation. This command receives the AppHandle for event emission and the deserialized InstallParams struct.
pub async fn install_sidestore_operation(
app: tauri::AppHandle,
params: InstallParams,
) -> Result<(), String> {
// 1. Download the SideStore IPA
// 2. Sign and install on the device
// 3. Copy the pairing file
// Emitting events via app.emit_all() at each transition
}
The Rust implementation executes three sequential sub-tasks:
- Download – Fetches the appropriate SideStore IPA based on the
nightlyflag. - Install – Handles code signing and deployment to the connected iOS device.
- Pairing – Transfers the pairing file required for subsequent device communication.
At each transition point, the backend emits structured events using app.emit_all("operation_install_sidestore", OperationUpdate { ... }). These payloads carry a status field (started, finished, or failed) and the step identifier, enabling the frontend to update progress bars and status messages reactively.
Event-Driven State Synchronization
The frontend listener registered by startOperation processes the OperationUpdate events streaming from Rust. When an event arrives, the handler mutates the operationState to reflect the current step status, which drives the <OperationView> component’s rendered output.
This unidirectional data flow ensures that:
- UI progress indicators update immediately when a step starts.
- Completed steps accumulate in the
completedarray for visual checkmarks. - Errors trigger the
failedstate, displaying theAppErrorpayload to the user without manual polling.
Practical Usage Example
To trigger the installation flow programmatically from a custom component:
import { installSideStoreOperation } from './components/operations';
import { startOperation } from './App';
const deploySideStore = async (useNightly: boolean) => {
if (!ensureSelectedDevice()) return;
try {
await startOperation(installSideStoreOperation, {
nightly: useNightly,
liveContainer: false,
});
console.log("Installation completed successfully");
} catch (error) {
console.error(`Deployment failed: ${error.message}`);
}
};
This pattern leverages the same operation definition and backend command used by the built-in UI buttons, ensuring consistent behavior across the application.
Summary
- Operation Definition: Declared in
src/components/operations.tswith three steps: download, install, and pairing. - Frontend Orchestration: The
startOperationfunction insrc/App.tsxinitializes state, listens foroperation_install_sidestoreevents, and invokes the Tauri command. - Backend Execution: The
install_sidestore_operationasync function insrc-tauri/src/sideload.rsperforms the actual device work and emits progress events. - Event Bridge: Tauri’s
emit_allandlistenAPIs synchronize state between Rust and TypeScript without polling. - Reusable Architecture: The generic
Operationinterface andstartOperationhandler allow new installer flows to be added by defining a new operation object and corresponding Rust command.
Frequently Asked Questions
What parameters does install_sidestore_operation accept?
The command accepts an InstallParams object containing two boolean properties: nightly (determining whether to download the nightly or stable IPA build) and liveContainer (specifying whether to include LiveContainer in the installation bundle). These parameters originate in the UI and pass through to the Rust backend via Tauri's command invocation.
How does the frontend track the installation progress?
The frontend registers a Tauri event listener for the channel operation_install_sidestore before invoking the command. The Rust backend emits OperationUpdate structs with started, finished, or failed statuses at each step transition. The frontend listener captures these payloads and updates the reactive operationState, which the <OperationView> component renders as progress indicators and step completions.
Where is the IPA signing and installation logic implemented?
The actual device communication, code signing, and IPA installation occur in src-tauri/src/sideload.rs within the install_sidestore_operation function. This Rust code handles the low-level iOS deployment protocols, including transferring the binary to the device and installing the provisioning profile, while the TypeScript frontend remains responsible for UI state management.
Can this flow be adapted to install applications other than SideStore?
Yes. The architecture uses a generic Operation interface and the reusable startOperation handler. To install a different application, define a new operation object in operations.ts with the appropriate steps, implement a corresponding Tauri command in the Rust backend following the install_sidestore_operation pattern, and map the command ID to the operation ID. The event emission and state management infrastructure will work without modification.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →