Plugin Development
Plugins are able to hook into the Tauri lifecycle, expose Rust code that relies on the web view APIs, handle commands with Rust, Kotlin or Swift code, and much more.
Tauri offers a windowing system with web view functionality, a way to send messages between the Rust process and the web view, and an event system along with several tools to enhance the development experience. By design, the Tauri core does not contain features not needed by everyone. Instead it offers a mechanism to add external functionalities into a Tauri application called plugins.
A Tauri plugin is composed of a Cargo crate and an optional NPM package that provides API bindings for its commands and events. Additionally, a plugin project can include an Android library project and a Swift package for iOS. You can learn more about developing plugins for Android and iOS in the Mobile Plugin Development guide.
Naming Convention
Tauri plugins have a prefix followed by the plugin name. The plugin name is specified on the plugin configuration under tauri.conf.json > plugins
.
By default Tauri prefixes your plugin crate with tauri-plugin-
. This helps your plugin to be discovered by the Tauri community and to be used with the Tauri CLI. When initializing a new plugin project, you must provide its name. The generated crate name will be tauri-plugin-{plugin-name}
and the JavaScript NPM package name will be tauri-plugin-{plugin-name}-api
(although we recommend using an NPM scope if possible). The Tauri naming convention for NPM packages is @scope-name/plugin-{plugin-name}
.
Initialize Plugin Project
To bootstrap a new plugin project, run plugin new
. If you do not need the NPM package, use the --no-api
CLI flag. If you want to initialize the plugin with Android and/or iOS support, use the --android
and/or --ios
flags.
After installing, you can run the following to create a plugin project:
This will initialize the plugin at the directory tauri-plugin-[name]
and, depending on the used CLI flags, the resulting project will look like this:
If you have an existing plugin and would like to add Android or iOS capabilities to it, you can use plugin android add
and plugin ios add
to bootstrap the mobile library projects and guide you through the changes needed.
Mobile Plugin Development
Plugins can run native mobile code written in Kotlin (or Java) and Swift. The default plugin template includes an Android library project using Kotlin and a Swift package. It includes an example mobile command showing how to trigger its execution from Rust code.
Read more about developing plugins for mobile in the Mobile Plugin Development guide.
Plugin Configuration
In the Tauri application where the plugin is used, the plugin configuration is specified on tauri.conf.json
where plugin-name
is the name of the plugin:
The plugin’s configuration is set on the Builder
and is parsed at runtime. Here is an example of the Config
struct being used to specify the plugin configuration:
Lifecycle Events
Plugins can hook into several lifecycle events:
- setup: Plugin is being initialized
- on_navigation: Web view is attempting to perform navigation
- on_webview_ready: New window is being created
- on_event: Event loop events
- on_drop: Plugin is being deconstructed
There are additional lifecycle events for mobile plugins.
setup
- When: Plugin is being initialized
- Why: Register mobile plugins, manage state, run background tasks
on_navigation
- When: Web view is attempting to perform navigation
- Why: Validate the navigation or track URL changes
Returning false
cancels the navigation.
on_webview_ready
- When: New window has been created
- Why: Execute an initialization script for every window
on_event
- When: Event loop events
- Why: Handle core events such as window events, menu events and application exit requested
With this lifecycle hook you can be notified of any event loop events.
on_drop
- When: Plugin is being deconstructed
- Why: Execute code when the plugin has been destroyed
See Drop
for more information.
Exposing Rust APIs
The plugin APIs defined in the project’s desktop.rs
and mobile.rs
are exported to the user as a struct with the same name as the plugin (in pascal case). When the plugin is setup, an instance of this struct is created and managed as a state so that users can retrieve it at any point in time with a Manager
instance (such as AppHandle
, App
, or Window
) through the extension trait defined in the plugin.
For example, the global-shortcut plugin
defines a GlobalShortcut
struct that can be read by using the global_shortcut
method of the GlobalShortcutExt
trait:
Adding Commands
Commands are defined in the commands.rs
file. They are regular Tauri applications commands. They can access the AppHandle and Window instances directly, access state, and take input the same way as application commands. Read the Commands guide for more details on Tauri commands.
This command shows how to get access to the AppHandle
and Window
instance via dependency injection, and takes two input parameters (on_progress
and url
):
To expose the command to the webview, you must hook into the invoke_handler()
call in lib.rs
:
Define a binding function in webview-src/index.ts
so that plugin users can easily call the command in JavaScript:
Be sure to build the TypeScript code prior to testing it.
Command Permissions
By default your commands are not accessible by the frontend. If you try to execute one of them, you will get a denied error rejection. To actually expose commands, you also need to define permissions that allow each command.
Permission Files
Permissions are defined as JSON or TOML files inside the permissions
directory. Each file can define a list of permissions, a list of permission sets and your plugin’s default permission.
Permissions
A permission describes privileges of your plugin commands. It can allow or deny a list of commands and associate command-specific and global scopes.
Scope
Scopes allow your plugin to define deeper restrictions to individual commands. Each permission can define a list of scope objects that define something to be allowed or denied either specific to a command or globally to the plugin.
Let’s define an example struct that will hold scope data for a list of binaries a shell
plugin is allowed to spawn:
Command Scope
Your plugin consumer can define a scope for a specific command in their capability file (see the documentation).
You can read the command-specific scope with the tauri::ipc::CommandScope
struct:
Global Scope
When a permission does not define any commands to be allowed or denied, it’s considered a scope permission and it should only define a global scope for your plugin:
You can read the global scope with the tauri::ipc::GlobalScope
struct:
Schema
The scope entry requires the schemars
dependency to generate a JSON schema so the plugin consumers know the format of the scope and have autocomplete in their IDEs.
To define the schema, first add the dependency to your Cargo.toml file:
In your build script, add the following code:
Permission Sets
Permission sets are groups of individual permissions that helps users manage your plugin with a higher level of abstraction. For instance if a single API uses multiple commands or if there’s a logical connection between a collection of commands, you should define a set containing them:
Default Permission
The default permission is a special permission set with identifier default
. It’s recommended that you enable required commands by default.
For instance the http
plugin is useless without the request
command allowed:
Autogenerated Permissions
The easiest way to define permissions for each of your commands is to use the autogeneration option defined in your plugin’s build script defined in the build.rs
file.
Inside the COMMANDS
const, define the list of commands in snake_case (should match the command function name) and Tauri will automatically generate an allow-$commandname
and a deny-$commandname
permissions.
The following example generates the allow-upload
and deny-upload
permissions:
See the Permissions Overview documentation for more information.
Managing State
A plugin can manage state in the same way a Tauri application does. Read the State Management guide for more information.
© 2024 Tauri Contributors. CC-BY / MIT