← Back to Electron and Vue foundation team
See how it helps
Designing Safe, Non-Blocking
Tauri v2 Capabilities & Permissions (
Sidecar Binaries (
Tauri and Rust integration
Integrates Rust commands and native processes into Tauri with nonblocking execution, explicit permissions and controlled shutdown.
tauri-rust-integration
Team members using this skill
When is it useful?
Use it when desktop UI actions call Rust, share application state or start a bundled helper process.
What does it help you do?
- Uses nonblocking commands with typed serializable errors.
- Protects managed shared state and narrowly scoped capabilities.
- Packages target-specific sidecars and manages their process lifecycle.
Try asking this
Add a local sidecar that stops cleanly when the Tauri window exits. Start the packaged sidecar, cancel an active command and close the app. Verify typed errors reach the UI and no owned native process survives.
Detailed documentation
Read the skill’s original instructions, examples and checks in their authored language.
Show less
Tauri & Rust Integration
Tauri pairs a system WebView frontend with a Rust core process. Keep the Rust core responsive, type-safe, and governed by Tauri v2's fine-grained capability security model.
Designing Safe, Non-Blocking #[tauri::command] Handlers
- Use
asynccommands for all I/O and subprocess work:- Synchronous
#[tauri::command] fn my_cmd()runs on the main UI thread and freezes the window if it blocks on disk, SQLite, or child processes. Declare#[tauri::command] async fn my_cmd(...) -> Result<OutputDto, AppError>.
- Synchronous
- Serializable, typed error handling (
Result<T, AppError>):- Implement
serde::Serializeon a structuredAppError { code: &'static str, message: String }(usingthiserror) so the frontend receives machine-readable error codes rather than opaque string panics.
- Implement
- Thread-safe managed state (
tauri::State):- Register shared application state (
app.manage(AppState { ... })) wrapped intokio::sync::Mutex/RwLock(for async guards held across.await) orstd::sync::Mutex(only for fast synchronous lock/unlock blocks—never hold astd::sync::MutexGuardacross.await!).
- Register shared application state (
- Streaming events & binary payloads:
- For high-frequency progress streams or terminal/agent logs, use
tauri::ipc::Channel<EventPayload>passed as a command argument (or scopedapp.emit_to(window_label, ...)), which avoids global broadcast overhead.
- For high-frequency progress streams or terminal/agent logs, use
Tauri v2 Capabilities & Permissions (src-tauri/capabilities/)
Tauri v2 enforces an explicit Access Control List (ACL) per window/webview:
- Define capability files in
src-tauri/capabilities/default.jsontargeting specific windows ("windows": ["main"]). - Grant only the exact plugin permissions required (
"dialog:allow-open","fs:allow-app-data-recursive","opener:default"). - When exposing custom Rust commands in a workspace plugin or
build.rs, registerconst COMMANDS: &[&str]and declare explicitallow/denyscopes rather than opening unrestricted filesystem or shell access.
Sidecar Binaries (externalBin) & Lifecycle
Remember that Tauri does not bundle Node.js:
- If the application requires a local Node/Python/Go daemon, compile it into a standalone executable per target triple (
binaries/server-aarch64-apple-darwin,binaries/server-x86_64-pc-windows-msvc.exe) and register"externalBin": ["binaries/server"]intauri.conf.json. - Spawn the sidecar from Rust via
app.shell().sidecar("server")?.args([...]).spawn()?, store theCommandChildhandle in managed state, and hookRunEvent::ExitRequested/RunEvent::Exitin.build(...).run(|app_handle, event| ...)to terminate the sidecar cleanly when the app exits.
Included files 1
SKILL.md
