# Upgrade Guide # Migrate to v2 from v1 This guide walks you through migrating your Tauri v1 application to Tauri v2. Note that the v2 CLI includes a `migrate` command that automates most of the process and helps you finish the migration, so commit your pending changes and check it out. <Tabs> <TabItem label="npm"> ```sh npm install @tauri-apps/cli@latest npm run tauri migrate ``` </TabItem> <TabItem label="Yarn"> ```sh yarn upgrade @tauri-apps/cli --latest yarn tauri migrate ``` </TabItem> <TabItem label="pnpm"> ```sh pnpm update @tauri-apps/cli --latest pnpm tauri migrate ``` </TabItem> <TabItem label="Cargo"> ```sh cargo install tauri-cli cargo tauri migrate ``` </TabItem> </Tabs> ## Configuration Here's the list of tauri.conf.json breaking changes: ### Allowlist - The `tauri > allowlist` object has been removed. ### CLI - The `cli` configuration object has been moved from `tauri > cli` to `plugins > cli`. ### Protocol - The `tauri > allowlist > protocol > assetScope` configuration has been moved to `tauri > security > assetProtocol > scope`. ### Updater - The `updater` configuration object has been moved from `tauri > updater` to `tauri > bundle > updater`. - The `dialog` option has been removed. - The `endpoints` option has been moved to `plugins > updater`. ## Cargo features ### Removed Cargo features - reqwest-client: reqwest is now the only supported client. - reqwest-native-tls-vendored: use `native-tls-vendored` instead. - process-command-api: use the `shell` plugin instead, see instructions in the following section. - shell-open-api: use the `shell` plugin instead, see instructions in the following section. - windows7-compat: moved to the `notification` plugin. - updater: the updater is now a plugin. - linux-protocol-headers: Now enabled by default since we upgraded our minimum webkit2gtk version. ### New Cargo features - linux-protocol-body: Enables custom protocol request body parsing, allowing the IPC to use it. Requires webkit2gtk 2.40. ## Rust API - The plugin setup hook now receives a second argument, `tauri::plugin::PluginApi`. This type also exposes the plugin configuration object, so `Plugin::setup_with_config` has been removed. - The `tauri::api` module has been removed. Each API module can be found in a Tauri plugin. ### File System - The `tauri::api::file` module has been removed. Prefer the [`std::fs`](https://doc.rust-lang.org/std/fs/) functions. - The `tauri::Manager::fs_scope` has been removed. The file system scope can be accessed via `tauri_plugin_fs::FsExt`. ### Process and Shell - `tauri::api::process::current_binary` and `tauri::api::process::restart` has been moved to `tauri::process`. - The `tauri::api::process::Command`, `tauri::api::shell` and `tauri::Manager::shell_scope` APIs have been removed. Use the `shell` plugin instead: ```toml [dependencies] tauri-plugin-shell = "2" ``` ```rust use tauri_plugin_shell::{ShellExt, process::CommandEvent}; fn main() { tauri::Builder::default() .plugin(tauri_plugin_shell::init()) .setup(|app| { // open app.shell().open("https://github.com/tauri-apps/tauri", None)?; // status() let status = tauri::async_runtime::block_on(async move { app.shell().command("which").args(["ls"]).status().await.unwrap() }); println!("`which` finished with status: {:?}", status.code()); // output() let output = tauri::async_runtime::block_on(async move { app.shell().command("echo").args(["TAURI"]).output().await.unwrap() }); assert!(output.status.success()); assert_eq!(String::from_utf8(output.stdout).unwrap(), "TAURI"); // async let handle = app.handle(); tauri::async_runtime::spawn(async move { let (mut rx, mut child) = handle.shell().command("cargo") .args(["tauri", "dev"]) .spawn() .expect("Failed to spawn cargo"); let mut i = 0; while let Some(event) = rx.recv().await { if let CommandEvent::Stdout(line) = event { println!("got: {}", String::from_utf8(line).unwrap()); i += 1; if i == 4 { child.write("message from Rust\n".as_bytes()).unwrap(); i = 0; } } } }); Ok(()) }) } ``` ### Updater - The `tauri::updater` module has been removed. You must add the `tauri-plugin-updater` dependency: ```toml [dependencies] tauri-plugin-updater = "2" ``` ```rust fn main() { tauri::Builder::default() .plugin(tauri_plugin_updater::Builder::new().build()) } ``` - The `tauri::Builder` `updater_target` function has been removed. To set a custom updater target: ```rust fn main() { let mut updater = tauri_plugin_updater::Builder::new(); #[cfg(target_os = "macos")] { updater = updater.target("darwin-universal"); } tauri::Builder::default() .plugin(updater.build()) } ``` - The `App` and `AppHandle` `updater` function has been removed. To check for updates, use `updater` method from `tauri_plugin_updater::UpdaterExt`: ```rust use tauri_plugin_updater::UpdaterExt; fn main() { tauri::Builder::default() .plugin(tauri_plugin_updater::Builder::new().build()) .setup(|app| { let handle = app.handle(); tauri::async_runtime::spawn(async move { let response = handle.updater().check().await; }); Ok(()) }) } ``` - `tauri::RunEvent::Updater` has been removed. The updater state can now be handled in the `app.updater().check().await` return value itself. ### Dialog The `tauri::api::dialog` APIs were moved to the `dialog` plugin: ```toml [dependencies] tauri-plugin-dialog = "2" ``` ```rust use tauri_plugin_dialog::DialogExt; tauri::Builder::default() .plugin(tauri_plugin_dialog::init()) .setup(|app| { app.dialog().file().pick_file(|file_path| { // do something with the optional file path here // the file path is `None` if the user closed the dialog }); app.dialog().message("Tauri is Awesome!").show(); Ok(()) }) ``` ### HTTP The `tauri::api::http` module has been removed. Use the `http` plugin instead: ```toml [dependencies] tauri-plugin-http = "2" ``` ```rust use tauri_plugin_dialog::{DialogExt, client}; // `client` is a re-export of `reqwest`. APIs will be available in the future as DialogExt::http tauri::Builder::default() .plugin(tauri_plugin_http::init()) ``` ### IPC The `tauri::api::ipc` module has been rewritten and it is now exported as `tauri::ipc`. Check out the new APIs, specially `tauri::ipc::Channel`. ### Path The `tauri::api::path` module functions and `tauri::PathResolver` have been moved to `tauri::Manager::path`: ```rust use tauri::{path::BaseDirectory, Manager}; tauri::Builder::default() .setup(|app| { let home_dir_path = app.path().home_dir().expect("failed to get home dir"); let path = app.path().resolve("path/to/something", BaseDirectory::Config)?; Ok(()) }) ``` ### Version The `tauri::api::version` module has been removed. Check out the [semver crate](https://docs.rs/semver/latest/semver/) instead. ### Global Shortcut `App::global_shortcut_manager` and `AppHandle::global_shortcut_manager` APIs have been moved to the global shortcut plugin: ```toml [dependencies] tauri-plugin-global-shortcut = "2" ``` ```rust use tauri_plugin_global_shortcut::GlobalShortcutExt; tauri::Builder::default() .plugin(tauri_plugin_shortcut::init()) .setup(|app| { app.global_shortcut().register("CmdOrCtrl+Y")?; Ok(()) }) ``` ### Clipboard `App::clipboard_manager` and `AppHandle::clipboard_manager` APIs have been moved to the clipboard plugin: ```toml [dependencies] tauri-plugin-clipboard = "2" ``` ```rust use tauri_plugin_clipboard::{ClipboardExt, ClipKind}; tauri::Builder::default() .plugin(tauri_plugin_clipboard::init()) .setup(|app| { app.clipboard().write(ClipKind::PlainText { label: None, text: "Tauri is awesome!".into(), })?; Ok(()) }) ``` ### CLI The `App::get_cli_matches` function has been removed. Use the `cli` plugin instead: ```toml [dependencies] tauri-plugin-cli = "2" ``` ```rust use tauri_plugin_cli::CliExt; tauri::Builder::default() .plugin(tauri_plugin_cli::init()) .setup(|app| { let cli_matches = app.cli().matches()?; Ok(()) }) ``` ### Scope `tauri::scope::ipc::RemoteDomainAccessScope::enable_tauri_api` and `tauri::scope::ipc::RemoteDomainAccessScope::enables_tauri_api` have been removed. Enable each core plugin individually via `tauri::scope::ipc::RemoteDomainAccessScope::add_plugin` instead. ## JavaScript API The `@tauri-apps/api` package no longer provides non-core modules. Only the `tauri`, `path` and `event` modules are exported. ### File System The `@tauri-apps/api/fs` module has been removed. Use the `@tauri-apps/plugin-fs` plugin instead: ```toml # Cargo.toml [dependencies] tauri-plugin-fs = "2" ``` ```rust fn main() { tauri::Builder::default() .plugin(tauri_plugin_fs::init()) } ``` ```json // package.json { "dependencies": { "@tauri-apps/plugin-fs": "^2.0.0" } } ``` ```js import { createDir, BaseDirectory } from '@tauri-apps/plugin-fs' await createDir('db', { dir: BaseDirectory.AppLocalData }) ``` ### Process The `@tauri-apps/api/process` module has been removed. Use the `@tauri-apps/plugin-process` plugin instead: ```toml # Cargo.toml [dependencies] tauri-plugin-process = "2" ``` ```rust fn main() { tauri::Builder::default() .plugin(tauri_plugin_process::init()) } ``` ```json // package.json { "dependencies": { "@tauri-apps/plugin-process": "^2.0.0" } } ``` ```js import { exit, relaunch } from '@tauri-apps/plugin-process' await exit(0); await relaunch(); ``` ### Shell The `@tauri-apps/api/shell` module has been removed. Use the `@tauri-apps/plugin-shell` plugin instead: ```toml # Cargo.toml [dependencies] tauri-plugin-shell = "2" ``` ```rust fn main() { tauri::Builder::default() .plugin(tauri_plugin_shell::init()) } ``` ```json // package.json { "dependencies": { "@tauri-apps/plugin-shell": "^2.0.0" } } ``` ```js import { Command, open } from '@tauri-apps/plugin-shell' const output = await Command.create('echo', 'message').execute() await open('https://github.com/tauri-apps/tauri') ``` ### Updater The `@tauri-apps/api/updater` module has been removed. Use the `@tauri-apps/plugin-updater` plugin instead: ```toml # Cargo.toml [dependencies] tauri-plugin-updater = "2" ``` ```rust fn main() { tauri::Builder::default() .plugin(tauri_plugin_updater::init()) } ``` ```json // package.json { "dependencies": { "@tauri-apps/plugin-updater": "^2.0.0" } } ``` ```js import { check } from '@tauri-apps/plugin-updater' import { relaunch } from '@tauri-apps/plugin-process' const update = await check() if (update.response.available) { console.log(`Update to ${update.response.latestVersion} available! Date: ${update.response.date}`) console.log(`Release notes: ${update.response.body}`) await update.downloadAndInstall() // requires the `process` plugin await relaunch() } ``` ### Dialog The `@tauri-apps/api/dialog` module has been removed. Use the `@tauri-apps/plugin-dialog` plugin instead: ```toml # Cargo.toml [dependencies] tauri-plugin-dialog = "2" ``` ```rust fn main() { tauri::Builder::default() .plugin(tauri_plugin_dialog::init()) } ``` ```json // package.json { "dependencies": { "@tauri-apps/plugin-dialog": "^2.0.0" } } ``` ```js import { save } from '@tauri-apps/plugin-dialog'; const filePath = await save({ filters: [{ name: 'Image', extensions: ['png', 'jpeg'] }] }); ``` ### HTTP The `@tauri-apps/api/http` module has been removed. Use the `@tauri-apps/plugin-http` plugin instead: ```toml # Cargo.toml [dependencies] tauri-plugin-http = "2" ``` ```rust fn main() { tauri::Builder::default() .plugin(tauri_plugin_http::init()) } ``` ```json // package.json { "dependencies": { "@tauri-apps/plugin-http": "^2.0.0" } } ``` ```js import { fetch } from '@tauri-apps/plugin-http' const response = await fetch('https://raw.githubusercontent.com/tauri-apps/tauri/dev/package.json') ``` ### App The `@tauri-apps/api/app` module has been removed. Use the `@tauri-apps/plugin-app` plugin instead: ```toml # Cargo.toml [dependencies] tauri-plugin-app = "2" ``` ```rust fn main() { tauri::Builder::default() .plugin(tauri_plugin_app::init()) } ``` ```json // package.json { "dependencies": { "@tauri-apps/plugin-app": "^2.0.0" } } ``` ```js import { show, hide } from '@tauri-apps/plugin-app' await hide() await show() ``` ### OS The `@tauri-apps/api/os` module has been removed. Use the `@tauri-apps/plugin-os` plugin instead: ```toml # Cargo.toml [dependencies] tauri-plugin-os = "2" ``` ```rust fn main() { tauri::Builder::default() .plugin(tauri_plugin_os::init()) } ``` ```json // package.json { "dependencies": { "@tauri-apps/plugin-os": "^2.0.0" } } ``` ```js import { arch } from '@tauri-apps/plugin-os' const architecture = await arch() ``` ### CLI The `@tauri-apps/api/cli` module has been removed. Use the `@tauri-apps/plugin-cli` plugin instead: ```toml # Cargo.toml [dependencies] tauri-plugin-cli = "2" ``` ```rust fn main() { tauri::Builder::default() .plugin(tauri_plugin_cli::init()) } ``` ```json // package.json { "dependencies": { "@tauri-apps/plugin-cli": "^2.0.0" } } ``` ```js import { getMatches } from '@tauri-apps/plugin-cli' const matches = await getMatches() ``` ### Global Shortcut The `@tauri-apps/api/global-shortcut` module has been removed. Use the `@tauri-apps/plugin-global-shortcut` plugin instead: ```toml # Cargo.toml [dependencies] tauri-plugin-global-shortcut = "2" ``` ```rust fn main() { tauri::Builder::default() .plugin(tauri_plugin_global_shortcut::init()) } ``` ```json // package.json { "dependencies": { "@tauri-apps/plugin-global-shortcut": "^2.0.0" } } ``` ```js import { register } from '@tauri-apps/plugin-global-shortcut' await register('CommandOrControl+Shift+C', () => { console.log('Shortcut triggered'); }); ``` ### Clipboard The `@tauri-apps/api/clipboard` module has been removed. Use the `@tauri-apps/plugin-clipboard-manager` plugin instead: ```toml # Cargo.toml [dependencies] tauri-plugin-clipboard = "2" ``` ```rust fn main() { tauri::Builder::default() .plugin(tauri_plugin_clipboard::init()) } ``` ```json // package.json { "dependencies": { "@tauri-apps/plugin-clipboard-manager": "^2.0.0" } } ``` ```js import { writeText, readText } from '@tauri-apps/plugin-clipboard-manager'; await writeText('Tauri is awesome!'); assert(await readText(), 'Tauri is awesome!'); ``` ### Notification The `@tauri-apps/api/notification` module has been removed. Use the `@tauri-apps/plugin-notification` plugin instead: ```toml # Cargo.toml [dependencies] tauri-plugin-notification = "2" ``` ```rust fn main() { tauri::Builder::default() .plugin(tauri_plugin_notification::init()) } ``` ```json // package.json { "dependencies": { "@tauri-apps/plugin-notification": "^2.0.0" } } ``` ```js import { sendNotification } from '@tauri-apps/plugin-notification' sendNotification('Tauri is awesome!'); ``` ### Window The `@tauri-apps/api/window` module has been removed. Use the `@tauri-apps/plugin-window` plugin instead: ```toml # Cargo.toml [dependencies] tauri-plugin-window = "2" ``` ```rust fn main() { tauri::Builder::default() .plugin(tauri_plugin_window::init()) } ``` ```json // package.json { "dependencies": { "@tauri-apps/plugin-window": "^2.0.0" } } ``` ```js import { appWindow } from '@tauri-apps/plugin-window'; await appWindow.setTitle('Tauri'); ```