IPC

Compiler-derived Tauri commands, bindings, and typed events.

Tauri replaces Electron's preload bridge with a small, compiler-typed command surface. The webview calls tauri.<domain>.<method>() (or useTauri()); Rust owns privileged work. There is no Node API in the UI and no hand-written Zod IPC schema. The capabilities ACL permits plugin APIs, while Rust types constrain the custom commands.

The pipeline

#[tauri::command] and #[specta::specta] annotate a function in src-tauri/src/commands/. collect_commands![] in src-tauri/src/lib.rs registers it for both Tauri and tauri-specta. Specta generates the committed src/lib/bindings.ts; the small wrappers in src/lib/tauri/ make that generated surface pleasant to consume.

#[tauri::command]
#[specta::specta]
pub fn platform() -> String {
    std::env::consts::OS.to_string()
}

pnpm dev regenerates bindings in debug builds. The export_bindings Rust test also regenerates them during cargo test, and CI fails if the committed result drifts. Never edit bindings.ts directly.

Shipped command surface

There are 15 registered commands across seven frontend domains:

DomainCommands
appversion, platform, open_external
secureget, set, delete
logspath, tail, openFolder
windowshowWindowSystemMenu
diagnosticsget
updategetStatus, check, download, install
fileDialog/File-plugin wrappers; no custom Rust command

Use the domain API rather than invoke() directly:

import { tauri } from '@/lib/tauri'

const report = await tauri.diagnostics.get()
await tauri.app.openExternal('https://example.com')

In React, useTauri('logs') returns the same typed singleton. The legacy use-conveyor.ts remains because ported components still use it. It adapts real Tauri modules, but setLocale() and windowSetTitlebarDark() are intentional no-ops; new code should use tauri / useTauri.

Events

Rust-to-webview events use onTauriEvent() from src/lib/tauri/events.ts. Its event map types single-instance, settings-changed, and update-status. For example, a second launch focuses the current window in Rust and emits its argv; the frontend parses that input through the navigation allow-list before it navigates. The updater emits its typed status after each transition.

Add a command

Add a narrowly typed Rust function with both Tauri and Specta attributes.
Add it to collect_commands![]; the builder already feeds invoke_handler.
Run pnpm dev or cargo test --manifest-path src-tauri/Cargo.toml, then commit the generated bindings.
Add the narrowest capability permission when the command uses a plugin API, then create a wrapper in the appropriate src/lib/tauri/ domain.
Call the wrapper and handle its Result/rejected promise in the UI.

An ungranted plugin call is denied by Tauri before the implementation runs. Do not solve that by adding a wildcard: identify the required permission and scope it in Capabilities.

On this page