# Tauri Plugin System: Architecture, Official Plugins, and Implementation Guide

> Explore the Tauri plugin system, a Rust framework for adding native functionality. Discover official plugins and learn implementation details with our comprehensive guide.

- Repository: [Tauri/tauri](https://github.com/tauri-apps/tauri)
- Tags: deep-dive
- Published: 2026-02-26

---

**The Tauri plugin system is a Rust-based extension framework that enables developers to add native functionality to Tauri applications through reusable crates exposing both backend commands and JavaScript APIs via the `tauri::plugin::Builder` pattern.**

The Tauri plugin system provides the primary extension mechanism for the `tauri-apps/tauri` ecosystem, allowing developers to encapsulate platform-specific features into modular components. Each plugin consists of a Rust crate that registers invoke handlers and lifecycle callbacks with the core runtime, paired with TypeScript bindings that expose type-safe methods to the frontend webview. This architecture maintains strict separation between native capabilities and web content while enabling secure, asynchronous communication across the IPC boundary.

## Core Architecture and Builder Pattern

At the heart of the Tauri plugin system lies the **`tauri::plugin::Builder`** struct defined in [`crates/tauri/src/plugin.rs`](https://github.com/tauri-apps/tauri/blob/main/crates/tauri/src/plugin.rs). This builder implements a fluent API for constructing `TauriPlugin<R>` instances that attach to the application runtime at compile time.

The builder registers five key components:

- **Setup hooks** – Optional initialization code executed when the application starts
- **Invoke handlers** – Command receivers that process requests from the JavaScript frontend via `invoke`
- **JavaScript init scripts** – Code injected into the webview before page load
- **Custom URI scheme protocols** – Handlers for specialized resource loading
- **Lifecycle callbacks** – Hooks such as `on_page_load` or `on_window_ready` for responding to application state changes

The final `build()` method produces a `TauriPlugin<R>` that integrates with `tauri::Builder` through the `.plugin()` method.

## Plugin Registration and Initialization

Integrating a plugin requires calling its initialization function within the Tauri application builder. According to the source code in [`crates/tauri/src/plugin.rs`](https://github.com/tauri-apps/tauri/blob/main/crates/tauri/src/plugin.rs), every plugin exposes an `init()` function returning `TauriPlugin<R>`.

```rust
// src-tauri/src/main.rs
fn main() {
    tauri::Builder::default()
        .plugin(my_plugin::init())
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

```

The `my_plugin::init()` entry point constructs the plugin using the builder pattern, configuring all handlers and scripts before returning the typed plugin instance. This registration occurs at compile time, ensuring type safety across the Rust-JavaScript boundary.

## Implementing Custom Plugins

### Minimal Plugin Definition

Creating a plugin starts with defining a Rust crate that uses `PluginBuilder` to register commands. The following example from the plugin architecture demonstrates the essential structure:

```rust
// my_plugin/src/lib.rs
use tauri::{
    plugin::{Builder as PluginBuilder, TauriPlugin},
    Runtime,
    generate_handler,
};

#[tauri::command]
async fn greet(name: String) -> String {
    format!("Hello, {name}!")
}

pub fn init<R: Runtime>() -> TauriPlugin<R> {
    PluginBuilder::new("my_plugin")
        .invoke_handler(generate_handler![greet])
        .js_init_script(r#"
            window.__my_plugin = {
                greet: (name) => window.__TAURI_INVOKE__('my_plugin:greet', { name })
            };
        "#)
        .build()
}

```

The `generate_handler!` macro creates the dispatch logic for the `greet` command, while `js_init_script` injects frontend helpers into the webview context.

### TypeScript Frontend Integration

After adding the plugin via `tauri plugin add my_plugin`, the CLI generates TypeScript bindings in the `@tauri-apps/plugin-my-plugin-api` package:

```typescript
import { greet } from '@tauri-apps/plugin-my-plugin-api';

async function sayHello() {
  const reply = await greet('World');
  console.log(reply); // → "Hello, World!"
}

```

The generated API wraps the underlying `invoke` calls, providing IntelliSense and compile-time type checking for plugin commands.

## CLI Scaffolding and Plugin Templates

The Tauri CLI provides automated scaffolding for new plugins through the `tauri plugin new` command. This generator creates the complete project structure found in `crates/tauri-cli/templates/plugin/`, including:

- Cargo.toml with proper dependencies and metadata
- TypeScript binding definitions
- Android and iOS project stubs for mobile support
- Default permission configurations

The template implements the standard builder skeleton, allowing developers to focus on business logic rather than boilerplate. For existing projects, `tauri plugin init` adds the necessary configuration to consume external plugins, as implemented in [`crates/tauri-cli/src/plugin/init.rs`](https://github.com/tauri-apps/tauri/blob/main/crates/tauri-cli/src/plugin/init.rs).

## Permission Model and Security

Each plugin declares its required capabilities through a default permission set (e.g., `core:default`). The Tauri ACL (Access Control List) system, integrated into the plugin template, automatically grants these permissions when the plugin is registered. This model ensures that native capabilities remain explicitly opt-in, with granular control over which commands and resources each plugin can access.

## Official Tauri Plugins

The `tauri-apps` organization maintains several first-party plugins that demonstrate the system's capabilities. These plugins follow the standardized builder pattern and reside in dedicated repositories:

- **SQL Plugin** – Provides encrypted SQLite database access for desktop and mobile applications via `tauri-plugin-sql`
- **Stronghold Plugin** – Implements secure cryptographic storage using the IOTA Stronghold library through `tauri-plugin-stronghold`
- **Authenticator Plugin** – Enables biometric authentication including Face ID, Touch ID, and Windows Hello support via `tauri-plugin-authenticator`

These official plugins are referenced in the architecture documentation ([`ARCHITECTURE.md`](https://github.com/tauri-apps/tauri/blob/main/ARCHITECTURE.md)) and can be added to any Tauri project using `tauri plugin add <name>`.

## Summary

- The **Tauri plugin system** uses `tauri::plugin::Builder` in [`crates/tauri/src/plugin.rs`](https://github.com/tauri-apps/tauri/blob/main/crates/tauri/src/plugin.rs) to construct native extensions with invoke handlers, lifecycle hooks, and JavaScript initialization scripts.
- Plugins register with the application through an `init()` function called within `tauri::Builder`, enabling compile-time integration of native capabilities.
- The CLI scaffolding tools in `crates/tauri-cli/templates/plugin/` generate complete plugin projects including Rust crates, TypeScript bindings, and mobile platform stubs.
- **Official plugins** such as SQL, Stronghold, and Authenticator provide production-ready implementations of common native features while adhering to the system's security and permission models.

## Frequently Asked Questions

### How do I create a new Tauri plugin from scratch?

Use the CLI command `tauri plugin new <name>` to generate a complete scaffold including the Rust crate structure, TypeScript API definitions, and optional Android/iOS projects. This creates the standard builder pattern implementation in [`src/lib.rs`](https://github.com/tauri-apps/tauri/blob/main/src/lib.rs) with hooks for setup, invoke handlers, and JavaScript initialization scripts.

### What is the difference between a Tauri plugin and a Tauri command?

A **Tauri command** is a single function exposed to JavaScript via `invoke`, while a **Tauri plugin** is a complete crate bundling multiple commands, lifecycle hooks, initialization scripts, and platform-specific code. Plugins provide modular distribution through Cargo and NPM, whereas commands are typically defined inline within the application code.

### Where are official Tauri plugins maintained?

Official plugins including SQL, Stronghold, and Authenticator reside in separate repositories under the `tauri-apps` organization, distinct from the core `tauri-apps/tauri` repository. Each plugin follows the standardized builder pattern and publishes to crates.io and the NPM registry under the `@tauri-apps` scope.

### How does the Tauri plugin system handle security permissions?

Each plugin declares a default permission set in its configuration, which the Tauri ACL system automatically applies when the plugin is registered. This declarative model ensures that native capabilities remain explicitly scoped, requiring developers to grant specific permissions for filesystem access, network requests, or hardware features within their `capabilities` configuration.