# 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');
```