The Difference Between tauri-runtime and tauri-runtime-wry in Tauri Architecture

tauri-runtime is the abstract trait layer that defines what a runtime must do, while tauri-runtime-wry is the concrete implementation that connects Tauri to the WRY webview engine and TAO windowing system.

The Tauri framework uses a layered architecture to separate high-level application APIs from low-level system interactions. Understanding the difference between tauri-runtime and tauri-runtime-wry is essential for developers who want to extend Tauri or understand how it bridges Rust code with native webviews. These two crates work together in the tauri-apps/tauri repository to provide the abstraction and implementation that powers every Tauri application.

What Is tauri-runtime?

tauri-runtime acts as the glue layer between the high-level Tauri crates (tauri, tauri-builder, etc.) and any low-level webview implementation. Located in crates/tauri-runtime/src/lib.rs, this crate defines the generic traits that the rest of Tauri uses to stay agnostic of the underlying webview engine.

The core abstractions include:

  • Runtime – The primary trait that any backend must implement
  • RuntimeHandle – A cloneable handle for sending messages to the runtime
  • WindowDispatch – Interface for window-specific operations
  • WebviewDispatch – Interface for webview-specific operations

This crate contains only pure Rust code and depends on utility crates like serde, http, raw-window-handle, and dpi. It contains no platform-specific webview code, making it a lightweight dependency for plugins and core libraries that need to reference runtime concepts without pulling in heavy system libraries.

What Is tauri-runtime-wry?

tauri-runtime-wry provides the concrete implementation of the Runtime trait for the WRY webview library. Found in crates/tauri-runtime-wry/src/lib.rs, this crate bridges the abstract tauri-runtime interface with the actual wry crate (version 0.54.0) and the tao windowing library.

According to the ARCHITECTURE.md in the Tauri repository, this crate "opens up direct systems-level interactions specifically for WRY" by implementing the Runtime trait for the Wry<T> type. It handles platform-specific functionality such as printing, monitor detection, dialog handling, and clipboard operations by forwarding calls to the underlying OS APIs through WRY and TAO.

The Cargo.toml in crates/tauri-runtime-wry/Cargo.toml declares dependencies on both wry and tauri-runtime (path = "../tauri-runtime"), along with platform-specific crates like windows, gtk, or objc2 depending on the target OS.

Key Architectural Differences

Abstraction vs. Implementation

tauri-runtime declares what a runtime must be able to do—create windows and webviews, run tasks on the main thread, query monitors, and handle events—but leaves the how to backend implementations. tauri-runtime-wry supplies the how by creating real wry::WebView objects, translating TAO window events into Tauri’s WindowEvent, and implementing all platform-specific APIs.

Dependency Footprint

  • tauri-runtime: Pure Rust with no platform-specific webview dependencies
  • tauri-runtime-wry: Heavy dependencies on wry, tao, and platform-specific system crates

Usage Patterns

When you call tauri::Builder::default().run(...), you are implicitly using tauri-runtime-wry as the default backend. The high-level tauri crate imports tauri-runtime to maintain agnosticism, while tauri-runtime-wry is re-exported and instantiated automatically unless you provide a custom runtime implementation.

How They Work Together in the Tauri Stack

The separation allows Tauri to support multiple webview backends in theory, though WRY is currently the only official implementation. The ARCHITECTURE.md documentation explicitly distinguishes these components: tauri-runtime serves as the "glue layer between tauri itself and lower level webview libraries," while tauri-runtime-wry provides the "direct systems-level interactions specifically for WRY."

When building a Tauri application, the flow works as follows:

  1. Your application code uses tauri::Builder, which depends on the abstract Runtime trait from tauri-runtime
  2. At runtime, the builder instantiates the Wry struct from tauri-runtime-wry, which implements the Runtime trait
  3. Method calls on the App or Window types are dispatched through the trait interface to the concrete WRY implementation

Working with the Runtime Crates

Using the High-Level API (Default)

Most developers never interact with these crates directly. The default Tauri setup automatically uses tauri-runtime-wry behind the scenes:

use tauri::{Builder, generate_context};

fn main() {
    Builder::default()
        .run(generate_context!())
        .expect("error while running tauri application");
}

The Builder internally creates a Wry runtime, but your code only depends on the abstract tauri crate interface.

Implementing a Custom Runtime

To create a custom backend (for example, targeting a different webview engine), you would implement the traits defined in tauri-runtime:

use tauri_runtime::{
    Runtime, RuntimeHandle, WindowBuilder, WindowEvent, RunEvent, Result,
};

struct MyRuntime;
struct MyHandle;

impl Runtime<()> for MyRuntime {
    type WindowDispatcher = MyWindowDispatcher;
    type WebviewDispatcher = MyWebviewDispatcher;
    type Handle = MyHandle;
    type EventLoopProxy = (); // omitted for brevity

    fn new(_: RuntimeInitArgs) -> Result<Self> { Ok(MyRuntime) }

    // … implement all required methods, delegating to your own webview engine …
}

All required methods are defined in crates/tauri-runtime/src/lib.rs. By providing a concrete implementation, you could replace the default WRY backend while maintaining compatibility with the Tauri ecosystem.

Accessing Platform-Specific Features

Some methods, like printing, are implemented specifically in tauri-runtime-wry and exposed through the abstract interface:

use tauri::{Manager, Runtime};

fn print_window<R: Runtime>(app: &tauri::App<R>) {
    // The `print` method is implemented by `tauri-runtime-wry`
    let window = app.get_window("main").unwrap();
    window.print().expect("failed to print");
}

The print method forwards to the native print dialog via the WRY implementation found in the window.rs module of tauri-runtime-wry.

Summary

  • tauri-runtime defines the abstract Runtime trait and related interfaces in crates/tauri-runtime/src/lib.rs, serving as a platform-agnostic glue layer
  • tauri-runtime-wry provides the concrete Wry<T> implementation in crates/tauri-runtime-wry/src/lib.rs, bridging Tauri to the WRY webview and TAO windowing libraries
  • The separation allows Tauri core to remain agnostic while enabling pluggable backend implementations
  • Default Tauri applications use tauri-runtime-wry automatically through tauri::Builder
  • Custom runtime implementations require implementing the traits defined in tauri-runtime

Frequently Asked Questions

Can I use tauri-runtime without tauri-runtime-wry?

Yes, if you are building a custom runtime implementation or a plugin that only needs to reference the abstract trait definitions. However, to run an actual Tauri application with a webview, you need a concrete implementation like tauri-runtime-wry or your own custom backend that implements the Runtime trait.

What is WRY and how does it relate to tauri-runtime-wry?

WRY is the standalone Rust webview library maintained by the Tauri team that wraps native webview engines (WebKit on macOS, WebView2 on Windows, WebKitGTK on Linux). tauri-runtime-wry is the adapter crate that implements Tauri's abstract runtime interface using WRY as the underlying engine, effectively translating Tauri API calls into WRY method invocations.

How do I create a custom runtime implementation?

To create a custom runtime, implement the Runtime trait defined in crates/tauri-runtime/src/lib.rs along with its associated types like WindowDispatcher and WebviewDispatcher. Your implementation must handle event loop management, window creation, and webview instantiation using your chosen backend. This is an advanced use case typically only necessary when integrating Tauri with alternative webview engines or embedded systems.

Where are the runtime traits defined in the source code?

The core runtime traits—including Runtime, RuntimeHandle, WindowDispatch, and WebviewDispatch—are defined in crates/tauri-runtime/src/lib.rs according to the Tauri source code. The concrete implementation for the WRY backend resides in crates/tauri-runtime-wry/src/lib.rs.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →