new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Tauri · all subjects

commands & plugins

24 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Command system for calling Rust from frontend

Tauri provides a command system for calling Rust functions from the web app with type safety. Commands are defined using the #[tauri::command] attribute, can accept arguments and return values, support async operations, and can return errors.

Basic command definition and invocation

Commands are defined in src-tauri/src/lib.rs with the #[tauri::command] attribute. They must be registered using .invoke_handler(tauri::generate_handler![command_name]) in the builder. Frontend invokes them using invoke('command_name') from @tauri-apps/api/core.

Commands in lib.rs cannot be marked pub

Commands defined in lib.rs cannot be marked as pub due to a limitation in glue code generation. Marking them pub results in error E0255 with message 'the name `__cmd__command_name` is defined multiple times'.

Commands in separate modules must be marked pub

When defining commands in separate modules (e.g., src-tauri/src/commands.rs), they must be marked as pub. The module must be declared in lib.rs and commands passed to generate_handler with the module prefix (e.g., commands::my_custom_command).

Command names must be unique

Command names must be unique across all modules. The module prefix used in generate_handler is not part of the command name—the command is still invoked from frontend using just the command name.

WASM frontend calling invoke without arguments

When using a Rust frontend (WASM) to call invoke() without arguments, two separate bindings are needed via wasm_bindgen: one for invoke without arguments (js_name = invoke) and one for invoke with arguments (default invoke). This is because Rust does not support optional arguments.

Command arguments passed as JSON with camelCase keys

Arguments are passed to Tauri commands as a JSON object with camelCase keys. Arguments can use snake_case in Rust code by adding the rename_all = "snake_case" attribute to the #[tauri::command] macro.

Command return types require serde::Serialize

Returned data from commands can be of any type as long as it implements serde::Serialize. The invoke function returns a promise that resolves with the returned value.

Returning array buffers from commands

To return large data like files or HTTP responses optimally, return types that implement serde::Serialize are serialized to JSON which can be slow. Use tauri::ipc::Response instead for array buffers: `tauri::ipc::Response::new(data)` for optimized transfer.

Command error handling with Result

Command handlers can return errors by using Result<T, E> as the return type. If the command returns an error, the promise rejects; otherwise it resolves. Error types must implement serde::Serialize.

Custom error types for commands using thiserror

Custom error types can be created using the thiserror crate by deriving the Error trait on an enum. The error type must manually implement serde::Serialize to serialize to JSON. This makes errors explicit and gives full control over serialization.

Async commands executed on separate task

Async commands are executed on a separate async task using async_runtime::spawn, not on the main thread. Commands without the async keyword are executed on the main thread unless defined with #[tauri::command(async)].

Borrowed arguments in async commands limitation

Async commands cannot include borrowed arguments like &str or State<'_, Data> in their signature. This limitation is tracked at https://github.com/tauri-apps/tauri/issues/2533. Workarounds include converting to owned types (e.g., &str to String) or wrapping return type in Result.

Channel for streaming data to frontend

Tauri channels are the recommended mechanism for streaming data such as streamed HTTP responses to the frontend. Channels use type tauri::ipc::Channel<T> where T is the data type to send, and support async operations for progressive notifications.

Accessing WebviewWindow in commands

Commands can access the WebviewWindow instance that invoked the message by including tauri::WebviewWindow as a parameter. The window provides methods like label() to identify it.

Accessing AppHandle in commands

Commands can access an AppHandle instance which provides access to app state and functionality like app_dir path and global shortcut manager. AppHandle is obtained by including it as a parameter in the command signature.

Generic runtime parameter for AppHandle and WebviewWindow

AppHandle and WebviewWindow both take a generic parameter R: Runtime. When wry feature is enabled (default), generic defaults to Wry runtime. To use different runtimes or mock runtime, explicitly declare generic type in command signature using <R: Runtime>.

Accessing raw request in commands

Commands can access the full tauri::ipc::Request object which includes the raw body payload (accessible via request.body()) and request headers (via request.headers()). Raw body is accessed as tauri::ipc::InvokeBody::Raw(data).

Sending raw request body from frontend

Frontend can send raw request body to commands by providing an ArrayBuffer or Uint8Array as the payload argument to invoke(), and include request headers in the third argument: await __TAURI__.core.invoke('cmd', data, { headers: {...} })

Registering multiple commands

Multiple commands must be registered in a single invoke_handler call using tauri::generate_handler![cmd_a, cmd_b]. Calling invoke_handler multiple times will only use the last call. All commands are passed as a single array to generate_handler.

Event system for frontend-Rust communication

Tauri provides an event system for communication between frontend and Rust as an alternative to commands. Events are not type-safe, are always async, cannot return values, and only support JSON payloads. Events are simpler but less powerful than commands.

Global events emit to all listeners

Global events are triggered using event.emit() or WebviewWindow#emit() and are delivered to all listeners. They are broadcast across the entire application.

Webview-specific events emit to specific webview

Webview-specific events are triggered using event.emitTo(webviewLabel, eventName, payload) or WebviewWindow#emitTo() and are only delivered to listeners on that specific webview. They are not triggered to global event listeners.

Catch-all event listener with Any target

To listen to any event including webview-specific ones, provide the option { target: { kind: 'Any' } } to event.listen(). This makes the listener act as a catch-all for all emitted events.

Give your agent this brain