Files
CODE_ASSISTANT/4_rust_tauri/docs-lib/tauri-v2-llms-full.md
T
2026-09-16 17:22:14 +09:00

2.4 MiB
Raw Blame History

This is the full developer documentation for Tauri

Tauri 2.0

The cross-platform app building toolkit

Create small, fast, secure, cross-platform applications

Get startedTauri 1.0 Documentation

Create a Project

  • Bash

    sh <(curl https://create.tauri.app/sh)
    
  • PowerShell

    irm https://create.tauri.app/ps | iex
    
  • Fish

    sh (curl -sSL https://create.tauri.app/sh | psub)
    
  • npm

    npm create tauri-app@latest
    
  • Yarn

    yarn create tauri-app
    
  • pnpm

    pnpm create tauri-app
    
  • deno

    deno run -A npm:create-tauri-app
    
  • bun

    bun create tauri-app
    
  • Cargo

    cargo install create-tauri-app --locked
    cargo create-tauri-app
    

Frontend Independent

Bring your existing web stack to Tauri or start that new dream project. Tauri supports any frontend framework so you dont need to change your stack.

Cross Platform

Build your app for Linux, macOS, Windows, Android and iOS - all from a single codebase. Write your frontend in JavaScript, application logic in Rust, and integrate deep into the system with Swift and Kotlin.

Maximum Security

Front-of-mind for the Tauri Team that drives our highest priorities and biggest innovations.

Minimal Size

By using the OSs native web renderer, the size of a Tauri app can be little as 600KB.

What is Tauri?

Information for getting up and running with Tauri, including prerequisites and installation instructions

Tauri is a framework for building tiny, fast binaries for all major desktop and mobile platforms. Developers can integrate any frontend framework that compiles to HTML, JavaScript, and CSS for building their user experience while leveraging languages such as Rust, Swift, and Kotlin for backend logic when needed.

Get started building with create-tauri-app by using one of the below commands. Be sure to follow the prerequisites guide to install all of the dependencies required by Tauri. For a more detailed walk through, see Create a Project

  • Bash

    sh <(curl https://create.tauri.app/sh)
    
  • PowerShell

    irm https://create.tauri.app/ps | iex
    
  • Fish

    sh (curl -sSL https://create.tauri.app/sh | psub)
    
  • npm

    npm create tauri-app@latest
    
  • Yarn

    yarn create tauri-app
    
  • pnpm

    pnpm create tauri-app
    
  • deno

    deno run -A npm:create-tauri-app
    
  • bun

    bun create tauri-app
    
  • Cargo

    cargo install create-tauri-app --locked
    cargo create-tauri-app
    

After youve created your first app, take a look at Project Structure to understand what each file does.

Or explore the project setups and features from the examples (tauri | plugins-workspace)

Why Tauri?

Tauri has 3 main advantages for developers to build upon:

  • Secure foundation for building apps
  • Smaller bundle size by using the systems native webview
  • Flexibility for developers to use any frontend and bindings for multiple languages

Learn more about the Tauri philosophy in the Tauri 1.0 blog post.

Secure Foundation

By being built on Rust, Tauri is able to take advantage of the memory, thread, and type-safety offered by Rust. Apps built on Tauri can automatically get those benefits even without needing to be developed by Rust experts.

Tauri also undergoes a security audit for major and minor releases. This not only covers code in the Tauri organization, but also for upstream dependencies that Tauri relies on. Of course this doesnt mitigate all risks, but it provides a solid foundation for developers to build on top of.

Read the Tauri security policy and the Tauri 2.0 audit report.

Smaller App Size

Tauri apps take advantage of the web view already available on every users system. A Tauri app only contains the code and assets specific for that app and doesnt need to bundle a browser engine with every app. This means that a minimal Tauri app can be less than 600KB in size.

Learn more about creating optimized apps in the App Size concept.

Flexible Architecture

Since Tauri uses web technologies that means that virtually any frontend framework is compatible with Tauri. The Frontend Configuration guide contains common configurations for popular frontend frameworks.

Bindings between JavaScript and Rust are available to developers using the invoke function in JavaScript and Swift and Kotlin bindings are available for Tauri Plugins.

TAO is responsible for Tauri window creation and WRY is responsible for web view rendering. These are libraries maintained by Tauri and can be consumed directly if deeper system integration is required outside of what Tauri exposes.

In addition, Tauri maintains a number of plugins to extend what core Tauri exposes. You can find those plugins alongside those provided by the community in the Plugins section.

Create a Project

One thing that makes Tauri so flexible is its ability to work with virtually any frontend framework. Weve created the create-tauri-app utility to help you create a new Tauri project using one of the officially maintained framework templates.

create-tauri-app currently includes templates for vanilla (HTML, CSS and JavaScript without a framework), Vue.js, Svelte, React, SolidJS, Angular, Preact, Yew, Leptos, and Sycamore. You can also find or add your own community templates and frameworks in the Awesome Tauri repo.

Alternatively, you can add Tauri to an existing project to quickly turn your existing codebase into a Tauri app.

Using create-tauri-app

To get started using create-tauri-app run one of the below commands in the folder youd like to setup your project. If youre not sure which command to use we recommend the Bash command on Linux and macOS and the PowerShell command on Windows.

  • Bash

    sh <(curl https://create.tauri.app/sh)
    
  • PowerShell

    irm https://create.tauri.app/ps | iex
    
  • Fish

    sh (curl -sSL https://create.tauri.app/sh | psub)
    
  • npm

    npm create tauri-app@latest
    
  • Yarn

    yarn create tauri-app
    
  • pnpm

    pnpm create tauri-app
    
  • deno

    deno run -A npm:create-tauri-app
    
  • bun

    bun create tauri-app
    
  • Cargo

    cargo install create-tauri-app --locked
    cargo create-tauri-app
    

Follow along with the prompts to choose your project name, frontend language, package manager, and frontend framework, and frontend framework options if applicable.

Not sure what to choose?

We recommend starting with the vanilla template (HTML, CSS, and JavaScript without a frontend framework) to get started. You can always integrate a frontend framework later.

  • Choose which language to use for your frontend: TypeScript / JavaScript
  • Choose your package manager: pnpm
  • Choose your UI template: Vanilla
  • Choose your UI flavor: TypeScript

Scaffold a new project

  1. Choose a name and a bundle identifier (unique-id for your app):

    ? Project name (tauri-app) 
    ? Identifier (com.tauri-app.app) 
    
  2. Select a flavor for your frontend. First the language:

    ? Choose which language to use for your frontend 
    Rust  (cargo)
    TypeScript / JavaScript  (pnpm, yarn, npm, bun)
    .NET  (dotnet)
    
  3. Select a package manager (if there are multiple available):

    Options for TypeScript / JavaScript:

    ? Choose your package manager 
    pnpm
    yarn
    npm
    bun
    
  4. Select a UI Template and flavor (if there are multiple available):

    Options for Rust:

    ? Choose your UI template 
    Vanilla
    Yew
    Leptos
    Sycamore
    

    Options for TypeScript / JavaScript:

    ? Choose your UI template 
    Vanilla
    Vue
    Svelte
    React
    Solid
    Angular
    Preact
    
    
    ? Choose your UI flavor 
    TypeScript
    JavaScript
    

    Options for .NET:

    ? Choose your UI template 
    Blazor  (https://dotnet.microsoft.com/en-us/apps/aspnet/web-apps/blazor/)
    

Once completed, the utility reports that the template has been created and displays how to run it using the configured package manager. If it detects missing dependencies on your system, it prints a list of packages and prompts how to install them.

Start the development server

After create-tauri-app has completed, you can navigate into your projects folder, install dependencies, and then use the Tauri CLI to start the development server:

  • npm

    cd tauri-app
    npm install
    npm run tauri dev
    
  • yarn

    cd tauri-app
    yarn install
    yarn tauri dev
    
  • pnpm

    cd tauri-app
    pnpm install
    pnpm tauri dev
    
  • deno

    cd tauri-app
    deno install
    deno task tauri dev
    
  • bun

    cd tauri-app
    bun install
    bun tauri dev
    
  • cargo

    cd tauri-app
    cargo install tauri-cli --version "^2.0.0" --locked
    cargo tauri dev
    

Youll now see a new window open with your app running.

Congratulations! Youve made your Tauri app! 🚀

Manual Setup (Tauri CLI)

If you already have an existing frontend or prefer to set it up yourself, you can use the Tauri CLI to initialize the backend for your project separately.

Note

The following example assumes you are creating a new project. If youve already initialized the frontend of your application, you can skip the first step.

  1. Create a new directory for your project and initialize the frontend. You can use plain HTML, CSS, and JavaScript, or any framework you prefer such as Next.js, Nuxt, Svelte, Yew, or Leptos. You just need a way of serving the app in your browser. Just as an example, this is how you would setup a simple Vite app:

    • npm

      mkdir tauri-app
      cd tauri-app
      npm create vite@latest .
      
    • yarn

      mkdir tauri-app
      cd tauri-app
      yarn create vite .
      
    • pnpm

      mkdir tauri-app
      cd tauri-app
      pnpm create vite .
      
    • deno

      mkdir tauri-app
      cd tauri-app
      deno run -A npm:create-vite .
      
    • bun

      mkdir tauri-app
      cd tauri-app
      bun create vite
      
  2. Then, install Tauris CLI tool using your package manager of choice. If you are using cargo to install the Tauri CLI, you will have to install it globally.

    • npm

      npm install -D @tauri-apps/cli@latest
      
    • yarn

      yarn add -D @tauri-apps/cli@latest
      
    • pnpm

      pnpm add -D @tauri-apps/cli@latest
      
    • deno

      deno add -D npm:@tauri-apps/cli@latest
      
    • bun

      bun add -D @tauri-apps/cli@latest
      
    • cargo

      cargo install tauri-cli --version "^2.0.0" --locked
      
  3. Determine the URL of your frontend development server. This is the URL that Tauri will use to load your content. For example, if you are using Vite, the default URL is http://localhost:5173.

  4. In your project directory, initialize Tauri:

    • npm

      npx tauri init
      
    • yarn

      yarn tauri init
      
    • pnpm

      pnpm tauri init
      
    • deno

      deno task tauri init
      
    • bun

      bun tauri init
      
    • cargo

      cargo tauri init
      

    After running the command it will display a prompt asking you for different options:

    ✔ What is your app name? tauri-app
    ✔ What should the window title be? tauri-app
    ✔ Where are your web assets located? ..
    ✔ What is the url of your dev server? http://localhost:5173
    ✔ What is your frontend dev command? pnpm run dev
    ✔ What is your frontend build command? pnpm run build
    

    This will create a src-tauri directory in your project with the necessary Tauri configuration files.

  5. Configure the server.watch.ignored option in vite.config.ts to prevent Vite from watching the src-tauri directory:

    vite.config.ts

    import { defineConfig } from "vite";
    
    
    export default defineConfig({
      server: {
        watch: {
          ignored: ["**/src-tauri/**"],
        },
      },
    });
    
  6. Verify your Tauri app is working by running the development server:

    • npm

      npx tauri dev
      
    • yarn

      yarn tauri dev
      
    • pnpm

      pnpm tauri dev
      
    • deno

      deno task tauri dev
      
    • bun

      bun tauri dev
      
    • cargo

      cargo tauri dev
      

    This command will compile the Rust code and open a window with your web content.

Congratulations! Youve created a new Tauri project using the Tauri CLI! 🚀

Next Steps

Frontend Configuration

Tauri is frontend agnostic and supports most frontend frameworks out of the box. However, sometimes a framework need a bit of extra configuration to integrate with Tauri. Below is a list of frameworks with recommended configurations.

If a framework is not listed then it may work with Tauri with no additional configuration needed or it could have not been documented yet. Any contributions to add a framework that may require additional configuration are welcome to help others in the Tauri community.

Configuration Checklist

Conceptually Tauri acts as a static web host. You need to provide Tauri with a folder containing some mix of HTML, CSS, Javascript and possibly WASM that can be served to the webview Tauri provides.

Below is a checklist of common scenarios needed to integrate a frontend with Tauri:

  • Use static site generation (SSG), single-page applications (SPA), or classic multi-page apps (MPA). Tauri does not natively support server based alternatives (such as SSR).
  • For mobile development, a development server of some kind is necessary that can host the frontend on your internal IP.
  • Use a proper client-server relationship between your app and your APIs (no hybrid solutions with SSR).

JavaScript

For most projects we recommend Vite for SPA frameworks such as React, Vue, Svelte, and Solid, but also for plain JavaScript or TypeScript projects. Most other guides listed here show how to use Meta-Frameworks as they are typically designed for SSR and therefore require special configuration.

Next.js

Nuxt

Qwik

SvelteKit

Vite (recommended)

Rust

Leptos

Trunk

Framework Not Listed?

Dont see a framework listed? It may work with Tauri without any additional configuration required. Read the configuration checklist for any common configurations to check for.

Leptos

Leptos is a Rust based web framework. You can read more about Leptos on their official website. This guide is accurate as of Leptos version 0.6.

Checklist

  • Use SSG, Tauri doesnt officially support server based solutions.
  • Use serve.ws_protocol = "ws" so that the hot-reload websocket can connect properly for mobile development.
  • Enable withGlobalTauri to ensure that Tauri APIs are available in the window.__TAURI__ variable and can be imported using wasm-bindgen.

Example Configuration

  1. Update Tauri configuration

    src-tauri/tauri.conf.json

    {
      "build": {
        "beforeDevCommand": "trunk serve",
        "devUrl": "http://localhost:1420",
        "beforeBuildCommand": "trunk build",
        "frontendDist": "../dist"
      },
      "app": {
        "withGlobalTauri": true
      }
    }
    
  2. Update Trunk configuration

    Trunk.toml

    [build]
    target = "./index.html"
    
    
    [watch]
    ignore = ["./src-tauri"]
    
    
    [serve]
    port = 1420
    open = false
    ws_protocol = "ws"
    

Next.js

Next.js is a meta framework for React. Learn more about Next.js at https://nextjs.org. This guide is accurate as of Next.js 14.2.3.

Checklist

  • Use static exports by setting output: 'export'. Tauri doesnt support server-based solutions.
  • Use the out directory as frontendDist in tauri.conf.json.

Example Configuration

  1. Update Tauri configuration
    • npm

      src-tauri/tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "npm run dev",
          "beforeBuildCommand": "npm run build",
          "devUrl": "http://localhost:3000",
          "frontendDist": "../out"
        }
      }
      
    • yarn

      src-tauri/tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "yarn dev",
          "beforeBuildCommand": "yarn build",
          "devUrl": "http://localhost:3000",
          "frontendDist": "../out"
        }
      }
      
    • pnpm

      src-tauri/tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "pnpm dev",
          "beforeBuildCommand": "pnpm build",
          "devUrl": "http://localhost:3000",
          "frontendDist": "../out"
        }
      }
      
    • deno

      src-tauri/tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "deno task dev",
          "beforeBuildCommand": "deno task build",
          "devUrl": "http://localhost:3000",
          "frontendDist": "../out"
        }
      }
      
  2. Update Next.js configuration

    next.config.mjs

    const isProd = process.env.NODE_ENV === 'production';
    
    
    const internalHost = process.env.TAURI_DEV_HOST || 'localhost';
    
    
    /** @type {import('next').NextConfig} */
    const nextConfig = {
      // Ensure Next.js uses SSG instead of SSR
      // https://nextjs.org/docs/pages/building-your-application/deploying/static-exports
      output: 'export',
      // Note: This feature is required to use the Next.js Image component in SSG mode.
      // See https://nextjs.org/docs/messages/export-image-api for different workarounds.
      images: {
        unoptimized: true,
      },
      // Configure assetPrefix or else the server won't properly resolve your assets.
      assetPrefix: isProd ? undefined : `http://${internalHost}:3000`,
    };
    
    
    export default nextConfig;
    
  3. Update package.json configuration
    "scripts": {
      "dev": "next dev",
      "build": "next build",
      "start": "next start",
      "lint": "next lint",
      "tauri": "tauri"
    }
    

Nuxt

Nuxt is a meta framework for Vue. Learn more about Nuxt at https://nuxt.com. This guide is accurate as of Nuxt 4.2.

Checklist

  • Use SSG by setting ssr: false. Tauri doesnt support server based solutions.
  • Use default ../dist as frontendDist in tauri.conf.json.
  • Compile using nuxi build.
  • (Optional): Disable telemetry by setting telemetry: false in nuxt.config.ts.

Example Configuration

  1. Update Tauri configuration
    • npm

      tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "npm run dev",
          "beforeBuildCommand": "npm run generate",
          "devUrl": "http://localhost:3000",
          "frontendDist": "../dist"
        }
      }
      
    • yarn

      tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "yarn dev",
          "beforeBuildCommand": "yarn generate",
          "devUrl": "http://localhost:3000",
          "frontendDist": "../dist"
        }
      }
      
    • pnpm

      tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "pnpm dev",
          "beforeBuildCommand": "pnpm generate",
          "devUrl": "http://localhost:3000",
          "frontendDist": "../dist"
        }
      }
      
    • deno

      tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "deno task dev",
          "beforeBuildCommand": "deno task generate",
          "devUrl": "http://localhost:3000",
          "frontendDist": "../dist"
        }
      }
      
  2. Update Nuxt configuration
    export default defineNuxtConfig({
      compatibilityDate: '2025-05-15',
      // (optional) Enable the Nuxt devtools
      devtools: { enabled: true },
      // Enable SSG
      ssr: false,
      // Enables the development server to be discoverable by other devices when running on iOS physical devices
      devServer: {
        host: '0',
      },
      vite: {
        // Better support for Tauri CLI output
        clearScreen: false,
        // Enable environment variables
        // Additional environment variables can be found at
        // https://v2.tauri.app/reference/environment-variables/
        envPrefix: ['VITE_', 'TAURI_'],
        server: {
          // Tauri requires a consistent port
          strictPort: true,
        },
      },
      // Avoids error [unhandledRejection] EMFILE: too many open files, watch
      ignore: ['**/src-tauri/**'],
    });
    

Qwik

This guide will walk you through creating your Tauri app using the Qwik web framework. Learn more about Qwik at https://qwik.dev.

Checklist

  • Use SSG. Tauri doesnt support server-based solutions.
  • Use dist/ as frontendDist in tauri.conf.json.

Example Configuration

  1. Create a new Qwik app
    • npm

      npm create qwik@latest
      cd <PROJECT>
      
    • yarn

      yarn create qwik@latest
      cd <PROJECT>
      
    • pnpm

      pnpm create qwik@latest
      cd <PROJECT>
      
    • deno

      deno run -A npm:create-qwik@latest
      cd <PROJECT>
      
  2. Install the static adapter
    • npm

      npm run qwik add static
      
    • yarn

      yarn qwik add static
      
    • pnpm

      pnpm qwik add static
      
    • deno

      deno task qwik add static
      
  3. Add the Tauri CLI to your project
    • npm

      npm install -D @tauri-apps/cli@latest
      
    • yarn

      yarn add -D @tauri-apps/cli@latest
      
    • pnpm

      pnpm add -D @tauri-apps/cli@latest
      
    • deno

      deno add -D npm:@tauri-apps/cli@latest
      
  4. Initiate a new Tauri project
    • npm

      npm run tauri init
      
    • yarn

      yarn tauri init
      
    • pnpm

      pnpm tauri init
      
    • deno

      deno task tauri init
      
  5. Tauri configuration
    • npm

      tauri.conf.json

      {
        "build": {
          "devUrl": "http://localhost:5173"
          "frontendDist": "../dist",
          "beforeDevCommand": "npm run dev",
          "beforeBuildCommand": "npm run build"
        }
      }
      
    • yarn

      tauri.conf.json

      {
        "build": {
          "devUrl": "http://localhost:5173"
          "frontendDist": "../dist",
          "beforeDevCommand": "yarn dev",
          "beforeBuildCommand": "yarn build"
        }
      }
      
    • pnpm

      tauri.conf.json

      {
        "build": {
          "devUrl": "http://localhost:5173"
          "frontendDist": "../dist",
          "beforeDevCommand": "pnpm dev",
          "beforeBuildCommand": "pnpm build"
        }
      }
      
    • deno

      tauri.conf.json

      {
        "build": {
          "devUrl": "http://localhost:5173"
          "frontendDist": "../dist",
          "beforeDevCommand": "deno task dev",
          "beforeBuildCommand": "deno task build"
        }
      }
      
  6. Start your tauri app
    • npm

      npm run tauri dev
      
    • yarn

      yarn tauri dev
      
    • pnpm

      pnpm tauri dev
      
    • deno

      deno task tauri dev
      

SvelteKit

SvelteKit is a meta framework for Svelte. Learn more about SvelteKit at https://svelte.dev/. This guide is accurate as of SvelteKit 2.20.4 / Svelte 5.25.8.

Checklist

  • Use SSG and SPA via static-adapter. Tauri doesnt support server-based solutions.
  • If using SSG with prerendering, be aware that load functions will not have access to tauri APIs during the build process of your app. Using SPA mode (without prerendering) is recommended since the load functions will only run in the webview with access to tauri APIs.
  • Use build/ as frontendDist in tauri.conf.json.

Example Configuration

  1. Install @sveltejs/adapter-static
    • npm

      npm install --save-dev @sveltejs/adapter-static
      
    • yarn

      yarn add -D @sveltejs/adapter-static
      
    • pnpm

      pnpm add -D @sveltejs/adapter-static
      
    • deno

      deno add -D npm:@sveltejs/adapter-static
      
  2. Update Tauri configuration
    • npm

      tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "npm run dev",
          "beforeBuildCommand": "npm run build",
          "devUrl": "http://localhost:5173",
          "frontendDist": "../build"
        }
      }
      
    • yarn

      tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "yarn dev",
          "beforeBuildCommand": "yarn build",
          "devUrl": "http://localhost:5173",
          "frontendDist": "../build"
        }
      }
      
    • pnpm

      tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "pnpm dev",
          "beforeBuildCommand": "pnpm build",
          "devUrl": "http://localhost:5173",
          "frontendDist": "../build"
        }
      }
      
    • deno

      tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "deno task dev",
          "beforeBuildCommand": "deno task build",
          "devUrl": "http://localhost:5173",
          "frontendDist": "../build"
        }
      }
      
  3. Update SvelteKit configuration:

    svelte.config.js

    import adapter from '@sveltejs/adapter-static';
    import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
    
    
    /** @type {import('@sveltejs/kit').Config} */
    const config = {
      // Consult https://svelte.dev/docs/kit/integrations#preprocessors
      // for more information about preprocessors
      preprocess: vitePreprocess(),
    
    
      kit: {
        adapter: adapter({
          fallback: 'index.html',
        }),
      },
    };
    
    
    export default config;
    
  4. Disable SSR

    Lastly, we need to disable SSR by adding a root +layout.ts file (or +layout.js if you are not using TypeScript) with these contents:

    src/routes/+layout.ts

    export const ssr = false;
    

    Note that static-adapter doesnt require you to disable SSR for the whole app but it makes it possible to use APIs that depend on the global window object (like Tauris API) without Client-side checks.

    Furthermore, if you prefer Static Site Generation (SSG) over Single-Page Application (SPA) mode, you can change the adapter configurations and +layout.ts according to the adapter docs.

Trunk

Trunk is a WASM web application bundler for Rust. Learn more about Trunk at https://trunk-rs.github.io/trunk/. This guide is accurate as of Trunk 0.17.5.

Checklist

  • Use SSG, Tauri doesnt officially support server based solutions.
  • Use serve.ws_protocol = "ws" so that the hot-reload websocket can connect properly for mobile development.
  • Enable withGlobalTauri to ensure that Tauri APIs are available in the window.__TAURI__ variable and can be imported using wasm-bindgen.

Example Configuration

  1. Update Tauri configuration

    tauri.conf.json

    {
      "build": {
        "beforeDevCommand": "trunk serve",
        "beforeBuildCommand": "trunk build",
        "devUrl": "http://localhost:8080",
        "frontendDist": "../dist"
      },
      "app": {
        "withGlobalTauri": true
      }
    }
    
  2. Update Trunk configuration

    Trunk.toml

    [watch]
    ignore = ["./src-tauri"]
    
    
    [serve]
    ws_protocol = "ws"
    

Vite

Vite is a build tool that aims to provide a faster and leaner development experience for modern web projects. This guide is accurate as of Vite 5.4.8.

Checklist

  • Use ../dist as frontendDist in src-tauri/tauri.conf.json.
  • Use process.env.TAURI_DEV_HOST as the development server host IP when set to run on iOS physical devices.

Example configuration

  1. Update Tauri configuration

    Assuming you have the following dev and build scripts in your package.json:

    {
      "scripts": {
        "dev": "vite",
        "build": "tsc && vite build",
        "preview": "vite preview",
        "tauri": "tauri"
      }
    }
    

    You can configure the Tauri CLI to use your Vite development server and dist folder along with the hooks to automatically run the Vite scripts:

    • npm

      tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "npm run dev",
          "beforeBuildCommand": "npm run build",
          "devUrl": "http://localhost:5173",
          "frontendDist": "../dist"
        }
      }
      
    • yarn

      tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "yarn dev",
          "beforeBuildCommand": "yarn build",
          "devUrl": "http://localhost:5173",
          "frontendDist": "../dist"
        }
      }
      
    • pnpm

      tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "pnpm dev",
          "beforeBuildCommand": "pnpm build",
          "devUrl": "http://localhost:5173",
          "frontendDist": "../dist"
        }
      }
      
    • deno

      tauri.conf.json

      {
        "build": {
          "beforeDevCommand": "deno task dev",
          "beforeBuildCommand": "deno task build",
          "devUrl": "http://localhost:5173",
          "frontendDist": "../dist"
        }
      }
      
  2. Update Vite configuration:

    vite.config.js

    import { defineConfig } from 'vite';
    
    
    const host = process.env.TAURI_DEV_HOST;
    
    
    export default defineConfig({
      // prevent vite from obscuring rust errors
      clearScreen: false,
      server: {
        // make sure this port matches the devUrl port in tauri.conf.json file
        port: 5173,
        // Tauri expects a fixed port, fail if that port is not available
        strictPort: true,
        // if the host Tauri is expecting is set, use it
        host: host || false,
        hmr: host
          ? {
              protocol: 'ws',
              host,
              port: 1421,
            }
          : undefined,
    
    
        watch: {
          // tell vite to ignore watching `src-tauri`
          ignored: ['**/src-tauri/**'],
        },
      },
      // Env variables starting with the item of `envPrefix` will be exposed in tauri's source code through `import.meta.env`.
      envPrefix: ['VITE_', 'TAURI_ENV_*'],
      build: {
        // Tauri uses Chromium on Windows and WebKit on macOS and Linux
        target:
          process.env.TAURI_ENV_PLATFORM == 'windows'
            ? 'chrome105'
            : 'safari13',
        // don't minify for debug builds
        minify: !process.env.TAURI_ENV_DEBUG ? 'esbuild' : false,
        // produce sourcemaps for debug builds
        sourcemap: !!process.env.TAURI_ENV_DEBUG,
      },
    });
    

Upgrade & Migrate

Learn about common scenarios and steps to upgrade from Tauri 1.0 or migrate from another framework.

Upgrade from Tauri 1.0Read more about the updates you need to make to a version 1 project in order to upgrade to version 2.

Migrate from Tauri 2.0 betaRead more about the updates required for the 2.0 beta project to upgrade to 2.0.

Upgrade from Tauri 1.0

This guide walks you through upgrading your Tauri 1.0 application to Tauri 2.0.

Preparing for Mobile

The mobile interface of Tauri requires your project to output a shared library. If you are targeting mobile for your existing application, you must change your crate to produce that kind of artifact along with the desktop executable.

  1. Change the Cargo manifest to produce the library. Append the following block:

src-tauri/Cargo.toml

[lib]
name = "app_lib"
crate-type = ["staticlib", "cdylib", "rlib"]
  1. Rename src-tauri/src/main.rs to src-tauri/src/lib.rs. This file will be shared by both desktop and mobile targets.

  2. Rename the main function header in lib.rs to the following:

src-tauri/src/lib.rs

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    // your code here
}

The tauri::mobile_entry_point macro prepares your function to be executed on mobile.

  1. Recreate the main.rs file calling the shared run function:

src-tauri/src/main.rs

#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]


fn main() {
  app_lib::run();
}

Automated Migration

Danger

This command is not a substitute for this guide! Please read the whole page regardless of whether you chose to use the command.

The Tauri v2 CLI includes a migrate command that automates most of the process and helps you finish the migration:

  • npm

    npm install @tauri-apps/cli@latest
    npm run tauri migrate
    
  • yarn

    yarn upgrade @tauri-apps/cli@latest
    yarn tauri migrate
    
  • pnpm

    pnpm update @tauri-apps/cli@latest
    pnpm tauri migrate
    
  • cargo

    cargo install tauri-cli --version "^2.0.0" --locked
    cargo tauri migrate
    

Learn more about the migrate command in the Command Line Interface reference

Summary of Changes

Below is a summary of the changes from Tauri 1.0 to Tauri 2.0:

Tauri Configuration

  • package > productName and package > version moved to top-level object.
  • the binary name is no longer renamed to match productName automatically, so you must add a mainBinaryName string to the top-level object matching productName.
  • package removed.
  • tauri key renamed to app.
  • tauri > allowlist removed. Refer to Migrate Permissions.
  • tauri > allowlist > protocol > assetScope moved to app > security > assetProtocol > scope. See Asset protocol scope for enable, glob patterns, requireLiteralLeadingDot, and dynamic paths.
  • tauri > cli moved to plugins > cli.
  • tauri > windows > fileDropEnabled renamed to app > windows > dragDropEnabled.
  • tauri > updater > active removed.
  • tauri > updater > dialog removed.
  • tauri > updater moved to plugins > updater.
  • bundle > createUpdaterArtifacts added, must be set when using the app updater.
    • set it to v1Compatible when upgrading from v1 apps that were already distributed. See the updater guide for more information.
  • tauri > systemTray renamed to app > trayIcon.
  • tauri > pattern moved to app > security > pattern.
  • tauri > bundle moved top-level.
  • tauri > bundle > identifier moved to top-level object.
  • tauri > bundle > dmg moved to bundle > macOS > dmg
  • tauri > bundle > deb moved to bundle > linux > deb
  • tauri > bundle > appimage moved to bundle > linux > appimage
  • tauri > bundle > macOS > license removed, use bundle > licenseFile instead.
  • tauri > bundle > windows > wix > license removed, use bundle > licenseFile instead.
  • tauri > bundle > windows > nsis > license removed, use bundle > licenseFile instead.
  • tauri > bundle > windows > webviewFixedRuntimePath removed, use bundle > windows > webviewInstallMode instead.
  • build > withGlobalTauri moved to app > withGlobalTauri.
  • build > distDir renamed to frontendDist.
  • build > devPath renamed to devUrl.

Tauri 2.0 Configuration API reference

New Cargo Features

  • linux-protocol-body: Enables custom protocol request body parsing, allowing the IPC to use it. Requires webkit2gtk 2.40.

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: Updater is now a plugin.
  • linux-protocol-headers: Now enabled by default since we upgraded our minimum webkit2gtk version.
  • system-tray: renamed to tray-icon.

Rust Crate Changes

  • api module removed. Each API module can be found in a Tauri plugin.
  • api::dialog module removed. Use tauri-plugin-dialog instead. Migration
  • api::file module removed. Use Rusts std::fs instead.
  • api::http module removed. Use tauri-plugin-http instead. Migration
  • api::ip module rewritten and moved to tauri::ipc. Check out the new APIs, specially tauri::ipc::Channel.
  • api::path module functions and tauri::PathResolved moved to tauri::Manager::path. Migration
  • api::process::Command, tauri::api::shell and tauri::Manager::shell_scope APIs removed. Use tauri-plugin-shell instead. Migration
  • api::process::current_binary and tauri::api::process::restart moved to tauri::process.
  • api::version module has been removed. Use the semver crate instead.
  • App::clipboard_manager and AppHandle::clipboard_manager removed. Use tauri-plugin-clipboard instead. Migration
  • App::get_cli_matches removed. Use tauri-plugin-cli instead. Migration
  • App::global_shortcut_manager and AppHandle::global_shortcut_manager removed. Use tauri-plugin-global-shortcut instead. Migration
  • Manager::fs_scope removed. The file system scope can be accessed via tauri_plugin_fs::FsExt.
  • Plugin::PluginApi now receives a plugin configuration as a second argument.
  • Plugin::setup_with_config removed. Use the updated tauri::Plugin::PluginApi instead.
  • scope::ipc::RemoteDomainAccessScope::enable_tauri_api and scope::ipc::RemoteDomainAccessScope::enables_tauri_api removed. Enable each core plugin individually via scope::ipc::RemoteDomainAccessScope::add_plugin instead.
  • scope::IpcScope removed, use scope::ipc::Scope instead.
  • scope::FsScope, scope::GlobPattern and scope::FsScopeEvent removed, use scope::fs::Scope, scope::fs::Pattern and scope::fs::Event respectively.
  • updater module removed. Use tauri-plugin-updater instead. Migration
  • Env.args field has been removed, use Env.args_os field instead.
  • Menu, MenuEvent, CustomMenuItem, Submenu, WindowMenuEvent, MenuItem and Builder::on_menu_event APIs removed. Migration
  • SystemTray, SystemTrayHandle, SystemTrayMenu, SystemTrayMenuItemHandle, SystemTraySubmenu, MenuEntry and SystemTrayMenuItem APIs removed. Migration

JavaScript API Changes

The @tauri-apps/api package no longer provides non-core modules. Only the previous tauri (now core), path, event and window modules are exported. All others have been moved to plugins.

  • @tauri-apps/api/tauri module renamed to @tauri-apps/api/core. Migration
  • @tauri-apps/api/cli module removed. Use @tauri-apps/plugin-cli instead. Migration
  • @tauri-apps/api/clipboard module removed. Use @tauri-apps/plugin-clipboard instead. Migration
  • @tauri-apps/api/dialog module removed. Use @tauri-apps/plugin-dialog instead. Migration
  • @tauri-apps/api/fs module removed. Use @tauri-apps/plugin-fs instead. Migration
  • @tauri-apps/api/global-shortcut module removed. Use @tauri-apps/plugin-global-shortcut instead. Migration
  • @tauri-apps/api/http module removed. Use @tauri-apps/plugin-http instead. Migration
  • @tauri-apps/api/os module removed. Use @tauri-apps/plugin-os instead. Migration
  • @tauri-apps/api/notification module removed. Use @tauri-apps/plugin-notification instead. Migration
  • @tauri-apps/api/process module removed. Use @tauri-apps/plugin-process instead. Migration
  • @tauri-apps/api/shell module removed. Use @tauri-apps/plugin-shell instead. Migration
  • @tauri-apps/api/updater module removed. Use @tauri-apps/plugin-updater instead Migration
  • @tauri-apps/api/window module renamed to @tauri-apps/api/webviewWindow. Migration

The v1 plugins are now published as @tauri-apps/plugin-<plugin-name>. Previously they were available from git as tauri-plugin-<plugin-name>-api.

Environment Variables Changes

Most of the environment variables read and written by the Tauri CLI were renamed for consistency and prevention of mistakes:

  • TAURI_PRIVATE_KEY -> TAURI_SIGNING_PRIVATE_KEY
  • TAURI_KEY_PASSWORD -> TAURI_SIGNING_PRIVATE_KEY_PASSWORD
  • TAURI_SKIP_DEVSERVER_CHECK -> TAURI_CLI_NO_DEV_SERVER_WAIT
  • TAURI_DEV_SERVER_PORT -> TAURI_CLI_PORT
  • TAURI_PATH_DEPTH -> TAURI_CLI_CONFIG_DEPTH
  • TAURI_FIPS_COMPLIANT -> TAURI_BUNDLER_WIX_FIPS_COMPLIANT
  • TAURI_DEV_WATCHER_IGNORE_FILE -> TAURI_CLI_WATCHER_IGNORE_FILENAME
  • TAURI_TRAY -> TAURI_LINUX_AYATANA_APPINDICATOR
  • TAURI_APPLE_DEVELOPMENT_TEAM -> APPLE_DEVELOPMENT_TEAM
  • TAURI_PLATFORM -> TAURI_ENV_PLATFORM
  • TAURI_ARCH -> TAURI_ENV_ARCH
  • TAURI_FAMILY -> TAURI_ENV_FAMILY
  • TAURI_PLATFORM_VERSION -> TAURI_ENV_PLATFORM_VERSION
  • TAURI_PLATFORM_TYPE -> TAURI_ENV_PLATFORM_TYPE
  • TAURI_DEBUG -> TAURI_ENV_DEBUG

Event System

The event system was redesigned to be easier to use. Instead of relying on the source of the event, it now has a simpler implementation that relies on event targets.

  • The emit function now emits the event to all event listeners.
  • Added a new emit_to/emitTo function to trigger an event to a specific target.
  • emit_filter now filters based on EventTarget instead of a window.
  • Renamed listen_global to listen_any. It now listens to all events regardless of their filters and targets.
  • JavaScript: event.listen() behaves similar to listen_any. It now listens to all events regardless of their filters and targets, unless a target is set in the Options.
  • JavaScript: WebviewWindow.listen etc. only listen to events emitted to the respective EventTarget.

Multiwebview support

Tauri v2 introduces multiwebview support currently behind an unstable feature flag. In order to support it, we renamed the Rust Window type to WebviewWindow and the Manager get_window function to get_webview_window.

The WebviewWindow JS API type is now re-exported from @tauri-apps/api/webviewWindow instead of @tauri-apps/api/window.

New origin URL on Windows

On Windows the frontend files in production apps are now hosted on http://tauri.localhost instead of https://tauri.localhost. Because of this IndexedDB, LocalStorage and Cookies will be reset unless dangerousUseHttpScheme was used in v1. To prevent this you can set app > windows > useHttpsScheme to true or use WebviewWindowBuilder::use_https_scheme to keep using the https scheme.

Detailed Migration Steps

Common scenarios you may encounter when migrating your Tauri 1.0 app to Tauri 2.0.

Migrate to Core Module

The @tauri-apps/api/tauri module was renamed to @tauri-apps/api/core. Simply rename the module import:

import { invoke } from "@tauri-apps/api/tauri"
import { invoke } from "@tauri-apps/api/core"

Migrate to CLI Plugin

The Rust App::get_cli_matches JavaScript @tauri-apps/api/cli APIs have been removed. Use the @tauri-apps/plugin-cli plugin instead:

  1. Add to cargo dependencies:

Cargo.toml

[dependencies]
tauri-plugin-cli = "2"
  1. Use in JavaScript or Rust project:
  • JavaScript

    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_cli::init())
    }
    

    package.json

    {
      "dependencies": {
        "@tauri-apps/plugin-cli": "^2.0.0"
      }
    }
    
    import { getMatches } from '@tauri-apps/plugin-cli';
    const matches = await getMatches();
    
  • Rust

    fn main() {
        use tauri_plugin_cli::CliExt;
        tauri::Builder::default()
            .plugin(tauri_plugin_cli::init())
            .setup(|app| {
                let cli_matches = app.cli().matches()?;
                Ok(())
            })
    }
    

Migrate to Clipboard Plugin

The Rust App::clipboard_manager and AppHandle::clipboard_manager and JavaScript @tauri-apps/api/clipboard APIs have been removed. Use the @tauri-apps/plugin-clipboard-manager plugin instead:

[dependencies]
tauri-plugin-clipboard-manager = "2"
  • JavaScript

    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_clipboard_manager::init())
    }
    

    package.json

    {
      "dependencies": {
        "@tauri-apps/plugin-clipboard-manager": "^2.0.0"
      }
    }
    
    import { writeText, readText } from '@tauri-apps/plugin-clipboard-manager';
    await writeText('Tauri is awesome!');
    assert(await readText(), 'Tauri is awesome!');
    
  • 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(())
        })
    

Migrate to Dialog Plugin

The Rust tauri::api::dialog JavaScript @tauri-apps/api/dialog APIs have been removed. Use the @tauri-apps/plugin-dialog plugin instead:

  1. Add to cargo dependencies:

Cargo.toml

[dependencies]
tauri-plugin-dialog = "2"
  1. Use in JavaScript or Rust project:
  • JavaScript

    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_dialog::init())
    }
    

    package.json

    {
      "dependencies": {
        "@tauri-apps/plugin-dialog": "^2.0.0"
      }
    }
    
    import { save } from '@tauri-apps/plugin-dialog';
    const filePath = await save({
      filters: [
        {
          name: 'Image',
          extensions: ['png', 'jpeg'],
        },
      ],
    });
    
  • 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(())
         })
    

Migrate to File System Plugin

The Rust tauri::api::file and JavaScript @tauri-apps/api/fs APIs have been removed. Use std::fs for Rust and the @tauri-apps/plugin-fs plugin for JavaScript instead:

  1. Add to cargo dependencies:

Cargo.toml

[dependencies]
tauri-plugin-fs = "2"
  1. Use in JavaScript or Rust project:
  • JavaScript

    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_fs::init())
    }
    

    package.json

    {
      "dependencies": {
        "@tauri-apps/plugin-fs": "^2.0.0"
      }
    }
    
    import { mkdir, BaseDirectory } from '@tauri-apps/plugin-fs';
    await mkdir('db', { baseDir: BaseDirectory.AppLocalData });
    

    Some functions and types have been renamed or removed:

    • Dir enum alias removed, use BaseDirectory.
    • FileEntry, FsBinaryFileOption, FsDirOptions, FsOptions, FsTextFileOption and BinaryFileContents interfaces and type aliases have been removed and replaced with new interfaces suited for each function.
    • createDir renamed to mkdir.
    • readBinaryFile renamed to readFile.
    • removeDir removed and replaced with remove.
    • removeFile removed and replaced with remove.
    • renameFile removed and replaced with rename.
    • writeBinaryFile renamed to writeFile.
  • Rust

    Use the Rust std::fs functions.

Migrate to Global Shortcut Plugin

The Rust App::global_shortcut_manager and AppHandle::global_shortcut_manager and JavaScript @tauri-apps/api/global-shortcut APIs have been removed. Use the @tauri-apps/plugin-global-shortcut plugin instead:

  1. Add to cargo dependencies:

Cargo.toml

[dependencies]
[target."cfg(not(any(target_os = \"android\", target_os = \"ios\")))".dependencies]
tauri-plugin-global-shortcut = "2"
  1. Use in JavaScript or Rust project:
  • JavaScript

    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_global_shortcut::Builder::default().build())
    }
    

    package.json

    {
      "dependencies": {
        "@tauri-apps/plugin-global-shortcut": "^2.0.0"
      }
    }
    
    import { register } from '@tauri-apps/plugin-global-shortcut';
    await register('CommandOrControl+Shift+C', () => {
      console.log('Shortcut triggered');
    });
    
  • Rust

    use tauri_plugin_global_shortcut::GlobalShortcutExt;
    
    
    tauri::Builder::default()
        .plugin(
            tauri_plugin_global_shortcut::Builder::new().with_handler(|app, shortcut| {
                println!("Shortcut triggered: {:?}", shortcut);
            })
            .build(),
        )
        .setup(|app| {
            // register a global shortcut
            // on macOS, the Cmd key is used
            // on Windows and Linux, the Ctrl key is used
            app.global_shortcut().register("CmdOrCtrl+Y")?;
            Ok(())
        })
    

Migrate to HTTP Plugin

The Rust tauri::api::http JavaScript @tauri-apps/api/http APIs have been removed. Use the @tauri-apps/plugin-http plugin instead:

  1. Add to cargo dependencies:

Cargo.toml

[dependencies]
tauri-plugin-http = "2"
  1. Use in JavaScript or Rust project:
  • JavaScript

    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_http::init())
    }
    

    package.json

    {
      "dependencies": {
        "@tauri-apps/plugin-http": "^2.0.0"
      }
    }
    
    import { fetch } from '@tauri-apps/plugin-http';
    const response = await fetch(
      'https://raw.githubusercontent.com/tauri-apps/tauri/dev/package.json'
    );
    
  • Rust

    use tauri_plugin_http::reqwest;
    
    
    tauri::Builder::default()
        .plugin(tauri_plugin_http::init())
        .setup(|app| {
            let response_data = tauri::async_runtime::block_on(async {
                let response = reqwest::get(
                    "https://raw.githubusercontent.com/tauri-apps/tauri/dev/package.json",
                )
                .await
                .unwrap();
                response.text().await
            })?;
            Ok(())
        })
    

    The HTTP plugin re-exports reqwest so you can check out their documentation for more information.

Migrate to Notification Plugin

The Rust tauri::api::notification JavaScript @tauri-apps/api/notification APIs have been removed. Use the @tauri-apps/plugin-notification plugin instead:

  1. Add to cargo dependencies:

Cargo.toml

[dependencies]
tauri-plugin-notification = "2"
  1. Use in JavaScript or Rust project:
  • JavaScript

    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_notification::init())
    }
    

    package.json

    {
      "dependencies": {
        "@tauri-apps/plugin-notification": "^2.0.0"
      }
    }
    
    import { sendNotification } from '@tauri-apps/plugin-notification';
    sendNotification('Tauri is awesome!');
    
  • Rust

    use tauri_plugin_notification::NotificationExt;
    use tauri::plugin::PermissionState;
    
    
    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_notification::init())
            .setup(|app| {
                if app.notification().permission_state()? == PermissionState::Unknown {
                    app.notification().request_permission()?;
                }
                if app.notification().permission_state()? == PermissionState::Granted {
                    app.notification()
                        .builder()
                        .body("Tauri is awesome!")
                        .show()?;
                }
                Ok(())
            })
    }
    

Migrate to Menu Module

The Rust Menu APIs were moved to the tauri::menu module and refactored to use the muda crate.

Use tauri::menu::MenuBuilder

Use tauri::menu::MenuBuilder instead of tauri::Menu. Note that its constructor takes a Manager instance (one of App, AppHandle or WebviewWindow) as an argument:

use tauri::menu::MenuBuilder;


tauri::Builder::default()
    .setup(|app| {
        let menu = MenuBuilder::new(app)
            .copy()
            .paste()
            .separator()
            .undo()
            .redo()
            .text("open-url", "Open URL")
            .check("toggle", "Toggle")
            .icon("show-app", "Show App", app.default_window_icon().cloned().unwrap())
            .build()?;
        app.set_menu(menu);
        Ok(())
    })

Use tauri::menu::PredefinedMenuItem

Use tauri::menu::PredefinedMenuItem instead of tauri::MenuItem:

use tauri::menu::{MenuBuilder, PredefinedMenuItem};


tauri::Builder::default()
    .setup(|app| {
        let menu = MenuBuilder::new(app).item(&PredefinedMenuItem::copy(app)?).build()?;
        Ok(())
    })

Tip

The menu builder has dedicated methods to add each predefined menu item so you can call .copy() instead of .item(&PredefinedMenuItem::copy(app, None)?).

Use tauri::menu::MenuItemBuilder

Use tauri::menu::MenuItemBuilder instead of tauri::CustomMenuItem:

use tauri::menu::MenuItemBuilder;


tauri::Builder::default()
    .setup(|app| {
        let toggle = MenuItemBuilder::new("Toggle").accelerator("Ctrl+Shift+T").build(app)?;
        Ok(())
    })

Use tauri::menu::SubmenuBuilder

Use tauri::menu::SubmenuBuilder instead of tauri::Submenu:

use tauri::menu::{MenuBuilder, SubmenuBuilder};


tauri::Builder::default()
    .setup(|app| {
        let submenu = SubmenuBuilder::new(app, "Sub")
            .text("Tauri")
            .separator()
            .check("Is Awesome")
            .build()?;
        let menu = MenuBuilder::new(app).item(&submenu).build()?;
        Ok(())
    })

tauri::Builder::menu now takes a closure because the menu needs a Manager instance to be built. See the documentation for more information.

Menu Events

The Rust tauri::Builder::on_menu_event API was removed. Use tauri::App::on_menu_event or tauri::AppHandle::on_menu_event instead:

use tauri::menu::{CheckMenuItemBuilder, MenuBuilder, MenuItemBuilder};


tauri::Builder::default()
    .setup(|app| {
        let toggle = MenuItemBuilder::with_id("toggle", "Toggle").build(app)?;
        let check = CheckMenuItemBuilder::new("Mark").build(app)?;
        let menu = MenuBuilder::new(app).items(&[&toggle, &check]).build()?;


        app.set_menu(menu)?;


        app.on_menu_event(move |app, event| {
            if event.id() == check.id() {
                println!("`check` triggered, do something! is checked? {}", check.is_checked().unwrap());
            } else if event.id() == "toggle" {
                println!("toggle triggered!");
            }
        });
        Ok(())
    })

Note that there are two ways to check which menu item was selected: move the item to the event handler closure and compare IDs, or define a custom ID for the item through the with_id constructor and use that ID string to compare.

Tip

Menu items can be shared across menus, and the menu event is bound to a menu item instead of a menu or window. If you dont want all listeners to be triggered when a menu item is selected, do not share menu items and use dedicated instances instead, that you could move into tauri::WebviewWindow/WebviewWindowBuilder::on_menu_event closure.

Migrate to OS Plugin

The Rust tauri::api::os JavaScript @tauri-apps/api/os APIs have been removed. Use the @tauri-apps/plugin-os plugin instead:

  1. Add to cargo dependencies:

Cargo.toml

[dependencies]
tauri-plugin-os = "2"
  1. Use in JavaScript or Rust project:
  • JavaScript

    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_os::init())
    }
    

    package.json

    {
      "dependencies": {
        "@tauri-apps/plugin-os": "^2.0.0"
      }
    }
    
    import { arch } from '@tauri-apps/plugin-os';
    const architecture = await arch();
    
  • Rust

    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_os::init())
            .setup(|app| {
                let os_arch = tauri_plugin_os::arch();
                Ok(())
            })
    }
    

Migrate to Process Plugin

The Rust tauri::api::process JavaScript @tauri-apps/api/process APIs have been removed. Use the @tauri-apps/plugin-process plugin instead:

  1. Add to cargo dependencies:

Cargo.toml

[dependencies]
tauri-plugin-process = "2"
  1. Use in JavaScript or Rust project:
  • JavaScript

    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_process::init())
    }
    

    package.json

    {
      "dependencies": {
        "@tauri-apps/plugin-process": "^2.0.0"
      }
    }
    
    import { exit, relaunch } from '@tauri-apps/plugin-process';
    await exit(0);
    await relaunch();
    
  • Rust

    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_process::init())
            .setup(|app| {
                // exit the app with a status code
                app.handle().exit(1);
                // restart the app
                app.handle().restart();
                Ok(())
            })
    }
    

Migrate to Shell Plugin

The Rust tauri::api::shell JavaScript @tauri-apps/api/shell APIs have been removed. Use the @tauri-apps/plugin-shell plugin instead:

  1. Add to cargo dependencies:

Cargo.toml

[dependencies]
tauri-plugin-shell = "2"
  1. Use in JavaScript or Rust project:
  • JavaScript

    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_shell::init())
    }
    

    package.json

    {
      "dependencies": {
        "@tauri-apps/plugin-shell": "^2.0.0"
      }
    }
    
    import { Command, open } from '@tauri-apps/plugin-shell';
    const output = await Command.create('echo', 'message').execute();
    
    
    await open('https://github.com/tauri-apps/tauri');
    
  • Rust

    • Open an URL
    use tauri_plugin_shell::ShellExt;
    
    
    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_shell::init())
            .setup(|app| {
                app.shell().open("https://github.com/tauri-apps/tauri", None)?;
                Ok(())
            })
    }
    
    • Spawn a child process and retrieve the status code
    use tauri_plugin_shell::ShellExt;
    
    
    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_shell::init())
            .setup(|app| {
                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());
                Ok(())
            })
    }
    
    • Spawn a child process and capture its output
    use tauri_plugin_shell::ShellExt;
    
    
    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_shell::init())
            .setup(|app| {
                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");
                Ok(())
            })
    }
    
    • Spawn a child process and read its events asynchronously:
    use tauri_plugin_shell::{ShellExt, process::CommandEvent};
    
    
    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_shell::init())
            .setup(|app| {
                let handle = app.handle().clone();
                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(())
            })
    }
    

Migrate to Tray Icon Module

The Rust SystemTray APIs were renamed to TrayIcon for consistency. The new APIs can be found in the Rust tray module.

Use tauri::tray::TrayIconBuilder

Use tauri::tray::TrayIconBuilder instead of tauri::SystemTray:

let tray = tauri::tray::TrayIconBuilder::with_id("my-tray").build(app)?;

See TrayIconBuilder for more information.

Migrate to Menu

Use tauri::menu::Menu instead of tauri::SystemTrayMenu, tauri::menu::Submenu instead of tauri::SystemTraySubmenu and tauri::menu::PredefinedMenuItem instead of tauri::SystemTrayMenuItem.

Tray Events

tauri::SystemTray::on_event have been split into tauri::tray::TrayIconBuilder::on_menu_event and tauri::tray::TrayIconBuilder::on_tray_icon_event:

use tauri::{
    menu::{MenuBuilder, MenuItemBuilder},
    tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent},
};


tauri::Builder::default()
    .setup(|app| {
        let toggle = MenuItemBuilder::with_id("toggle", "Toggle").build(app)?;
        let menu = MenuBuilder::new(app).items(&[&toggle]).build()?;
        let tray = TrayIconBuilder::new()
            .menu(&menu)
            .on_menu_event(move |app, event| match event.id().as_ref() {
                "toggle" => {
                    println!("toggle clicked");
                }
                _ => (),
            })
            .on_tray_icon_event(|tray, event| {
                if let TrayIconEvent::Click {
                        button: MouseButton::Left,
                        button_state: MouseButtonState::Up,
                        ..
                } = event
                {
                    let app = tray.app_handle();
                    if let Some(webview_window) = app.get_webview_window("main") {
                       let _ = webview_window.unminimize();
                       let _ = webview_window.show();
                       let _ = webview_window.set_focus();
                    }
                }
            })
            .build(app)?;


        Ok(())
    })

Migrate to Updater Plugin

Change of default behavior

The built-in dialog with an automatic update check was removed, use the Rust and JS APIs to check for and install updates instead. Failing to do so will prevent your users from getting further updates!

The Rust tauri::updater and JavaScript @tauri-apps/api-updater APIs have been removed. To set a custom updater target with the @tauri-apps/plugin-updater:

  1. Add to cargo dependencies:
[dependencies]
tauri-plugin-updater = "2"
  1. Use in JavaScript or Rust project:
  • JavaScript

    fn main() {
        tauri::Builder::default()
            .plugin(tauri_plugin_updater::Builder::new().build())
    }
    

    package.json

    {
      "dependencies": {
        "@tauri-apps/plugin-updater": "^2.0.0"
      }
    }
    
    import { check } from '@tauri-apps/plugin-updater';
    import { relaunch } from '@tauri-apps/plugin-process';
    
    
    const update = await check();
    if (update?.available) {
      console.log(`Update to ${update.version} available! Date: ${update.date}`);
      console.log(`Release notes: ${update.body}`);
      await update.downloadAndInstall();
      // requires the `process` plugin
      await relaunch();
    }
    
  • Rust

    To check for updates:

    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(())
            })
    }
    

    To set a custom updater target:

    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())
    }
    

Migrate Path to Tauri Manager

The Rust tauri::api::path module functions and tauri::PathResolver have been moved to tauri::Manager::path:

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(())
  })

Migrate to new Window API

On the Rust side, Window was renamed to WebviewWindow, its builder WindowBuilder is now named WebviewWindowBuilder and WindowUrl is now named WebviewUrl.

Additionally, the Manager::get_window function was renamed to get_webview_window and the windows parent_window API was renamed to parent_raw to support a high level window parent API.

On the JavaScript side, the WebviewWindow class is now exported in the @tauri-apps/api/webviewWindow path.

The onMenuClicked function was removed, you can intercept menu events when creating a menu in JavaScript instead.

Migrate Embedded Additional Files (Resources)

On the JavaScript side, make sure you Migrate to File System Plugin. Additionally, note the changes made to the v1 allowlist in Migrate Permissions.

On the Rust side, make sure you Migrate Path to Tauri Manager.

Migrate Embedded External Binaries (Sidecar)

In Tauri v1, the external binaries and their arguments were defined in the allowlist. In v2, use the new permissions system. Read Migrate Permissions for more information.

On the JavaScript side, make sure you Migrate to Shell Plugin.

On the Rust side, tauri::api::process API has been removed. Use tauri_plugin_shell::ShellExt and tauri_plugin_shell::process::CommandEvent APIs instead. Read the Embedding External Binaries guide to see how.

The “process-command-api” features flag has been removed in v2. So running the external binaries does not require this feature to be defined in the Tauri config anymore.

Migrate Permissions

The v1 allowlist have been rewritten to a completely new system for permissions that works for individual plugins and is much more configurable for multiwindow and remote URL support. This new system works like an access control list (ACL) where you can allow or deny commands, allocate permissions to a specific set of windows and domains, and define access scopes.

To enable permissions for your app, you must create capability files inside the src-tauri/capabilities folder, and Tauri will automatically configure everything else for you.

The migrate CLI command automatically parses your v1 allowlist and generates the associated capability file.

To learn more about permissions and capabilities, see the security documentation.

Upgrade from Tauri 2.0 Beta

This guide walks you through upgrading your Tauri 2.0 beta application to Tauri 2.0 release candidate.

Automated Migration

The Tauri v2 CLI includes a migrate command that automates most of the process and helps you finish the migration:

  • npm

    npm install @tauri-apps/cli@latest
    npm run tauri migrate
    
  • yarn

    yarn upgrade @tauri-apps/cli@latest
    yarn tauri migrate
    
  • pnpm

    pnpm update @tauri-apps/cli@latest
    pnpm tauri migrate
    
  • cargo

    cargo install tauri-cli --version "^2.0.0" --locked
    cargo tauri migrate
    

Learn more about the migrate command in the Command Line Interface reference

Breaking Changes

We have had several breaking changes going from beta to release candidate. These can be either auto-migrated (see above) or manually performed.

Tauri Core Plugins

We changed how Tauri built-in plugins are addressed in the capabilities PR #10390.

To migrate from the latest beta version you need to prepend all core permission identifiers in your capabilities with core: or switch to the core:default permission and remove old core plugin identifiers.

...
"permissions": [
    "path:default",
    "event:default",
    "window:default",
    "app:default",
    "image:default",
    "resources:default",
    "menu:default",
    "tray:default",
]
...
...
"permissions": [
    "core:path:default",
    "core:event:default",
    "core:window:default",
    "core:app:default",
    "core:image:default",
    "core:resources:default",
    "core:menu:default",
    "core:tray:default",
]
...

We also added a new special core:default permission set which will contain all default permissions of all core plugins, so you can simplify the permissions boilerplate in your capabilities config.

...
"permissions": [
    "core:default"
]
...

Built-In Development Server

We introduced changes to the network exposure of the built-in development server PR #10437 and PR #10456.

The built-in mobile development server no longer exposes network wide and tunnels traffic from the local machine directly to the device.

Currently this improvement does not automatically apply when running on iOS devices (either directly or from Xcode). In this case we default to using the public network address for the development server, but theres a way around it which involves opening Xcode to automatically start a connection between your macOS machine and your connected iOS device, then running tauri ios dev --force-ip-prompt to select the iOS devices TUN address (ends with ::2).

Your development server configuration needs to adapt to this change if running on a physical iOS device is intended. Previously we recommended checking if the TAURI_ENV_PLATFORM environment variable matches either android or ios, but since we can now connect to localhost unless using an iOS device, you should instead check the TAURI_DEV_HOST environment variable. Heres an example of a Vite configuration migration:

  • 2.0.0-beta:
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
import { internalIpV4Sync } from 'internal-ip';


const mobile = !!/android|ios/.exec(process.env.TAURI_ENV_PLATFORM);


export default defineConfig({
  plugins: [svelte()],
  clearScreen: false,
  server: {
    host: mobile ? '0.0.0.0' : false,
    port: 1420,
    strictPort: true,
    hmr: mobile
      ? {
          protocol: 'ws',
          host: internalIpV4Sync(),
          port: 1421,
        }
      : undefined,
  },
});
  • 2.0.0:
import { defineConfig } from 'vite';
import Unocss from 'unocss/vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';


const host = process.env.TAURI_DEV_HOST;


export default defineConfig({
  plugins: [svelte()],
  clearScreen: false,
  server: {
    host: host || false,
    port: 1420,
    strictPort: true,
    hmr: host
      ? {
          protocol: 'ws',
          host: host,
          port: 1430,
        }
      : undefined,
  },
});

Note

The internal-ip NPM package is no longer required, you can directly use the TAURI_DEV_HOST value instead.

Prerequisites

In order to get started building your project with Tauri youll first need to install a few dependencies:

  1. System Dependencies
  2. Rust
  3. Configure for Mobile Targets (only required if developing for mobile)

System Dependencies

Follow the link to get started for your respective operating system:

Linux

Tauri requires various system dependencies for development on Linux. These may be different depending on your distribution but weve included some popular distributions below to help you get setup.

  • Debian

    sudo apt update
    sudo apt install libwebkit2gtk-4.1-dev \
      build-essential \
      curl \
      wget \
      file \
      libxdo-dev \
      libssl-dev \
      libayatana-appindicator3-dev \
      librsvg2-dev
    
  • Arch

    sudo pacman -Syu
    sudo pacman -S --needed \
      webkit2gtk-4.1 \
      base-devel \
      curl \
      wget \
      file \
      openssl \
      appmenu-gtk-module \
      libappindicator-gtk3 \
      librsvg \
      xdotool
    
  • Fedora

    sudo dnf check-update
    sudo dnf install webkit2gtk4.1-devel \
      openssl-devel \
      curl \
      wget \
      file \
      libappindicator-gtk3-devel \
      librsvg2-devel \
      libxdo-devel
    sudo dnf group install "c-development"
    
  • Gentoo

    sudo emerge --ask \
      net-libs/webkit-gtk:4.1 \
      dev-libs/libayatana-appindicator \
      net-misc/curl \
      net-misc/wget \
      sys-apps/file
    
  • OSTree

    sudo rpm-ostree install webkit2gtk4.1-devel \
      openssl-devel \
      curl \
      wget \
      file \
      libappindicator-gtk3-devel \
      librsvg2-devel \
      libxdo-devel \
      gcc \
      gcc-c++ \
      make
    sudo systemctl reboot
    
  • openSUSE

    sudo zypper up
    sudo zypper in webkit2gtk3-devel \
      libopenssl-devel \
      curl \
      wget \
      file \
      libappindicator3-1 \
      librsvg-devel
    sudo zypper in -t pattern devel_basis
    
  • Alpine

    sudo apk add \
      build-base \
      webkit2gtk-4.1-dev \
      curl \
      wget \
      file \
      openssl \
      libayatana-appindicator-dev \
      librsvg
    

    Note: Alpine Linux containers dont include any fonts by default. To ensure text renders correctly in your Tauri app, install at least one font package (for example, font-dejavu ).

  • NixOS

    Note

    Instructions for Nix/NixOS can be found in the NixOS Wiki.

If your distribution isnt included above then you may want to check Awesome Tauri on GitHub to see if a guide has been created.

Next: Install Rust

macOS

Tauri uses Xcode and various macOS and iOS development dependencies.

Download and install Xcode from one of the following places:

Be sure to launch Xcode after installing so that it can finish setting up.

Only developing for desktop targets?

If youre only planning to develop desktop apps and not targeting iOS then you can install Xcode Command Line Tools instead:

xcode-select --install

Next: Install Rust

Windows

Tauri uses the Microsoft C++ Build Tools for development as well as Microsoft Edge WebView2. These are both required for development on Windows.

Follow the steps below to install the required dependencies.

Microsoft C++ Build Tools

  1. Download the Microsoft C++ Build Tools installer and open it to begin installation.
  2. During installation check the “Desktop development with C++” option.

Visual Studio C++ Build Tools installer screenshot

Next: Install WebView2.

WebView2

Tip

WebView 2 is already installed on Windows 10 (from version 1803 onward) and later versions of Windows. If you are developing on one of these versions then you can skip this step and go directly to installing Rust.

Tauri uses Microsoft Edge WebView2 to render content on Windows.

Install WebView2 by visiting the WebView2 Runtime download section. Download the “Evergreen Bootstrapper” and install it.

Next: Check VBSCRIPT

VBSCRIPT (for MSI installers)

MSI package building only

This is only required if you plan to build MSI installer packages ("targets": "msi" or "targets": "all" in tauri.conf.json).

Building MSI packages on Windows requires the VBSCRIPT optional feature to be enabled. This feature is enabled by default on most Windows installations, but may have been disabled on some systems.

If you encounter errors like failed to run light.exe when building MSI packages, you may need to enable the VBSCRIPT feature:

  1. Open SettingsAppsOptional featuresMore Windows features
  2. Locate VBSCRIPT in the list and ensure its checked
  3. Click Next and restart your computer if prompted

Note: VBSCRIPT is currently enabled by default on most Windows installations, but is being deprecated and may be disabled in future Windows versions.

Next: Install Rust

Rust

Tauri is built with Rust and requires it for development. Install Rust using one of following methods. You can view more installation methods at https://www.rust-lang.org/tools/install.

  • Linux and macOS

    Install via rustup using the following command:

    curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
    

    Security Tip

    We have audited this bash script, and it does what it says it is supposed to do. Nevertheless, before blindly curl-bashing a script, it is always wise to look at it first.

    Here is the file as a plain script: rustup.sh

  • Windows

    Visit https://www.rust-lang.org/tools/install to install rustup.

    Alternatively, you can use winget to install rustup using the following command in PowerShell:

    winget install --id Rustlang.Rustup
    

    MSVC toolchain as default

    For full support for Tauri and tools like trunk make sure the MSVC Rust toolchain is the selected default host triple in the installer dialog. Depending on your system it should be either x86_64-pc-windows-msvc, i686-pc-windows-msvc, or aarch64-pc-windows-msvc.

    If you already have Rust installed, you can make sure the correct toolchain is installed by running this command:

    rustup default stable-msvc
    

Be sure to restart your Terminal (and in some cases your system) for the changes to take effect.

Next: Configure for Mobile Targets if youd like to build for Android and iOS, or, if youd like to use a JavaScript framework, install Node. Otherwise Create a Project.

Node.js

JavaScript ecosystem

Only if you intend to use a JavaScript frontend framework

  1. Go to the Node.js website, download the Long Term Support (LTS) version and install it.
  2. Check if Node was successfully installed by running:
node -v
# v20.10.0
npm -v
# 10.2.3

Its important to restart your Terminal to ensure it recognizes the new installation. In some cases, you might need to restart your computer.

While npm is the default package manager for Node.js, you can also use others like pnpm or yarn. To enable these, run corepack enable in your Terminal. This step is optional and only needed if you prefer using a package manager other than npm.

Next: Configure for Mobile Targets or Create a project.

Configure for Mobile Targets

If youd like to target your app for Android or iOS then there are a few additional dependencies that you need to install:

Android

  1. Download and install Android Studio from the Android Developers website
  2. Set the JAVA_HOME environment variable:
  • Linux

    export JAVA_HOME=/opt/android-studio/jbr
    
  • macOS

    export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home"
    
  • Windows

    [System.Environment]::SetEnvironmentVariable("JAVA_HOME", "C:\Program Files\Android\Android Studio\jbr", "User")
    
  1. Use the SDK Manager in Android Studio to install the following:
  • Android SDK Platform
  • Android SDK Platform-Tools
  • NDK (Side by side)
  • Android SDK Build-Tools
  • Android SDK Command-line Tools

Selecting “Show Package Details” in the SDK Manager enables the installation of older package versions. Only install older versions if necessary, as they may introduce compatibility issues or security risks.

  1. Set ANDROID_HOME and NDK_HOME environment variables.
  • Linux

    export ANDROID_HOME="$HOME/Android/Sdk"
    export NDK_HOME="$ANDROID_HOME/ndk/$(ls -1 $ANDROID_HOME/ndk)"
    
  • macOS

    export ANDROID_HOME="$HOME/Library/Android/sdk"
    export NDK_HOME="$ANDROID_HOME/ndk/$(ls -1 $ANDROID_HOME/ndk)"
    
  • Windows

    [System.Environment]::SetEnvironmentVariable("ANDROID_HOME", "$env:LocalAppData\Android\Sdk", "User")
    $VERSION = Get-ChildItem -Name "$env:LocalAppData\Android\Sdk\ndk" | Select-Object -Last 1
    [System.Environment]::SetEnvironmentVariable("NDK_HOME", "$env:LocalAppData\Android\Sdk\ndk\$VERSION", "User")
    

    Tip

    Most apps dont refresh their environment variables automatically, so to let them pickup the changes, you can either restart your terminal and IDE or for your current PowerShell session, you can refresh it with

    [System.Environment]::GetEnvironmentVariables("User").GetEnumerator() | % { Set-Item -Path "Env:\$($_.key)" -Value $_.value }
    
  1. Add the Android targets with rustup:
rustup target add aarch64-linux-android armv7-linux-androideabi i686-linux-android x86_64-linux-android

Next: Setup for iOS or Create a project.

iOS

macOS Only

iOS development requires Xcode and is only available on macOS. Be sure that youve installed Xcode and not Xcode Command Line Tools in the macOS system dependencies section.

  1. Add the iOS targets with rustup in Terminal:
rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim
  1. Install Homebrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  1. Install Cocoapods using Homebrew:
brew install cocoapods

Next: Create a project.

Troubleshooting

If you run into any issues during installation be sure to check the Troubleshooting Guide or reach out on the Tauri Discord.

Next Steps

Now that youve installed all of the prerequisites youre ready to create your first Tauri project!

Project Structure

A Tauri project is usually made of 2 parts, a Rust project and a JavaScript project (optional), and typically the setup looks something like this:

.
├── package.json
├── index.html
├── src/
│   ├── main.js
├── src-tauri/
│   ├── Cargo.toml
│   ├── Cargo.lock
│   ├── build.rs
│   ├── tauri.conf.json
│   ├── src/
│   │   ├── main.rs
│   │   └── lib.rs
│   ├── icons/
│   │   ├── icon.png
│   │   ├── icon.icns
│   │   └── icon.ico
│   └── capabilities/
│       └── default.json

In this case, the JavaScript project is at the top level, and the Rust project is inside src-tauri/, the Rust project is a normal Cargo project with some extra files:

  • tauri.conf.json is the main configuration file for Tauri, it contains everything from the application identifier to dev server url, this file is also a marker for the Tauri CLI to find the Rust project, to learn more about it, see Tauri Config
  • capabilities/ directory is the default folder Tauri reads capability files from (in short, you need to allow commands here to use them in your JavaScript code), to learn more about it, see Security
  • icons/ directory is the default output directory of the tauri icon command, its usually referenced in tauri.conf.json > bundle > icon and used for the apps icons
  • build.rs contains tauri_build::build() which is used for tauris build system
  • src/lib.rs contains the Rust code and the mobile entry point (the function marked with #[cfg_attr(mobile, tauri::mobile_entry_point)]), the reason we dont write directly in main.rs is because we compile your app to a library in mobile builds and load them through the platform frameworks
  • src/main.rs is the main entry point for the desktop, and we run app_lib::run() in main to use the same entry point as mobile, so to keep it simple, dont modify this file, modify lib.rs instead. Note that app_lib corresponds to [lib.name] in Cargo.toml.

Tauri works similar to a static web host, and the way it builds is that you would compile your JavaScript project to static files first, and then compile the Rust project that will bundle those static files in, so the JavaScript project setup is basically the same as if you were to build a static website, to learn more, see Frontend Configuration

If you want to work with Rust code only, simply remove everything else and use the src-tauri/ folder as your top level project or as a member of your Rust workspace

Next Steps

404

Page not found. Check the URL or try using the search bar.

If you're having trouble navigating, please create an issue on GitHub or report on Discord.

About Tauri

Various information about Tauri from governance, philosophy, and trademark guidelines

Tip

If youre looking for a quick technical overview and to start building an app then visit the What is Tauri page. If youd like to learn more about the projects philosophy then keep reading.

Tauri PhilosophyLearn more about the approach behind Tauri

GovernanceUnderstand how the Tauri governance structure is setup

TrademarkGuidelines for using the Tauri trademark

The Tauri Book

Progress Update

Were actively working on authoring and writing The Tauri Book. Weve encountered delays due to the immense growth of Tauri but have recently re-prioritized this project. While we dont yet have details on the timelines of a release, you can keep an eye on this page for updates.

Wed like to apologize for this being delayed beyond the originally communicated publish date. If youve donated through GitHub Sponsors or Open Collective and would like to request a refund you may do so via Open Collective: Contact Tauri on Open Collective.

Overview

The Tauri Book will guide you through the history of Tauri and the design decisions weve made. It will also talk in depth about why privacy, security and sustainability are important and fundamental discussions you can apply to any modern software project.

Topics included are:

  • The method and reasoning behind the design of Tauri
  • The options you have when building with Tauri
  • That you dont have to choose between shipping fast and being sustainable and responsible
  • Why we chose the Rust language as a binding and application layer for Tauri
  • Why a binary review is important

History

In 2020, the manufacture of native-apps has become easier and more accessible than ever before. All the same, beginners and seasoned developers alike are confronted with tough choices in a rapidly changing landscape of security and privacy. This is especially true in the semi-trusted environment of user devices.

Tauri takes the guesswork out of the equation, as it was designed from the ground up to embrace new paradigms of secure development and creative flexibility that leverage the language features of Rust and lets you build an app using any frontend framework you like. Find out how you can design, build, audit and deploy tiny, fast, robust, and secure native applications for the major desktop and mobile platforms, all from the exact same codebase and in record time - without even needing to know the Rust programming language.

Authors and Tauri co-founders Daniel and Lucas take you on a journey from theory to execution, during which you will learn why Tauri was built and how it works under the hood. Together with guest insights that specialize in Open Source, DevOps, Security and Enterprise Architecture, this book also presents discourse-formatted philosophical discussions and open-source sustainability viewpoints from which your next-gen apps will profit - and your users will benefit.

Tauri Governance

One of the main goals of the organizational structure of Tauri is to guarantee we stay true to our open source values and do so sustainably while respecting the health and well-being of contributors. The Tauri Programme within the Commons Conservancy was established to commit to those values, and facilitate an open, transparent and efficient governance process throughout the future development of the Tauri and its auxiliary materials.

Tauri Working Group

The Tauri Working Group is the collective framework created to enable this governance process. Its composed of the following components:

  • Working Group Members
  • Tauri Board & Board Directors
  • Domains & Domain Leads
  • Teams

Tauri governance diagram

Working Group Members

All of the individuals that make up the Tauri Working Group.

Tauri Board & Board Directors

The Tauri Board is the central decision making body for the Tauri Programme and is responsible for the overall health and stability of the Tauri Programme. The Board votes on major decisions within the Programme and issues raised by the Working Group.

An individual Board Director may be a technical contributor, be a stakeholder in Tauris future, share experience from the industry, or have a passion for regulatory and legal aspects within Open Source.

Domains & Domain Leads

Domains are organizational units that represent an area of interest within Tauri.

Domain Leads are trusted contributors within the Tauri community with expertise in the Domain they are leading. They are responsible for setting direction, overseeing and supporting the activities within that Domain.

The current Domains and Domain leads are outlined in the Governance and Guidance repo on GitHub.

Teams

Teams are small groups of contributors that support or maintain specific areas of the Tauri Programme. They are a means for Tauri to execute its longer-term tasks and goals, especially when ad-hoc contributions cannot achieve the same results.

Get Involved

If youre interested in becoming a Tauri Board Director or a Domain Lead, elections for those positions are run throughout the year. For Domain Leads those take place in both the spring and fall and for Board Directors in the summer. Instructions for how to apply are posted to the Tauri Blog leading up to the respective election.

Additional Resources

Tauri Philosophy

Tauri is a toolkit that helps developers make applications for the major desktop platforms - using virtually any frontend framework in existence. The core is built with Rust, and the CLI leverages Node.js making Tauri a genuinely polyglot approach to creating and maintaining great apps.

YouTube video player

Security First

In todays world, every honest threat model assumes that the users device has already been compromised. This puts app developers in a complicated situation because if the device is already at risk, how can the software be trusted?

Defense in depth is the approach weve taken. We want you to be able to take every precaution possible to minimize the surface area you present to attackers. Tauri lets you choose which API endpoints to ship, whether or not you want a localhost server built into your app, and it even randomizes functional handles at runtime. These and other techniques form a secure baseline that empowers you and your users.

Slowing down attackers by making static attacks crushingly difficult and isolating systems from one another is the name of the game. And if you are coming from the Electron ecosystem - rest assured - by default Tauri only ships binaries, not ASAR files.

By choosing to build Tauri with security as a guiding force, we give you every opportunity to take a proactive security posture.

Polyglots, not Silos

Most contemporary frameworks use a single language paradigm and are therefore trapped in a bubble of knowledge and idiom. This can work well for certain niche applications, but it also fosters a kind of tribalism.

This can be seen in the way that the React, Angular, and Vue development communities huddle on their stacks, ultimately breeding very little cross-pollination.

This same situation can be seen in the Rust vs. Node vs. C++ battlefields, where hardliners take their stances and refuse to collaborate across communities.

Today, Tauri uses Rust for the backend - but in the not too distant future, other backends like Go, Nim, Python, Csharp, etc. will be possible. This is because we are maintaining the official Rust bindings to the webview organization and plan to let you switch out the backend for your needs. Since our API can be implemented in any language with C interop, full compliance is only a PR away.

Honest Open Source

None of this would make any sense without a community. Today software communities are amazing places where people help each other and make awesome things - open source is a very big part of that.

Open source means different things to different people, but most will agree that it serves to support freedom. When software doesnt respect your rights, then it can seem unfair and potentially compromise your freedoms by operating in unethical ways.

This is why we are proud that FLOSS advocates can build applications with Tauri that are “certifiably” open source and can be included in FSF endorsed GNU/Linux distributions.

The Future

Tauris future depends on your involvement and contributions. Try it out, file issues, join a working group or make a donation - every contribution is important. Please, at any rate, do get in touch!!!

Trademark Guidelines

This trademark policy was prepared to help you understand how to use the TAURI trademarks, service marks and logos owned by the Tauri Programme within the Commons Conservancy.

While our software is available under a free and open source software license, that copyright license does not include a license to use our trademark, and this Policy is intended to explain how to use our marks consistent with background law and community expectation.

This Policy covers:

  • Our word trademarks and service marks: TAURI, TAO, WRY
  • Our logos: The TAURI, TAO, WRY logos (and all visual derivatives)

This policy encompasses all trademarks and service marks, whether they are registered or not.

General Guidelines

Whenever you use one of our marks, you must always do so in a way that does not mislead anyone about what they are getting and from whom. For example, you cannot say you are distributing TAURI software when youre distributing a modified version of it (aka a Fork), because recipients may not understand the differences between your modified versions and our own.

You also cannot use our logo on your website in a way that suggests that your website is an official website or that we endorse your website.

You can, though, say you like TAURI software, that you participate in the TAURI community, that you are providing an unmodified version of the TAURI software.

You may not use or register our marks, or variations of them as part of your own trademark, service mark, domain name, company name, trade name, product name or service name.

Trademark law does not allow your use of names or trademarks that are too similar to ours. You therefore may not use an obvious variation of any of our marks or any phonetic equivalent, foreign language equivalent, takeoff, or abbreviation for a similar or compatible product or service. We would consider the following too similar to one of our Marks:

  • TAURIMAGE
  • Tauri Wallet App

Acceptable Uses

Applications

TAURI is a framework for making applications for computing devices. You may claim that your application uses TAURI, but care should be taken to avoid giving the impression that your application is approved by The Tauri Programme within the Commons Conservancy, or is an official application. Care must be taken, not to ship your application with the default ICON.

Plugins & Templates

You may publish the code for plugins and templates using the appropriate naming conventions, but please mention that these works are not officially approved. Only such codebases that are managed by the organization within the GitHub organization tauri-apps are considered official.

Core Modifications (Forks)

If you distribute a modified version of our software (TAURI CORE), you must remove all of our logos and naming from it. You must retain our original license in SPDX format. You may use our word marks, but not our logos, to truthfully describe the origin of the software that you are providing. For example, if the code you are distributing is a modification of our software, you may say, “This software is derived from the source code for TAURI software.”

Statements About Compatibility

You may use the word marks, but not the logos, to truthfully describe the relationship between your software and ours. Any other use may imply that we have certified or approved your software. If you wish to use our logos, please contact us to discuss license terms.

Naming Compatible Products

If you wish to describe your product with reference to the TAURI software, here are the conditions under which you may do so. You may call your software XYZ (where XYZ is your product name) for TAURI only if:

  • All versions of the TAURI software you deliver with your product are the exact binaries provided by us, or manufactured by the core software and tooling we provide.
  • Your product is fully compatible with the APIs for the TAURI software.
  • You use the following legend in marketing materials or product descriptions: “TAURI is a trademark of The Tauri Programme within the Commons Conservancy. https://tauri.app/

User Groups

You can use the Word Marks as part of your user group name provided that:

  • The main focus of the group is our software
  • The group does not make a profit
  • Any charge to attend meetings are to cover the cost of the venue, food and drink only

You are not authorized to conduct a conference using our marks.

No Domain Names

You must not register any domain that includes our word marks or any variant or combination of them.

Other For Profit Usage of the TAURI Marks

If you are making a video, tutorial series, book, or other educational material, for which you are receiving payment through subscriptions, sales, advertising or the like, then you must acquire explicit licensing permission from The Tauri Programme within the Commons Conservancy.

How to Display Our Marks

When you have the right to use our mark, here is how to display it.

Trademark Marking and Legends

The first or most prominent mention of a mark on a webpage, document, or documentation should be accompanied by a symbol indicating whether the mark is a registered trademark (“®”) or an unregistered trademark (“™”). If you dont know which applies, contact us. (TAURI itself is a registered trademark.)

Place the following notice at the foot of the page where you have used the mark: TAURI is trademark of [The Tauri Programme within the Commons Conservancy].”

Use of Trademarks in Text

Always use trademarks in their exact form with the correct spelling, neither abbreviated, hyphenated, or combined with any other word or words.

  • Unacceptable: TAUREE
  • Acceptable: TAURI

Dont pluralize a trademark.

  • Unacceptable: I have seventeen TAURIs running on my computer.
  • Acceptable: I am running seventeen TAURI applications on my computer and have ram to spare.

Always use a trademark as an adjective modifying a noun.

  • Unacceptable: This is a TAURI.
  • Acceptable: This is a TAURI software application.

Use of Logos

You may not change any logo except to scale it. This means you may not add decorative elements, change the colors, change the proportions, distort it, add elements, or combine it with other logos.

We have a high-contrast version of the logo, which you can download below in the assets section.

Assets

  • Here you may download the entire Brand Guidelines - (PDF, 74.3 MB)
  • Here you may download SVG and PNG formats of the LOGO and Wordmark in the Logopack - (ZIP, 203 KB)

The Tauri Programme within the Commons Conservancy retains all rights to the modification of these trademark guidelines at any time. If you have a question or enquiry, please send an email to trademark@tauri.app.

These guidelines are based on the Model Trademark Guidelines, available at http://www.modeltrademarkguidelines.org, used under a Creative Commons Attribution 3.0 Unported license: https://creativecommons.org/licenses/by/3.0/deed.en_EU. Version 1.0 dated 20th, August 2022

Core Concepts

Topics that you should get more intimately familiar with if you want to get the most out of the framework

Tauri has a variety of topics that are considered to be core concepts, things any developer should be aware of when developing their applications. Heres a variety of topics that you should get more intimately familiar with if you want to get the most out of the framework.

Tauri ArchitectureArchitecture and ecosystem.

Inter-Process Communication (IPC)The inner workings on the IPC.

SecurityHow Tauri enforces security practices.

Process ModelWhich processes Tauri manages and why.

App SizeHow to make your app as small as possible.

Tauri Architecture

Introduction

Tauri is a polyglot and generic toolkit that is very composable and allows engineers to make a wide variety of applications. It is used for building applications for desktop computers using a combination of Rust tools and HTML rendered in a Webview. Apps built with Tauri can ship with any number of pieces of an optional JS API and Rust API so that webviews can control the system via message passing. Developers can extend the default API with their own functionality and bridge the Webview and Rust-based backend easily.

Tauri apps can have tray-type interfaces. They can be updated and are managed by the users operating system as expected. They are very small because they use the OSs webview. They do not ship a runtime since the final binary is compiled from Rust. This makes the reversing of Tauri apps not a trivial task.

What Tauri is Not

Tauri is not a lightweight kernel wrapper. Instead, it directly uses WRY and TAO to do the heavy lifting in making system calls to the OS.

Tauri is not a VM or virtualized environment. Instead, it is an application toolkit that allows making Webview OS applications.

Core Ecosystem

Simplified representation of the Tauri architecture.

tauri

View on GitHub

This is the major crate that holds everything together. It brings the runtimes, macros, utilities and API into one final product. It reads the tauri.conf.json file at compile time to bring in features and undertake the actual configuration of the app (and even the Cargo.toml file in the projects folder). It handles script injection (for polyfills / prototype revision) at runtime, hosts the API for systems interaction, and even manages the updating process.

tauri-runtime

View on GitHub

The glue layer between Tauri itself and lower-level webview libraries.

tauri-macros

View on GitHub

Creates macros for the context, handler, and commands by leveraging the tauri-codegen crate.

tauri-utils

View on GitHub

Common code that is reused in many places and offers useful utilities like parsing configuration files, detecting platform triples, injecting the CSP, and managing assets.

tauri-build

View on GitHub

Applies the macros at build-time to rig some special features needed by cargo.

tauri-codegen

View on GitHub

Embeds, hashes, and compresses assets, including icons for the app as well as the system tray. Parses tauri.conf.json at compile time and generates the Config struct.

tauri-runtime-wry

View on GitHub

This crate opens up direct systems-level interactions specifically for WRY, such as printing, monitor detection, and other windowing-related tasks.

Tauri Tooling

API (JavaScript / TypeScript)

View on GitHub

A typescript library that creates cjs and esm JavaScript endpoints for you to import into your frontend framework so that the Webview can call and listen to backend activity. Also ships in pure typescript, because for some frameworks this is more optimal. It uses the message passing of webviews to their hosts.

Bundler (Rust / Shell)

View on GitHub

A library that builds a Tauri app for the platform it detects or is told. Currently supports macOS, Windows and Linux - but in the near future will support mobile platforms as well. May be used outside of Tauri projects.

cli.rs (Rust)

View on GitHub

This Rust executable provides the full interface to all of the required activities for which the CLI is required. It runs on macOS, Windows, and Linux.

cli.js (JavaScript)

View on GitHub

Wrapper around cli.rs using napi-rs to produce npm packages for each platform.

create-tauri-app (JavaScript)

View on GitHub

A toolkit that will enable engineering teams to rapidly scaffold out a new tauri-apps project using the frontend framework of their choice (as long as it has been configured).

Upstream Crates

The Tauri-Apps organization maintains two “upstream” crates from Tauri, namely TAO for creating and managing application windows, and WRY for interfacing with the Webview that lives within the window.

TAO

View on GitHub

Cross-platform application window creation library in Rust that supports all major platforms like Windows, macOS, Linux, iOS and Android. Written in Rust, it is a fork of winit that we have extended for our own needs - like menu bar and system tray.

WRY

View on GitHub

WRY is a cross-platform WebView rendering library in Rust that supports all major desktop platforms like Windows, macOS, and Linux. Tauri uses WRY as the abstract layer responsible to determine which webview is used (and how interactions are made).

Additional Tooling

tauri-action

View on GitHub

GitHub workflow that builds Tauri binaries for all platforms. Even allows creating a (very basic) Tauri app even if Tauri is not set up.

tauri-vscode

View on GitHub

This project enhances the Visual Studio Code interface with several nice-to-have features.

Plugins

Tauri Plugin Guide

Generally speaking, plugins are authored by third parties (even though there may be official, supported plugins). A plugin generally does 3 things:

  1. Enables Rust code to do “something”.
  2. Provides interface glue to make it easy to integrate into an app.
  3. Provides a JavaScript API for interfacing with the Rust code.

Here are some examples of Tauri Plugins:

License

Tauri itself is licensed under MIT or Apache-2.0. If you repackage it and modify any source code, it is your responsibility to verify that you are complying with all upstream licenses. Tauri is provided AS-IS with no explicit claim for suitability for any purpose.

Here you may peruse our Software Bill of Materials.

Inter-Process Communication

Inter-Process Communication (IPC) allows isolated processes to communicate securely and is key to building more complex applications.

Learn more about the specific IPC patterns in the following guides:

Brownfield

Isolation

Tauri uses a particular style of Inter-Process Communication called Asynchronous Message Passing, where processes exchange requests and responses serialized using some simple data representation. Message Passing should sound familiar to anyone with web development experience, as this paradigm is used for client-server communication on the internet.

Message passing is a safer technique than shared memory or direct function access because the recipient is free to reject or discard requests as it sees fit. For example, if the Tauri Core process determines a request to be malicious, it simply discards the requests and never executes the corresponding function.

In the following, we explain Tauris two IPC primitives - Events and Commands - in more detail.

Events

Events are fire-and-forget, one-way IPC messages that are best suited to communicate lifecycle events and state changes. Unlike Commands, Events can be emitted by both the Frontend and the Tauri Core.

Events sent between the Core and the Webview.

Commands

Tauri also provides a foreign function interface-like abstraction on top of IPC messages1. The primary API, invoke, is similar to the browsers fetch API and allows the Frontend to invoke Rust functions, pass arguments, and receive data.

Because this mechanism uses a JSON-RPC like protocol under the hood to serialize requests and responses, all arguments and return data must be serializable to JSON.

IPC messages involved in a command invocation.

Footnotes

  1. Because Commands still use message passing under the hood, they do not share the same security pitfalls as real FFI interfaces do.

Brownfield Pattern

This is the default pattern.

This is the simplest and most straightforward pattern to use Tauri with, because it tries to be as compatible as possible with existing frontend projects. In short, it tries to require nothing additional to what an existing web frontend might use inside a browser. Not everything that works in existing browser applications will work out-of-the-box.

If you are unfamiliar with Brownfield software development in general, the Brownfield Wikipedia article provides a nice summary. For Tauri, the existing software is current browser support and behavior, instead of legacy systems.

Configuration

Because the Brownfield pattern is the default pattern, it doesnt require a configuration option to be set. To explicitly set it, you can use the app > security > pattern object in the tauri.conf.json configuration file.

{
  "app": {
    "security": {
      "pattern": {
        "use": "brownfield"
      }
    }
  }
}

There are no additional configuration options for the brownfield pattern.

Isolation Pattern

The Isolation pattern is a way to intercept and modify Tauri API messages sent by the frontend before they get to Tauri Core, all with JavaScript. The secure JavaScript code that is injected by the Isolation pattern is referred to as the Isolation application.

Why

The Isolation patterns purpose is to provide a mechanism for developers to help protect their application from unwanted or malicious frontend calls to Tauri Core. The need for the Isolation pattern rose out of threats coming from untrusted content running on the frontend, a common case for applications with many dependencies. See Security: Threat Models for a list of many sources of threats that an application may see.

The largest threat model described above that the Isolation pattern was designed in mind was Development Threats. Not only do many frontend build-time tools consist of many dozen (or hundreds) of often deeply-nested dependencies, but a complex application may also have a large amount of (also often deeply-nested) dependencies that are bundled into the final output.

When

Tauri highly recommends using the isolation pattern whenever it can be used. Because the Isolation application intercepts all messages from the frontend, it can always be used.

Tauri also strongly suggests locking down your application whenever you use external Tauri APIs. As the developer, you can utilize the secure Isolation application to try and verify IPC inputs, to make sure they are within some expected parameters. For example, you may want to check that a call to read or write a file is not trying to access a path outside your applications expected locations. Another example is making sure that a Tauri API HTTP fetch call is only setting the Origin header to what your application expects it to be.

That said, it intercepts all messages from the frontend, so it will even work with always-on APIs such as Events. Since some events may cause your own rust code to perform actions, the same sort of validation techniques can be used with them.

How

The Isolation pattern is all about injecting a secure application in between your frontend and Tauri Core to intercept and modify incoming IPC messages. It does this by using the sandboxing feature of <iframe>s to run the JavaScript securely alongside the main frontend application. Tauri enforces the Isolation pattern while loading the page, forcing all IPC calls to Tauri Core to instead be routed through the sandboxed Isolation application first. Once the message is ready to be passed to Tauri Core, it is encrypted using the browsers SubtleCrypto implementation and passed back to the main frontend application. Once there, it is directly passed to Tauri Core, where it is then decrypted and read like normal.

To ensure that someone cannot manually read the keys for a specific version of your application and use that to modify the messages after being encrypted, new keys are generated each time your application is run.

Approximate Steps of an IPC Message

To make it easier to follow, heres an ordered list with the approximate steps an IPC message will go through when being sent to Tauri Core with the Isolation pattern:

  1. Tauris IPC handler receives a message
  2. IPC handler -> Isolation application
  3. [sandbox] Isolation application hook runs and potentially modifies the message
  4. [sandbox] Message is encrypted with AES-GCM using a runtime-generated key
  5. [encrypted] Isolation application -> IPC handler
  6. [encrypted] IPC handler -> Tauri Core

Note: Arrows (->) indicate message passing.

Performance Implications

Because encryption of the message does occur, there are additional overhead costs compared to the Brownfield pattern, even if the secure Isolation application doesnt do anything. Aside from performance-sensitive applications (who likely have a carefully-maintained and small set of dependencies, to keep the performance adequate), most applications should not notice the runtime costs of encrypting/decrypting the IPC messages, as they are relatively small and AES-GCM is relatively fast. If you are unfamiliar with AES-GCM, all that is relevant in this context is that its the only authenticated mode algorithm included in SubtleCrypto and that you probably already use it every day under the hood with TLS.

There is also a cryptographically secure key generated once each time the Tauri application is started. It is not generally noticeable if the system already has enough entropy to immediately return enough random numbers, which is extremely common for desktop environments. If running in a headless environment to perform some integration testing with WebDriver then you may want to install some sort of entropy-generating service such as haveged if your operating system does not have one included. Linux 5.6 (March 2020) now includes entropy generation using speculative execution.

Limitations

There are a few limitations in the Isolation pattern that arose out of platform inconsistencies. The most significant limitation is due to external files not loading correctly inside sandboxed <iframes> on Windows. Because of this, we have implemented a simple script inlining step during build time that takes the content of scripts relative to the Isolation application and injects them inline. This means that typical bundling or simple including of files like <script src="index.js"></script> still works properly, but newer mechanisms such as ES Modules will not successfully load.

Recommendations

Because the point of the Isolation application is to protect against Development Threats, we highly recommend keeping your Isolation application as simple as possible. Not only should you strive to keep dependencies of your isolation application minimal, but you should also consider keeping its required build steps minimal. This would allow you to not need to worry about supply chain attacks against your Isolation application on top of your frontend application.

Creating the Isolation Application

In this example, we will make a small hello-world style Isolation application and hook it up to an imaginary existing Tauri application. It will do no verification of the messages passing through it, only print the contents to the WebView console.

For the purposes of this example, lets imagine we are in the same directory as tauri.conf.json. The existing Tauri application has its frontendDist set to ../dist.

../dist-isolation/index.html:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Isolation Secure Script</title>
  </head>
  <body>
    <script src="index.js"></script>
  </body>
</html>

../dist-isolation/index.js:

window.__TAURI_ISOLATION_HOOK__ = (payload) => {
  // let's not verify or modify anything, just print the content from the hook
  console.log('hook', payload);
  return payload;
};

Now, all we need to do is set up our tauri.conf.json configuration to use the Isolation pattern, and have just bootstrapped to the Isolation pattern from the Brownfield pattern.

Configuration

Lets assume that our main frontend frontendDist is set to ../dist. We also output our Isolation application to ../dist-isolation.

{
  "build": {
    "frontendDist": "../dist"
  },
  "app": {
    "security": {
      "pattern": {
        "use": "isolation",
        "options": {
          "dir": "../dist-isolation"
        }
      }
    }
  }
}

Process Model

Tauri employs a multi-process architecture similar to Electron or many modern web browsers. This guide explores the reasons behind the design choice and why it is key to writing secure applications.

Why Multiple Processes?

In the early days of GUI applications, it was common to use a single process to perform computation, draw the interface and react to user input. As you can probably guess, this meant that a long-running, expensive computation would leave the user interface unresponsive, or worse, a failure in one app component would bring the whole app crashing down.

It became clear that a more resilient architecture was needed, and applications began running different components in different processes. This makes much better use of modern multi-core CPUs and creates far safer applications. A crash in one component doesnt affect the whole system anymore, as components are isolated on different processes. If a process gets into an invalid state, we can easily restart it.

We can also limit the blast radius of potential exploits by handing out only the minimum amount of permissions to each process, just enough so they can get their job done. This pattern is known as the Principle of Least Privilege, and you see it in the real world all the time. If you have a gardener coming over to trim your hedge, you give them the key to your garden. You would not give them the keys to your house; why would they need access to that? The same concept applies to computer programs. The less access we give them, the less harm they can do if they get compromised.

The Core Process

Each Tauri application has a core process, which acts as the applications entry point and which is the only component with full access to the operating system.

The Cores primary responsibility is to use that access to create and orchestrate application windows, system-tray menus, or notifications. Tauri implements the necessary cross-platform abstractions to make this easy. It also routes all Inter-Process Communication through the Core process, allowing you to intercept, filter, and manipulate IPC messages in one central place.

The Core process should also be responsible for managing global state, such as settings or database connections. This allows you to easily synchronize state between windows and protect your business-sensitive data from prying eyes in the Frontend.

We chose Rust to implement Tauri because of its concept of Ownership guarantees memory safety while retaining excellent performance.

Simplified representation of the Tauri process model. A single Core process manages one or more WebView processes.

The WebView Process

The Core process doesnt render the actual user interface (UI) itself; it spins up WebView processes that leverage WebView libraries provided by the operating system. A WebView is a browser-like environment that executes your HTML, CSS, and JavaScript.

This means that most of your techniques and tools used in traditional web development can be used to create Tauri applications. For example, many Tauri examples are written using the Svelte frontend framework and the Vite bundler.

Security best practices apply as well; for example, you must always sanitize user input, never handle secrets in the Frontend, and ideally defer as much business logic as possible to the Core process to keep your attack surface small.

Unlike other similar solutions, the WebView libraries are not included in your final executable but dynamically linked at runtime1. This makes your application significantly smaller, but it also means that you need to keep platform differences in mind, just like traditional web development.

Footnotes

  1. Currently, Tauri uses Microsoft Edge WebView2 on Windows, WKWebView on macOS and webkitgtk on Linux.

App Size

While Tauri by default provides very small binaries it doesnt hurt to push the limits a bit, so here are some tips and tricks for reaching optimal results.

Cargo Configuration

One of the simplest frontend agnostic size improvements you can do to your project is adding a Cargo profile to it.

Dependent on whether you use the stable or nightly Rust toolchain the options available to you differ a bit. Its recommended you stick to the stable toolchain unless youre an advanced user.

  • Stable

    src-tauri/Cargo.toml

    [profile.dev]
    incremental = true # Compile your binary in smaller steps.
    
    
    [profile.release]
    codegen-units = 1 # Allows LLVM to perform better optimization.
    lto = true # Enables link-time-optimizations.
    opt-level = "s" # Prioritizes small binary size. Use `3` if you prefer speed.
    panic = "abort" # Higher performance by disabling panic handlers.
    strip = true # Ensures debug symbols are removed.
    
  • Nightly

    src-tauri/Cargo.toml

    [profile.dev]
    incremental = true # Compile your binary in smaller steps.
    rustflags = ["-Zthreads=8"] # Better compile performance.
    
    
    [profile.release]
    codegen-units = 1 # Allows LLVM to perform better optimization.
    lto = true # Enables link-time-optimizations.
    opt-level = "s" # Prioritizes small binary size. Use `3` if you prefer speed.
    panic = "abort" # Higher performance by disabling panic handlers.
    strip = true # Ensures debug symbols are removed.
    trim-paths = "all" # Removes potentially privileged information from your binaries.
    rustflags = ["-Cdebuginfo=0", "-Zthreads=8"] # Better compile performance.
    

References

Note

This is not a complete reference over all available options, merely the ones that wed like to draw extra attention to.

  • incremental: Compile your binary in smaller steps.

  • codegen-units: Speeds up compile times at the cost of compile time optimizations.

  • lto: Enables link time optimizations.

  • opt-level: Determines the focus of the compiler. Use 3 to optimize performance, z to optimize for size, and s for something in-between.

  • panic: Reduce size by removing panic unwinding.

  • strip: Strip either symbols or debuginfo from a binary.

  • rpath: Assists in finding the dynamic libraries the binary requires by hard coding information into the binary.

  • trim-paths: Removes potentially privileged information from binaries.

  • rustflags: Sets Rust compiler flags on a profile by profile basis.

    • -Cdebuginfo=0: Whether debuginfo symbols should be included in the build.
    • -Zthreads=8: Increases the number of threads used during compilation.

Remove Unused Commands

In Pull Request feat: add a new option to remove unused commands, we added in a new option in the tauri config file

tauri.conf.json

{
  "build": {
    "removeUnusedCommands": true
  }
}

to remove commands thatre never allowed in your capability files (ACL), so you dont have to pay for what you dont use

Tip

To maximize the benefit of this, only include commands that you use in the ACL instead of using defaultss

Note

This feature requires tauri@2.4, tauri-build@2.1, tauri-plugin@2.1 and tauri-cli@2.4

Note

This wont be accounting for dynamically added ACLs at runtime so make sure to check it when using this

How does it work under the hood?

tauri-cli will communicate with tauri-build and the build script of tauri, tauri-plugin through an environment variable and let them generate a list of allowed commands from the ACL, this will then be used by the generate_handler macro to remove unused commands based on that

An internal detail is this environment variable is currently REMOVE_UNUSED_COMMANDS, and its set to projects directory, usually the src-tauri directory, this is used for the build scripts to find the capability files, and although its not encouraged, you can still set this environment variable yourself if you cant or dont want to use tauri-cli to get this to work (do note that as this is an implementation detail, we dont guarantee the stability of it)

Contribute

Guide for Tauri contributors

We, the maintainers, are really excited that you are interested in contributing to Tauri. We welcome contributors of any skill level and are happy to provide guidance on PRs. In case of any doubts you can reach out to us on our Discord server.

Project repositories

Main Tauri repositories you can contribute to are:

  • The core Tauri repository containing the Tauri runtime, build tools, macros and utils.
  • Plugins workspace repository with all the official Tauri plugins
  • Tauri Docs repository containing this website

Each of those Tauri repositories contains a .github/CONTRIBUTING.md file. In it you will find instructions on how to set up local development environment and submit a Pull Request.

Translating

The Tauri documentation is available in multiple languages: English, French, Spanish, Chinese (Simplified), Japanese, and Korean. Contributions to translations are welcome.

When translating or reviewing documentation, consider using the following tools:

  • zhlint — A linting tool for Chinese text that checks punctuation, spacing, and other common issues. Recommended for contributors working on the zh-cn locale. Available at zhlint.jinjiang.dev.
  • Chinese Copywriting Guidelines — A style guide for writing consistent and correct Chinese text. Available at github.com/sparanoid/chinese-copywriting-guidelines.
  • Starlight i18n VS Code extension — A useful extension for managing i18n content in Starlight-based documentation sites. Available on the VS Code Marketplace.

Develop

Topics pertaining to the development of Tauri applications, including how to use the Tauri API, communicating between the frontend and backend, configuration, state management, debugging and more

Now that you have everything set up, you are ready to run your application using Tauri.

If you are using a UI framework or JavaScript bundler, you likely have access to a development server that will speed up your development process, so if you havent configured your apps dev URL and script that starts it, you can do so via the devUrl and beforeDevCommand config values:

tauri.conf.json

{
  "build": {
    "devUrl": "http://localhost:3000",
    "beforeDevCommand": "npm run dev"
  }
}

Note

Every framework has its own development tooling. It is outside of the scope of this document to cover them all or stay up to date.

Please refer to your frameworks documentation to learn more and determine the correct values to be configured.

Otherwise, if you are not using a UI framework or module bundler, you can point Tauri to your frontend source code and the Tauri CLI will start a development server for you:

tauri.conf.json

{
  "build": {
    "frontendDist": "./src"
  }
}

Note that in this example, the src folder must include an index.html file along with any other assets loaded by your frontend.

Plain/Vanilla Dev Server Security

The built-in Tauri development server does not support mutual authentication or encryption. You should never use it for development on untrusted networks. See the development server security considerations for a more detailed explanation.

Developing Your Desktop Application

To develop your application for desktop, run the tauri dev command.

  • npm

    npm run tauri dev
    
  • yarn

    yarn tauri dev
    
  • pnpm

    pnpm tauri dev
    
  • deno

    deno task tauri dev
    
  • bun

    bun tauri dev
    
  • cargo

    cargo tauri dev
    

The first time you run this command, the Rust package manager may need several minutes to download and build all the required packages. Since they are cached, subsequent builds are much faster, as only your code needs rebuilding.

Once Rust has finished building, the webview opens, displaying your web app. You can make changes to your web app, and if your tooling supports it, the webview should update automatically, just like a browser.

Opening the Web Inspector

You can open the Web Inspector to debug your application by performing a right-click on the webview and clicking “Inspect” or using the Ctrl + Shift + I shortcut on Windows and Linux or Cmd + Option + I shortcut on macOS.

Developing Your Mobile Application

Developing for mobile is similar to how desktop development works, but you must run tauri android dev or tauri ios dev instead:

  • npm

    npm run tauri [android|ios] dev
    
  • yarn

    yarn tauri [android|ios] dev
    
  • pnpm

    pnpm tauri [android|ios] dev
    
  • deno

    deno task tauri [android|ios] dev
    
  • bun

    bun tauri [android|ios] dev
    
  • cargo

    cargo tauri [android|ios] dev
    

The first time you run this command, the Rust package manager may need several minutes to download and build all the required packages. Since they are cached, subsequent builds are much faster, as only your code needs rebuilding.

Development Server

The development server on mobile works similarly to the desktop one, but if you are trying to run on a physical iOS device, you must configure it to listen to a particular address provided by the Tauri CLI, defined in the TAURI_DEV_HOST environment variable. This address is either a public network address (which is the default behavior) or the actual iOS device TUN address — which is more secure, but currently needs Xcode to connect to the device.

To use the iOS devices address you must open Xcode before running the dev command and ensure your device is connected via network in the Window > Devices and Simulators menu. Then you must run tauri ios dev --force-ip-prompt to select the iOS device address (an IPv6 address ending with ::2).

To make your development server listen on the correct host to be accessible by the iOS device, you must tweak its configuration to use the TAURI_DEV_HOST value if it has been provided. Here is an example configuration for Vite:

import { defineConfig } from 'vite';


const host = process.env.TAURI_DEV_HOST;


// https://vitejs.dev/config/
export default defineConfig({
  clearScreen: false,
  server: {
    host: host || false,
    port: 1420,
    strictPort: true,
    hmr: host
      ? {
          protocol: 'ws',
          host,
          port: 1421,
        }
      : undefined,
  },
});

Check your frameworks setup guide for more information.

Note

Projects created with create-tauri-app configure your development server for mobile dev out of the box.

Device Selection

By default, the mobile dev command tries to run your application on a connected device, and falls back to prompting you to select a simulator to use. To define the run target upfront, you can provide the device or simulator name as an argument:

  • npm

    npm run tauri ios dev 'iPhone 15'
    
  • yarn

    yarn tauri ios dev 'iPhone 15'
    
  • pnpm

    pnpm tauri ios dev 'iPhone 15'
    
  • deno

    deno task tauri ios dev 'iPhone 15'
    
  • bun

    bun tauri ios dev 'iPhone 15'
    
  • cargo

    cargo tauri ios dev 'iPhone 15'
    

Using Xcode or Android Studio

Alternatively you can choose to use Xcode or Android Studio to develop your application. This can help you troubleshoot some development issues by using the IDE instead of the command line tools. To open the mobile IDE instead of running on a connected device or simulator, use the --open flag:

  • npm

    npm run tauri [android|ios] dev --open
    
  • yarn

    yarn tauri [android|ios] dev --open
    
  • pnpm

    pnpm tauri [android|ios] dev --open
    
  • deno

    deno task tauri [android|ios] dev --open
    
  • bun

    bun tauri [android|ios] dev --open
    
  • cargo

    cargo tauri [android|ios] dev --open
    

Note

If you intend to run the application on a physical iOS device, you must also provide the --host argument and your development server must use the process.env.TAURI_DEV_HOST value as host. See your frameworks setup guide for more information.

  • npm

    npm run tauri [android|ios] dev --open --host
    
  • yarn

    yarn tauri [android|ios] dev --open --host
    
  • pnpm

    pnpm tauri [android|ios] dev --open --host
    
  • deno

    deno task tauri [android|ios] dev --open --host
    
  • bun

    bun tauri [android|ios] dev --open --host
    
  • cargo

    cargo tauri [android|ios] dev --open --host
    

Caution

To use Xcode or Android Studio, the Tauri CLI process must be running and cannot be killed. It is recommended to use the tauri [android|ios] dev --open command and keep the process alive until you close the IDE.

Opening the Web Inspector

  • iOS

    Safari must be used to access the Web Inspector for your iOS application.

    Open Safari on your Mac, choose Safari > Settings in the menu bar, click Advanced, then select Show features for web developers.

    If you are running on a physical device, you must enable Web Inspector in Settings > Safari > Advanced.

    After following all steps you should see a Develop menu in Safari, where you will find the connected devices and applications to inspect. Select your device or simulator and click on localhost to open the Safari Developer Tools window.

  • Android

    The inspector is enabled by default for Android emulators, but you must enable it for physical devices. Connect your Android device to the computer, open the Settings app on the Android device, select About, scroll to Build Number, and tap it 7 times. This will enable Developer Mode for your Android device and the Developer Options settings.

    To enable application debugging on your device, you must enter the Developer Options settings, toggle on the developer options switch and enable USB Debugging.

    Note

    Each Android distribution has its own way to enable the Developer Mode. Please check your manufacturers documentation for more information.

    The Web Inspector for Android is powered by Google Chromes DevTools and can be accessed by navigating to chrome://inspect in the Chrome browser on your computer. Your device or emulator should appear in the remote devices list if your Android application is running, and you can open the developer tools by clicking inspect on the entry matching your device.

Troubleshooting

  1. Error running build script on Xcode

Tauri hooks into the iOS Xcode project by creating a build phase that executes the Tauri CLI to compile the Rust source as a library that is loaded at runtime. The build phase is executed on the Xcode process context, so it might not be able to use shell modifications such as PATH additions, so be careful when using tools such as Node.js version managers which may not be compatible.

  1. Network permission prompt on first iOS app execution

When you first execute tauri ios dev, you might see iOS prompting you for permission to find and connect to devices on your local network. This permission is required because, to access your development server from an iOS device, it must be exposed on the local network. To run your app on your device, you must click Allow and restart your application.

Reacting to Source Code Changes

Similarly to how your webview reflects changes in real time, tauri dev watches your src-tauri folder and its dependent crates in the workspace for changes, so your application is automatically rebuilt and restarted whenever you modify them.

You can disable this behavior by using the --no-watch flag on the tauri dev command.

To ignore watching certain files, you can create .taurignore files which work like regular .gitignore files:

.taurignore

build/
src/generated/*.rs
deny.toml

.taurignore files are usually put in the src-tauri directory or cargo workspace root folder. Currently, tauri dev looks for .taurignore files anywhere inside the common ancestor of the watched folders and the Cargo workspace root folder.

Using the Browser DevTools

Tauris APIs only work in your app window, so once you start using them you wont be able to open your frontend in your systems browser anymore.

If you prefer using your browsers developer tooling, you must configure tauri-invoke-http to bridge Tauri API calls through a HTTP server.

Source Control

In your project repository, you SHOULD commit the src-tauri/Cargo.lock along with the src-tauri/Cargo.toml to git because Cargo uses the lockfile to provide deterministic builds. As a result, it is recommended that all applications check in their Cargo.lock. You SHOULD NOT commit the src-tauri/target folder or any of its contents.

Calling the Frontend from Rust

The @tauri-apps/api NPM package offers APIs to listen to both global and webview-specific events.

  • Listening to global events

    import { listen } from '@tauri-apps/api/event';
    
    
    type DownloadStarted = {
      url: string;
      downloadId: number;
      contentLength: number;
    };
    
    
    listen<DownloadStarted>('download-started', (event) => {
      console.log(
        `downloading ${event.payload.contentLength} bytes from ${event.payload.url}`
      );
    });
    
  • Listening to webview-specific events

    import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';
    
    
    const appWebview = getCurrentWebviewWindow();
    appWebview.listen<string>('logged-in', (event) => {
      localStorage.setItem('session-token', event.payload);
    });
    

The listen function keeps the event listener registered for the entire lifetime of the application. To stop listening on an event you can use the unlisten function which is returned by the listen function:

import { listen } from '@tauri-apps/api/event';


const unlisten = await listen('download-started', (event) => {});
unlisten();

Note

Always use the unlisten function when your execution context goes out of scope such as when a component is unmounted.

When the page is reloaded or you navigate to another URL the listeners are unregistered automatically. This does not apply to a Single Page Application (SPA) router though.

Common Pitfalls

Dont call unlisten() before the listener resolves

The listen function returns a Promise that resolves to the unlisten handle. If you call unlisten synchronously before the Promise resolves, the handler will be removed immediately and you wont receive any events:

// Wrong: unlisten is called before the listener is registered
const unlisten = listen('sync-complete', (event) => {
  console.log('sync finished');
});
unlisten(); // unlisten is a Promise here, not a function -- the listener is not cleaned up


// Correct: await the Promise to get the unlisten handle
const unlisten = await listen('sync-complete', (event) => {
  console.log('sync finished');
});
// Now you can store and call it later, e.g. in a cleanup function
unlisten();
Timing in setup hooks

In frameworks like React, Vue, and Svelte, the setup or mount hook runs before the component is fully rendered. If you listen for events during setup, make sure the event handler does not depend on DOM elements that havent been rendered yet, or defer the listener registration to an effect/hook that runs after mount.

// Wrong: DOM ref may not be available yet
function MyComponent() {
  const ref = useRef(null);
  listen('scroll-to', (event) => {
    ref.current.scrollIntoView(); // ref.current may be null during setup
  });
  return <div ref={ref} />;
}


// Correct: use useEffect which runs after the component mounts
function MyComponent() {
  const ref = useRef(null);
  useEffect(() => {
    const unlisten = listen('scroll-to', (event) => {
      ref.current?.scrollIntoView();
    });
    return () => {
      unlisten.then((fn) => fn());
    };
  }, []);
  return <div ref={ref} />;
}
Event ordering and async listeners

Event listeners are called in the order they are registered, but if a listener is async and the event emitter sends multiple events in rapid succession, the listeners may process events out of order. For ordered, high-throughput data delivery, consider using Channels instead of the event system.

Framework-specific Cleanup Examples

When using a frontend framework, you should clean up event listeners when a component is unmounted to avoid memory leaks and duplicate handlers.

  • React

    import { useEffect, useState } from 'react';
    import { listen } from '@tauri-apps/api/event';
    
    
    function DownloadTracker() {
      const [progress, setProgress] = useState(0);
    
    
      useEffect(() => {
        const unlisten = listen<number>('download-progress', (event) => {
          setProgress(event.payload);
        });
    
    
        return () => {
          unlisten.then((fn) => fn());
        };
      }, []);
    
    
      return <div>Download progress: {progress}%</div>;
    }
    
  • Vue

    <script setup lang="ts">
    import { ref, onMounted, onUnmounted } from 'vue';
    import { listen } from '@tauri-apps/api/event';
    
    
    const progress = ref(0);
    let unlistenPromise;
    
    
    onMounted(() => {
      unlistenPromise = listen<number>('download-progress', (event) => {
        progress.value = event.payload;
      });
    });
    
    
    onUnmounted(() => {
      unlistenPromise?.then((fn) => fn());
    });
    </script>
    
    
    <template>
      <div>Download progress: {{ progress }}%</div>
    </template>
    
  • Svelte

    <script lang="ts">
    import { listen } from '@tauri-apps/api/event';
    
    
    let progress = $state(0);
    
    
    $effect(() => {
      const unlistenPromise = listen<number>(
        'download-progress',
        (event) => {
          progress = event.payload;
        }
      );
    
    
      return () => {
        unlistenPromise.then((unlisten) => unlisten());
      };
    });
    </script>
    
    
    <div>Download progress: {progress}%</div>
    

Additionally Tauri provides a utility function for listening to an event exactly once:

import { once } from '@tauri-apps/api/event';
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';


once('ready', (event) => {});


const appWebview = getCurrentWebviewWindow();
appWebview.once('ready', () => {});

Note

Events emitted in the frontend also trigger listeners registered by these APIs. For more information, see the Calling Rust from the Frontend documentation.

Listening to Events on Rust

Global and webview-specific events are also delivered to listeners registered in Rust.

  • Listening to global events

    src-tauri/src/lib.rs

    use tauri::Listener;
    
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
      tauri::Builder::default()
        .setup(|app| {
          app.listen("download-started", |event| {
            if let Ok(payload) = serde_json::from_str::<DownloadStarted>(&event.payload()) {
              println!("downloading {}", payload.url);
            }
          });
          Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
    }
    
  • Listening to webview-specific events

    src-tauri/src/lib.rs

    use tauri::{Listener, Manager};
    
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
      tauri::Builder::default()
        .setup(|app| {
          let webview = app.get_webview_window("main").unwrap();
          webview.listen("logged-in", |event| {
            let session_token = event.data;
            // save token..
          });
          Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
    }
    

The listen function keeps the event listener registered for the entire lifetime of the application. To stop listening on an event you can use the unlisten function:

// unlisten outside of the event handler scope:
let event_id = app.listen("download-started", |event| {});
app.unlisten(event_id);


// unlisten when some event criteria is matched
let handle = app.handle().clone();
app.listen("status-changed", |event| {
  if event.data == "ready" {
    handle.unlisten(event.id);
  }
});

Additionally Tauri provides a utility function for listening to an event exactly once:

app.once("ready", |event| {
  println!("app is ready");
});

In this case the event listener is immediately unregistered after its first trigger.

Calling the Frontend from Rust

This document includes guides on how to communicate with your application frontend from your Rust code. To see how to communicate with your Rust code from your frontend, see Calling Rust from the Frontend.

The Rust side of your Tauri application can call the frontend by leveraging the Tauri event system, using channels or directly evaluating JavaScript code.

Event System

Tauri ships a simple event system you can use to have bi-directional communication between Rust and your frontend.

The event system was designed for situations where small amounts of data need to be streamed or you need to implement a multi consumer multi producer pattern (e.g. push notification system).

The event system is not designed for low latency or high throughput situations. See the channels section for the implementation optimized for streaming data.

The major differences between a Tauri command and a Tauri event are that events have no strong type support, event payloads are always JSON strings making them not suitable for bigger messages and there is no support of the capabilities system to fine grain control event data and channels.

The AppHandle and WebviewWindow types implement the event system traits Listener and Emitter.

Events are either global (delivered to all listeners) or webview-specific (only delivered to the webview matching a given label).

Global Events

To trigger a global event you can use the Emitter#emit function:

src-tauri/src/lib.rs

use tauri::{AppHandle, Emitter};


#[tauri::command]
fn download(app: AppHandle, url: String) {
  app.emit("download-started", &url).unwrap();
  for progress in [1, 15, 50, 80, 100] {
    app.emit("download-progress", progress).unwrap();
  }
  app.emit("download-finished", &url).unwrap();
}

Note

Global events are delivered to all listeners

Webview Event

To trigger an event to a listener registered by a specific webview you can use the Emitter#emit_to function:

src-tauri/src/lib.rs

use tauri::{AppHandle, Emitter};


#[tauri::command]
fn login(app: AppHandle, user: String, password: String) {
  let authenticated = user == "tauri-apps" && password == "tauri";
  let result = if authenticated { "loggedIn" } else { "invalidCredentials" };
  app.emit_to("login", "login-result", result).unwrap();
}

It is also possible to trigger an event to a list of webviews by calling Emitter#emit_filter. In the following example we emit a open-file event to the main and file-viewer webviews:

src-tauri/src/lib.rs

use tauri::{AppHandle, Emitter, EventTarget};


#[tauri::command]
fn open_file(app: AppHandle, path: std::path::PathBuf) {
  app.emit_filter("open-file", path, |target| match target {
    EventTarget::WebviewWindow { label } => label == "main" || label == "file-viewer",
    _ => false,
  }).unwrap();
}

Note

Webview-specific events are not triggered to regular global event listeners. To listen to any event you must use the listen_any function instead of listen, which defines the listener to act as a catch-all for emitted events.

Event Payload

The event payload can be any serializable type that also implements Clone. Lets enhance the download event example by using an object to emit more information in each event:

src-tauri/src/lib.rs

use tauri::{AppHandle, Emitter};
use serde::Serialize;


#[derive(Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct DownloadStarted<'a> {
  url: &'a str,
  download_id: usize,
  content_length: usize,
}


#[derive(Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct DownloadProgress {
  download_id: usize,
  chunk_length: usize,
}


#[derive(Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct DownloadFinished {
  download_id: usize,
}


#[tauri::command]
fn download(app: AppHandle, url: String) {
  let content_length = 1000;
  let download_id = 1;


  app.emit("download-started", DownloadStarted {
    url: &url,
    download_id,
    content_length
  }).unwrap();


  for chunk_length in [15, 150, 35, 500, 300] {
    app.emit("download-progress", DownloadProgress {
      download_id,
      chunk_length,
    }).unwrap();
  }


  app.emit("download-finished", DownloadFinished { download_id }).unwrap();
}

Listening to Events

Tauri provides APIs to listen to events on both the webview and the Rust interfaces.

Listening to Events on the Frontend

The @tauri-apps/api NPM package offers APIs to listen to both global and webview-specific events.

  • Listening to global events

    import { listen } from '@tauri-apps/api/event';
    
    
    type DownloadStarted = {
      url: string;
      downloadId: number;
      contentLength: number;
    };
    
    
    listen<DownloadStarted>('download-started', (event) => {
      console.log(
        `downloading ${event.payload.contentLength} bytes from ${event.payload.url}`
      );
    });
    
  • Listening to webview-specific events

    import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';
    
    
    const appWebview = getCurrentWebviewWindow();
    appWebview.listen<string>('logged-in', (event) => {
      localStorage.setItem('session-token', event.payload);
    });
    

The listen function keeps the event listener registered for the entire lifetime of the application. To stop listening on an event you can use the unlisten function which is returned by the listen function:

import { listen } from '@tauri-apps/api/event';


const unlisten = await listen('download-started', (event) => {});
unlisten();

Note

Always use the unlisten function when your execution context goes out of scope such as when a component is unmounted.

When the page is reloaded or you navigate to another URL the listeners are unregistered automatically. This does not apply to a Single Page Application (SPA) router though.

Common Pitfalls

Dont call unlisten() before the listener resolves

The listen function returns a Promise that resolves to the unlisten handle. If you call unlisten synchronously before the Promise resolves, the handler will be removed immediately and you wont receive any events:

// Wrong: unlisten is called before the listener is registered
const unlisten = listen('sync-complete', (event) => {
  console.log('sync finished');
});
unlisten(); // unlisten is a Promise here, not a function -- the listener is not cleaned up


// Correct: await the Promise to get the unlisten handle
const unlisten = await listen('sync-complete', (event) => {
  console.log('sync finished');
});
// Now you can store and call it later, e.g. in a cleanup function
unlisten();
Timing in setup hooks

In frameworks like React, Vue, and Svelte, the setup or mount hook runs before the component is fully rendered. If you listen for events during setup, make sure the event handler does not depend on DOM elements that havent been rendered yet, or defer the listener registration to an effect/hook that runs after mount.

// Wrong: DOM ref may not be available yet
function MyComponent() {
  const ref = useRef(null);
  listen('scroll-to', (event) => {
    ref.current.scrollIntoView(); // ref.current may be null during setup
  });
  return <div ref={ref} />;
}


// Correct: use useEffect which runs after the component mounts
function MyComponent() {
  const ref = useRef(null);
  useEffect(() => {
    const unlisten = listen('scroll-to', (event) => {
      ref.current?.scrollIntoView();
    });
    return () => {
      unlisten.then((fn) => fn());
    };
  }, []);
  return <div ref={ref} />;
}
Event ordering and async listeners

Event listeners are called in the order they are registered, but if a listener is async and the event emitter sends multiple events in rapid succession, the listeners may process events out of order. For ordered, high-throughput data delivery, consider using Channels instead of the event system.

Framework-specific Cleanup Examples

When using a frontend framework, you should clean up event listeners when a component is unmounted to avoid memory leaks and duplicate handlers.

  • React

    import { useEffect, useState } from 'react';
    import { listen } from '@tauri-apps/api/event';
    
    
    function DownloadTracker() {
      const [progress, setProgress] = useState(0);
    
    
      useEffect(() => {
        const unlisten = listen<number>('download-progress', (event) => {
          setProgress(event.payload);
        });
    
    
        return () => {
          unlisten.then((fn) => fn());
        };
      }, []);
    
    
      return <div>Download progress: {progress}%</div>;
    }
    
  • Vue

    <script setup lang="ts">
    import { ref, onMounted, onUnmounted } from 'vue';
    import { listen } from '@tauri-apps/api/event';
    
    
    const progress = ref(0);
    let unlistenPromise;
    
    
    onMounted(() => {
      unlistenPromise = listen<number>('download-progress', (event) => {
        progress.value = event.payload;
      });
    });
    
    
    onUnmounted(() => {
      unlistenPromise?.then((fn) => fn());
    });
    </script>
    
    
    <template>
      <div>Download progress: {{ progress }}%</div>
    </template>
    
  • Svelte

    <script lang="ts">
    import { listen } from '@tauri-apps/api/event';
    
    
    let progress = $state(0);
    
    
    $effect(() => {
      const unlistenPromise = listen<number>(
        'download-progress',
        (event) => {
          progress = event.payload;
        }
      );
    
    
      return () => {
        unlistenPromise.then((unlisten) => unlisten());
      };
    });
    </script>
    
    
    <div>Download progress: {progress}%</div>
    

Additionally Tauri provides a utility function for listening to an event exactly once:

import { once } from '@tauri-apps/api/event';
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';


once('ready', (event) => {});


const appWebview = getCurrentWebviewWindow();
appWebview.once('ready', () => {});

Note

Events emitted in the frontend also trigger listeners registered by these APIs. For more information, see the Calling Rust from the Frontend documentation.

Listening to Events on Rust

Global and webview-specific events are also delivered to listeners registered in Rust.

  • Listening to global events

    src-tauri/src/lib.rs

    use tauri::Listener;
    
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
      tauri::Builder::default()
        .setup(|app| {
          app.listen("download-started", |event| {
            if let Ok(payload) = serde_json::from_str::<DownloadStarted>(&event.payload()) {
              println!("downloading {}", payload.url);
            }
          });
          Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
    }
    
  • Listening to webview-specific events

    src-tauri/src/lib.rs

    use tauri::{Listener, Manager};
    
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
      tauri::Builder::default()
        .setup(|app| {
          let webview = app.get_webview_window("main").unwrap();
          webview.listen("logged-in", |event| {
            let session_token = event.data;
            // save token..
          });
          Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
    }
    

The listen function keeps the event listener registered for the entire lifetime of the application. To stop listening on an event you can use the unlisten function:

// unlisten outside of the event handler scope:
let event_id = app.listen("download-started", |event| {});
app.unlisten(event_id);


// unlisten when some event criteria is matched
let handle = app.handle().clone();
app.listen("status-changed", |event| {
  if event.data == "ready" {
    handle.unlisten(event.id);
  }
});

Additionally Tauri provides a utility function for listening to an event exactly once:

app.once("ready", |event| {
  println!("app is ready");
});

In this case the event listener is immediately unregistered after its first trigger.

Channels

The event system is designed to be a simple two way communication that is globally available in your application. Under the hood it directly evaluates JavaScript code so it might not be suitable to sending a large amount of data.

Channels are designed to be fast and deliver ordered data. They are used internally for streaming operations such as download progress, child process output and WebSocket messages.

Lets rewrite our download command example to use channels instead of the event system:

src-tauri/src/lib.rs

use tauri::{AppHandle, ipc::Channel};
use serde::Serialize;


#[derive(Clone, Serialize)]
#[serde(rename_all = "camelCase", rename_all_fields = "camelCase", tag = "event", content = "data")]
enum DownloadEvent<'a> {
  Started {
    url: &'a str,
    download_id: usize,
    content_length: usize,
  },
  Progress {
    download_id: usize,
    chunk_length: usize,
  },
  Finished {
    download_id: usize,
  },
}


#[tauri::command]
fn download(app: AppHandle, url: String, on_event: Channel<DownloadEvent>) {
  let content_length = 1000;
  let download_id = 1;


  on_event.send(DownloadEvent::Started {
    url: &url,
    download_id,
    content_length,
  }).unwrap();


  for chunk_length in [15, 150, 35, 500, 300] {
    on_event.send(DownloadEvent::Progress {
      download_id,
      chunk_length,
    }).unwrap();
  }


  on_event.send(DownloadEvent::Finished { download_id }).unwrap();
}

When calling the download command you must create the channel and provide it as an argument:

import { invoke, Channel } from '@tauri-apps/api/core';


type DownloadEvent =
  | {
      event: 'started';
      data: {
        url: string;
        downloadId: number;
        contentLength: number;
      };
    }
  | {
      event: 'progress';
      data: {
        downloadId: number;
        chunkLength: number;
      };
    }
  | {
      event: 'finished';
      data: {
        downloadId: number;
      };
    };


const onEvent = new Channel<DownloadEvent>();
onEvent.onmessage = (message) => {
  console.log(`got download event ${message.event}`);
};


await invoke('download', {
  url: 'https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-schema-generator/schemas/config.schema.json',
  onEvent,
});

Evaluating JavaScript

To directly execute any JavaScript code on the webview context you can use the WebviewWindow#eval function:

src-tauri/src/lib.rs

use tauri::Manager;


tauri::Builder::default()
  .setup(|app| {
    let webview = app.get_webview_window("main").unwrap();
    webview.eval("console.log('hello from Rust')")?;
    Ok(())
  })

If the script to be evaluated is not so simple and must use input from Rust objects we recommend using the serialize-to-javascript crate.

Calling Rust from the Frontend

This document includes guides on how to communicate with your Rust code from your application frontend. To see how to communicate with your frontend from your Rust code, see Calling the Frontend from Rust.

Tauri provides a command primitive for reaching Rust functions with type safety, along with an event system that is more dynamic.

Commands

Tauri provides a simple yet powerful command system for calling Rust functions from your web app. Commands can accept arguments and return values. They can also return errors and be async.

Basic Example

Commands can be defined in your src-tauri/src/lib.rs file. To create a command, just add a function and annotate it with #[tauri::command]:

src-tauri/src/lib.rs

#[tauri::command]
fn my_custom_command() {
  println!("I was invoked from JavaScript!");
}

Note

Command names must be unique.

Note

Commands defined in the lib.rs file cannot be marked as pub due to a limitation in the glue code generation. You will see an error like this if you mark it as a public function:

error[E0255]: the name `__cmd__command_name` is defined multiple times
  --> src/lib.rs:28:8
   |
27 | #[tauri::command]
   | ----------------- previous definition of the macro `__cmd__command_name` here
28 | pub fn x() {}
   |        ^ `__cmd__command_name` reimported here
   |
   = note: `__cmd__command_name` must be defined only once in the macro namespace of this module

You will have to provide a list of your commands to the builder function like so:

src-tauri/src/lib.rs

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
  tauri::Builder::default()
    +.invoke_handler(tauri::generate_handler![my_custom_command])
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

Now, you can invoke the command from your JavaScript code:

// When using the Tauri API npm package:
import { invoke } from '@tauri-apps/api/core';


// When using the Tauri global script (if not using the npm package)
// Be sure to set `app.withGlobalTauri` in `tauri.conf.json` to true
const invoke = window.__TAURI__.core.invoke;


// Invoke the command
invoke('my_custom_command');

Defining Commands in a Separate Module

If your application defines a lot of components or if they can be grouped, you can define commands in a separate module instead of bloating the lib.rs file.

As an example lets define a command in the src-tauri/src/commands.rs file:

src-tauri/src/commands.rs

#[tauri::command]
pub fn my_custom_command() {
  println!("I was invoked from JavaScript!");
}

Note

When defining commands in a separate module they should be marked as pub.

Note

The command name is not scoped to the module so they must be unique even between modules.

In the lib.rs file, define the module and provide the list of your commands accordingly;

src-tauri/src/lib.rs

mod commands;


#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
  tauri::Builder::default()
    +.invoke_handler(tauri::generate_handler![commands::my_custom_command])
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

Note the commands:: prefix in the command list, which denotes the full path to the command function.

The command name in this example is my_custom_command so you can still call it by executing invoke("my_custom_command") in your frontend, the commands:: prefix is ignored.

WASM

When using a Rust frontend to call invoke() without arguments, you will need to adapt your frontend code as below. The reason is that Rust doesnt support optional arguments.

#[wasm_bindgen]
extern "C" {
    // invoke without arguments
+    #[wasm_bindgen(js_namespace = ["window", "__TAURI__", "core"], js_name = invoke)]
    +async fn invoke_without_args(cmd: &str) -> JsValue;


    // invoke with arguments (default)
    #[wasm_bindgen(js_namespace = ["window", "__TAURI__", "core"])]
    async fn invoke(cmd: &str, args: JsValue) -> JsValue;


    // They need to have different names!
}

Passing Arguments

Your command handlers can take arguments:

#[tauri::command]
fn my_custom_command(invoke_message: String) {
  println!("I was invoked from JavaScript, with this message: {}", invoke_message);
}

Arguments should be passed as a JSON object with camelCase keys:

invoke('my_custom_command', { invokeMessage: 'Hello!' });

Note

You can use snake_case for the arguments with the rename_all attribute:

#[tauri::command(rename_all = "snake_case")]
fn my_custom_command(invoke_message: String) {}

The corresponding JavaScript:

invoke('my_custom_command', { invoke_message: 'Hello!' });

Arguments can be of any type, as long as they implement serde::Deserialize.

Returning Data

Command handlers can return data as well:

#[tauri::command]
fn my_custom_command() -> String {
  "Hello from Rust!".into()
}

The invoke function returns a promise that resolves with the returned value:

invoke('my_custom_command').then((message) => console.log(message));

Returned data can be of any type, as long as it implements serde::Serialize.

Returning Array Buffers

Return values that implements serde::Serialize are serialized to JSON when the response is sent to the frontend. This can slow down your application if you try to return a large data such as a file or a download HTTP response. To return array buffers in an optimized way, use tauri::ipc::Response:

use tauri::ipc::Response;
#[tauri::command]
fn read_file() -> Response {
  let data = std::fs::read("/path/to/file").unwrap();
  tauri::ipc::Response::new(data)
}

Error Handling

If your handler could fail and needs to be able to return an error, have the function return a Result:

#[tauri::command]
fn login(user: String, password: String) -> Result<String, String> {
  if user == "tauri" && password == "tauri" {
    // resolve
    Ok("logged_in".to_string())
  } else {
    // reject
    Err("invalid credentials".to_string())
  }
}

If the command returns an error, the promise will reject, otherwise, it resolves:

invoke('login', { user: 'tauri', password: '0j4rijw8=' })
  .then((message) => console.log(message))
  .catch((error) => console.error(error));

As mentioned above, everything returned from commands must implement serde::Serialize, including errors. This can be problematic if youre working with error types from Rusts std library or external crates as most error types do not implement it. In simple scenarios you can use map_err to convert these errors to String:

#[tauri::command]
fn my_custom_command() -> Result<(), String> {
  std::fs::File::open("path/to/file").map_err(|err| err.to_string())?;
  // Return `null` on success
  Ok(())
}

Since this is not very idiomatic you may want to create your own error type which implements serde::Serialize. In the following example, we use the thiserror crate to help create the error type. It allows you to turn enums into error types by deriving the thiserror::Error trait. You can consult its documentation for more details.

// create the error type that represents all errors possible in our program
#[derive(Debug, thiserror::Error)]
enum Error {
  #[error(transparent)]
  Io(#[from] std::io::Error)
}


// we must manually implement serde::Serialize
impl serde::Serialize for Error {
  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  where
    S: serde::ser::Serializer,
  {
    serializer.serialize_str(self.to_string().as_ref())
  }
}


#[tauri::command]
fn my_custom_command() -> Result<(), Error> {
  // This will return an error
  std::fs::File::open("path/that/does/not/exist")?;
  // Return `null` on success
  Ok(())
}

A custom error type has the advantage of making all possible errors explicit so readers can quickly identify what errors can happen. This saves other people (and yourself) enormous amounts of time when reviewing and refactoring code later.
It also gives you full control over the way your error type gets serialized. In the above example, we simply returned the error message as a string, but you could assign each error a code so you could more easily map it to a similar looking TypeScript error enum for example:

#[derive(Debug, thiserror::Error)]
enum Error {
  #[error(transparent)]
  Io(#[from] std::io::Error),
  #[error("failed to parse as string: {0}")]
  Utf8(#[from] std::str::Utf8Error),
}


#[derive(serde::Serialize)]
#[serde(tag = "kind", content = "message")]
#[serde(rename_all = "camelCase")]
enum ErrorKind {
  Io(String),
  Utf8(String),
}


impl serde::Serialize for Error {
  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  where
    S: serde::ser::Serializer,
  {
    let error_message = self.to_string();
    let error_kind = match self {
      Self::Io(_) => ErrorKind::Io(error_message),
      Self::Utf8(_) => ErrorKind::Utf8(error_message),
    };
    error_kind.serialize(serializer)
  }
}


#[tauri::command]
fn read() -> Result<Vec<u8>, Error> {
  let data = std::fs::read("/path/to/file")?;
  Ok(data)
}

In your frontend you now get a { kind: 'io' | 'utf8', message: string } error object:

type ErrorKind = {
  kind: 'io' | 'utf8';
  message: string;
};


invoke('read').catch((e: ErrorKind) => {});

Async Commands

Asynchronous commands are preferred in Tauri to perform heavy work in a manner that doesnt result in UI freezes or slowdowns.

Note

Async commands are executed on a separate async task using async_runtime::spawn. Commands without the async keyword are executed on the main thread unless defined with #[tauri::command(async)].

If your command needs to run asynchronously, simply declare it as async.

Caution

You need to be careful when creating asynchronous functions using Tauri. Currently, you cannot simply include borrowed arguments in the signature of an asynchronous function. Some common examples of types like this are &str and State<'_, Data>. This limitation is tracked here: https://github.com/tauri-apps/tauri/issues/2533 and workarounds are shown below.

When working with borrowed types, you have to make additional changes. These are your two main options:

Option 1: Convert the type, such as &str to a similar type that is not borrowed, such as String. This may not work for all types, for example State<'_, Data>.

Example:

// Declare the async function using String instead of &str, as &str is borrowed and thus unsupported
#[tauri::command]
async fn my_custom_command(value: String) -> String {
  // Call another async function and wait for it to finish
  some_async_function().await;
  value
}

Option 2: Wrap the return type in a Result. This one is a bit harder to implement, but works for all types.

Use the return type Result<a, b>, replacing a with the type you wish to return, or () if you wish to return null, and replacing b with an error type to return if something goes wrong, or () if you wish to have no optional error returned. For example:

  • Result<String, ()> to return a String, and no error.
  • Result<(), ()> to return null.
  • Result<bool, Error> to return a boolean or an error as shown in the Error Handling section above.

Example:

// Return a Result<String, ()> to bypass the borrowing issue
#[tauri::command]
async fn my_custom_command(value: &str) -> Result<String, ()> {
  // Call another async function and wait for it to finish
  some_async_function().await;
  // Note that the return value must be wrapped in `Ok()` now.
  Ok(format!(value))
}
Invoking from JavaScript

Since invoking the command from JavaScript already returns a promise, it works just like any other command:

invoke('my_custom_command', { value: 'Hello, Async!' }).then(() =>
  console.log('Completed!')
);

Channels

The Tauri channel is the recommended mechanism for streaming data such as streamed HTTP responses to the frontend. The following example reads a file and notifies the frontend of the progress in chunks of 4096 bytes:

use tokio::io::AsyncReadExt;


#[tauri::command]
async fn load_image(path: std::path::PathBuf, reader: tauri::ipc::Channel<&[u8]>) {
  // for simplicity this example does not include error handling
  let mut file = tokio::fs::File::open(path).await.unwrap();


  let mut chunk = vec![0; 4096];


  loop {
    let len = file.read(&mut chunk).await.unwrap();
    if len == 0 {
      // Length of zero means end of file.
      break;
    }
    reader.send(&chunk).unwrap();
  }
}

See the channels documentation for more information.

Accessing the WebviewWindow in Commands

Commands can access the WebviewWindow instance that invoked the message:

src-tauri/src/lib.rs

#[tauri::command]
async fn my_custom_command(webview_window: tauri::WebviewWindow) {
  println!("WebviewWindow: {}", webview_window.label());
}

Accessing an AppHandle in Commands

Commands can access an AppHandle instance:

src-tauri/src/lib.rs

#[tauri::command]
async fn my_custom_command(app_handle: tauri::AppHandle) {
  let app_dir = app_handle.path().app_dir();
  use tauri::GlobalShortcutManager;
  app_handle.global_shortcut_manager().register("CTRL + U", move || {});
}

Tip

AppHandle and WebviewWindow both take a generic parameter R: Runtime, when the wry feature is enabled in tauri (which is enabled by default), we default the generic to the Wry runtime so you can use it directly, but if you want to use a different runtime, for example the mock runtime, you need to write your functions like this

src-tauri/src/lib.rs

use tauri::{AppHandle, GlobalShortcutManager, Runtime, WebviewWindow};


#[tauri::command]
async fn my_custom_command<R: Runtime>(app_handle: AppHandle<R>, webview_window: WebviewWindow<R>) {
  let app_dir = app_handle.path().app_dir();
  app_handle
    .global_shortcut_manager()
    .register("CTRL + U", move || {});
  println!("WebviewWindow: {}", webview_window.label());
}

Accessing Managed State

Tauri can manage state using the manage function on tauri::Builder. The state can be accessed on a command using tauri::State:

src-tauri/src/lib.rs

struct MyState(String);


#[tauri::command]
fn my_custom_command(state: tauri::State<MyState>) {
  assert_eq!(state.0 == "some state value", true);
}


#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
  tauri::Builder::default()
    .manage(MyState("some state value".into()))
    .invoke_handler(tauri::generate_handler![my_custom_command])
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

Accessing Raw Request

Tauri commands can also access the full tauri::ipc::Request object which includes the raw body payload and the request headers.

#[derive(Debug, thiserror::Error)]
enum Error {
  #[error("unexpected request body")]
  RequestBodyMustBeRaw,
  #[error("missing `{0}` header")]
  MissingHeader(&'static str),
}


impl serde::Serialize for Error {
  fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
  where
    S: serde::ser::Serializer,
  {
    serializer.serialize_str(self.to_string().as_ref())
  }
}


#[tauri::command]
fn upload(request: tauri::ipc::Request) -> Result<(), Error> {
  let tauri::ipc::InvokeBody::Raw(upload_data) = request.body() else {
    return Err(Error::RequestBodyMustBeRaw);
  };
  let Some(authorization_header) = request.headers().get("Authorization") else {
    return Err(Error::MissingHeader("Authorization"));
  };


  // upload...


  Ok(())
}

In the frontend you can call invoke() sending a raw request body by providing an ArrayBuffer or Uint8Array on the payload argument, and include request headers in the third argument:

const data = new Uint8Array([1, 2, 3]);
await __TAURI__.core.invoke('upload', data, {
  headers: {
    Authorization: 'apikey',
  },
});

Creating Multiple Commands

The tauri::generate_handler! macro takes an array of commands. To register multiple commands, you cannot call invoke_handler multiple times. Only the last call will be used. You must pass each command to a single call of tauri::generate_handler!.

src-tauri/src/lib.rs

#[tauri::command]
fn cmd_a() -> String {
  "Command a"
}
#[tauri::command]
fn cmd_b() -> String {
  "Command b"
}


#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
  tauri::Builder::default()
    .invoke_handler(tauri::generate_handler![cmd_a, cmd_b])
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

Complete Example

Any or all of the above features can be combined:

src-tauri/src/lib.rs

struct Database;


#[derive(serde::Serialize)]
struct CustomResponse {
  message: String,
  other_val: usize,
}


async fn some_other_function() -> Option<String> {
  Some("response".into())
}


#[tauri::command]
async fn my_custom_command(
  window: tauri::WebviewWindow,
  number: usize,
  database: tauri::State<'_, Database>,
) -> Result<CustomResponse, String> {
  println!("Called from {}", window.label());
  let result: Option<String> = some_other_function().await;
  if let Some(message) = result {
    Ok(CustomResponse {
      message,
      other_val: 42 + number,
    })
  } else {
    Err("No result".into())
  }
}


#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
  tauri::Builder::default()
    .manage(Database {})
    .invoke_handler(tauri::generate_handler![my_custom_command])
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}
import { invoke } from '@tauri-apps/api/core';


// Invocation from JavaScript
invoke('my_custom_command', {
  number: 42,
})
  .then((res) =>
    console.log(`Message: ${res.message}, Other Val: ${res.other_val}`)
  )
  .catch((e) => console.error(e));

Event System

The event system is a simpler communication mechanism between your frontend and the Rust. Unlike commands, events are not type safe, are always async, cannot return values and only supports JSON payloads.

Global Events

To trigger a global event you can use the event.emit or the WebviewWindow#emit functions:

import { emit } from '@tauri-apps/api/event';
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';


// emit(eventName, payload)
emit('file-selected', '/path/to/file');


const appWebview = getCurrentWebviewWindow();
appWebview.emit('route-changed', { url: window.location.href });

Note

Global events are delivered to all listeners

Webview Event

To trigger an event to a listener registered by a specific webview you can use the event.emitTo or the WebviewWindow#emitTo functions:

import { emitTo } from '@tauri-apps/api/event';
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';


// emitTo(webviewLabel, eventName, payload)
emitTo('settings', 'settings-update-requested', {
  key: 'notification',
  value: 'all',
});


const appWebview = getCurrentWebviewWindow();
appWebview.emitTo('editor', 'file-changed', {
  path: '/path/to/file',
  contents: 'file contents',
});

Note

Webview-specific events are not triggered to regular global event listeners. To listen to any event you must provide the { target: { kind: 'Any' } } option to the event.listen function, which defines the listener to act as a catch-all for emitted events:

import { listen } from '@tauri-apps/api/event';
listen(
  'state-changed',
  (event) => {
    console.log('got state changed event', event);
  },
  {
    target: { kind: 'Any' },
  }
);

Listening to Events

The @tauri-apps/api NPM package offers APIs to listen to both global and webview-specific events.

  • Listening to global events

    import { listen } from '@tauri-apps/api/event';
    
    
    type DownloadStarted = {
      url: string;
      downloadId: number;
      contentLength: number;
    };
    
    
    listen<DownloadStarted>('download-started', (event) => {
      console.log(
        `downloading ${event.payload.contentLength} bytes from ${event.payload.url}`
      );
    });
    
  • Listening to webview-specific events

    import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';
    
    
    const appWebview = getCurrentWebviewWindow();
    appWebview.listen<string>('logged-in', (event) => {
      localStorage.setItem('session-token', event.payload);
    });
    

The listen function keeps the event listener registered for the entire lifetime of the application. To stop listening on an event you can use the unlisten function which is returned by the listen function:

import { listen } from '@tauri-apps/api/event';


const unlisten = await listen('download-started', (event) => {});
unlisten();

Note

Always use the unlisten function when your execution context goes out of scope such as when a component is unmounted.

When the page is reloaded or you navigate to another URL the listeners are unregistered automatically. This does not apply to a Single Page Application (SPA) router though.

Common Pitfalls

Dont call unlisten() before the listener resolves

The listen function returns a Promise that resolves to the unlisten handle. If you call unlisten synchronously before the Promise resolves, the handler will be removed immediately and you wont receive any events:

// Wrong: unlisten is called before the listener is registered
const unlisten = listen('sync-complete', (event) => {
  console.log('sync finished');
});
unlisten(); // unlisten is a Promise here, not a function -- the listener is not cleaned up


// Correct: await the Promise to get the unlisten handle
const unlisten = await listen('sync-complete', (event) => {
  console.log('sync finished');
});
// Now you can store and call it later, e.g. in a cleanup function
unlisten();
Timing in setup hooks

In frameworks like React, Vue, and Svelte, the setup or mount hook runs before the component is fully rendered. If you listen for events during setup, make sure the event handler does not depend on DOM elements that havent been rendered yet, or defer the listener registration to an effect/hook that runs after mount.

// Wrong: DOM ref may not be available yet
function MyComponent() {
  const ref = useRef(null);
  listen('scroll-to', (event) => {
    ref.current.scrollIntoView(); // ref.current may be null during setup
  });
  return <div ref={ref} />;
}


// Correct: use useEffect which runs after the component mounts
function MyComponent() {
  const ref = useRef(null);
  useEffect(() => {
    const unlisten = listen('scroll-to', (event) => {
      ref.current?.scrollIntoView();
    });
    return () => {
      unlisten.then((fn) => fn());
    };
  }, []);
  return <div ref={ref} />;
}
Event ordering and async listeners

Event listeners are called in the order they are registered, but if a listener is async and the event emitter sends multiple events in rapid succession, the listeners may process events out of order. For ordered, high-throughput data delivery, consider using Channels instead of the event system.

Framework-specific Cleanup Examples

When using a frontend framework, you should clean up event listeners when a component is unmounted to avoid memory leaks and duplicate handlers.

  • React

    import { useEffect, useState } from 'react';
    import { listen } from '@tauri-apps/api/event';
    
    
    function DownloadTracker() {
      const [progress, setProgress] = useState(0);
    
    
      useEffect(() => {
        const unlisten = listen<number>('download-progress', (event) => {
          setProgress(event.payload);
        });
    
    
        return () => {
          unlisten.then((fn) => fn());
        };
      }, []);
    
    
      return <div>Download progress: {progress}%</div>;
    }
    
  • Vue

    <script setup lang="ts">
    import { ref, onMounted, onUnmounted } from 'vue';
    import { listen } from '@tauri-apps/api/event';
    
    
    const progress = ref(0);
    let unlistenPromise;
    
    
    onMounted(() => {
      unlistenPromise = listen<number>('download-progress', (event) => {
        progress.value = event.payload;
      });
    });
    
    
    onUnmounted(() => {
      unlistenPromise?.then((fn) => fn());
    });
    </script>
    
    
    <template>
      <div>Download progress: {{ progress }}%</div>
    </template>
    
  • Svelte

    <script lang="ts">
    import { listen } from '@tauri-apps/api/event';
    
    
    let progress = $state(0);
    
    
    $effect(() => {
      const unlistenPromise = listen<number>(
        'download-progress',
        (event) => {
          progress = event.payload;
        }
      );
    
    
      return () => {
        unlistenPromise.then((unlisten) => unlisten());
      };
    });
    </script>
    
    
    <div>Download progress: {progress}%</div>
    

Additionally Tauri provides a utility function for listening to an event exactly once:

import { once } from '@tauri-apps/api/event';
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';


once('ready', (event) => {});


const appWebview = getCurrentWebviewWindow();
appWebview.once('ready', () => {});

Note

Events emitted in the frontend also trigger listeners registered by these APIs. For more information, see the Calling Rust from the Frontend documentation.

Listening to Events on Rust

Global and webview-specific events are also delivered to listeners registered in Rust.

  • Listening to global events

    src-tauri/src/lib.rs

    use tauri::Listener;
    
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
      tauri::Builder::default()
        .setup(|app| {
          app.listen("download-started", |event| {
            if let Ok(payload) = serde_json::from_str::<DownloadStarted>(&event.payload()) {
              println!("downloading {}", payload.url);
            }
          });
          Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
    }
    
  • Listening to webview-specific events

    src-tauri/src/lib.rs

    use tauri::{Listener, Manager};
    
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
      tauri::Builder::default()
        .setup(|app| {
          let webview = app.get_webview_window("main").unwrap();
          webview.listen("logged-in", |event| {
            let session_token = event.data;
            // save token..
          });
          Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
    }
    

The listen function keeps the event listener registered for the entire lifetime of the application. To stop listening on an event you can use the unlisten function:

// unlisten outside of the event handler scope:
let event_id = app.listen("download-started", |event| {});
app.unlisten(event_id);


// unlisten when some event criteria is matched
let handle = app.handle().clone();
app.listen("status-changed", |event| {
  if event.data == "ready" {
    handle.unlisten(event.id);
  }
});

Additionally Tauri provides a utility function for listening to an event exactly once:

app.once("ready", |event| {
  println!("app is ready");
});

In this case the event listener is immediately unregistered after its first trigger.

To learn how to listen to events and emit events from your Rust code, see the Rust Event System documentation.

Configuration Files

Since Tauri is a toolkit for building applications there can be many files to configure project settings. Some common files that you may run across are tauri.conf.json, package.json and Cargo.toml. We briefly explain each on this page to help point you in the right direction for which files to modify.

Tauri Config

The Tauri configuration is used to define the source of your Web app, describe your applications metadata, configure bundles, set plugin configurations, modify runtime behavior by configuring windows, tray icons, menus and more.

This file is used by the Tauri runtime and the Tauri CLI. You can define build settings (such as the command run before tauri build or tauri dev kicks in), set the name and version of your app, control the Tauri runtime, and configure plugins.

Tip

You can find all of the options in the configuration reference.

Supported Formats

The default Tauri config format is JSON. The JSON5 or TOML format can be enabled by adding the config-json5 or config-toml feature flag (respectively) to the tauri and tauri-build dependencies in Cargo.toml.

Cargo.toml

[build-dependencies]
tauri-build = { version = "2.0.0", features = [ "config-json5" ] }


[dependencies]
tauri = { version = "2.0.0", features = [  "config-json5" ] }

The structure and values are the same across all formats, however, the formatting should be consistent with the respective files format:

tauri.conf.json

{
  build: {
    devUrl: 'http://localhost:3000',
    // start the dev server
    beforeDevCommand: 'npm run dev',
  },
  bundle: {
    active: true,
    icon: ['icons/app.png'],
  },
  app: {
    windows: [
      {
        title: 'MyApp',
      },
    ],
  },
  plugins: {
    updater: {
      pubkey: 'updater pub key',
      endpoints: ['https://my.app.updater/{{target}}/{{current_version}}'],
    },
  },
}

Tauri.toml

[build]
dev-url = "http://localhost:3000"
# start the dev server
before-dev-command = "npm run dev"


[bundle]
active = true
icon = ["icons/app.png"]


[[app.windows]]
title = "MyApp"


[plugins.updater]
pubkey = "updater pub key"
endpoints = ["https://my.app.updater/{{target}}/{{current_version}}"]

Note that JSON5 and TOML supports comments, and TOML can use kebab-case for config names which are more idiomatic. Field names are case-sensitive in all 3 formats.

Platform-specific Configuration

In addition to the default configuration file, Tauri can read a platform-specific configuration from:

  • tauri.linux.conf.json or Tauri.linux.toml for Linux
  • tauri.windows.conf.json or Tauri.windows.toml for Windows
  • tauri.macos.conf.json or Tauri.macos.toml for macOS
  • tauri.android.conf.json or Tauri.android.toml for Android
  • tauri.ios.conf.json or Tauri.ios.toml for iOS

The platform-specific configuration file gets merged with the main configuration object following the JSON Merge Patch (RFC 7396) specification.

For example, given the following base tauri.conf.json:

tauri.conf.json

{
  "productName": "MyApp",
  "bundle": {
    "resources": ["./resources"]
  },
  "plugins": {
    "deep-link": {}
  }
}

And the given tauri.linux.conf.json:

tauri.linux.conf.json

{
  "productName": "my-app",
  "bundle": {
    "resources": ["./linux-assets"]
  },
  "plugins": {
    "cli": {
      "description": "My app",
      "subcommands": {
        "update": {}
      }
    },
    "deep-link": {}
  }
}

The resolved configuration for Linux would be the following object:

{
  "productName": "my-app",
  "bundle": {
    "resources": ["./linux-assets"]
  },
  "plugins": {
    "cli": {
      "description": "My app",
      "subcommands": {
        "update": {}
      }
    },
    "deep-link": {}
  }
}

Additionally you can provide a configuration to be merged via the CLI, see the following section for more information.

Extending the Configuration

The Tauri CLI allows you to extend the Tauri configuration when running one of the dev, android dev, ios dev, build, android build, ios build or bundle commands. The configuration extension can be provided by the --config argument either as a raw JSON string or as a path to a JSON file. Tauri uses the JSON Merge Patch (RFC 7396) specification to merge the provided configuration value with the originally resolved configuration object.

This mechanism can be used to define multiple flavours of your application or have more flexibility when configuring your application bundles.

For instance to distribute a completely isolated beta application you can use this feature to configure a separate application name and identifier:

src-tauri/tauri.beta.conf.json

{
  "productName": "My App Beta",
  "identifier": "com.myorg.myappbeta"
}

And to distribute this separate beta app you provide this configuration file when building it:

  • npm

    npm run tauri build -- --config src-tauri/tauri.beta.conf.json
    
  • yarn

    yarn tauri build --config src-tauri/tauri.beta.conf.json
    
  • pnpm

    pnpm tauri build --config src-tauri/tauri.beta.conf.json
    
  • deno

    deno task tauri build --config src-tauri/tauri.beta.conf.json
    
  • bun

    bun tauri build --config src-tauri/tauri.beta.conf.json
    
  • cargo

    cargo tauri build --config src-tauri/tauri.beta.conf.json
    

Cargo.toml

Cargos manifest file is used to declare Rust crates your app depends on, metadata about your app, and other Rust-related features. If you do not intend to do backend development using Rust for your app then you may not be modifying it much, but its important to know that it exists and what it does.

Below is an example of a barebones Cargo.toml file for a Tauri project:

Cargo.toml

[package]
name = "app"
version = "0.1.0"
description = "A Tauri App"
authors = ["you"]
license = ""
repository = ""
default-run = "app"
edition = "2021"
rust-version = "1.57"


[build-dependencies]
tauri-build = { version = "2.0.0" }


[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "2.0.0", features = [ ] }

The most important parts to take note of are the tauri-build and tauri dependencies. Generally, they must both be on the same latest minor versions as the Tauri CLI, but this is not strictly required. If you encounter issues while trying to run your app you should check that any Tauri versions (tauri and tauri-cli) are on the latest versions for their respective minor releases.

Cargo version numbers use Semantic Versioning. Running cargo update in the src-tauri folder will pull the latest available Semver-compatible versions of all dependencies. For example, if you specify 2.0.0 as the version for tauri-build, Cargo will detect and download version 2.0.1 because it is the latest Semver-compatible version available. Tauri will update the major version number whenever a breaking change is introduced, meaning you should always be capable of safely upgrading to the latest minor and patch versions without fear of your code breaking.

If you want to use a specific crate version you can use exact versions instead by prepending = to the version number of the dependency:

tauri-build = { version = "=2.0.0" }

An additional thing to take note of is the features=[] portion of the tauri dependency. Running tauri dev and tauri build will automatically manage which features need to be enabled in your project based on the your Tauri configuration. For more information about tauri feature flags see the documentation.

When you build your application a Cargo.lock file is produced. This file is used primarily for ensuring that the same dependencies are used across machines during development (similar to yarn.lock, pnpm-lock.yaml or package-lock.json in Node.js). It is recommended to commit this file to your source repository so you get consistent builds.

To learn more about the Cargo manifest file please refer to the official documentation.

package.json

This is the package file used by Node.js. If the frontend of your Tauri app is developed using Node.js-based technologies (such as npm, yarn, or pnpm) this file is used to configure the frontend dependencies and scripts.

An example of a barebones package.json file for a Tauri project might look a little something like this:

package.json

{
  "scripts": {
    "dev": "command to start your app development mode",
    "build": "command to build your app frontend",
    "tauri": "tauri"
  },
  "dependencies": {
    "@tauri-apps/api": "^2.0.0",
    "@tauri-apps/cli": "^2.0.0"
  }
}

Its common to use the "scripts" section to store the commands used to launch and build the frontend used by your Tauri application. The above package.json file specifies the dev command that you can run using yarn dev or npm run dev to start the frontend framework and the build command that you can run using yarn build or npm run build to build your frontends Web assets to be added by Tauri in production. The most convenient way to use these scripts is to hook them with the Tauri CLI via the Tauri configurations beforeDevCommand and beforeBuildCommand hooks:

tauri.conf.json

{
  "build": {
    "beforeDevCommand": "yarn dev",
    "beforeBuildCommand": "yarn build"
  }
}

Note

The "tauri" script is only needed when using npm

The dependencies object specifies which dependencies Node.js should download when you run either yarn, pnpm install or npm install (in this case the Tauri CLI and API).

In addition to the package.json file you may see either a yarn.lock, pnpm-lock.yaml or package-lock.json file. These files assist in ensuring that when you download the dependencies later youll get the exact same versions that you have used during development (similar to Cargo.lock in Rust).

To learn more about the package.json file format please refer to the official documentation.

Debug

With all the moving pieces in Tauri, you may run into a problem that requires debugging. There are many locations where error details are printed, and Tauri includes some tools to make the debugging process more straightforward.

Development Only Code

One of the most useful tools in your toolkit for debugging is the ability to add debugging statements in your code. However, you generally dont want these to end up in production, which is where the ability to check whether youre running in development mode or not comes in handy.

In Rust

fn main() {
  // Whether the current instance was started with `tauri dev` or not.
  #[cfg(dev)]
  {
    // `tauri dev` only code
  }
  if cfg!(dev) {
    // `tauri dev` only code
  } else {
    // `tauri build` only code
  }
  let is_dev: bool = tauri::is_dev();


  // Whether debug assertions are enabled or not. This is true for `tauri dev` and `tauri build --debug`.
  #[cfg(debug_assertions)]
  {
    // Debug only code
  }
  if cfg!(debug_assertions) {
    // Debug only code
  } else {
    // Production only code
  }
}

Rust Console

The first place to look for errors is in the Rust Console. This is in the terminal where you ran, e.g., tauri dev. You can use the following code to print something to that console from within a Rust file:

println!("Message from Rust: {}", msg);

Sometimes you may have an error in your Rust code, and the Rust compiler can give you lots of information. If, for example, tauri dev crashes, you can rerun it like this on Linux and macOS:

RUST_BACKTRACE=1 tauri dev

or like this on Windows (PowerShell):

$env:RUST_BACKTRACE=1
tauri dev

This command gives you a granular stack trace. Generally speaking, the Rust compiler helps you by giving you detailed information about the issue, such as:

error[E0425]: cannot find value `sun` in this scope
  --> src/main.rs:11:5
   |
11 |     sun += i.to_string().parse::<u64>().unwrap();
   |     ^^^ help: a local variable with a similar name exists: `sum`


error: aborting due to previous error


For more information about this error, try `rustc --explain E0425`.

WebView Console

Right-click in the WebView, and choose Inspect Element. This opens up a web-inspector similar to the Chrome or Firefox dev tools you are used to. You can also use the Ctrl + Shift + i shortcut on Linux and Windows, and Command + Option + i on macOS to open the inspector.

The inspector is platform-specific, rendering the webkit2gtk WebInspector on Linux, Safaris inspector on macOS and the Microsoft Edge DevTools on Windows.

Opening Devtools Programmatically

You can control the inspector window visibility by using the WebviewWindow::open_devtools and WebviewWindow::close_devtools functions:

tauri::Builder::default()
  .setup(|app| {
    #[cfg(debug_assertions)] // only include this code on debug builds
    {
      let window = app.get_webview_window("main").unwrap();
      window.open_devtools();
      window.close_devtools();
    }
    Ok(())
  });

Using the Inspector in Production

By default, the inspector is only enabled in development and debug builds unless you enable it with a Cargo feature.

Create a Debug Build

To create a debug build, run the tauri build --debug command.

  • npm

    npm run tauri build -- --debug
    
  • yarn

    yarn tauri build --debug
    
  • pnpm

    pnpm tauri build --debug
    
  • deno

    deno task tauri build --debug
    
  • bun

    bun tauri build --debug
    
  • cargo

    cargo tauri build --debug
    

Like the normal build and dev processes, building takes some time the first time you run this command but is significantly faster on subsequent runs. The final bundled app has the development console enabled and is placed in src-tauri/target/debug/bundle.

You can also run a built app from the terminal, giving you the Rust compiler notes (in case of errors) or your println messages. Browse to the file src-tauri/target/(release|debug)/[app name] and run it in directly in your console or double-click the executable itself in the filesystem (note: the console closes on errors with this method).

Enable Devtools Feature

Danger

The devtools API is private on macOS. Using private APIs on macOS prevents your application from being accepted to the App Store.

To enable the devtools in production builds, you must enable the devtools Cargo feature in the src-tauri/Cargo.toml file:

[dependencies]
tauri = { version = "...", features = ["...", "devtools"] }

Debugging the Core Process

The Core process is powered by Rust so you can use GDB or LLDB to debug it. You can follow the Debugging in VS Code guide to learn how to use the LLDB VS Code Extension to debug the Core Process of Tauri applications.

CrabNebula DevTools

CrabNebula provides a free DevTools application for Tauri as part of its partnership with the Tauri project. This application allows you to instrument your Tauri app by capturing its embedded assets, Tauri configuration file, logs and spans and providing a web frontend to seamlessly visualize data in real time.

With the CrabNebula DevTools you can inspect your apps log events (including logs from dependencies), track down the performance of your command calls and overall Tauri API usage, with a special interface for Tauri events and commands, including payload, responses and inner logs and execution spans.

To enable the CrabNebula DevTools, install the devtools crate:

cargo add tauri-plugin-devtools@2.0.0

And initialize the plugin as soon as possible in your main function:

fn main() {
    // This should be called as early in the execution of the app as possible
    #[cfg(debug_assertions)] // only enable instrumentation in development builds
    let devtools = tauri_plugin_devtools::init();


    let mut builder = tauri::Builder::default();


    #[cfg(debug_assertions)]
    {
        builder = builder.plugin(devtools);
    }


    builder
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

And then run your app as usual, if everything is set up correctly devtools will print the following message:

DevTools message on terminal

Note

In this case we only initialize the devtools plugin for debug applications, which is recommended.

For more information, see the CrabNebula DevTools documentation.

Linux Graphics Issues

On Linux, Tauri renders through WebKitGTK. On some setups, most often NVIDIA GPUs, WebKitGTK and the graphics driver disagree and you get anything from a blank window to subtle rendering problems. This page collects the known symptoms and workarounds. See tauri-apps/tauri#9394 for the original reports.

Common symptoms

  • The window opens but stays blank or white.
  • The window flickers, especially while resizing.
  • The app dies on resize with no useful error output.
  • Console shows AcceleratedSurfaceDMABuf was unable to construct a complete framebuffer.
  • Console shows Gdk-Message: Error 71 (Protocol error) dispatching to Wayland display.

Most of these come from the WebKitGTK DMABUF renderer requesting buffer formats the NVIDIA driver does not provide. See the WebKitGTK bug tracker and the NVIDIA forums for upstream discussion.

Workarounds

Try these in order. The earlier ones keep hardware acceleration.

  1. Make sure kernel mode setting is on. NVIDIA drivers older than 545 often need nvidia_drm.modeset=1 as a kernel parameter.
  2. Set __NV_DISABLE_EXPLICIT_SYNC=1. This often fixes the Wayland Error 71 crash without a performance cost.
  3. Set WEBKIT_DISABLE_DMABUF_RENDERER=1. Fixes the DMABUF framebuffer error and the Error 71 crash, at the cost of the faster rendering path.
  4. Set WEBKIT_DISABLE_COMPOSITING_MODE=1. Last resort for the silent crash on resize. This disables accelerated compositing entirely.

You can set these in your shell to test, or set them in main() before the webview is created so users do not have to:

fn main() {
  // Workaround for WebKitGTK on NVIDIA, see tauri-apps/tauri#9394
  #[cfg(target_os = "linux")]
  std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1");


  tauri::Builder::default()
    // ...
}

Only ship an unconditional override like this if you have verified your app is affected. It disables a faster path for everyone, including users on working setups.

Silent failures: WebGL and canvas

Not every problem crashes or shows an error. WebGL and canvas content can silently land on a slow path while the rest of the app looks fine. Two things make this hard to detect from inside your frontend:

  • WebGL2 context creation succeeds even when the result is backed by a software rasterizer or a slow presentation path. There is no error to catch.
  • WebKitGTK masks the WebGL renderer string for fingerprinting protection. WEBGL_debug_renderer_info reports Apple GPU on every Linux machine, so you cannot check what is actually behind the context.

In practice this shows up as high input latency or low frame rates in WebGL heavy views (terminal emulators, editors, maps, charts), while the same code is fast in a regular browser. If your app has a WebGL rendering path, give it a non WebGL fallback on Linux and consider exposing a setting so users can switch, instead of trusting the context to tell you.

Debug in Neovim

There are many different plugins that can be used to debug Rust code in Neovim. This guide will show you how to set up nvim-dap and some additional plugins to debug Tauri application.

Prerequisites

nvim-dap extension requires codelldb binary. Download the version for your system from https://github.com/vadimcn/codelldb/releases and unzip it. We will point to it later in the nvim-dap configuration.

Configuring nvim-dap

Install nvim-dap and nvim-dap-ui plugins. Follow the instructions provided on their github pages or simply use your favourite plugin manager. Note that nvim-dap-ui requires nvim-nio plugin.

Next, setup the plugin in your Neovim configuration:

init.lua

local dap = require("dap")


dap.adapters.codelldb = {
  type = 'server',
  port = "${port}",
  executable = {
    -- Change this to your path!
    command = '/opt/codelldb/adapter/codelldb',
    args = {"--port", "${port}"},
  }
}


dap.configurations.rust= {
  {
    name = "Launch file",
    type = "codelldb",
    request = "launch",
    program = function()
      return vim.fn.input('Path to executable: ', vim.fn.getcwd() .. '/target/debug/', 'file')
    end,
    cwd = '${workspaceFolder}',
    stopOnEntry = false
  },
}

This setup will ask you to point to the Tauri App binary you want to debug each time you lanuch the debugger.

Optionally, you can setup nvim-dap-ui plugin to toggle debugger view automatically each time debugging session starts and stops:

init.lua

local dapui = require("dapui")
dapui.setup()


dap.listeners.before.attach.dapui_config = function()
  dapui.open()
end
dap.listeners.before.launch.dapui_config = function()
  dapui.open()
end
dap.listeners.before.event_terminated.dapui_config = function()
  dapui.close()
end
dap.listeners.before.event_exited.dapui_config = function()
  dapui.close()
end

Lastly, you can change the default way the breakpoints are displayed in the editor:

init.lua

vim.fn.sign_define('DapBreakpoint',{ text ='🟥', texthl ='', linehl ='', numhl =''})
vim.fn.sign_define('DapStopped',{ text ='▶️', texthl ='', linehl ='', numhl =''})

Starting the dev server

Since were not using Tauri CLI to launch the app the development server will not start automatically. To control the state of development server from Neovim you can use the overseer plugin.

Best way to control tasks running in background is to use VS Code style task configuration. To do this create a .vscode/tasks.json file in the projects directory.

You can find example task configuration for project using trunk below.

.vscode/tasks.json

{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "process",
      "label": "dev server",
      "command": "trunk",
      "args": ["serve"],
      "isBackground": true,
      "presentation": {
        "revealProblems": "onProblem"
      },
      "problemMatcher": {
        "pattern": {
          "regexp": "^error:.*",
          "file": 1,
          "line": 2
        },
        "background": {
          "activeOnStart": false,
          "beginsPattern": ".*Rebuilding.*",
          "endsPattern": ".*server listening at:.*"
        }
      }
    }
  ]
}

Example key bindings

Below you can find example key bindings to start and control debugging sessions.

init.lua

vim.keymap.set('n', '<F5>', function() dap.continue() end)
vim.keymap.set('n', '<F6>', function() dap.disconnect({ terminateDebuggee = true }) end)
vim.keymap.set('n', '<F10>', function() dap.step_over() end)
vim.keymap.set('n', '<F11>', function() dap.step_into() end)
vim.keymap.set('n', '<F12>', function() dap.step_out() end)
vim.keymap.set('n', '<Leader>b', function() dap.toggle_breakpoint() end)
vim.keymap.set('n', '<Leader>o', function() overseer.toggle() end)
vim.keymap.set('n', '<Leader>R', function() overseer.run_template() end)

Debug in JetBrains IDEs

In this guide, well be setting up JetBrains RustRover for debugging the Core Process of your Tauri app. It also mostly applies to IntelliJ and CLion.

Setting up a Cargo project

Depending on which frontend stack is used in a project, the project directory may or may not be a Cargo project. By default, Tauri places the Rust project in a subdirectory called src-tauri. It creates a Cargo project in the root directory only if Rust is used for frontend development as well.

If theres no Cargo.toml file at the top level, you need to attach the project manually. Open the Cargo tool window (in the main menu, go to View | Tool Windows | Cargo), click + (Attach Cargo Project) on the toolbar, and select the src-tauri/Cargo.toml file.

Alternatively, you could create a top-level Cargo workspace manually by adding the following file to the projects root directory:

Cargo.toml

[workspace]
members = ["src-tauri"]

Before you proceed, make sure that your project is fully loaded. If the Cargo tool window shows all the modules and targets of the workspace, youre good to go.

Setting up Run Configurations

You will need to set up two separate Run/Debug configurations:

  • one for launching the Tauri app in debugging mode,
  • another one for running your frontend development server of choice.

Tauri App

  1. In the main menu, go to Run | Edit Configurations.
  2. In the Run/Debug Configurations dialog:
  • To create a new configuration, click + on the toolbar and select Cargo.

Add Run/Debug Configuration

With that created, we need to configure RustRover, so it instructs Cargo to build our app without any default features. This will tell Tauri to use your development server instead of reading assets from the disk. Normally this flag is passed by the Tauri CLI, but since were completely sidestepping that here, we need to pass the flag manually.

Add --no-default-features flag

Now we can optionally rename the Run/Debug Configuration to something more memorable, in this example we called it “Run Tauri App”, but you can name it whatever you want.

Rename Configuration

Development Server

The above configuration will use Cargo directly to build the Rust application and attach the debugger to it. This means we completely sidestep the Tauri CLI, so features like the beforeDevCommand and beforeBuildCommand will not be executed. We need to take care of that by running the development server manually.

To create the corresponding Run configuration, you need to check the actual development server in use. Look for the src-tauri/tauri.conf.json file and find the following line:

    "beforeDevCommand": "pnpm dev"

For npm, pnpm, or yarn, you could use the npm Run Configuration, for example:

NPM Configuration

Make sure you have the correct values in the Command, Scripts, and Package Manager fields.

If your development server is trunk for Rust-based WebAssembly frontend frameworks, you could use the generic Shell Script Run Configuration:

Trunk Serve Configuration

Launching a Debugging Session

To launch a debugging session, you first need to run your development server, and then start debugging the Tauri App by clicking the Debug button next to the Run Configurations Switcher. RustRover will automatically recognize breakpoints placed in any Rust file in your project and stop on the first one hit.

Debug Session

From this point, you can explore the values of your variables, step further into the code, and check whats going at runtime in detail.

Debug in VS Code

This guide will walk you through setting up VS Code for debugging the Core Process of your Tauri app.

All platforms with vscode-lldb extension

Prerequisites

Install the vscode-lldb extension.

Configure launch.json

Create a .vscode/launch.json file and paste the below JSON contents into it:

.vscode/launch.json

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "type": "lldb",
      "request": "launch",
      "name": "Tauri Development Debug",
      "cargo": {
        "args": [
          "build",
          "--manifest-path=./src-tauri/Cargo.toml",
          "--no-default-features"
        ]
      },
      // task for the `beforeDevCommand` if used, must be configured in `.vscode/tasks.json`
      "preLaunchTask": "ui:dev"
    },
    {
      "type": "lldb",
      "request": "launch",
      "name": "Tauri Production Debug",
      "cargo": {
        "args": ["build", "--release", "--manifest-path=./src-tauri/Cargo.toml"]
      },
      // task for the `beforeBuildCommand` if used, must be configured in `.vscode/tasks.json`
      "preLaunchTask": "ui:build"
    }
  ]
}

This uses cargo directly to build the Rust application and load it in both development and production modes.

Note that it does not use the Tauri CLI, so exclusive CLI features are not executed. The beforeDevCommand and beforeBuildCommand scripts must be executed beforehand or configured as a task in the preLaunchTask field. Below is an example .vscode/tasks.json file that has two tasks, one for a beforeDevCommand that spawns a development server and one for beforeBuildCommand:

.vscode/tasks.json

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "label": "ui:dev",
      "type": "shell",
      // `dev` keeps running in the background
      // ideally you should also configure a `problemMatcher`
      // see https://code.visualstudio.com/docs/editor/tasks#_can-a-background-task-be-used-as-a-prelaunchtask-in-launchjson
      "isBackground": true,
      // change this to your `beforeDevCommand`:
      "command": "yarn",
      "args": ["dev"]
    },
    {
      "label": "ui:build",
      "type": "shell",
      // change this to your `beforeBuildCommand`:
      "command": "yarn",
      "args": ["build"]
    }
  ]
}

Now you can set breakpoints in src-tauri/src/main.rs or any other Rust file and start debugging by pressing F5.

With Visual Studio Windows Debugger on Windows

Visual Studio Windows Debugger is a Windows-only debugger that is generally faster than vscode-lldb with better support for some Rust features such as enums.

Prerequisites

Install the C/C++ extension and follow https://code.visualstudio.com/docs/cpp/config-msvc#_prerequisites to install Visual Studio Windows Debugger.

Configure launch.json and tasks.json

.vscode/launch.json

{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch App Debug",
      "type": "cppvsdbg",
      "request": "launch",
      // change the exe name to your actual exe name
      // (to debug release builds, change `target/debug` to `release/debug`)
      "program": "${workspaceRoot}/src-tauri/target/debug/your-app-name-here.exe",
      "cwd": "${workspaceRoot}",
      "preLaunchTask": "ui:dev"
    }
  ]
}

Note that it does not use the Tauri CLI, so exclusive CLI features are not executed. The tasks.json is the same as with lldb, except you need to add a config group and target your preLaunchTask from launch.json to it if you want it to always compile before launching.

Here is an example of running a dev server (equivalent of beforeDevCommand) and the compilation (cargo build) as a group, to use it, change the preLaunchTask config in launch.json to dev (or anything you named your group).

.vscode/tasks.json

{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "tasks": [
    {
      "label": "build:debug",
      "type": "cargo",
      "command": "build",
      "options": {
        "cwd": "${workspaceRoot}/src-tauri"
      }
    },
    {
      "label": "ui:dev",
      "type": "shell",
      // `dev` keeps running in the background
      // ideally you should also configure a `problemMatcher`
      // see https://code.visualstudio.com/docs/editor/tasks#_can-a-background-task-be-used-as-a-prelaunchtask-in-launchjson
      "isBackground": true,
      // change this to your `beforeDevCommand`:
      "command": "yarn",
      "args": ["dev"]
    },
    {
      "label": "dev",
      "dependsOn": ["build:debug", "ui:dev"],
      "group": {
        "kind": "build"
      }
    }
  ]
}

App Icons

Tauri ships with a default iconset based on its logo. This is NOT what you want when you ship your application. To remedy this common situation, Tauri provides the icon command that will take an input file ("./app-icon.png" by default) and create all the icons needed for the various platforms.

Note on filetypes

  • icon.icns = macOS
  • icon.ico = Windows
  • *.png = Linux
  • Square*Logo.png & StoreLogo.png = Currently unused but intended for AppX/MS Store targets.

Some icon types may be used on platforms other than those listed above (especially png). Therefore we recommend including all icons even if you intend to only build for a subset of platforms.

Command Usage

  • npm

    npm run tauri icon
    
  • yarn

    yarn tauri icon
    
  • pnpm

    pnpm tauri icon
    
  • deno

    deno task tauri icon
    
  • cargo

    cargo tauri icon
    
> pnpm tauri icon --help


Generate various icons for all major platforms


Usage: pnpm run tauri icon [OPTIONS] [INPUT]


Arguments:
  [INPUT]  Path to the source icon (squared PNG or SVG file with transparency) [default: ./app-icon.png]


Options:
  -o, --output <OUTPUT>        Output directory. Default: 'icons' directory next to the tauri.conf.json file
  -v, --verbose...             Enables verbose logging
  -p, --png <PNG>              Custom PNG icon sizes to generate. When set, the default icons are not generated
      --ios-color <IOS_COLOR>  The background color of the iOS icon - string as defined in the W3C's CSS Color Module Level 4 <https://www.w3.org/TR/css-color-4/> [default: #fff]
  -h, --help                   Print help
  -V, --version                Print version

The desktop icons will be placed in your src-tauri/icons folder by default, where they will be included in your built app automatically. If you want to source your icons from a different location, you can edit this part of the tauri.conf.json file:

{
  "bundle": {
    "icon": [
      "icons/32x32.png",
      "icons/128x128.png",
      "icons/128x128@2x.png",
      "icons/icon.icns",
      "icons/icon.ico"
    ]
  }
}

The mobile icons will be placed into the Xcode and Android Studio projects directly!

Creating icons manually

If you prefer to build these icons yourself, for example if you want to have a simpler design for small sizes or because you dont want to depend on the CLIs internal image resizing, you must make sure your icons meet some requirements:

  • icon.icns: The required layer sizes and names for the icns file are described in the Tauri repo
  • icon.ico: The ico file must include layers for 16, 24, 32, 48, 64 and 256 pixels. For an optimal display of the ICO image in development, the 32px layer should be the first layer.
  • png: The requirements for the png icons are: width == height, RGBA (RGB + Transparency), and 32bit per pixel (8bit per channel). Commonly expected sizes on desktop are 32, 128, 256, and 512 pixels. We recommend to at least match the output of tauri icon: 32x32.png, 128x128.png, 128x128@2x.png, and icon.png.

Android

On Android you will need png icons with the same requirements but in different sizes. They will also need to be placed directly in the Android Studio project:

  • src-tauri/gen/android/app/src/main/res/

    • mipmap-hdpi/

      • ic_launcher.png & ic_launcher_round.png: 49x49px
      • ic_launcher_foreground.png: 162x162px
    • mipmap-mdpi/

      • ic_launcher.png & ic_launcher_round.png: 48x48px
      • ic_launcher_foreground.png: 108x108px
    • mipmap-xhdpi/

      • ic_launcher.png & ic_launcher_round.png: 96x96px
      • ic_launcher_foreground.png: 216x216px
    • mipmap-xxhdpi/

      • ic_launcher.png & ic_launcher_round.png: 144x144px
      • ic_launcher_foreground.png: 324x324px
    • mipmap-xxxhdpi/

      • ic_launcher.png & ic_launcher_round.png: 192x192px
      • ic_launcher_foreground.png: 432x432px

If tauri icon cannot be used, we recommend checking out Android Studios Image Asset Studio instead.

iOS

On iOS you will need png icons with the same requirements but without transparency and in different sizes. They will also need to be placed directly in the Xcode project into src-tauri/gen/apple/Assets.xcassets/AppIcon.appiconset/. The following icons are expected:

  • 20px in 1x, 2x, 3x, with an extra icon
  • 29px in 1x, 2x, 3x, with an extra icon
  • 40px in 1x, 2x, 3x, with an extra icon
  • 60px in 2x, 3x
  • 76px in 1x, 2x
  • 83.5px in 2x
  • 512px in 2x saved as AppIcon-512@2x.png

The file names are in the format of AppIcon-{size}x{size}@{scaling}{extra}.png. For the 20px icons this means you need icons in sizes 20x20, 40x40 and 60x60 named as AppIcon-20x20@1x.png, AppIcon-20x20@2x.png, AppIcon-20x20@3x.png and 2x saved additionally as AppIcon-20x20@2x-1.png (“extra icon”).

Plugin Development

Plugin Development

This guide is for developing Tauri plugins. If youre looking for a list of the currently available plugins and how to use them then visit the Features and Recipes list.

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:

  • npm

    npx @tauri-apps/cli plugin new [name]
    

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:

. tauri-plugin-[name]/
├── src/                - Rust code
│ ├── commands.rs       - Defines the commands the webview can use
| ├── desktop.rs        - Desktop implementation
| ├── error.rs          - Default error type to use in returned results
│ ├── lib.rs            - Re-exports appropriate implementation, setup state...
│ ├── mobile.rs         - Mobile implementation
│ └── models.rs         - Shared structs
├── permissions/        - This will host (generated) permission files for commands
├── android             - Android library
├── ios                 - Swift package
├── guest-js            - Source code of the JavaScript API bindings
├── dist-js             - Transpiled assets from guest-js
├── Cargo.toml          - Cargo crate metadata
└── package.json        - NPM package metadata

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.

Declaring Platform Support

Plugins can declare which platforms they support, and to what extent, in the [package.metadata.platforms.support] section of the crates Cargo.toml:

Cargo.toml

[package.metadata.platforms.support]
windows = { level = "full" }
linux = { level = "full" }
macos = { level = "full" }
android = { level = "partial", notes = "Access is restricted to the Application folder by default" }
ios = { level = "none" }

Each key is a platform (windows, linux, macos, android, ios) and accepts two fields:

  • level (required): "full" if the plugin works as intended, "partial" if it works with limitations, or "none" if the platform isnt supported.
  • notes (optional): a short description of the caveats or limitations. It renders as Markdown on the plugins page. In the support table it shows up as plain text in a tooltip.

The support table and the platform filter on the Features & Recipes page are generated from this metadata.

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:

{
  "build": { ... },
  "tauri": { ... },
  "plugins": {
    "plugin-name": {
      "timeout": 30
    }
  }
}

The plugins 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:

src/lib.rs

use serde::Deserialize;
use tauri::{
    plugin::{Builder, TauriPlugin},
    Runtime,
};


// Define the plugin config
#[derive(Deserialize)]
pub struct Config {
  timeout: usize,
}


pub fn init<R: Runtime>() -> TauriPlugin<R, Config> {
  // Make the plugin config optional
  // by using `Builder::<R, Option<Config>>` instead
  Builder::<R, Config>::new("<plugin-name>")
    .setup(|app, api| {
      let timeout = api.config().timeout;
      Ok(())
    })
    .build()
}

Lifecycle Events

Plugins can hook into several lifecycle events:

There are additional lifecycle events for mobile plugins.

setup

  • When: Plugin is being initialized
  • Why: Register mobile plugins, manage state, run background tasks

src/lib.rs

use tauri::{Manager, plugin::Builder};
use std::{collections::HashMap, sync::Mutex, time::Duration};


struct DummyStore(Mutex<HashMap<String, String>>);


Builder::new("<plugin-name>")
  .setup(|app, api| {
    app.manage(DummyStore(Default::default()));


    let app_ = app.clone();
    std::thread::spawn(move || {
      loop {
        app_.emit("tick", ());
        std::thread::sleep(Duration::from_secs(1));
      }
    });


    Ok(())
  })

on_navigation

  • When: Web view is attempting to perform navigation
  • Why: Validate the navigation or track URL changes

Returning false cancels the navigation.

src/lib.rs

use tauri::plugin::Builder;


Builder::new("<plugin-name>")
  .on_navigation(|window, url| {
    println!("window {} is navigating to {}", window.label(), url);
    // Cancels the navigation if forbidden
    url.scheme() != "forbidden"
  })

on_webview_ready

  • When: New window has been created
  • Why: Execute an initialization script for every window

src/lib.rs

use tauri::plugin::Builder;


Builder::new("<plugin-name>")
  .on_webview_ready(|window| {
    window.listen("content-loaded", |event| {
      println!("webview content has been loaded");
    });
  })

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.

src/lib.rs

use std::{collections::HashMap, fs::write, sync::Mutex};
use tauri::{plugin::Builder, Manager, RunEvent};


struct DummyStore(Mutex<HashMap<String, String>>);


Builder::new("<plugin-name>")
  .setup(|app, _api| {
    app.manage(DummyStore(Default::default()));
    Ok(())
  })
  .on_event(|app, event| {
    match event {
      RunEvent::ExitRequested { api, .. } => {
        // user requested a window to be closed and there's no windows left


        // we can prevent the app from exiting:
        api.prevent_exit();
      }
      RunEvent::Exit => {
        // app is going to exit, you can cleanup here


        let store = app.state::<DummyStore>();
        write(
          app.path().app_local_data_dir().unwrap().join("store.json"),
          serde_json::to_string(&*store.0.lock().unwrap()).unwrap(),
        )
        .unwrap();
      }
      _ => {}
    }
  })

on_drop

  • When: Plugin is being deconstructed
  • Why: Execute code when the plugin has been destroyed

See Drop for more information.

src/lib.rs

use tauri::plugin::Builder;


Builder::new("<plugin-name>")
  .on_drop(|app| {
    // plugin has been destroyed...
  })

Exposing Rust APIs

The plugin APIs defined in the projects 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:

src-tauri/src/lib.rs

use tauri_plugin_global_shortcut::GlobalShortcutExt;


tauri::Builder::default()
  .plugin(tauri_plugin_global_shortcut::init())
  .setup(|app| {
    app.global_shortcut().register(...);
    Ok(())
  })

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):

src/commands.rs

use tauri::{command, ipc::Channel, AppHandle, Runtime, Window};


#[command]
async fn upload<R: Runtime>(app: AppHandle<R>, window: Window<R>, on_progress: Channel, url: String) {
  // implement command logic here
  on_progress.send(100).unwrap();
}

To expose the command to the webview, you must hook into the invoke_handler() call in lib.rs:

src/lib.rs

Builder::new("<plugin-name>")
    .invoke_handler(tauri::generate_handler![commands::upload])

Define a binding function in webview-src/index.ts so that plugin users can easily call the command in JavaScript:

import { invoke, Channel } from '@tauri-apps/api/core'


export async function upload(url: string, onProgressHandler: (progress: number) => void): Promise<void> {
  const onProgress = new Channel<number>()
  onProgress.onmessage = onProgressHandler
  await invoke('plugin:<plugin-name>|upload', { url, onProgress })
}

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 plugins 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.

permissions/start-server.toml

"$schema" = "schemas/schema.json"


[[permission]]
identifier = "allow-start-server"
description = "Enables the start_server command."
commands.allow = ["start_server"]


[[permission]]
identifier = "deny-start-server"
description = "Denies the start_server command."
commands.deny = ["start_server"]
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.

Lets define an example struct that will hold scope data for a list of binaries a shell plugin is allowed to spawn:

src/scope.rs

#[derive(Debug, schemars::JsonSchema)]
pub struct Entry {
    pub binary: String,
}
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:

src/commands.rs

use tauri::ipc::CommandScope;
use crate::scope::Entry;


async fn spawn<R: tauri::Runtime>(app: tauri::AppHandle<R>, command_scope: CommandScope<'_, Entry>) -> Result<()> {
  let allowed = command_scope.allows();
  let denied = command_scope.denies();
  todo!()
}
Global Scope

When a permission does not define any commands to be allowed or denied, its considered a scope permission and it should only define a global scope for your plugin:

permissions/spawn-node.toml

[[permission]]
identifier = "allow-spawn-node"
description = "This scope permits spawning the `node` binary."


[[permission.scope.allow]]
binary = "node"

You can read the global scope with the tauri::ipc::GlobalScope struct:

src/commands.rs

use tauri::ipc::GlobalScope;
use crate::scope::Entry;


async fn spawn<R: tauri::Runtime>(app: tauri::AppHandle<R>, scope: GlobalScope<'_, Entry>) -> Result<()> {
  let allowed = scope.allows();
  let denied = scope.denies();
  todo!()
}

Note

We recommend checking both global and command scopes for flexibility

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:

# we need to add schemars to both dependencies and build-dependencies because the scope.rs module is shared between the app code and build script
[dependencies]
schemars = "0.8"


[build-dependencies]
schemars = "0.8"

In your build script, add the following code:

build.rs

#[path = "src/scope.rs"]
mod scope;


const COMMANDS: &[&str] = &[];


fn main() {
    tauri_plugin::Builder::new(COMMANDS)
        .global_scope_schema(schemars::schema_for!(scope::Entry))
        .build();
}
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 theres a logical connection between a collection of commands, you should define a set containing them:

permissions/websocket.toml

"$schema" = "schemas/schema.json"
[[set]]
identifier = "allow-websocket"
description = "Allows connecting and sending messages through a WebSocket"
permissions = ["allow-connect", "allow-send"]
Default Permission

The default permission is a special permission set with identifier default. Its recommended that you enable required commands by default. For instance the http plugin is useless without the request command allowed:

permissions/default.toml

"$schema" = "schemas/schema.json"
[default]
description = "Allows making HTTP requests"
permissions = ["allow-request"]

Autogenerated Permissions

The easiest way to define permissions for each of your commands is to use the autogeneration option defined in your plugins 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:

src/commands.rs

const COMMANDS: &[&str] = &["upload"];


fn main() {
    tauri_plugin::Builder::new(COMMANDS).build();
}

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.

Mobile Plugin Development

Plugin Development

Be sure that youre familiar with the concepts covered in the Plugin Development guide as many concepts in this guide build on top of foundations covered there.

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 including an example mobile command showing how to trigger its execution from Rust code.

Initialize Plugin Project

Follow the steps in the Plugin Development guide to initialize a new plugin project.

If you have an existing plugin and would like to add Android or iOS capabilities to it, you can use plugin android init and plugin ios init to bootstrap the mobile library projects and guide you through the changes needed.

The default plugin template splits the plugins implementation into two separate modules: desktop.rs and mobile.rs.

The desktop implementation uses Rust code to implement a functionality, while the mobile implementation sends a message to the native mobile code to execute a function and get a result back. If shared logic is needed across both implementations, it can be defined in lib.rs:

src/lib.rs

use tauri::Runtime;


impl<R: Runtime> <plugin-name><R> {
  pub fn do_something(&self) {
    // do something that is a shared implementation between desktop and mobile
  }
}

This implementation simplifies the process of sharing an API that can be used both by commands and Rust code.

Develop an Android Plugin

A Tauri plugin for Android is defined as a Kotlin class that extends app.tauri.plugin.Plugin and is annotated with app.tauri.annotation.TauriPlugin. Each method annotated with app.tauri.annotation.Command can be called by Rust or JavaScript.

Tauri uses Kotlin by default for the Android plugin implementation, but you can switch to Java if you prefer. After generating a plugin, right click the Kotlin plugin class in Android Studio and select the “Convert Kotlin file to Java file” option from the menu. Android Studio will guide you through the project migration to Java.

Develop an iOS Plugin

A Tauri plugin for iOS is defined as a Swift class that extends the Plugin class from the Tauri package. Each function with the @objc attribute and the (_ invoke: Invoke) parameter (for example @objc private func download(_ invoke: Invoke) { }) can be called by Rust or JavaScript.

The plugin is defined as a Swift package so that you can use its package manager to manage dependencies.

Plugin Configuration

Refer to the Plugin Configuration section of the Plugin Development guide for more details on developing plugin configurations.

The plugin instance on mobile has a getter for the plugin configuration:

  • Android

    import android.app.Activity
    import android.webkit.WebView
    import app.tauri.annotation.TauriPlugin
    import app.tauri.annotation.InvokeArg
    
    
    @InvokeArg
    class Config {
        var timeout: Int? = 3000
    }
    
    
    @TauriPlugin
    class ExamplePlugin(private val activity: Activity): Plugin(activity) {
      private var timeout: Int? = 3000
    
    
      override fun load(webView: WebView) {
        getConfig(Config::class.java).let {
           this.timeout = it.timeout
        }
      }
    }
    
  • iOS

    struct Config: Decodable {
      let timeout: Int?
    }
    
    
    class ExamplePlugin: Plugin {
      var timeout: Int? = 3000
    
    
      @objc public override func load(webview: WKWebView) {
        do {
          let config = try parseConfig(Config.self)
          self.timeout = config.timeout
        } catch {}
      }
    }
    

Lifecycle Events

Plugins can hook into several lifecycle events:

  • load: When the plugin is loaded into the web view
  • onNewIntent: Android only, when the activity is re-launched

There are also the additional lifecycle events for plugins in the Plugin Development guide.

load

  • When: When the plugin is loaded into the web view
  • Why: Execute plugin initialization code
  • Android

    import android.app.Activity
    import android.webkit.WebView
    import app.tauri.annotation.TauriPlugin
    
    
    @TauriPlugin
    class ExamplePlugin(private val activity: Activity): Plugin(activity) {
      override fun load(webView: WebView) {
        // perform plugin setup here
      }
    }
    
  • iOS

    class ExamplePlugin: Plugin {
      @objc public override func load(webview: WKWebView) {
        let timeout = self.config["timeout"] as? Int ?? 30
      }
    }
    

onNewIntent

Note: This is only available on Android.

  • When: When the activity is re-launched. See Activity#onNewIntent for more information.
  • Why: Handle application re-launch such as when a notification is clicked or a deep link is accessed.
import android.app.Activity
import android.content.Intent
import app.tauri.annotation.TauriPlugin


@TauriPlugin
class ExamplePlugin(private val activity: Activity): Plugin(activity) {
  override fun onNewIntent(intent: Intent) {
    // handle new intent event
  }
}

Adding Mobile Commands

There is a plugin class inside the respective mobile projects where commands can be defined that can be called by the Rust code:

  • Android

    import android.app.Activity
    import app.tauri.annotation.Command
    import app.tauri.annotation.TauriPlugin
    
    
    @TauriPlugin
    class ExamplePlugin(private val activity: Activity): Plugin(activity) {
      @Command
      fun openCamera(invoke: Invoke) {
        val ret = JSObject()
        ret.put("path", "/path/to/photo.jpg")
        invoke.resolve(ret)
      }
    }
    

    If you want to use a Kotlin suspend function, you need to use a custom coroutine scope

    import android.app.Activity
    import app.tauri.annotation.Command
    import app.tauri.annotation.TauriPlugin
    
    
    // Change to Dispatchers.IO if it is intended for fetching data
    val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
    
    
    @TauriPlugin
    class ExamplePlugin(private val activity: Activity): Plugin(activity) {
      @Command
      fun openCamera(invoke: Invoke) {
        scope.launch {
          openCameraInner(invoke)
        }
      }
    
    
      private suspend fun openCameraInner(invoke: Invoke) {
        val ret = JSObject()
        ret.put("path", "/path/to/photo.jpg")
        invoke.resolve(ret)
      }
    }
    

    Note

    On Android native commands are scheduled on the main thread. Performing long-running operations will cause the UI to freeze and potentially “Application Not Responding” (ANR) error.

    If you need to wait for some blocking IO, you can launch a corouting like that:

    CoroutineScope(Dispatchers.IO).launch {
      val result = myLongRunningOperation()
      invoke.resolve(result)
    }
    
  • iOS

    class ExamplePlugin: Plugin {
      @objc public func openCamera(_ invoke: Invoke) throws {
        invoke.resolve(["path": "/path/to/photo.jpg"])
      }
    }
    

Use the tauri::plugin::PluginHandle to call a mobile command from Rust:

use std::path::PathBuf;
use serde::{Deserialize, Serialize};
use tauri::Runtime;


#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
pub struct CameraRequest {
  quality: usize,
  allow_edit: bool,
}


#[derive(Deserialize)]
pub struct Photo {
  path: PathBuf,
}




impl<R: Runtime> <plugin-name;pascal-case><R> {
  pub fn open_camera(&self, payload: CameraRequest) -> crate::Result<Photo> {
    self
      .0
      .run_mobile_plugin("openCamera", payload)
      .map_err(Into::into)
  }
}

Command Arguments

Arguments are serialized to commands and can be parsed on the mobile plugin with the Invoke::parseArgs function, taking a class describing the argument object.

Android

On Android, the arguments are defined as a class annotated with @app.tauri.annotation.InvokeArg. Inner objects must also be annotated:

import android.app.Activity
import android.webkit.WebView
import app.tauri.annotation.Command
import app.tauri.annotation.InvokeArg
import app.tauri.annotation.TauriPlugin


@InvokeArg
internal class OpenAppArgs {
  lateinit var name: String
  var timeout: Int? = null
}


@InvokeArg
internal class OpenArgs {
  lateinit var requiredArg: String
  var allowEdit: Boolean = false
  var quality: Int = 100
  var app: OpenAppArgs? = null
}


@TauriPlugin
class ExamplePlugin(private val activity: Activity): Plugin(activity) {
  @Command
  fun openCamera(invoke: Invoke) {
    val args = invoke.parseArgs(OpenArgs::class.java)
  }
}

Note

Optional arguments are defined as var <argumentName>: Type? = null

Arguments with default values are defined as var <argumentName>: Type = <default-value>

Required arguments are defined as lateinit var <argumentName>: Type

iOS

On iOS, the arguments are defined as a class that inherits Decodable. Inner objects must also inherit the Decodable protocol:

class OpenAppArgs: Decodable {
  let name: String
  var timeout: Int?
}


class OpenArgs: Decodable {
  let requiredArg: String
  var allowEdit: Bool?
  var quality: UInt8?
  var app: OpenAppArgs?
}


class ExamplePlugin: Plugin {
  @objc public func openCamera(_ invoke: Invoke) throws {
    let args = try invoke.parseArgs(OpenArgs.self)


    invoke.resolve(["path": "/path/to/photo.jpg"])
  }
}

Note

Optional arguments are defined as var <argumentName>: Type?

Arguments with default values are NOT supported. Use a nullable type and set the default value on the command function instead.

Required arguments are defined as let <argumentName>: Type

Calling Rust From Mobile Plugins

It is often preferable to write plugin code in Rust, for performance and reusability. While Tauri doesnt directly provide a mechanism to call Rust from your plugin code, using JNI on Android and FFI on iOS allows plugins to call shared code, even when the application WebView is suspended.

Android

In your plugins Cargo.toml, add the jni crate as a dependency:

[target.'cfg(target_os = "android")'.dependencies]
jni = "0.21"

Load the application library statically and define native functions in your Kotlin code. In this example, the Kotlin class is com.example.HelloWorld, we need to reference the full package name from the Rust side.

private const val TAG = "MyPlugin"


init {
  try {
    // Load the native library (libapp_lib.so)
    // This is the shared library built by Cargo with crate-type = ["cdylib"]
    System.loadLibrary("app_lib")
    Log.d(TAG, "Successfully loaded libapp_lib.so")
  } catch (e: UnsatisfiedLinkError) {
    Log.e(TAG, "Failed to load libapp_lib.so", e)
    throw e
  }
}


external fun helloWorld(name: String): String?

Then in your plugins Rust code, define the function JNI will look for. The function format is Java_package_class_method, so for our class above this becomes Java_com_example_HelloWorld_helloWorld to get called by our helloWorld method:

#[cfg(target_os = "android")]
#[no_mangle]
pub extern "system" fn Java_com_example_HelloWorld_helloWorld(
    mut env: JNIEnv,
    _class: JClass,
    name: JString,
) -> jstring {
    log::debug!("Calling JNI Hello World!");
    let result = format!("Hello, {}!", name);


    match env.new_string(result) {
        Ok(jstr) => jstr.into_raw(),
        Err(e) => {
            log::error!("Failed to create JString: {}", e);
            std::ptr::null_mut()
        }
    }
}

iOS

iOS only uses standard C FFI, so doesnt need any new dependencies. Add the hook in your Swift code, as well as any necessary cleanup. These functions can be named anything valid, but must be annotated with @_silgen_name(FFI_FUNC), where FFI_FUNC is a function name to be called from Rust:

@_silgen_name("hello_world_ffi")
private static func helloWorldFFI(_ name: UnsafePointer<CChar>) -> UnsafeMutablePointer<CChar>?


@_silgen_name("free_hello_result_ffi")
private static func freeHelloResult(_ result: UnsafeMutablePointer<CChar>)


static func helloWorld(name: String) -> String? {
  // Call Rust FFI
  let resultPtr = name.withCString({ helloWorldFFI($0) })


  // Convert C string to Swift String
  let result = String(cString: resultPtr)


  // Free the C string
  freeHelloResult(resultPtr)


  return result
}

Then, implement the Rust side. The extern functions here must match the @_silgen_name annotations on the Swift side:

#[no_mangle]
pub unsafe extern "C" fn hello_world_ffi(c_name: *const c_char) -> *mut c_char {
    let name = match CStr::from_ptr(c_name).to_str() {
        Ok(s) => s,
        Err(e) => {
            log::error!("[iOS FFI] Failed to convert C string: {}", e);
            return std::ptr::null_mut();
        }
    };


    let result = format!("Hello, {}!", name);


    match CString::new(result) {
        Ok(c_str) => c_str.into_raw(),
        Err(e) => {
            log::error!("[iOS FFI] Failed to create C string: {}", e);
            std::ptr::null_mut()
        }
    }
}


#[no_mangle]
pub unsafe extern "C" fn free_hello_result_ffi(result: *mut c_char) {
    if !result.is_null() {
        drop(CString::from_raw(result));
    }
}

Android 16KB Memory Pages

Google is moving to make 16KB memory pages a requirement in all new Android app submissions. Building with an NDK version 28 or higher should automatically generate bundles that meet this requirement, but in the event an older NDK version must be used or generated files arent 16KB aligned, the following can be added to .cargo/config.toml to flag this to rustc:

[target.aarch64-linux-android]
rustflags = ["-C", "link-arg=-Wl,-z,max-page-size=16384"]

Permissions

If a plugin requires permissions from the end user, Tauri simplifies the process of checking and requesting permissions.

  • Android

    First define the list of permissions needed and an alias to identify each group in code. This is done inside the TauriPlugin annotation:

    @TauriPlugin(
      permissions = [
        Permission(strings = [Manifest.permission.POST_NOTIFICATIONS], alias = "postNotification")
      ]
    )
    class ExamplePlugin(private val activity: Activity): Plugin(activity) { }
    
  • iOS

    First override the checkPermissions and requestPermissions functions:

    class ExamplePlugin: Plugin {
      @objc open func checkPermissions(_ invoke: Invoke) {
        invoke.resolve(["postNotification": "prompt"])
      }
    
    
      @objc public override func requestPermissions(_ invoke: Invoke) {
        // request permissions here
        // then resolve the request
        invoke.resolve(["postNotification": "granted"])
      }
    }
    

Tauri automatically implements two commands for the plugin: checkPermissions and requestPermissions. Those commands can be directly called from JavaScript or Rust:

  • JavaScript

    import { invoke, PermissionState } from '@tauri-apps/api/core'
    
    
    interface Permissions {
      postNotification: PermissionState
    }
    
    
    // check permission state
    const permission = await invoke<Permissions>('plugin:<plugin-name>|checkPermissions')
    
    
    if (permission.postNotification === 'prompt-with-rationale') {
      // show information to the user about why permission is needed
    }
    
    
    // request permission
    if (permission.postNotification.startsWith('prompt')) {
      const state = await invoke<Permissions>('plugin:<plugin-name>|requestPermissions', { permissions: ['postNotification'] })
    }
    
  • Rust

    use serde::{Serialize, Deserialize};
    use tauri::{plugin::PermissionState, Runtime};
    
    
    #[derive(Deserialize)]
    #[serde(rename_all = "camelCase")]
    struct PermissionResponse {
      pub post_notification: PermissionState,
    }
    
    
    #[derive(Serialize)]
    #[serde(rename_all = "camelCase")]
    struct RequestPermission {
      post_notification: bool,
    }
    
    
    impl<R: Runtime> Notification<R> {
      pub fn request_post_notification_permission(&self) -> crate::Result<PermissionState> {
        self.0
          .run_mobile_plugin::<PermissionResponse>("requestPermissions", RequestPermission { post_notification: true })
          .map(|r| r.post_notification)
          .map_err(Into::into)
      }
    
    
      pub fn check_permissions(&self) -> crate::Result<PermissionResponse> {
        self.0
          .run_mobile_plugin::<PermissionResponse>("checkPermissions", ())
          .map_err(Into::into)
      }
    }
    

Plugin Events

Plugins can emit events at any point of time using the trigger function:

  • Android

    @TauriPlugin
    class ExamplePlugin(private val activity: Activity): Plugin(activity) {
        override fun load(webView: WebView) {
          trigger("load", JSObject())
        }
    
    
        override fun onNewIntent(intent: Intent) {
          // handle new intent event
          if (intent.action == Intent.ACTION_VIEW) {
            val data = intent.data.toString()
            val event = JSObject()
            event.put("data", data)
            trigger("newIntent", event)
          }
        }
    
    
        @Command
        fun openCamera(invoke: Invoke) {
          val payload = JSObject()
          payload.put("open", true)
          trigger("camera", payload)
        }
    }
    
  • iOS

    class ExamplePlugin: Plugin {
      @objc public override func load(webview: WKWebView) {
        trigger("load", data: [:])
      }
    
    
      @objc public func openCamera(_ invoke: Invoke) {
        trigger("camera", data: ["open": true])
      }
    }
    

The helper functions can then be called from the NPM package by using the addPluginListener helper function:

import { addPluginListener, PluginListener } from '@tauri-apps/api/core';


export async function onRequest(
  handler: (url: string) => void
): Promise<PluginListener> {
  return await addPluginListener(
    '<plugin-name>',
    'event-name',
    handler
  );
}

Capability Required

Listening to plugin events from JavaScript is gated by the same capability and permission system that gates plugin commands. Add the plugins permission (commonly <plugin-name>:default, or a specific allow-listen-* permission if the plugin defines one) to the permissions array of a capability under src-tauri/capabilities/:

src-tauri/capabilities/default.json

{
  "identifier": "default",
  "windows": ["main"],
  "permissions": ["<plugin-name>:default"]
}

Refer to the plugins own documentation for the exact permission identifiers it exposes.

Embedding Additional Files

You may need to include additional files in your application bundle that arent part of your frontend (your frontendDist) directly or which are too big to be inlined into the binary. We call these files resources.

Configuration

To bundle the files of your choice, add the resources property to the bundle object in your tauri.conf.json file.

To include a list of files:

  • Syntax

    tauri.conf.json

    {
      "bundle": {
        "resources": [
          "./path/to/some-file.txt",
          "/absolute/path/to/textfile.txt",
          "../relative/path/to/jsonfile.json",
          "some-folder/",
          "resources/**/*.md"
        ]
      }
    }
    
  • Explanation

    tauri.conf.json5

    {
      "bundle": {
        "resources": [
          // Will be placed to `$RESOURCE/path/to/some-file.txt`
          "./path/to/some-file.txt",
    
    
          // The root in an absolute path will be replaced by `_root_`,
          // so `textfile.txt` will be placed to `$RESOURCE/_root_/absolute/path/to/textfile.txt`
          "/absolute/path/to/textfile.txt",
    
    
          // `..` in a relative path will be replaced by `_up_`,
          // so `jsonfile.json` will be placed to `$RESOURCE/_up_/relative/path/to/textfile.txt`,
          "../relative/path/to/jsonfile.json",
    
    
          // If the path is a directory, the entire directory will be copied to the `$RESOURCE` directory,
          // preserving the original structures, for example:
          //   - `some-folder/file.txt`                   -> `$RESOURCE/some-folder/file.txt`
          //   - `some-folder/another-folder/config.json` -> `$RESOURCE/some-folder/another-folder/config.json`
          // This is the same as `some-folder/**/*`
          "some-folder/",
    
    
          // You can also include multiple files at once through glob patterns.
          // All the `.md` files inside `resources` will be placed to `$RESOURCE/resources/`,
          // preserving their original directory structures, for example:
          //   - `resources/index.md`      -> `$RESOURCE/resources/index.md`
          //   - `resources/docs/setup.md` -> `$RESOURCE/resources/docs/setup.md`
          "resources/**/*.md"
        ]
      }
    }
    

The bundled files will be in $RESOURCES/ with the original directory structure preserved, for example: ./path/to/some-file.txt -> $RESOURCE/path/to/some-file.txt

To fine control where the files will get copied to, use a map instead:

  • Syntax

    tauri.conf.json

    {
      "bundle": {
        "resources": {
          "/absolute/path/to/textfile.txt": "resources/textfile.txt",
          "relative/path/to/jsonfile.json": "resources/jsonfile.json",
          "resources/": "",
          "docs/**/*md": "website-docs/"
        }
      }
    }
    
  • Explanation

    tauri.conf.json5

    {
      "bundle": {
        "resources": {
          // `textfile.txt` will be placed to `$RESOURCE/resources/textfile.txt`
          "/absolute/path/to/textfile.txt": "resources/textfile.txt",
    
    
          // `jsonfile.json` will be placed to `$RESOURCE/resources/jsonfile.json`
          "relative/path/to/jsonfile.json": "resources/jsonfile.json",
    
    
          // Copy the entire directory to `$RESOURCE`, preserving the original structures,
          // the target is "" which means it will be placed directly in the resource directory `$RESOURCE`, for example:
          //   - `resources/file.txt`                -> `$RESOURCE/file.txt`
          //   - `resources/some-folder/config.json` -> `$RESOURCE/some-folder/config.json`
          "resources/": "",
    
    
          // When using glob patterns, the behavior is different from the list one,
          // all the matching files will be placed to the target directory without preserving the original file structures
          // for example:
          //   - `docs/index.md`         -> `$RESOURCE/website-docs/index.md`
          //   - `docs/plugins/setup.md` -> `$RESOURCE/website-docs/setup.md`
          "docs/**/*md": "website-docs/"
        }
      }
    }
    

To learn about where $RESOURCE resolves to on each platforms, see the documentation of resource_dir

Source path syntax

In the following explanations “target resource directory” is either the value after the colon in the object notation, or a reconstruction of the original file paths in the array notation.

  • "dir/file.txt": copies the file.txt file into the target resource directory.
  • "dir/": copies all files and directories recursively into the target resource directory. Use this if you also want to preserve the file system structure of your files and directories.
  • "dir/*": copies all files in the dir directory non-recursively (sub-directories will be ignored) into the target resource directory.
  • "dir/**: throws an error because ** only matches directories and therefore no files can be found.
  • "dir/**/*": copies all files in the dir directory recursively (all files in dir/ and all files in all sub-directories) into the target resource directory.
  • "dir/**/**: throws an error because ** only matches directories and therefore no files can be found.

Resolve resource file paths

To resolve the path for a resource file, instead of manually calculating the path, use the following APIs

  • Rust

    On the Rust side, you need an instance of the PathResolver which you can get from App and AppHandle, then call PathResolver::resolve:

    tauri::Builder::default()
      .setup(|app| {
        let resource_path = app.path().resolve("lang/de.json", BaseDirectory::Resource)?;
        Ok(())
      })
    

    To use it in a command:

    #[tauri::command]
    fn hello(handle: tauri::AppHandle) {
      let resource_path = handle.path().resolve("lang/de.json", BaseDirectory::Resource)?;
    }
    
  • JavaScript

    To resolve the path in JavaScript, use resolveResource:

    import { resolveResource } from '@tauri-apps/api/path';
    const resourcePath = await resolveResource('lang/de.json');
    

Path syntax

The path in the API calls can be either a normal relative path like folder/json_file.json that resolves to $RESOURCE/folder/json_file.json, or a paths like ../relative/folder/toml_file.toml that resolves to $RESOURCE/_up_/relative/folder/toml_file.toml, these APIs use the same rules as you write tauri.conf.json > bundle > resources, for example:

tauri.conf.json

{
  "bundle": {
    "resources": ["folder/json_file.json", "../relative/folder/toml_file.toml"]
  }
}
let json_path = app.path().resolve("folder/json_file.json", BaseDirectory::Resource)?;
let toml_path = app.path().resolve("../relative/folder/toml_file.toml", BaseDirectory::Resource)?;

Android

Currently the resources are stored in the APK as assets so the return value of those APIs are not normal file system paths, we use a special URI prefix asset://localhost/ here that can be used with the fs plugin, with that, you can read the files through FsExt::fs like this:

let resource_path = app.path().resolve("lang/de.json", BaseDirectory::Resource).unwrap();
let json = app.fs().read_to_string(&resource_path);

If you want or must have the resource files to be on a real file system, copy the contents out manually through the fs plugin

Reading resource files

In this example we want to bundle additional i18n json files like this:

.
├── src-tauri/
│   ├── tauri.conf.json
│   ├── lang/
│   │   ├── de.json
│   │   └── en.json
│   └── ...
└── ...

tauri.conf.json

{
  "bundle": {
    "resources": ["lang/*"]
  }
}

lang/de.json

{
  "hello": "Guten Tag!",
  "bye": "Auf Wiedersehen!"
}

Rust

On the Rust side, you need an instance of the PathResolver which you can get from App and AppHandle:

tauri::Builder::default()
  .setup(|app| {
    // The path specified must follow the same syntax as defined in
    // `tauri.conf.json > bundle > resources`
    let resource_path = app.path().resolve("lang/de.json", BaseDirectory::Resource)?;


    let json = std::fs::read_to_string(&resource_path).unwrap();
    // Or when dealing with Android, use the file system plugin instead
    // let json = app.fs().read_to_string(&resource_path);


    let lang_de: serde_json::Value = serde_json::from_str(json).unwrap();


    // This will print 'Guten Tag!' to the terminal
    println!("{}", lang_de.get("hello").unwrap());


    Ok(())
  })
#[tauri::command]
fn hello(handle: tauri::AppHandle) -> String {
    let resource_path = handle.path().resolve("lang/de.json", BaseDirectory::Resource)?;


    let json = std::fs::read_to_string(&resource_path).unwrap();
    // Or when dealing with Android, use the file system plugin instead
    // let json = handle.fs().read_to_string(&resource_path);


    let lang_de: serde_json::Value = serde_json::from_str(json).unwrap();


    lang_de.get("hello").unwrap()
}

JavaScript

For the JavaScript side, you can either use a command like the one above and call it through await invoke('hello') or access the files using the fs plugin.

When using the fs plugin, in addition to the basic setup, youll also need to configure the access control list to enable any plugin APIs you need as well as the permissions to access the $RESOURCE folder:

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    "core:default",
    +"fs:allow-read-text-file",
    +"fs:allow-resource-read-recursive"
  ]
}

Note

Here we use fs:allow-resource-read-recursive to allow for full recursive read access to the complete $RESOURCE folder, files, and subdirectories. For more information, read Scope Permissions for other options, or Scopes for more fine-grained control.

import { resolveResource } from '@tauri-apps/api/path';
import { readTextFile } from '@tauri-apps/plugin-fs';


const resourcePath = await resolveResource('lang/de.json');
const langDe = JSON.parse(await readTextFile(resourcePath));
console.log(langDe.hello); // This will print 'Guten Tag!' to the devtools console

Permissions

Since we replace ../ to _up_ in relative paths and the root to _root_ in absolute paths when using a list, those files will be in sub folders inside the resource directory, to allow those paths in Tauris permission system, use $RESOURCE/**/* to allow recursive access to those files

Examples

With a file bundled like this:

tauri.conf.json

{
  "bundle": {
    "resources": ["../relative/path/to/jsonfile.json"]
  }
}

To use it with the fs plugin:

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    "core:default",
    +"fs:allow-stat",
    +"fs:allow-read-text-file",
    +"fs:allow-resource-read-recursive",
+    {
      +"identifier": "fs:scope",
      +"allow": ["$RESOURCE/**/*"],
      +"deny": ["$RESOURCE/secret.txt"]
+    }
  ]
}

To use it with the opener plugin:

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    "core:default",
+    {
      +"identifier": "opener:allow-open-path",
      +"allow": [
+        {
          +"path": "$RESOURCE/**/*"
+        }
+      ]
+    }
  ]
}

Embedding External Binaries

You may need to embed external binaries to add additional functionality to your application or prevent users from installing additional dependencies (e.g., Node.js or Python). We call this binary a sidecar.

Binaries are executables written in any programming language. Common use cases are Python CLI applications or API servers bundled using pyinstaller.

To bundle the binaries of your choice, you can add the externalBin property to the bundle object in your tauri.conf.json. The externalBin configuration expects a list of strings targeting binaries either with absolute or relative paths.

Here is a Tauri configuration snippet to illustrate a sidecar configuration:

src-tauri/tauri.conf.json

{
  "bundle": {
    "externalBin": [
      "/absolute/path/to/sidecar",
      "../relative/path/to/binary",
      "binaries/my-sidecar"
    ]
  }
}

Note

The relative paths are relative to the tauri.conf.json file which is in the src-tauri directory. So binaries/my-sidecar would represent <PROJECT ROOT>/src-tauri/binaries/my-sidecar.

To make the external binary work on each supported architecture, a binary with the same name and a -$TARGET_TRIPLE suffix must exist on the specified path. For instance, "externalBin": ["binaries/my-sidecar"] requires a src-tauri/binaries/my-sidecar-x86_64-unknown-linux-gnu executable on Linux or src-tauri/binaries/my-sidecar-aarch64-apple-darwin on Mac OS with Apple Silicon.

You can find your current platforms -$TARGET_TRIPLE suffix by running the following command:

rustc --print host-tuple

This directly outputs your hosts target triple (e.g., x86_64-unknown-linux-gnu or aarch64-apple-darwin).

Note

The --print host-tuple flag was added in Rust 1.84.0. If youre using an older version, youll need to parse the output of rustc -Vv instead:

# Unix (Linux/macOS)
rustc -Vv | grep host | cut -f2 -d' '


# Windows PowerShell
rustc -Vv | Select-String "host:" | ForEach-Object {$_.Line.split(" ")[1]}

Heres a Node.js script to append the target triple to a binary:

import { execSync } from 'child_process';
import fs from 'fs';


const extension = process.platform === 'win32' ? '.exe' : '';


const targetTriple = execSync('rustc --print host-tuple').toString().trim();
if (!targetTriple) {
  console.error('Failed to determine platform target triple');
}
fs.renameSync(
  `src-tauri/binaries/sidecar${extension}`,
  `src-tauri/binaries/sidecar-${targetTriple}${extension}`
);

Note that this script will not work if you compile for a different architecture than the one its running on, so only use it as a starting point for your own build scripts.

Running it from Rust

Note

Please follow the shell plugin guide first to set up and initialize the plugin correctly. Without the plugin being initialized and configured the example wont work.

On the Rust side, import the tauri_plugin_shell::ShellExt trait and call the shell().sidecar() function on the AppHandle:

use tauri_plugin_shell::ShellExt;
use tauri_plugin_shell::process::CommandEvent;
use tauri::Emitter;


let sidecar_command = app.shell().sidecar("my-sidecar").unwrap();
let (mut rx, mut child) = sidecar_command
  .spawn()
  .expect("Failed to spawn sidecar");


tauri::async_runtime::spawn(async move {
  // read events such as stdout
  while let Some(event) = rx.recv().await {
    if let CommandEvent::Stdout(line_bytes) = event {
      let line = String::from_utf8_lossy(&line_bytes);
      app
        .emit("message", Some(format!("'{}'", line)))
        .expect("failed to emit event");
      // write to stdin
      child.write("message from Rust\n".as_bytes()).unwrap();
    }
  }
});

Note

The sidecar() function expects just the filename, NOT the whole path configured in the externalBin array.

Given the following configuration:

src-tauri/tauri.conf.json

{
  "bundle": {
    "externalBin": ["binaries/app", "my-sidecar", "../scripts/sidecar"]
  }
}

The appropriate way to execute the sidecar is by calling app.shell().sidecar(name) where name is either "app", "my-sidecar" or "sidecar" instead of "binaries/app" for instance.

You can place this code inside a Tauri command to easily pass the AppHandle or you can store a reference to the AppHandle in the builder script to access it elsewhere in your application.

Running it from JavaScript

When running the sidecar, Tauri requires you to give the sidecar permission to run the execute or spawn method on the child process. To grant this permission, go to the file <PROJECT ROOT>/src-tauri/capabilities/default.json and add the section below to the permissions array. Dont forget to name your sidecar according to the relative path mentioned earlier.

src-tauri/capabilities/default.json

{
  "permissions": [
    "core:default",
+    {
      +"identifier": "shell:allow-execute",
      +"allow": [
+        {
          +"name": "binaries/app",
          +"sidecar": true
+        }
+      ]
+    }
  ]
}

Note

The shell:allow-execute identifier is used because the sidecars child process will be started using the command.execute() method. To run it with command.spawn(), you need to change the identifier to shell:allow-spawn or add another entry to the array with the same structure as the one above, but with the identifier set to shell:allow-spawn.

In the JavaScript code, import the Command class from the @tauri-apps/plugin-shell module and use the sidecar static method.

import { Command } from '@tauri-apps/plugin-shell';
const command = Command.sidecar('binaries/my-sidecar');
const output = await command.execute();

Note

The string provided to Command.sidecar must match one of the strings defined in the externalBin configuration array.

Passing arguments

You can pass arguments to Sidecar commands just like you would for running normal Command.

Arguments can be either static (e.g. -o or serve) or dynamic (e.g. <file_path> or localhost:<PORT>). A value of true will allow any arguments to be passed to the command. false will disable all arguments. If neither true or false is set, you define the arguments in the exact order in which youd call them. Static arguments are defined as-is, while dynamic arguments can be defined using a regular expression.

First, define the arguments that need to be passed to the sidecar command in src-tauri/capabilities/default.json:

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "default",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    "core:default",
+    {
      +"identifier": "shell:allow-execute",
      +"allow": [
+        {
          +"args": [
            +"arg1",
            +"-a",
            +"--arg2",
+            {
              +"validator": "\\S+"
+            }
+          ],
          +"name": "binaries/my-sidecar",
          +"sidecar": true
+        }
+      ]
+    }
  ]
}

Note

If you are migrating from Tauri v1, the migrate command in Tauri v2 CLI should take care of this for you. Read Automated Migration for more.

Then, to call the sidecar command, simply pass in all the arguments as an array.

In Rust:

use tauri_plugin_shell::ShellExt;
#[tauri::command]
async fn call_my_sidecar(app: tauri::AppHandle) {
  let sidecar_command = app
    .shell()
    .sidecar("my-sidecar")
    .unwrap()
    .args(["arg1", "-a", "--arg2", "any-string-that-matches-the-validator"]);
  let (mut _rx, mut _child) = sidecar_command.spawn().unwrap();
}

In JavaScript:

import { Command } from '@tauri-apps/plugin-shell';
// notice that the args array matches EXACTLY what is specified in `capabilities/default.json`.
const command = Command.sidecar('binaries/my-sidecar', [
  'arg1',
  '-a',
  '--arg2',
  'any-string-that-matches-the-validator',
]);
const output = await command.execute();

State Management

In a Tauri application, you often need to keep track of the current state of your application or manage the lifecycle of things associated with it. Tauri provides an easy way to manage the state of your application using the Manager API, and read it when commands are called.

Here is a simple example:

use tauri::{Builder, Manager};


struct AppData {
  welcome_message: &'static str,
}


fn main() {
  Builder::default()
    .setup(|app| {
      app.manage(AppData {
        welcome_message: "Welcome to Tauri!",
      });
      Ok(())
    })
    .run(tauri::generate_context!())
    .unwrap();
}

You can later access your state with any type that implements the Manager trait, for example the App instance:

let data = app.state::<AppData>();

For more info, including accessing state in commands, see the Accessing State section.

Mutability

In Rust, you cannot directly mutate values which are shared between multiple threads or when ownership is controlled through a shared pointer such as Arc (or Tauris State). Doing so could cause data races (for example, two writes happening simultaneously).

To work around this, you can use a concept known as interior mutability. For example, the standard librarys Mutex can be used to wrap your state. This allows you to lock the value when you need to modify it, and unlock it when you are done.

use std::sync::Mutex;


use tauri::{Builder, Manager};


#[derive(Default)]
struct AppState {
  counter: u32,
}


fn main() {
  Builder::default()
    .setup(|app| {
      app.manage(Mutex::new(AppState::default()));
      Ok(())
    })
    .run(tauri::generate_context!())
    .unwrap();
}

The state can now be modified by locking the mutex:

let state = app.state::<Mutex<AppState>>();


// Lock the mutex to get mutable access:
let mut state = state.lock().unwrap();


// Modify the state:
state.counter += 1;

At the end of the scope, or when the MutexGuard is otherwise dropped, the mutex is unlocked automatically so that other parts of your application can access and mutate the data within.

When to use an async mutex

To quote the Tokio documentation, its often fine to use the standard librarys Mutex instead of an async mutex such as the one Tokio provides:

Contrary to popular belief, it is ok and often preferred to use the ordinary Mutex from the standard library in asynchronous code … The primary use case for the async mutex is to provide shared mutable access to IO resources such as a database connection.

Its a good idea to read the linked documentation fully to understand the trade-offs between the two. One reason you would need an async mutex is if you need to hold the MutexGuard across await points.

Do you need Arc?

Its common to see Arc used in Rust to share ownership of a value across multiple threads (usually paired with a Mutex in the form of Arc<Mutex<T>>). However, you dont need to use Arc for things stored in State because Tauri will do this for you.

In case States lifetime requirements prevent you from moving your state into a new thread you can instead move an AppHandle into the thread and then retrieve your state as shown below in the “Access state with the Manager trait” section. AppHandles are deliberately cheap to clone for use-cases like this.

Accessing State

Access state in commands

#[tauri::command]
fn increase_counter(state: State<'_, Mutex<AppState>>) -> u32 {
  let mut state = state.lock().unwrap();
  state.counter += 1;
  state.counter
}

For more information on commands, see Calling Rust from the Frontend.

Async commands

If you are using async commands and want to use Tokios async Mutex, you can set it up the same way and access the state like this:

#[tauri::command]
async fn increase_counter(state: State<'_, Mutex<AppState>>) -> Result<u32, ()> {
  let mut state = state.lock().await;
  state.counter += 1;
  Ok(state.counter)
}

Note that the return type must be Result if you use asynchronous commands.

Access state with the Manager trait

Sometimes you may need to access the state outside of commands, such as in a different thread or in an event handler like on_window_event. In such cases, you can use the state() method of types that implement the Manager trait (such as the AppHandle) to get the state:

use std::sync::Mutex;
use tauri::{Builder, Window, WindowEvent, Manager};


#[derive(Default)]
struct AppState {
  counter: u32,
}


// In an event handler:
fn on_window_event(window: &Window, _event: &WindowEvent) {
    // Get a handle to the app so we can get the global state.
    let app_handle = window.app_handle();
    let state = app_handle.state::<Mutex<AppState>>();


    // Lock the mutex to mutably access the state.
    let mut state = state.lock().unwrap();
    state.counter += 1;
}


fn main() {
  Builder::default()
    .setup(|app| {
      app.manage(Mutex::new(AppState::default()));
      Ok(())
    })
    .on_window_event(on_window_event)
    .run(tauri::generate_context!())
    .unwrap();
}

This method is useful when you cannot rely on command injection. For example, if you need to move the state into a thread where using an AppHandle is easier, or if you are not in a command context.

Mismatching Types

Caution

If you use the wrong type for the State parameter, you will get a runtime panic instead of compile time error.

For example, if you use State<'_, AppState> instead of State<'_, Mutex<AppState>>, there wont be any state managed with that type.

If you prefer, you can wrap your state with a type alias to prevent this mistake:

use std::sync::Mutex;


#[derive(Default)]
struct AppStateInner {
  counter: u32,
}


type AppState = Mutex<AppStateInner>;

However, make sure to use the type alias as it is, and not wrap it in a Mutex a second time, otherwise you will run into the same issue.

Tests

Techniques for testing inside and outside the Tauri runtime

Tauri offers support for both unit and integration testing utilizing a mock runtime. Under the mock runtime, native webview libraries are not executed. See more about the mock runtime here.

Tauri also provides support for end-to-end testing utilizing the WebDriver protocol. WebdriverIO Tauri testing supports Windows, Linux, and macOS; the WebDriver protocol can also be driven directly on Windows and Linux, as macOS provides no desktop WebDriver client. See more about WebDriver support here.

We offer tauri-action to help run GitHub actions, but any sort of CI/CD runner can be used with Tauri as long as each platform has the required libraries installed to compile against.

Mock Tauri APIs

When writing your frontend tests, having a “fake” Tauri environment to simulate windows or intercept IPC calls is common, so-called mocking. The @tauri-apps/api/mocks module provides some helpful tools to make this easier for you:

Caution

Remember to clear mocks after each test run to undo mock state changes between runs! See clearMocks() docs for more info.

IPC Requests

Most commonly, you want to intercept IPC requests; this can be helpful in a variety of situations:

  • Ensure the correct backend calls are made
  • Simulate different results from backend functions

Tauri provides the mockIPC function to intercept IPC requests. You can find more about the specific API in detail here.

Note

The following examples use Vitest, but you can use any other frontend testing library such as jest.

Mocking Commands for invoke

import { beforeAll, expect, test } from "vitest";
import { randomFillSync } from "crypto";


import { mockIPC } from "@tauri-apps/api/mocks";
import { invoke } from "@tauri-apps/api/core";


// jsdom doesn't come with a WebCrypto implementation
beforeAll(() => {
  Object.defineProperty(window, 'crypto', {
    value: {
      // @ts-ignore
      getRandomValues: (buffer) => {
        return randomFillSync(buffer);
      },
    },
  });
});




test("invoke simple", async () => {
  mockIPC((cmd, args) => {
    // simulated rust command called "add" that just adds two numbers
    if(cmd === "add") {
      return (args.a as number) + (args.b as number);
    }
  });
});

Sometimes you want to track more information about an IPC call; how many times was the command invoked? Was it invoked at all? You can use mockIPC() with other spying and mocking tools to test this:

import { beforeAll, expect, test, vi } from "vitest";
import { randomFillSync } from "crypto";


import { mockIPC } from "@tauri-apps/api/mocks";
import { invoke } from "@tauri-apps/api/core";


// jsdom doesn't come with a WebCrypto implementation
beforeAll(() => {
  Object.defineProperty(window, 'crypto', {
    value: {
      // @ts-ignore
      getRandomValues: (buffer) => {
        return randomFillSync(buffer);
      },
    },
  });
});




test("invoke", async () => {
  mockIPC((cmd, args) => {
    // simulated rust command called "add" that just adds two numbers
    if(cmd === "add") {
      return (args.a as number) + (args.b as number);
    }
  });


  // we can use the spying tools provided by vitest to track the mocked function
  const spy = vi.spyOn(window.__TAURI_INTERNALS__, "invoke");


  expect(invoke("add", { a: 12, b: 15 })).resolves.toBe(27);
  expect(spy).toHaveBeenCalled();
});

To mock IPC requests to a sidecar or shell command you need to grab the ID of the event handler when spawn() or execute() is called and use this ID to emit events the backend would send back:

mockIPC(async (cmd, args) => {
  if (args.message.cmd === 'execute') {
    const eventCallbackId = `_${args.message.onEventFn}`;
    const eventEmitter = window[eventCallbackId];


    // 'Stdout' event can be called multiple times
    eventEmitter({
      event: 'Stdout',
      payload: 'some data sent from the process',
    });


    // 'Terminated' event must be called at the end to resolve the promise
    eventEmitter({
      event: 'Terminated',
      payload: {
        code: 0,
        signal: 'kill',
      },
    });
  }
});

See also

mockIPC fakes invoke under the mock runtime — no real webview or Rust backend runs. To mock the same commands in end-to-end tests, against a running app or your frontend in a browser, @wdio/tauri-service provides an equivalent browser.tauri.mock(). See WebDriver testing.

Mocking Events

Since 2.7.0

There is partial support of the Event System to simulate events emitted by your Rust code via the shouldMockEvents option:

import { mockIPC, clearMocks } from '@tauri-apps/api/mocks';
import { emit, listen } from '@tauri-apps/api/event';
import { afterEach, expect, test, vi } from 'vitest';


test('mocked event', () => {
  mockIPC(() => {}, { shouldMockEvents: true }); // enable event mocking


  const eventHandler = vi.fn();
  listen('test-event', eventHandler);


  emit('test-event', { foo: 'bar' });
  expect(eventHandler).toHaveBeenCalledWith({
    event: 'test-event',
    payload: { foo: 'bar' },
  });
});

emitTo and emit_filter are not supported yet.

Windows

Sometimes you have window-specific code (a splash screen window, for example), so you need to simulate different windows. You can use the mockWindows() method to create fake window labels. The first string identifies the “current” window (i.e., the window your JavaScript believes itself in), and all other strings are treated as additional windows.

Note

mockWindows() only fakes the existence of windows but no window properties. To simulate window properties, you need to intercept the correct calls using mockIPC()

import { beforeAll, expect, test } from 'vitest';
import { randomFillSync } from 'crypto';


import { mockWindows } from '@tauri-apps/api/mocks';


// jsdom doesn't come with a WebCrypto implementation
beforeAll(() => {
  Object.defineProperty(window, 'crypto', {
    value: {
      // @ts-ignore
      getRandomValues: (buffer) => {
        return randomFillSync(buffer);
      },
    },
  });
});


test('invoke', async () => {
  mockWindows('main', 'second', 'third');


  const { getCurrent, getAll } = await import('@tauri-apps/api/webviewWindow');


  expect(getCurrent()).toHaveProperty('label', 'main');
  expect(getAll().map((w) => w.label)).toEqual(['main', 'second', 'third']);
});

WebDriver

WebDriver Testing

WebDriver is a standardized interface to interact with web documents, primarily intended for automated testing. The recommended way to use it with Tauri is WebdriverIO and the @wdio/tauri-service, which works on Windows, Linux, and macOS. Maintained under the WebdriverIO project, it provides Tauri API access through browser.tauri.execute(), command (IPC) mocking, frontend and backend log capture, and multiremote.

By default the service runs an embedded WebDriver server inside your app, so no external driver is needed on any platform — and this is how macOS is supported. It can also drive the platforms native WebDriver through tauri-driver on Windows and Linux, or CrabNebulas cross-platform fork of tauri-driver on all platforms (a paid API key is required for macOS). Whichever route you choose, the service detects your application binary, and on the tauri-driver route it keeps the Edge WebDriver in sync on Windows for you.

The quickest way to scaffold a project is the WebdriverIO starter:

npm create wdio@latest ./

Pick Desktop Testing and choose Tauri at the framework prompt. A minimal configuration looks like this:

export const config: WebdriverIO.Config = {
  services: [
    [
      'tauri',
      {
        appBinaryPath: './src-tauri/target/release/my-tauri-app',
        driverProvider: 'embedded',
      },
    ],
  ],
};

Setting this up uses two small Tauri plugins, both optional depending on your requirements:

  • tauri-plugin-wdio-webdriver runs the embedded WebDriver server. Its required for the embedded provider (the default) — the service drives your app through it, with no external driver, and its how macOS is supported. You can skip it if you want to use the external or crabnebula provider instead.
  • tauri-plugin-wdio enables backend access including: browser.tauri.execute(), command (IPC) mocking, and log capture.

See Plugin Setup for the full steps, and the CrabNebula setup guide if you use that provider.

For fast, renderer-only tests there is also a browser mode that runs your Tauri frontend in plain Chrome against a Vite dev server — no Tauri binary, driver, or plugin required. It intercepts invoke() calls so you can mock commands and assert on their arguments with the same WDIO API. See the browser mode guide.

WebdriverIO Tauri documentationFull setup, configuration, and API reference for @wdio/tauri-service

Example Applications

Complete, runnable examples that use the service live in the WebdriverIO desktop-mobile repository.

Continuous Integration (CI)

The WebDriver CI guide explains how to run these tests under GitHub Actions and the concepts behind it.

Continuous Integration (CI)

Driving tauri-driver directly

If you are not using Node.js, prefer Selenium, or are integrating WebDriver into a custom test harness, you can drive tauri-driver directly instead of using the service. Driven directly, only Windows and Linux are supported on desktop, as macOS has no WKWebView driver tool available (use the services embedded WebDriver server for macOS).

Manual WebDriver setupInstall and drive tauri-driver yourself (Windows and Linux only)

Continuous Integration

WebDriver Testing

It is possible to run WebDriver tests with tauri-driver on your CI. The following example uses the WebdriverIO example we previously built together and GitHub Actions.

The WebDriver tests are executed on Linux by creating a fake display. Some CI systems such as GitHub Actions also support running WebDriver tests on Windows.

GitHub Actions

The following GitHub Actions assumes:

  1. The Tauri application is in the src-tauri folder.
  2. The WebDriverIO test runner is in the e2e-tests directory and runs when yarn test is used in that directory.

.github/workflows/webdriver.yml

# run this action when the repository is pushed to
on: [push]


# the name of our workflow
name: WebDriver


jobs:
  # a single job named test
  test:
    # the display name of the test job
    name: WebDriverIO Test Runner


    # run on the matrix platform
    runs-on: ${{ matrix.platform }}
    strategy:
      # do not fail other matrix runs if one fails
      fail-fast: false
      # set all platforms our test should run on
      matrix:
        platform: [ubuntu-latest, windows-latest]


    # the steps our job runs **in order**
    steps:
      # checkout the code on the workflow runner
      - uses: actions/checkout@v4


      # install system dependencies that Tauri needs to compile on Linux.
      # note the extra dependencies for `tauri-driver` to run which are: `webkit2gtk-driver` and `xvfb`
      - name: Tauri dependencies
        if: matrix.platform == 'ubuntu-latest'
        run: |
          sudo apt-get update &&
          sudo apt-get install -y \
          libwebkit2gtk-4.1-dev \
          libayatana-appindicator3-dev \
          webkit2gtk-driver \
          xvfb


      # install a matching Microsoft Edge Driver version using msedgedriver-tool
      - name: install msdgedriver (Windows)
        if: matrix.platform == 'windows-latest'
        run: |
          cargo install --git https://github.com/chippers/msedgedriver-tool
          & "$HOME/.cargo/bin/msedgedriver-tool.exe"
          $PWD.Path >> $env:GITHUB_PATH


      # install latest stable Rust release
      - name: Setup rust-toolchain stable
        uses: dtolnay/rust-toolchain@stable


      # setup caching for the Rust target folder
      - name: Setup Rust cache
        uses: Swatinem/rust-cache@v2
        with:
          workspaces: src-tauri


      # we run our Rust tests before the webdriver tests to avoid testing a broken application
      - name: Cargo test
        run: cargo test


      # install the latest stable node version at the time of writing
      - name: Node 24
        uses: actions/setup-node@v4
        with:
          node-version: 24
          cache: 'yarn'


      # install the application Node.js dependencies with Yarn
      - name: Yarn install
        run: yarn install --frozen-lockfile


      # install the e2e-tests Node.js dependencies with Yarn
      - name: Yarn install
        run: yarn install --frozen-lockfile
        working-directory: e2e-tests


      # install the latest version of `tauri-driver`.
      # note: the tauri-driver version is independent of any other Tauri versions
      - name: Install tauri-driver
        run: cargo install tauri-driver --locked


      # run the WebdriverIO test suite on Linux.
      # we run it through `xvfb-run` (the dependency we installed earlier) to have a fake
      # display server which allows our application to run headless without any changes to the code
      - name: WebdriverIO (Linux)
        if: matrix.platform == 'ubuntu-latest'
        run: xvfb-run yarn test
        working-directory: e2e-tests


      # run the WebdriverIO test suite on Windows.
      # in this case we can run the tests directly.
      - name: WebdriverIO (Windows)
        if: matrix.platform == 'windows-latest'
        run: yarn test
        working-directory: e2e-tests

Selenium

Note

Make sure to go through the prerequisites instructions to be able to follow this guide.

This WebDriver testing example will use Selenium and a popular Node.js testing suite. You are expected to already have Node.js installed, along with npm or yarn although the finished example project uses pnpm.

Create a Directory for the Tests

Lets create a space to write these tests in our project. We will be using a nested directory for this example project as we will later also go over other frameworks, but typically you will only need to use one. Create the directory we will use with mkdir -p e2e-tests. The rest of this guide will assume you are inside the e2e-tests directory.

Initializing a Selenium Project

We will be using a pre-existing package.json to bootstrap this test suite because we have already chosen specific dependencies to use and want to showcase a simple working solution. The bottom of this section has a collapsed guide on how to set it up from scratch.

package.json:

{
  "name": "selenium",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "mocha"
  },
  "dependencies": {
    "chai": "^5.2.1",
    "mocha": "^11.7.1",
    "selenium-webdriver": "^4.34.0"
  }
}

We have a script that runs Mocha as a test framework exposed as the test command. We also have various dependencies that we will be using to run the tests. Mocha as the testing framework, Chai as the assertion library, and selenium-webdriver which is the Node.js Selenium package.

Click me if you want to see how to set a project up from scratch

If you want to install the dependencies from scratch, just run the following command.

  • npm

    npm install mocha chai selenium-webdriver
    
  • yarn

    yarn add mocha chai selenium-webdriver
    

I suggest also adding a "test": "mocha" item in the package.json "scripts" key so that running Mocha can be called simply with

  • npm

    npm test
    
  • yarn

    yarn test
    

Testing

Unlike the WebdriverIO Test Suite, Selenium does not come out of the box with a Test Suite and leaves it up to the developer to build those out. We chose Mocha, which is pretty neutral and not related to WebDrivers, so our script will need to do a bit of work to set up everything for us in the correct order. Mocha expects a testing file at test/test.js by default, so lets create that file now.

test/test.js:

import os from 'os';
import path from 'path';
import { expect } from 'chai';
import { spawn, spawnSync } from 'child_process';
import { Builder, By, Capabilities } from 'selenium-webdriver';
import { fileURLToPath } from 'url';


const __dirname = fileURLToPath(new URL('.', import.meta.url));


// create the path to the expected application binary
const application = path.resolve(
  __dirname,
  '..',
  '..',
  'src-tauri',
  'target',
  'debug',
  'tauri-app'
);


// keep track of the webdriver instance we create
let driver;


// keep track of the tauri-driver process we start
let tauriDriver;
let exit = false;


before(async function () {
  // set timeout to 2 minutes to allow the program to build if it needs to
  this.timeout(120000);


  // ensure the app has been built
  spawnSync('yarn', ['tauri', 'build', '--debug', '--no-bundle'], {
    cwd: path.resolve(__dirname, '../..'),
    stdio: 'inherit',
    shell: true,
  });


  // start tauri-driver
  tauriDriver = spawn(
    path.resolve(os.homedir(), '.cargo', 'bin', 'tauri-driver'),
    [],
    { stdio: [null, process.stdout, process.stderr] }
  );
  tauriDriver.on('error', (error) => {
    console.error('tauri-driver error:', error);
    process.exit(1);
  });
  tauriDriver.on('exit', (code) => {
    if (!exit) {
      console.error('tauri-driver exited with code:', code);
      process.exit(1);
    }
  });


  const capabilities = new Capabilities();
  capabilities.set('tauri:options', { application });
  capabilities.setBrowserName('wry');


  // start the webdriver client
  driver = await new Builder()
    .withCapabilities(capabilities)
    .usingServer('http://127.0.0.1:4444/')
    .build();
});


after(async function () {
  // stop the webdriver session
  await closeTauriDriver();
});


describe('Hello Tauri', () => {
  it('should be cordial', async () => {
    const text = await driver.findElement(By.css('body > h1')).getText();
    expect(text).to.match(/^[hH]ello/);
  });


  it('should be excited', async () => {
    const text = await driver.findElement(By.css('body > h1')).getText();
    expect(text).to.match(/!$/);
  });


  it('should be easy on the eyes', async () => {
    // selenium returns color css values as rgb(r, g, b)
    const text = await driver
      .findElement(By.css('body'))
      .getCssValue('background-color');


    const rgb = text.match(/^rgb\((?<r>\d+), (?<g>\d+), (?<b>\d+)\)$/).groups;
    expect(rgb).to.have.all.keys('r', 'g', 'b');


    const luma = 0.2126 * rgb.r + 0.7152 * rgb.g + 0.0722 * rgb.b;
    expect(luma).to.be.lessThan(100);
  });
});


async function closeTauriDriver() {
  exit = true;
  // kill the tauri-driver process
  tauriDriver.kill();
  // stop the webdriver session
  await driver.quit();
}


function onShutdown(fn) {
  const cleanup = () => {
    try {
      fn();
    } finally {
      process.exit();
    }
  };


  process.on('exit', cleanup);
  process.on('SIGINT', cleanup);
  process.on('SIGTERM', cleanup);
  process.on('SIGHUP', cleanup);
  process.on('SIGBREAK', cleanup);
}


onShutdown(() => {
  closeTauriDriver();
});

If you are familiar with JS testing frameworks, describe, it, and expect should look familiar. We also have semi-complex before() and after() callbacks to set up and teardown mocha. Lines that are not the tests themselves have comments explaining the setup and teardown code. If you were familiar with the Spec file from the WebdriverIO example, you notice a lot more code that isnt tests, as we have to set up a few more WebDriver related items.

Running the Test Suite

Now that we are all set up with our dependencies and our test script, lets run it!

  • npm

    npm test
    
  • yarn

    yarn test
    

We should see output the following output:

➜  selenium git:(main) ✗ yarn test
yarn run v1.22.11
$ Mocha




  Hello Tauri
    ✔ should be cordial (120ms)
    ✔ should be excited
    ✔ should be easy on the eyes




  3 passing (588ms)


Done in 0.93s.

We can see that our Hello Tauri test suite we created with describe had all 3 items we created with it pass their tests!

With Selenium and some hooking up to a test suite, we just enabled e2e testing without modifying our Tauri application at all!

WebdriverIO

Note

Make sure to go through the prerequisites instructions to be able to follow this guide.

Using the WebdriverIO Tauri service?

This guide wires WebdriverIO up to tauri-driver by hand so you can see how the pieces fit together. Most projects should use the @wdio/tauri-service instead, which automates all of this and supports macOS — see the WebDriver overview.

This WebDriver testing example will use WebdriverIO, and its testing suite. It is expected to have Node.js already installed, along with npm or yarn although the finished example project uses pnpm.

Create a Directory for the Tests

Lets create a space to write these tests in our project. We will be using a nested directory for this example project as we will later also go over other frameworks, but typically you only need to use one. Create the directory we will use with mkdir e2e-tests. The rest of this guide assumes you are inside the e2e-tests directory.

Initializing a WebdriverIO Project

We will be using a pre-existing package.json to bootstrap this test suite because we have already chosen specific WebdriverIO config options and want to showcase a simple working solution. The bottom of this section has a collapsed guide on setting it up from scratch.

package.json:

{
  "name": "webdriverio",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "scripts": {
    "test": "wdio run wdio.conf.js"
  },
  "dependencies": {
    "@wdio/cli": "^9.19.0"
  },
  "devDependencies": {
    "@wdio/local-runner": "^9.19.0,
    "@wdio/mocha-framework": "^9.19.0",
    "@wdio/spec-reporter": "^9.19.0"
  }
}

We have a script that runs a WebdriverIO config as a test suite exposed as the test command. We also have various dependencies added by the @wdio/cli command when we first set it up. In short, these dependencies are for the most simple setup using a local WebDriver runner, Mocha as the test framework, and a simple Spec Reporter.

Click me if you want to see how to set a project up from scratch

The CLI is interactive, and you may choose the tools to work with yourself. Note that you will likely diverge from the rest of the guide, and you need to set up the differences yourself.

Lets add the WebdriverIO CLI to this npm project.

  • npm

    npm install @wdio/cli
    
  • yarn

    yarn add @wdio/cli
    

To then run the interactive config command to set up a WebdriverIO test suite, you can then run:

  • npm

    npx wdio config
    
  • yarn

    yarn wdio config
    

Config

You may have noticed that the test script in our package.json mentions a file wdio.conf.js. Thats the WebdriverIO config file which controls most aspects of our testing suite.

wdio.conf.js:

import os from 'os';
import path from 'path';
import { spawn, spawnSync } from 'child_process';
import { fileURLToPath } from 'url';


const __dirname = fileURLToPath(new URL('.', import.meta.url));


// keep track of the `tauri-driver` child process
let tauriDriver;
let exit = false;


export const config = {
  host: '127.0.0.1',
  port: 4444,
  specs: ['./develop/tests/specs/**/*.js'],
  maxInstances: 1,
  capabilities: [
    {
      maxInstances: 1,
      'tauri:options': {
        application: '../src-tauri/target/debug/tauri-app',
      },
    },
  ],
  reporters: ['spec'],
  framework: 'mocha',
  mochaOpts: {
    ui: 'bdd',
    timeout: 60000,
  },


  // ensure the rust project is built since we expect this binary to exist for the webdriver sessions
  onPrepare: () => {
    // Remove the extra `--` if you're not using npm!
    spawnSync(
      'npm',
      ['run', 'tauri', 'build', '--', '--debug', '--no-bundle'],
      {
        cwd: path.resolve(__dirname, '..'),
        stdio: 'inherit',
        shell: true,
      }
    );
  },


  // ensure we are running `tauri-driver` before the session starts so that we can proxy the webdriver requests
  beforeSession: () => {
    tauriDriver = spawn(
      path.resolve(os.homedir(), '.cargo', 'bin', 'tauri-driver'),
      [],
      { stdio: [null, process.stdout, process.stderr] }
    );


    tauriDriver.on('error', (error) => {
      console.error('tauri-driver error:', error);
      process.exit(1);
    });
    tauriDriver.on('exit', (code) => {
      if (!exit) {
        console.error('tauri-driver exited with code:', code);
        process.exit(1);
      }
    });
  },


  // clean up the `tauri-driver` process we spawned at the start of the session
  // note that afterSession might not run if the session fails to start, so we also run the cleanup on shutdown
  afterSession: () => {
    closeTauriDriver();
  },
};


function closeTauriDriver() {
  exit = true;
  tauriDriver?.kill();
}


function onShutdown(fn) {
  const cleanup = () => {
    try {
      fn();
    } finally {
      process.exit();
    }
  };


  process.on('exit', cleanup);
  process.on('SIGINT', cleanup);
  process.on('SIGTERM', cleanup);
  process.on('SIGHUP', cleanup);
  process.on('SIGBREAK', cleanup);
}


// ensure tauri-driver is closed when our test process exits
onShutdown(() => {
  closeTauriDriver();
});

If you are interested in the properties on the config object, we suggest reading the documentation. For non-WDIO specific items, there are comments explaining why we are running commands in onPrepare, beforeSession, and afterSession. We also have our specs set to "./test/specs/**/*.js", so lets create a spec now.

Spec

A spec contains the code that is testing your actual application. The test runner will load these specs and automatically run them as it sees fit. Lets create our spec now in the directory we specified.

test/specs/example.e2e.js:

// calculates the luma from a hex color `#abcdef`
function luma(hex) {
  if (hex.startsWith('#')) {
    hex = hex.substring(1);
  }


  const rgb = parseInt(hex, 16);
  const r = (rgb >> 16) & 0xff;
  const g = (rgb >> 8) & 0xff;
  const b = (rgb >> 0) & 0xff;
  return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}


describe('Hello Tauri', () => {
  it('should be cordial', async () => {
    const header = await $('body > h1');
    const text = await header.getText();
    expect(text).toMatch(/^[hH]ello/);
  });


  it('should be excited', async () => {
    const header = await $('body > h1');
    const text = await header.getText();
    expect(text).toMatch(/!$/);
  });


  it('should be easy on the eyes', async () => {
    const body = await $('body');
    const backgroundColor = await body.getCSSProperty('background-color');
    expect(luma(backgroundColor.parsed.hex)).toBeLessThan(100);
  });
});

The luma function on top is just a helper function for one of our tests and is not related to the actual testing of the application. If you are familiar with other testing frameworks, you may notice similar functions being exposed that are used, such as describe, it, and expect. The other APIs, such as items like $ and its exposed methods, are covered by the WebdriverIO API docs.

Running the Test Suite

Now that we are all set up with config and a spec lets run it!

  • npm

    npm test
    
  • yarn

    yarn test
    

We should see output the following output:

➜  webdriverio git:(main) ✗ yarn test
yarn run v1.22.11
$ wdio run wdio.conf.js


Execution of 1 workers started at 2021-08-17T08:06:10.279Z


[0-0] RUNNING in undefined - /develop/tests/specs/example.e2e.js
[0-0] PASSED in undefined - /develop/tests/specs/example.e2e.js


 "spec" Reporter:
------------------------------------------------------------------
[wry 0.12.1 linux #0-0] Running: wry (v0.12.1) on linux
[wry 0.12.1 linux #0-0] Session ID: 81e0107b-4d38-4eed-9b10-ee80ca47bb83
[wry 0.12.1 linux #0-0]
[wry 0.12.1 linux #0-0] » /develop/tests/specs/example.e2e.js
[wry 0.12.1 linux #0-0] Hello Tauri
[wry 0.12.1 linux #0-0]    ✓ should be cordial
[wry 0.12.1 linux #0-0]    ✓ should be excited
[wry 0.12.1 linux #0-0]    ✓ should be easy on the eyes
[wry 0.12.1 linux #0-0]
[wry 0.12.1 linux #0-0] 3 passing (244ms)




Spec Files:   1 passed, 1 total (100% completed) in 00:00:01


Done in 1.98s.

We see the Spec Reporter tell us that all 3 tests from the test/specs/example.e2e.js file, along with the final report Spec Files: 1 passed, 1 total (100% completed) in 00:00:01.

Using the WebdriverIO test suite, we just easily enabled e2e testing for our Tauri application from just a few lines of configuration and a single command to run it! Even better, we didnt have to modify the application at all.

Manual setup

Driving tauri-driver directly without the WebdriverIO Tauri service

This page covers driving tauri-driver directly, without the @wdio/tauri-service. Reach for it if you are not using Node.js, prefer Selenium, or are integrating WebDriver into a custom test harness. For most projects the service is the easier path — it automates everything below and additionally supports macOS. See the WebDriver overview to get started with it.

When driving tauri-driver directly, only Windows and Linux are supported on desktop, as macOS has no WKWebView driver tool available. iOS and Android work through Appium 2, but the process is not currently streamlined.

System Dependencies

Install the latest tauri-driver or update an existing installation by running:

cargo install tauri-driver --locked

Because we currently utilize the platforms native WebDriver server, there are some requirements for running tauri-driver on supported platforms.

Linux

We use WebKitWebDriver on Linux platforms. Check if this binary exists already by running the which WebKitWebDriver command as some distributions bundle it with the regular WebKit package. Other platforms may have a separate package for them, such as webkit2gtk-driver on Debian-based distributions.

Windows

Make sure to grab the version of Microsoft Edge Driver that matches your Windows Edge version that the application is being built and tested on. This should almost always be the latest stable version on up-to-date Windows installs. If the two versions do not match, you may experience your WebDriver testing suite hanging while trying to connect.

You can use the msedgedriver-tool to download the appropriate Microsoft Edge Driver:

cargo install --git https://github.com/chippers/msedgedriver-tool
& "$HOME/.cargo/bin/msedgedriver-tool.exe"

The download contains a binary called msedgedriver.exe. tauri-driver looks for that binary in the $PATH so make sure its either available on the path or use the --native-driver option on tauri-driver. You may want to download this automatically as part of the CI setup process to ensure the Edge, and Edge Driver versions stay in sync on Windows CI machines. A guide on how to do this may be added at a later date.

Example Applications

Below are step-by-step guides to show how to create a minimal example application that is tested with WebDriver.

If you prefer to see the result of the guide and look over a finished minimal codebase that utilizes it, you can look at https://github.com/tauri-apps/webdriver-example.

Selenium

WebdriverIO

Continuous Integration (CI)

The above examples also comes with a CI script to test with GitHub Actions, but you may still be interested in the below WebDriver CI guide as it explains the concept a bit more.

Continuous Integration (CI)

Updating Dependencies

Update npm Packages

If you are using the tauri package:

  • npm

    npm install @tauri-apps/cli@latest @tauri-apps/api@latest
    
  • yarn

    yarn up @tauri-apps/cli @tauri-apps/api
    
  • pnpm

    pnpm update @tauri-apps/cli @tauri-apps/api --latest
    

You can also detect what the latest version of Tauri is on the command line, using:

  • npm

    npm outdated @tauri-apps/cli
    
  • yarn

    yarn outdated @tauri-apps/cli
    
  • pnpm

    pnpm outdated @tauri-apps/cli
    

Update Cargo Packages

You can check for outdated packages with cargo outdated or on the crates.io pages: tauri / tauri-build.

Go to src-tauri/Cargo.toml and change tauri and tauri-build to

[build-dependencies]
tauri-build = "%version%"


[dependencies]
tauri = { version = "%version%" }

where %version% is the corresponding version number from above.

Then do the following:

cd src-tauri
cargo update

Alternatively, you can run the cargo upgrade command provided by cargo-edit which does all of this automatically.

Sync npm Packages and Cargo Crates versions

Since the JavaScript APIs rely on Rust code in the backend, adding a new feature requires upgrading both sides to ensure compatibility. Please make sure you have the same minor version of the npm package @tauri-apps/api and cargo crate tauri synced

And for the plugins, we might introduce this type of changes in patch releases, so we bump the npm package and cargo crate versions together, and you need to keep the exact versions synced, for example, you need the same version (e.g. 2.2.1) of the npm package @tauri-apps/plugin-fs and cargo crate tauri-plugin-fs

Distribute

Information on the tooling you need to distribute your application either to the platform app stores or as platform-specific installers

Tauri provides the tooling you need to distribute your application either to the platform app stores or as platform-specific installers.

Building

Tauri builds your application directly from its CLI via the build, android build and ios build commands.

  • npm

    npm run tauri build
    
  • yarn

    yarn tauri build
    
  • pnpm

    pnpm tauri build
    
  • deno

    deno task tauri build
    
  • bun

    bun tauri build
    
  • cargo

    cargo tauri build
    

See the distributing section to learn more about the configuration options available for each bundle and how to distribute them to your users.

Note

Most platforms requires code signing. See the signing section for more information.

Bundling

By default the build command automatically bundles your application for the configured formats.

If you need further customization on how the platform bundles are generated, you can split the build and bundle steps:

  • npm

    npm run tauri build -- --no-bundle
    # bundle for distribution outside the macOS App Store
    npm run tauri bundle -- --bundles app,dmg
    # bundle for App Store distribution
    npm run tauri bundle -- --bundles app --config src-tauri/tauri.appstore.conf.json
    
  • yarn

    yarn tauri build --no-bundle
    # bundle for distribution outside the macOS App Store
    yarn tauri bundle --bundles app,dmg
    # bundle for App Store distribution
    yarn tauri bundle --bundles app --config src-tauri/tauri.appstore.conf.json
    
  • pnpm

    pnpm tauri build --no-bundle
    # bundle for distribution outside the macOS App Store
    pnpm tauri bundle --bundles app,dmg
    # bundle for App Store distribution
    pnpm tauri bundle --bundles app --config src-tauri/tauri.appstore.conf.json
    
  • deno

    deno task tauri build --no-bundle
    # bundle for distribution outside the macOS App Store
    deno task tauri bundle --bundles app,dmg
    # bundle for App Store distribution
    deno task tauri bundle --bundles app --config src-tauri/tauri.appstore.conf.json
    
  • bun

    bun tauri build --no-bundle
    # bundle for distribution outside the macOS App Store
    bun tauri bundle --bundles app,dmg
    # bundle for App Store distribution
    bun tauri bundle --bundles app --config src-tauri/tauri.appstore.conf.json
    
  • cargo

    cargo tauri build --no-bundle
    # bundle for distribution outside the macOS App Store
    cargo tauri bundle --bundles app,dmg
    # bundle for App Store distribution
    cargo tauri bundle --bundles app --config src-tauri/tauri.appstore.conf.json
    

Versioning

Your application version can be defined in the tauri.conf.json > version configuration option, which is the recommended way for managing the app version. If that config value is not set, Tauri uses the package > version value from your src-tauri/Cargo.toml file instead.

Note

Some platforms have some limitations and special cases for the version string. See the individual distribution documentation pages for more information.

Signing

Code signing enhances the security of your application by applying a digital signature to your applications executables and bundles, validating your identity of the provider of your application.

Signing is required on most platforms. See the documentation for each platform for more information.

macOSCode signing and notarization for macOS apps

WindowsCode signing Windows installers

LinuxCode signing Linux packages

AndroidCode signing for Android

iOSCode signing for iOS

Distributing

Learn how to distribute your application for each platform.

Linux

For Linux you can distribute your app using the Debian package, Snap, AppImage, Flatpak, RPM or Arch User Repository (AUR) formats.

AppImageDistribute as an AppImage

AURPublishing To The Arch User Repository

DebianDistribute as a Debian package

RPMDistribute as an RPM package

SnapcraftDistribute on Snapcraft.io

Code signing

macOS

For macOS you can either distribute your application directly to the App Store or ship a DMG installer as direct download. Both methods requires code signing, and distributing outside the App Store also requires notarization.

App BundleDistribute macOS apps as an App Bundle

App StoreDistribute iOS and macOS apps to the App Store

DMGDistribute macOS apps as Apple Disk Images

Code signing and notarization

Windows

Learn how to distribute to the Microsoft Store or configure a Windows installer.

Microsoft StoreDistribute Windows apps to the Microsoft Store

Windows InstallerDistribute installers for Windows

Code signing

Android

Distribute your Android application to Google Play.

Google PlayDistribute Android apps to Google Play

Code signing

iOS

Learn how to upload your application to the App Store.

App StoreDistribute iOS and macOS apps to the App Store

Code signing

Cloud Services

Distribute your application to Cloud services that globally distribute your application and support auto updates out of the box.

CrabNebula CloudDistribute your app using CrabNebula

App Store

The Apple App Store is the app marketplace maintained by Apple. You can distribute your Tauri app targeting macOS and iOS via this App Store.

This guide only covers details for distributing apps directly to the App Store. See the general App Bundle for more information on macOS distribution options and configurations.

Requirements

Distributing iOS and macOS apps requires enrolling to the Apple Developer program.

Additionally, you must setup code signing for macOS and iOS.

Changing App Icon

After running tauri ios init to setup the Xcode project, you can use the tauri icon command to update the app icons.

  • npm

    npm run tauri icon /path/to/app-icon.png -- --ios-color '#fff'
    
  • yarn

    yarn tauri icon /path/to/app-icon.png --ios-color '#fff'
    
  • pnpm

    pnpm tauri icon /path/to/app-icon.png --ios-color '#fff'
    
  • deno

    deno task tauri icon /path/to/app-icon.png --ios-color '#fff'
    
  • bun

    bun tauri icon /path/to/app-icon.png --ios-color '#fff'
    
  • cargo

    cargo tauri icon /path/to/app-icon.png --ios-color '#fff'
    

The --ios-color argument defines the background color for the iOS icons.

Setting up

After enrolling to the Apple Developer program, the first step to distribute your Tauri app in the App Store is to register your app in the App Store Connect.

Note

The value provided in the Bundle ID field must match the identifier defined in tauri.conf.json > identifier.

Build and upload

The Tauri CLI can package your app for macOS and iOS. Running on a macOS machine is a requirement.

Tauri derives the CFBundleVersion from the value defined in [tauri.conf.json > version]. You can set a custom bundle version in the [tauri.conf.json > bundle > iOS > bundleVersion] or [tauri.conf.json > bundle > macOS > bundleVersion] configuration if you need a different bundle version scheme e.g. sequential codes:

tauri.conf.json

{
  "bundle": {
    "iOS": {
      +"bundleVersion": "100"
    }
  }
}

Caution

Code signing is required. See the documentation for macOS and iOS.

Note that Tauri leverages Xcode for the iOS app so you can use Xcode to archive and distribute for iOS instead of the Tauri CLI. To open the iOS project in Xcode for building you must run the following command:

  • npm

    npm run tauri ios build -- --open
    
  • yarn

    yarn tauri ios build --open
    
  • pnpm

    pnpm tauri ios build --open
    
  • deno

    deno task tauri ios build --open
    
  • bun

    bun tauri ios build --open
    
  • cargo

    cargo tauri ios build --open
    

macOS

To upload your app to the App Store, first you must ensure all required configuration options are set so you can package the App Bundle, create a signed .pkg file and upload it.

The following sections will guide you through the process.

Setup

Your app must include some configurations to be accepted by the App Store verification system.

Tip

The following sections guides you through configuring your app for App Store submissions.

To apply the following config changes only when building for App Store, you can create a separate Tauri configuration file:

"src-tauri/tauri.appstore.conf.json

{
  "bundle": {
    "macOS": {
      "entitlements": "./Entitlements.plist",
      "files": {
        "embedded.provisionprofile": "path/to/profile-name.provisionprofile"
      }
    }
  }
}

Then merge that config file with the main one when bundling your Tauri app for App Store:

  • npm

    npm run tauri build -- --no-bundle
    npm run tauri bundle -- --bundles app --target universal-apple-darwin --config src-tauri/tauri.appstore.conf.json
    
  • yarn

    yarn tauri build --no-bundle
    yarn tauri bundle --bundles app --target universal-apple-darwin --config src-tauri/tauri.appstore.conf.json
    
  • pnpm

    pnpm tauri build --no-bundle
    pnpm tauri bundle --bundles app --target universal-apple-darwin --config src-tauri/tauri.appstore.conf.json
    
  • deno

    deno task tauri build --no-bundle
    deno task tauri bundle --bundles app --target universal-apple-darwin --config src-tauri/tauri.appstore.conf.json
    
  • bun

    bun tauri build --no-bundle
    bun tauri bundle --bundles app --target universal-apple-darwin --config src-tauri/tauri.appstore.conf.json
    
  • cargo

    cargo tauri build --no-bundle
    cargo tauri bundle --bundles app --target universal-apple-darwin --config src-tauri/tauri.appstore.conf.json
    

This is particularly useful when setting up your CI/CD to upload your app to the App Store while not requiring the provision profile locally or when compiling the app for distribution outside the App Store.

  • Category

Your app must define its tauri.conf.json > bundle > category to be displayed in the App Store:

tauri.conf.json

{
  "bundle": {
    +"category": "Utility"
  }
}
  • Provisioning profile

You must also create a provisioning profile for your app to be accepted by Apple.

In the Identifiers page, create a new App ID and make sure its “Bundle ID” value matches the identifier set in tauri.conf.json > identifier.

Navigate to the Profiles page to create a new provisioning profile. For App Store macOS distribution, it must be a “Mac App Store Connect” profile. Select the appropriate App ID and link the certificate you are using for code signing.

After creating the provisioning profile, download it and save it to a known location and configure Tauri to include it in your app bundle:

tauri.conf.json

{
  "bundle": {
    "macOS": {
      +"files": {
        +"embedded.provisionprofile": "path/to/profile-name.provisionprofile"
+      }
    }
  }
}
  • Info.plist

Your app must comply with encryption export regulations. See the official documentation for more information.

Create a Info.plist file in the src-tauri folder:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>ITSAppUsesNonExemptEncryption</key>
  <false/> # or `true` if your app uses encryption
</dict>
</plist>
  • Entitlements

Your app must include the App Sandbox capability to be distributed in the App Store. Additionally, you must also set your App ID and Team ID in the code signing entitlements.

Create a Entitlements.plist file in the src-tauri folder:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.application-identifier</key>
    <string>$TEAM_ID.$IDENTIFIER</string>
    <key>com.apple.developer.team-identifier</key>
    <string>$TEAM_ID</string>
</dict>
</plist>

Note that you must replace $IDENTIFIER with the tauri.conf.json > identifier value and $TEAM_ID with your Apple Developer team ID, which can be found in the App ID Prefix section in the Identifier you created for the provisioning profile.

And reference that file in the macOS bundle configuration tauri.conf.json > bundle > macOS > entitlements:

tauri.conf.json

{
  "bundle": {
    "macOS": {
      +"entitlements": "./Entitlements.plist"
    }
  }
}

You now must build your application with code signing enabled for the entitlements to apply.

Make sure your app works when running in an App Sandbox context.

Build

You must upload your macOS application as a .pkg file to the App Store. Run the following command to package your app as a macOS App Bundle (.app extension):

tauri build --bundles app --target universal-apple-darwin

Note

The above command creates an Universal App Binary application, supporting both Apple Silicon and Intel processors.

If you prefer to only support Apple Silicon instead, you must change tauri.conf.json > bundle > macOS > minimumSystemVersion to 12.0:

tauri.conf.json

{
  "bundle": {
    "macOS": {
      +"minimumSystemVersion": "12.0"
    }
  }
}

And change the CLI command and output path based on the Mac system you are running:

  • if your build system uses an Apple Silicon chip, remove the --target universal-apple-darwin arguments and use target/release instead of target/universal-apple-darwin/release in the paths referenced below.

  • if your build system uses an Intel chip:

    • install the Rust Apple Silicon target:

      rustup target add aarch64-apple-darwin
      
    • change the universal-apple-darwin argument to aarch64-apple-darwin and use target/aarch64-apple-darwin/release instead of target/universal-apple-darwin/release in the paths referenced below.

See the App Bundle distribution guide for more information on configuration options.

To generate a signed .pkg from your app bundle, run the following command:

xcrun productbuild --sign "<certificate signing identity>" --component "target/universal-apple-darwin/release/bundle/macos/$APPNAME.app" /Applications "$APPNAME.pkg"

Note that you must replace $APPNAME with your app name.

Note

You must sign the PKG with a Mac Installer Distribution signing certificate.

Upload

Now you can use the altool CLI to upload your app PKG to the App Store:

xcrun altool --upload-app --type macos --file "$APPNAME.pkg" --apiKey $APPLE_API_KEY_ID --apiIssuer $APPLE_API_ISSUER

Note that altool requires an App Store Connect API key to upload your app. See the authentication section for more information.

Your app will then be validated by Apple and available in TestFlight if approved.

iOS

To build your iOS app, run the tauri ios build command:

  • npm

    npm run tauri ios build -- --export-method app-store-connect
    
  • yarn

    yarn tauri ios build --export-method app-store-connect
    
  • pnpm

    pnpm tauri ios build --export-method app-store-connect
    
  • deno

    deno task tauri ios build --export-method app-store-connect
    
  • bun

    bun tauri ios build --export-method app-store-connect
    
  • cargo

    cargo tauri ios build --export-method app-store-connect
    

The generated IPA file can be found in src-tauri/gen/apple/build/arm64/$APPNAME.ipa.

Note that you must replace $APPNAME with your app name.

Now you can use the altool CLI to upload your iOS app to the App Store:

xcrun altool --upload-app --type ios --file "src-tauri/gen/apple/build/arm64/$APPNAME.ipa" --apiKey $APPLE_API_KEY_ID --apiIssuer $APPLE_API_ISSUER

Note that altool requires an App Store Connect API key to upload your app. See the authentication section for more information.

Your app will then be validated by Apple and available in TestFlight if approved.

Authentication

The iOS and macOS apps are uploaded using altool, which uses an App Store Connect API key to authenticate.

To create a new API key, open the App Store Connects Users and Access page, select the Integrations > Individual Keys tab, click on the Add button and select a name and the Developer access. The APPLE_API_ISSUER (Issuer ID) is presented above the keys table, and the APPLE_API_KEY_ID is the value on the Key ID column on that table. You also need to download the private key, which can only be done once and is only visible after a page reload (the button is shown on the table row for the newly created key). The private key file path must be saved as AuthKey\_<APPLE_API_KEY_ID>.p8 in one of these directories:<current-working-directory>/private_keys, ~/private_keys, ~/.private_keysor~/.appstoreconnect/private_keys.

AppImage

AppImage is a distribution format that does not rely on the system installed packages and instead bundles all dependencies and files needed by the application. For this reason, the output file is larger but easier to distribute since it is supported on many Linux distributions and can be executed without installation. The user just needs to make the file executable (chmod a+x MyProject.AppImage) and can then run it (./MyProject.AppImage).

AppImages are convenient, simplifying the distribution process if you cannot make a package targeting the distributions package manager. Still, you should carefully use it as the file size grows from the 2-6 MB range to 70+ MB.

Note

GUI apps on macOS and Linux do not inherit the $PATH from your shell dotfiles (.bashrc, .bash_profile, .zshrc, etc). Check out Tauris fix-path-env-rs crate to fix this issue.

Limitations

Core libraries such as glibc frequently break compatibility with older systems. For this reason, you must build your Tauri application using the oldest base system you intend to support that also provides Tauri v2s required WebKitGTK 4.1 packages. Ubuntu 22.04 and Debian 12 are suitable baseline examples because they provide libwebkit2gtk-4.1-dev from their standard package repositories. Building on a newer base system can raise the minimum glibc version required by your app, so when running on an older system, you may face a runtime error like /usr/lib/libc.so.6: version 'GLIBC_2.33' not found. We recommend using a Docker container or GitHub Actions to build your Tauri application for Linux.

See the issues tauri-apps/tauri#1355 and rust-lang/rust#57497, in addition to the AppImage guide for more information.

Multimedia support via GStreamer

If your app plays audio/video you need to enable tauri.conf.json > bundle > linux > appimage > bundleMediaFramework. This will increase the size of the AppImage bundle to include additional gstreamer files needed for media playback. This flag is currently only fully supported on Ubuntu build systems. Make sure that your build system has all the plugins your app may need at runtime.

Caution

GStreamer plugins in the ugly package are licensed in a way that may make it hard to distribute them as part of your app.

Custom Files

To include custom files in the AppImage that you do not want to include via Tauris resources feature, you can provide a list of files or folders in tauri.conf.json > bundle > linux > appimage > files. The configuration object maps the path in the AppImage to the path to the file on your filesystem, relative to the tauri.conf.json file. Heres an example configuration:

tauri.conf.json

{
  "bundle": {
    "linux": {
      "appimage": {
        "files": {
          "/usr/share/README.md": "../README.md", // copies the ../README.md file to <appimage>/usr/share/README.md
          "/usr/assets": "../assets/" // copies the entire ../assets directory to <appimage>/usr/assets
        }
      }
    }
  }
}

Note

Note that the destination paths must currently begin with /usr/.

AppImages for ARM-based devices

August 2025 Update

Github has released publicly available ubuntu-22.04-arm and ubuntu-24.04-arm runners. You can use these to build your app with no changes, a typical build should take ~10 minutes.

linuxdeploy, the AppImage tooling Tauri uses, currently does not support cross-compiling ARM AppImages. This means ARM AppImages can only be built on ARM devices or emulators.

Check out our GitHub Action guide for an example workflow that leverages QEMU to build the app. Note that this is extremely slow and only recommended in public repositories where Build Minutes are free. In private repositories GitHubs ARM runners should be more cost-efficient and much easier to set up.

AUR

Publishing To The Arch User Repository

Setup

First go to https://aur.archlinux.org and make an account. Be sure to add the proper ssh keys. Next, clone an empty git repository using this command.

git clone https://aur.archlinux.org/your-repo-name

After completing the steps above, create a file with the name PKGBUILD. Once the file is created you can move onto the next step.

Writing a PKGBUILD file

PKGBUILD

pkgname=<pkgname>
pkgver=1.0.0
pkgrel=1
pkgdesc="Description of your app"
arch=('x86_64' 'aarch64')
url="https://github.com/<user>/<project>"
license=('MIT')
depends=('cairo' 'desktop-file-utils' 'gdk-pixbuf2' 'glib2' 'gtk3' 'hicolor-icon-theme' 'libsoup' 'pango' 'webkit2gtk-4.1')
options=('!strip' '!emptydirs')
install=${pkgname}.install
source_x86_64=("${url}/releases/download/v${pkgver}/appname_${pkgver}_amd64.deb")
source_aarch64=("${url}/releases/download/v${pkgver}/appname_${pkgver}_arm64.deb")
  • At the top of the file, define your package name and assign it the variable pkgname.
  • Set your pkgver variable. Typically it is best to use this variable in the source variable to increase maintainability.
  • The pkgdesc variable on your aur repos page and tells vistors what your app does.
  • The arch variable controls what architectures can install your package.
  • The url variable, while not required, helps to make your package appear more professional.
  • The install variable specifies the name of .install script which will be run when the package is installed, removed or upgraded.
  • The depends variable includes a list of items that are required to make your app run. For any Tauri app you must include all of the dependencies shown above.
  • The source variable is required and defines the location where your upstream package is. You can make a source architecture specific by adding the architecture to the end of the variable name.

Generating .SRCINFO

In order to push your repo to the aur you must generate an .SRCINFO file. This can be done with this command.

makepkg --printsrcinfo > .SRCINFO

Testing

Testing the app is extremely simple. All you have to do is run makepkg within the same directory as the PKGBUILD file and see if it works

Publishing

Finally, after the testing phase is over, you can publish the application to AUR (Arch User Repository) with these commands.

git add .


git commit -m "Initial Commit"


git push

If all goes well, your repository should now appear on the AUR website.

Examples

Extracting From A Debian Package

PKGBUILD

# Maintainer:
# Contributor:
pkgname=<pkgname>
pkgver=1.0.0
pkgrel=1
pkgdesc="Description of your app"
arch=('x86_64' 'aarch64')
url="https://github.com/<user>/<project>"
license=('MIT')
depends=('cairo' 'desktop-file-utils' 'gdk-pixbuf2' 'glib2' 'gtk3' 'hicolor-icon-theme' 'libsoup' 'pango' 'webkit2gtk-4.1')
options=('!strip' '!debug')
install=${pkgname}.install
source_x86_64=("${url}/releases/download/v${pkgver}/appname_${pkgver}_amd64.deb")
source_aarch64=("${url}/releases/download/v${pkgver}/appname_${pkgver}_arm64.deb")
sha256sums_x86_64=('ca85f11732765bed78f93f55397b4b4cbb76685088553dad612c5062e3ec651f')
sha256sums_aarch64=('ed2dc3169d34d91188fb55d39867713856dd02a2360ffe0661cb2e19bd701c3c')
package() {
  # Extract package data
  tar -xvf data.tar.gz -C "${pkgdir}"


}

my-tauri-app.install

post_install() {
  gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
  update-desktop-database -q
}


post_upgrade() {
  post_install
}


post_remove() {
  gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
  update-desktop-database -q
}

Building from source

PKGBUILD

# Maintainer:
pkgname=<pkgname>-git
pkgver=<pkgver>
pkgrel=1
pkgdesc="Description of your app"
arch=('x86_64' 'aarch64')
url="https://github.com/<user>/<project>"
license=('MIT')
depends=('cairo' 'desktop-file-utils' 'gdk-pixbuf2' 'glib2' 'gtk3' 'hicolor-icon-theme' 'libsoup' 'pango' 'webkit2gtk-4.1')
makedepends=('git' 'openssl' 'appmenu-gtk-module' 'libappindicator-gtk3' 'librsvg' 'cargo' 'pnpm' 'nodejs')
provides=('<pkgname>')
conflicts=('<binname>' '<pkgname>')
source=("git+${url}.git")
sha256sums=('SKIP')


pkgver() {
  cd <project>
  ( set -o pipefail
    git describe --long --abbrev=7 2>/dev/null | sed 's/\([^-]*-g\)/r\1/;s/-/./g' ||
    printf "r%s.%s" "$(git rev-list --count HEAD)" "$(git rev-parse --short=7 HEAD)"
  )
}


prepare() {
  cd <project>
  pnpm install
}


build() {
  cd <project>
  pnpm tauri build -b deb
}


package() {
  cp -a <project>/src-tauri/target/release/bundle/deb/<project>_${pkgver}_*/data/* "${pkgdir}"
}

Distributing with CrabNebula Cloud

CrabNebula is an official Tauri partner providing services and tooling for Tauri applications. The CrabNebula Cloud is a platform for application distribution that seamlessly integrates with the Tauri updater.

The Cloud offers a Content Delivery Network (CDN) that is capable of shipping your application installers and updates globally while being cost effective and exposing download metrics.

With the CrabNebula Cloud service it is simple to implement multiple release channels, download buttons for your application website and more.

Setting up your Tauri app to use the Cloud is easy: all you need to do is to sign in to the Cloud website using your GitHub account, create your organization and application and install its CLI to create a release and upload the Tauri bundles. Additionally, a GitHub Action is provided to simplify the process of using the CLI on GitHub workflows.

For more information, see the CrabNebula Cloud documentation.

Debian

The stock Debian package generated by the Tauri bundler has everything you need to ship your application to Debian-based Linux distributions, defining your applications icons, generating a Desktop file, and specifying the dependencies libwebkit2gtk-4.1-0 and libgtk-3-0, along with libappindicator3-1 if your app uses the system tray.

Note

GUI apps on macOS and Linux do not inherit the $PATH from your shell dotfiles (.bashrc, .bash_profile, .zshrc, etc). Check out Tauris fix-path-env-rs crate to fix this issue.

Limitations

Core libraries such as glibc frequently break compatibility with older systems. For this reason, you must build your Tauri application using the oldest base system you intend to support that also provides Tauri v2s required WebKitGTK 4.1 packages. Ubuntu 22.04 and Debian 12 are suitable baseline examples because they provide libwebkit2gtk-4.1-dev from their standard package repositories. Building on a newer base system can raise the minimum glibc version required by your app, so when running on an older system, you may face a runtime error like /usr/lib/libc.so.6: version 'GLIBC_2.33' not found. We recommend using a Docker container or GitHub Actions to build your Tauri application for Linux.

See the issues tauri-apps/tauri#1355 and rust-lang/rust#57497, in addition to the AppImage guide for more information.

Custom Files

Tauri exposes a few configurations for the Debian package in case you need more control.

If your app depends on additional system dependencies you can specify them in tauri.conf.json > bundle > linux > deb.

To include custom files in the Debian package, you can provide a list of files or folders in tauri.conf.json > bundle > linux > deb > files. The configuration object maps the path in the Debian package to the path to the file on your filesystem, relative to the tauri.conf.json file. Heres an example configuration:

{
  "bundle": {
    "linux": {
      "deb": {
        "files": {
          "/usr/share/README.md": "../README.md", // copies the README.md file to /usr/share/README.md
          "/usr/share/assets": "../assets/" // copies the entire assets directory to /usr/share/assets
        }
      }
    }
  }
}

Cross-Compiling for ARM-based Devices

This guide covers manual compilation. Check out our GitHub Action guide for an example workflow that leverages QEMU to build the app. This will be much slower but will also be able to build AppImages.

Manual compilation is suitable when you dont need to compile your application frequently and prefer a one-time setup. The following steps expect you to use a Linux distribution based on Debian/Ubuntu.

  1. Install Rust targets for your desired architecture

    • For ARMv7 (32-bit): rustup target add armv7-unknown-linux-gnueabihf
    • For ARMv8 (ARM64, 64-bit): rustup target add aarch64-unknown-linux-gnu
  2. Install the corresponding linker for your chosen architecture

    • For ARMv7: sudo apt install gcc-arm-linux-gnueabihf
    • For ARMv8 (ARM64): sudo apt install gcc-aarch64-linux-gnu
  3. Open or create the file <project-root>/.cargo/config.toml and add the following configurations accordingly

    [target.armv7-unknown-linux-gnueabihf]
    linker = "arm-linux-gnueabihf-gcc"
    
    
    [target.aarch64-unknown-linux-gnu]
    linker = "aarch64-linux-gnu-gcc"
    
  4. Enable the respective architecture in the package manager

    • For ARMv7: sudo dpkg --add-architecture armhf
    • For ARMv8 (ARM64): sudo dpkg --add-architecture arm64
  5. Adjusting Package Sources

    On Debian, this step should not be necessary, but on other distributions, you might need to edit /etc/apt/sources.list to include the ARM architecture variant. For example on Ubuntu 22.04 add these lines to the bottom of the file (Remember to replace jammy with the codename of your Ubuntu version):

    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy main restricted
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy universe
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates universe
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy multiverse
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates multiverse
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-backports main restricted universe multiverse
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security universe
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security multiverse
    

    Then, to prevent issues with the main packages, you have to add the correct main architecture to all other lines the file contained beforehand. For standard 64-bit systems you need to add [arch=amd64], the full file on Ubuntu 22.04 then looks similar to this:

    Show solution

    # See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
    # newer versions of the distribution.
    deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy main restricted
    # deb-src http://archive.ubuntu.com/ubuntu/ jammy main restricted
    
    
    ## Major bug fix updates produced after the final release of the
    ## distribution.
    deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted
    # deb-src http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted
    
    
    ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
    ## team. Also, please note that software in universe WILL NOT receive any
    ## review or updates from the Ubuntu security team.
    deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy universe
    # deb-src http://archive.ubuntu.com/ubuntu/ jammy universe
    deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-updates universe
    # deb-src http://archive.ubuntu.com/ubuntu/ jammy-updates universe
    
    
    ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
    ## team, and may not be under a free licence. Please satisfy yourself as to
    ## your rights to use the software. Also, please note that software in
    ## multiverse WILL NOT receive any review or updates from the Ubuntu
    ## security team.
    deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy multiverse
    # deb-src http://archive.ubuntu.com/ubuntu/ jammy multiverse
    deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-updates multiverse
    
    
    ## N.B. software from this repository may not have been tested as
    ## extensively as that contained in the main release, although it includes
    ## newer versions of some applications which may provide useful features.
    ## Also, please note that software in backports WILL NOT receive any review
    ## or updates from the Ubuntu security team.
    deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse
    # deb-src http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse
    
    
    deb [arch=amd64] http://security.ubuntu.com/ubuntu/ jammy-security main restricted
    # deb-src http://security.ubuntu.com/ubuntu/ jammy-security main restricted
    deb [arch=amd64] http://security.ubuntu.com/ubuntu/ jammy-security universe
    # deb-src http://security.ubuntu.com/ubuntu/ jammy-security universe
    deb [arch=amd64] http://security.ubuntu.com/ubuntu/ jammy-security multiverse
    # deb-src http://security.ubuntu.com/ubuntu/ jammy-security multiverse
    
    
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy main restricted
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy universe
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates universe
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy multiverse
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates multiverse
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-backports main restricted universe multiverse
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security universe
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security multiverse
    
  6. Update the package information: sudo apt-get update && sudo apt-get upgrade -y

  7. Install the required webkitgtk library for your chosen architecture

    • For ARMv7: sudo apt install libwebkit2gtk-4.1-dev:armhf
    • For ARMv8 (ARM64): sudo apt install libwebkit2gtk-4.1-dev:arm64
  8. Install OpenSSL or use a vendored version

    This is not always required so you may want to proceed first and check if you see errors like Failed to find OpenSSL development headers.

    • Either install the development headers system-wide:

      • For ARMv7: sudo apt install libssl-dev:armhf
      • For ARMv8 (ARM64): sudo apt install libssl-dev:arm64
    • Or enable the vendor feature for the OpenSSL Rust crate which will affect all other Rust dependencies using the same minor version. You can do so by adding this to the dependencies section in your Cargo.toml file:

    openssl-sys = {version = "0.9", features = ["vendored"]}
    
  9. Set the PKG_CONFIG_SYSROOT_DIR to the appropriate directory based on your chosen architecture

    • For ARMv7: export PKG_CONFIG_SYSROOT_DIR=/usr/arm-linux-gnueabihf/
    • For ARMv8 (ARM64): export PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu/
  10. Build the app for your desired ARM version

    • For ARMv7: cargo tauri build target armv7-unknown-linux-gnueabihf
    • For ARMv8 (ARM64): cargo tauri build target aarch64-unknown-linux-gnu

    Choose the appropriate set of instructions based on whether you want to cross-compile your Tauri application for ARMv7 or ARMv8 (ARM64). Please note that the specific steps may vary depending on your Linux distribution and setup.

DMG

The DMG (Apple Disk Image) format is a common macOS installer file that wraps your App Bundle in a user-friendly installation window.

The installer window includes your app icon and the Applications folder icon, where the user is expected to drag the app icon to the Applications folder icon to install it. It is the most common installation method for macOS applications distributed outside the App Store.

This guide only covers details for distributing apps outside the App Store using the DMG format. See the App Bundle distribution guide for more information on macOS distribution options and configurations. To distribute your macOS app in the App Store, see the App Store distribution guide.

To create an Apple Disk Image for your app you can use the Tauri CLI and run the tauri build command in a Mac computer:

  • npm

    npm run tauri build -- --bundles dmg
    
  • yarn

    yarn tauri build --bundles dmg
    
  • pnpm

    pnpm tauri build --bundles dmg
    
  • deno

    deno task tauri build --bundles dmg
    
  • bun

    bun tauri build --bundles dmg
    
  • cargo

    cargo tauri build --bundles dmg
    

Standard DMG windowStandard DMG window

Note

GUI apps on macOS and Linux do not inherit the $PATH from your shell dotfiles (.bashrc, .bash_profile, .zshrc, etc). Check out Tauris fix-path-env-rs crate to fix this issue.

Window background

You can set a custom background image to the DMG installation window with the [tauri.conf.json > bundle > macOS > dmg > background] configuration option:

tauri.conf.json

{
  "bundle": {
    "macOS": {
      +"dmg": {
        +"background": "./images/"
+      }
    }
  }
}

For instance your DMG background image can include an arrow to indicate to the user that it must drag the app icon to the Applications folder.

Window size and position

The default window size is 660x400. If you need a different size to fit your custom background image, set the [tauri.conf.json > bundle > macOS > dmg > windowSize] configuration:

tauri.conf.json

{
  "bundle": {
    "macOS": {
      "dmg": {
        +"windowSize": {
          +"width": 800,
          +"height": 600
+        }
      }
    }
  }
}

Additionally you can set the initial window position via [tauri.conf.json > bundle > macOS > dmg > windowPosition]:

tauri.conf.json

{
  "bundle": {
    "macOS": {
      "dmg": {
        +"windowPosition": {
          +"x": 400,
          +"y": 400
+        }
      }
    }
  }
}

Icon position

You can change the app and Applications folder icon position with the appPosition and applicationFolderPosition configuration values respectively:

tauri.conf.json

{
  "bundle": {
    "macOS": {
      "dmg": {
        +"appPosition": {
          +"x": 180,
          +"y": 220
+        },
        +"applicationFolderPosition": {
          +"x": 480,
          +"y": 220
+        }
      }
    }
  }
}

Caution

Due to a known issue, icon sizes and positions are not applied when creating DMGs on CI/CD platforms. See tauri-apps/tauri#1731 for more information.

Flathub

  • Open Source

    1. Get your required tools.
    git submodule add https://github.com/flatpak/flatpak-builder-tools.git
    cd flatpak-builder-tools/node/flatpak_node_generator
    pipx install . # Change this to your prefered installation method
    
    1. Generate your sources
    • Yarn

      # Generate your Node Sources
      flatpak-node-generator --no-requests-cache -o node-sources.json yarn /path/to/your/lock/file/yarn.lock
      
      
      # Generate your cargo sources
      
      
      python3 flatpak-builder-tools/cargo/flatpak-cargo-generator.py -o cargo-sources.json src-tauri/Cargo.lock
      
    • NPM

      # Generate your Node Sources
      flatpak-node-generator --no-requests-cache -o node-sources.json npm /path/to/your/lock/file/package-lock.json
      
      
      # Generate your cargo sources
      python3 flatpak-builder-tools/cargo/flatpak-cargo-generator.py -o cargo-sources.json src-tauri/Cargo.lock
      
    1. Create your metainfo Make sure to replace the relevant fields.
    <?xml version="1.0" encoding="UTF-8"?>
    <component type="desktop-application">
        <id>org.your.id</id>
        <launchable type="desktop-id">org.your.id.desktop</launchable>
        <name>Your Apps Name</name>
        <developer id="io.github.roseblume.rosemusic">
            <name>Your Name</name>
        </developer>
        <content_rating type="oars-1.1">
        </content_rating>
        <keywords>
            <keyword>Keyword1</keyword>
            <keyword>Keyword2</keyword>
        </keywords>
        <branding>
            <color type="primary" scheme_preference="light">#00ffff</color>
            <color type="primary" scheme_preference="dark">#0c9aff</color>
        </branding>
        <recommends>
            <display_length compare="ge">360</display_length>
        </recommends>
        <summary>Your Summary</summary>
    
    
        <metadata_license>MIT</metadata_license>
        <project_license>MIT</project_license>
        <url type="homepage">https://github.com/Your-Username/Your-Repo</url>
    
    
        <supports>
            <control>pointing</control>
            <control>keyboard</control>
            <control>touch</control>
        </supports>
    
    
        <description>
            <p>
                Your Description
            </p>
        </description>
        <screenshots>
            <screenshot type="default">
                <image>https://site.com/your-image.png</image>
                <caption>Your Caption</caption>
            </screenshot>
        </screenshots>
        <releases>
            <release version="1.0.0" date="2024-11-02" >
                <description>
                <ul>
                    <li>Updated UI</li>
                    <li>Added Electronic Genre</li>
                </ul>
                </description>
            </release>
        </releases>
        <update_contact>your-email@place.com</update_contact>
    
    
    </component>
    

    Your metadata is recommended to be included into your debian bundle although it is not required. This can be done by adjusting your bundle configuration like so.

    "linux": {
          "deb": {
            "files": {
              "/usr/share/metainfo/org.your.id.metainfo.xml": "relative/path/from/your/tauri.conf.json/to/your/org.your.id.metainfo.xml"
            }
          }
        }
    
    1. Create your manifest
    id: org.your.id
    
    
    runtime: org.gnome.Platform
    runtime-version: '47'
    sdk: org.gnome.Sdk
    
    
    command: tauri-app
    finish-args:
    
    
    - --socket=wayland # Permission needed to show the window
    - --socket=fallback-x11 # Permission needed to show the window on legacy windowing systems
    - --device=dri # OpenGL, not necessary for all projects
    - --share=ipc
      sdk-extensions:
    - org.freedesktop.Sdk.Extension.node20
    - org.freedesktop.Sdk.Extension.rust-stable
      build-options:
      append-path: /usr/lib/sdk/node20/bin:/usr/lib/sdk/rust-stable/bin
    
    
    modules:
    
    
    - name: your-command
      buildsystem: simple
      env:
      HOME: /run/build/your-module
      CARGO_HOME: /run/build/your-module/src-tauri
      XDG_CACHE_HOME: /run/build/your-module/flatpak-node/cache
      yarn_config_offline: 'true'
      yarn_config_cache: /run/build/your-module/flatpak-node/yarn-cache
      sources:
      - type: git
        url: https://github.com/Your-Github-Username/Your-Git-Repo.git
        tag: v1.2.2
      - cargo-sources.json
      - node-sources.json
        build-commands:
      - echo -e 'yarn-offline-mirror "/run/build/your-module/flatpak-node/yarn-mirror"\nyarn-offline-mirror-pruning true' > /run/build/your-module/.yarnrc
      - mkdir -p src-tauri/.cargo && echo -e '[source.crates-io]\nreplace-with = "vendored-sources"\n\n[source.vendored-sources]\ndirectory = "/run/build/your-module/cargo/vendor"' > src-tauri/.cargo/config.toml
      - yarn install --offline --immutable --immutable-cache --inline-builds
      - yarn run tauri build -- -b deb
      - ar -x src-tauri/target/release/bundle/deb/\*.deb
      - tar -xf src-tauri/target/release/bundle/deb/your-app/data.tar.gz
      - install -Dm755 src-tauri/target/release/bundle/deb/your-app/data/usr/bin/your-command /app/bin/your-command
      - install -Dm644 src-tauri/target/release/bundle/deb/your-app/data/usr/share/applications/your-app.desktop /app/share/applications/org.your.id.desktop
      - install -Dm644 src-tauri/target/release/bundle/deb/your-app/data/usr/share/icons/hicolor/128x128/apps/your-app.png /app/share/icons/hicolor/128x128/apps/your-app.png
      - install -Dm644 src-tauri/target/release/bundle/deb/your-app/data/usr/share/icons/hicolor/32x32/apps/your-app.png /app/share/icons/hicolor/32x32/apps/your-app.png
      - install -Dm644 src-tauri/target/release/bundle/deb/your-app/data/usr/share/icons/hicolor/256x256@2/apps/your-app.png /app/share/icons/hicolor/512x512/apps/your-app.png
      - install -Dm644 src-tauri/target/release/bundle/deb/your-app/data/usr/share/icons/hicolor/scalable/apps/your-app.svg /app/share/icons/hicolor/scalable/apps/your-app.svg
    
    
      - install -Dm644 src-tauri/target/release/bundle/deb/your-app/data/usr/share/metainfo/org.your.id /app/share/metainfo/org.your.id
    

    Submitting To Flathub

    1. Fork The Flathub Repository

    2. Clone the Fork

    git clone --branch=new-pr git@github.com:your_github_username/flathub.git
    

    3. Enter the repository

    cd flathub
    

    4. Create a new branch

    git checkout -b your_app_name
    

    5. Open a pull request against the new-pr branch on github

    6. Your app will now enter the review process in which you may be asked to make changes to your project.

  • Closed Source

    # Generate your Node Sources
    flatpak-node-generator --no-requests-cache -o node-sources.json yarn /path/to/your/lock/file/yarn.lock
    
    
    # Generate your cargo sources
    
    
    python3 flatpak-builder-tools/cargo/flatpak-cargo-generator.py -o cargo-sources.json src-tauri/Cargo.lock
    
  • Yarn

    # Generate your Node Sources
    flatpak-node-generator --no-requests-cache -o node-sources.json npm /path/to/your/lock/file/package-lock.json
    
    
    # Generate your cargo sources
    python3 flatpak-builder-tools/cargo/flatpak-cargo-generator.py -o cargo-sources.json src-tauri/Cargo.lock
    
  • NPM

    For detailed information on how Flatpak works, you can read Building your first Flatpak

    This guide assumes you want to distribute your Flatpak via Flathub, the most commonly used platform for Flatpak distribution. If you plan on using other platforms, please consult their documentation instead.

    Prerequisites

    To test your app inside the Flatpak runtime you can build the Flatpak locally first before uploading your app to Flathub. This can also be helpful if you want to quickly share development builds.

    1. Install flatpak and flatpak-builder

    To build Flatpaks locally you need the flatpak and flatpak-builder tools. For example on Ubuntu you can run this command:

    • Debian

      sudo apt install flatpak flatpak-builder
      
    • Arch

      sudo pacman -S --needed flatpak flatpak-builder
      
    • Fedora

      sudo dnf install flatpak flatpak-builder
      
    • Gentoo

      sudo emerge --ask \
      sys-apps/flatpak \
      dev-util/flatpak-builder
      

    2. Install the Flatpak Runtime

    flatpak install flathub org.gnome.Platform//46 org.gnome.Sdk//46
    

    3. Build the .deb of your tauri-app

    4. Create an AppStream MetaInfo file

    5. Create the flatpak manifest

    flatpak-builder.yaml

    id: <identifier>
    
    
    runtime: org.gnome.Platform
    runtime-version: '47'
    sdk: org.gnome.Sdk
    
    
    command: <main_binary_name>
    finish-args:
      - --socket=wayland # Permission needed to show the window
      - --socket=fallback-x11 # Permission needed to show the window
      - --device=dri # OpenGL, not necessary for all projects
      - --share=ipc
      - --talk-name=org.kde.StatusNotifierWatcher # Optional: needed only if your app uses the tray icon
      - --filesystem=xdg-run/tray-icon:create # Optional: needed only if your app uses the tray icon - see an alternative way below
      # - --env=WEBKIT_DISABLE_COMPOSITING_MODE=1 # Optional: may solve some issues with black webviews on Wayland
    
    
    modules:
      - name: binary
        buildsystem: simple
    
    
        sources:
          # A reference to the previously generated flatpak metainfo file
          - type: file
            path: flatpak.metainfo.xml
          # If you use GitHub releases, you can target an existing remote file
          - type: file
            url: https://github.com/your_username/your_repository/releases/download/v1.0.1/yourapp_1.0.1_amd64.deb
            sha256: 08305b5521e2cf0622e084f2b8f7f31f8a989fc7f407a7050fa3649facd61469 # This is required if you are using a remote source
            only-arches: [x86_64] # This source is only used on x86_64 Computers
          # You can also use a local file for testing
          # - type: file
          #   path: yourapp_1.0.1_amd64.deb
        build-commands:
          - set -e
    
    
          # Extract the deb package
          - mkdir deb-extract
          - ar -x *.deb --output deb-extract
          - tar -C deb-extract -xf deb-extract/data.tar.gz
    
    
          # Copy binary
          - 'install -Dm755 deb-extract/usr/bin/<executable_name> /app/bin/<executable_name>'
    
    
          # If you bundle files with additional resources, you should copy them:
          - mkdir -p /app/lib/<product_name>
          - cp -r deb-extract/usr/lib/<product_name>/. /app/lib/<product_name>
          - find /app/lib/<product_name> -type f -exec chmod 644 {} \;
    
    
          # Copy desktop file + ensure the right icon is set
          - sed -i 's/^Icon=.*/Icon=<identifier>/' deb-extract/usr/share/applications/<product_name>.desktop
          - install -Dm644 deb-extract/usr/share/applications/<product_name>.desktop /app/share/applications/<identifier>.desktop
    
    
          # Copy icons
          - install -Dm644 deb-extract/usr/share/icons/hicolor/128x128/apps/<main_binary_name>.png /app/share/icons/hicolor/128x128/apps/<identifier>.png
          - install -Dm644 deb-extract/usr/share/icons/hicolor/32x32/apps/<main_binary_name>.png /app/share/icons/hicolor/32x32/apps/<identifier>.png
          - install -Dm644 deb-extract/usr/share/icons/hicolor/256x256@2/apps/<main_binary_name>.png /app/share/icons/hicolor/256x256@2/apps/<identifier>.png
          - install -Dm644 flatpak.metainfo.xml /app/share/metainfo/<identifier>.metainfo.xml
    

    The Gnome 46 runtime includes all dependencies of the standard Tauri app with their correct versions.

    Using tray-icon without changing the Flatpak manifest

    If you prefer not opening access from your app to $XDG_RUNTIME_DIR (where tray-icon is saved on linux), you can change the path tauri saves the tray image:

    TrayIconBuilder::new()
      .icon(app.default_window_icon().unwrap().clone())
      .temp_dir_path(app.path().app_cache_dir().unwrap()) // will save to the cache folder ($XDG_CACHE_HOME) where the app already has permission
      .build()
      .unwrap();
    

    5. Install, and Test the app

    # Install the flatpak
    flatpak-builder --force-clean --user --disable-cache --repo flatpak-repo flatpak flatpak-builder.yaml
    
    
    # Run it
    flatpak run <your flatpak id> # or via your desktop environment
    
    
    # Update it
    flatpak -y --user update <your flatpak id>
    

    Adding additional libraries

    If your final binary requires more libraries than the default tauri app, you need to add them in your flatpak manifest. There are two ways to do this. For fast local development, it may work to simply include the already built library file (.so) from your local system. However, this is not recommended for the final build of the flatpak, as your local library file is not built for the flatpak runtime environment. This can introduce various bugs that can be very hard to find. Therefore, it is recommended to build the library your program depends on from source inside the flatpak as a build step.

    Submitting to flathub

    1. Fork The Flathub Repository

    2. Clone the Fork

    git clone --branch=new-pr git@github.com:your_github_username/flathub.git
    

    3. Enter the repository

    cd flathub
    

    4. Create a new branch

    git checkout -b your_app_name
    

    5. Add your apps manifest to the branch. Commit your changes, and then push them.

    6. Open a pull request against the new-pr branch on github

    7. Your app will now enter the review process in which you may be asked to make changes to your project.

    When your pull request is approved then you will receive an invitation to edit your apps repository. From here on you can update your app continuously.

    You can read more about this in the flatpak documentation

  • Debian

    sudo apt install flatpak flatpak-builder
    
  • Arch

    sudo pacman -S --needed flatpak flatpak-builder
    
  • Fedora

    sudo dnf install flatpak flatpak-builder
    
  • Gentoo

    sudo emerge --ask \
    sys-apps/flatpak \
    dev-util/flatpak-builder
    

Google Play

Google Play is the Android app distribution service maintained by Google.

This guide covers the requirements for publishing your Android app on Google Play.

Note

Tauri uses an Android Studio project under the hood, so any official practice for building and publishing Android apps also apply to your app. See the official documentation for more information.

Requirements

To distribute Android apps in the Play Store you must create a Play Console developer account.

Additionally, you must setup code signing.

See the release checklist for more information.

Changing App Icon

After running tauri android init to setup the Android Studio project, you can use the tauri icon command to update the app icons.

  • npm

    npm run tauri icon /path/to/app-icon.png
    
  • yarn

    yarn tauri icon /path/to/app-icon.png
    
  • pnpm

    pnpm tauri icon /path/to/app-icon.png
    
  • deno

    deno task tauri icon /path/to/app-icon.png
    
  • bun

    bun tauri icon /path/to/app-icon.png
    
  • cargo

    cargo tauri icon /path/to/app-icon.png
    

Setting up

Once youve created a Play Console developer account, you need to register your app on the Google Play Console website. It will guide you through all the required forms and setup tasks.

Build

You can build an Android App Bundle (AAB) to upload to Google Play by running the following command:

  • npm

    npm run tauri android build -- --aab
    
  • yarn

    yarn tauri android build --aab
    
  • pnpm

    pnpm tauri android build --aab
    
  • deno

    deno task tauri android build --aab
    
  • bun

    bun tauri android build --aab
    
  • cargo

    cargo tauri android build --aab
    

Tauri derives the version code from the value defined in tauri.conf.json > version (versionCode = major*1000000 + minor*1000 + patch). You can set a custom version code in the [tauri.conf.json > bundle > android > versionCode] configuration if you need a different version code scheme e.g. sequential codes:

tauri.conf.json

{
  "bundle": {
    "android": {
      +"versionCode": 100
    }
  }
}

Build APKs

The AAB format is the recommended bundle file to upload to Google Play, but it is also possible to generate APKs that can be used for testing or distribution outside the store. To compile APKs for your app you can use the --apk argument:

  • npm

    npm run tauri android build -- --apk
    
  • yarn

    yarn tauri android build --apk
    
  • pnpm

    pnpm tauri android build --apk
    
  • deno

    deno task tauri android build --apk
    
  • bun

    bun tauri android build --apk
    
  • cargo

    cargo tauri android build --apk
    

Architecture selection

By default Tauri builds your app for all supported architectures (aarch64, armv7, i686 and x86_64). To only compile for a subset of targets, you can use the --target argument:

  • npm

    npm run tauri android build -- --aab --target aarch64 --target armv7
    
  • yarn

    yarn tauri android build --aab --target aarch64 --target armv7
    
  • pnpm

    pnpm tauri android build --aab --target aarch64 --target armv7
    
  • deno

    deno task tauri android build --aab --target aarch64 --target armv7
    
  • bun

    bun tauri android build --aab --target aarch64 --target armv7
    
  • cargo

    cargo tauri android build --aab --target aarch64 --target armv7
    

Separate bundles per architecture

By default the generated AAB and APK is universal, containing all supported targets. To generate individual bundles per target, use the --split-per-abi argument.

Note

This is only useful for testing or distribution outside Google Play, as it reduces the file size but is less convenient to upload. Google Play handles the supported architectures for you.

  • npm

    npm run tauri android build -- --apk --split-per-abi
    
  • yarn

    yarn tauri android build --apk --split-per-abi
    
  • pnpm

    pnpm tauri android build --apk --split-per-abi
    
  • deno

    deno task tauri android build --apk --split-per-abi
    
  • bun

    bun tauri android build --apk --split-per-abi
    
  • cargo

    cargo tauri android build --apk --split-per-abi
    

Changing the minimum supported Android version

The minimum supported Android version for Tauri apps is Android 7.0 (codename Nougat, SDK 24).

There are some techniques to use newer Android APIs while still supporting older systems. See the Android documentation for more information.

If your app must execute on a newer Android version, you can configure [tauri.conf.json > bundle > android > minSdkVersion]:

tauri.conf.json

{
  "bundle": {
    "android": {
      +"minSdkVersion": 28
    }
  }
}

Upload

After building your app and generating the Android App Bundle file, which can be found in gen/android/app/build/outputs/bundle/universalRelease/app-universal-release.aab, you can now create a new release and upload it in the Google Play Console.

The first upload must be made manually in the website so it can verify your app signature and bundle identifier. Tauri currently does not offer a way to automate the process of creating Android releases, which must leverage the Google Play Developer API, but it is a work in progress.

macOS Application Bundle

An application bundle is the package format that is executed on macOS. It is a simple directory that includes everything your application requires for successful operation, including your app executable, resources, the Info.plist file and other files such as macOS frameworks.

To package your app as a macOS application bundle you can use the Tauri CLI and run the tauri build command in a Mac computer:

  • npm

    npm run tauri build -- --bundles app
    
  • yarn

    yarn tauri build --bundles app
    
  • pnpm

    pnpm tauri build --bundles app
    
  • deno

    deno task tauri build --bundles app
    
  • bun

    bun tauri build --bundles app
    
  • cargo

    cargo tauri build --bundles app
    

Note

GUI apps on macOS and Linux do not inherit the $PATH from your shell dotfiles (.bashrc, .bash_profile, .zshrc, etc). Check out Tauris fix-path-env-rs crate to fix this issue.

File structure

The macOS app bundle is a directory with the following structure:

├── <productName>.app
│   ├── Contents
│   │   ├── Info.plist
│   │   ├── ...additional files from [`tauri.conf.json > bundle > macOS > files`]
│   ├── MacOS
│   │   ├── <app-name> (app executable)
│   ├── Resources
│   │   ├── icon.icns (app icon)
│   │   ├── ...resources from [`tauri.conf.json > bundle > resources`]
│   ├── _CodeSignature (codesign information generated by Apple)
│   ├── Frameworks
│   ├── PlugIns
│   ├── SharedSupport

See the official documentation for more information.

Native configuration

The app bundle is configured by the Info.plist file, which includes key-value pairs with your app identity and configuration values read by macOS.

Tauri automatically configures the most important properties such as your app binary name, version. bundle identifier, minimum system version and more.

To extend the configuration file, create an Info.plist file in the src-tauri folder and include the key-pairs you desire:

src-tauri/Info.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>NSCameraUsageDescription</key>
  <string>Request camera access for WebRTC</string>
  <key>NSMicrophoneUsageDescription</key>
  <string>Request microphone access for WebRTC</string>
</dict>
</plist>

This Info.plist file is merged with the values generated by the Tauri CLI. Be careful when overwriting default values such as application version as they might conflict with other configuration values and introduce unexpected behavior.

See the official Info.plist documentation for more information.

Info.plist localization

The Info.plist file by itself only supports a single language, typically English. If you want to support multiple languages, you can create InfoPlist.strings files for each additional language. Each file belongs in its own language specific lproj directory in the Resources directory in the application bundle.

To bundle these files automatically you can leverage Tauris resources feature. To do that, create a file structure in your project following this pattern:

├── src-tauri
│   ├── tauri.conf.json
│   ├── infoplist
│   │   ├── de.lproj
│   │   │   ├── InfoPlist.strings
│   │   ├── fr.lproj
│   │   │   ├── InfoPlist.strings

While the infoplist directory name can be chosen freely, as long as you update it in the resources config below, the lproj directories must follow the <lang-code>.lproj naming and the string catalogue files must be named InfoPlist.strings (capital i and p). For most cases the language code should be a two letter code following BCP 47.

For the Info.plist example shown above, the de.lproj > InfoPlist.strings file could look like this:

de.lproj/InfoPlist.strings

NSCameraUsageDescription = "Kamera Zugriff wird benötigt für WebRTC Funktionalität";
NSMicrophoneUsageDescription = "Mikrofon Zugriff wird benötigt für WebRTC Funktionalität";

Lastly, make Tauri pick up these files by using the resources feature mentioned above:

src-tauri/tauri.conf.json

{
  "bundle": {
    "resources": {
      "infoplist/**": "./"
    }
  }
}

Entitlements

An entitlement is a special Apple configuration key-value pair that acts as a right or privilege that grants your app particular capabilities, such as act as the users default email client and using the App Sandbox feature.

Entitlements are applied when your application is signed. See the code signing documentation for more information.

To define the entitlements required by your application, you must create the entitlements file and configure Tauri to use it.

  1. Create a Entitlements.plist file in the src-tauri folder and configure the key-value pairs you app requires:

src-tauri/Entitlements.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
</dict>
</plist>
  1. Configure Tauri to use the Entitlements.plist file:

tauri.conf.json

{
  "bundle": {
    "macOS": {
      +"entitlements": "./Entitlements.plist"
    }
  }
}

See the official documentation for more information.

Minimum system version

By default your Tauri application supports macOS 10.13 and above. If you are using an API that requires a newer macOS system and want to enforce that requirement in your app bundle, you can configure the tauri.conf.json > bundle > macOS > minimumSystemVersion value:

tauri.conf.json

{
  "bundle": {
    "macOS": {
      +"minimumSystemVersion": "12.0"
    }
  }
}

Including macOS frameworks

If your application requires additional macOS frameworks to run, you can list them in the tauri.conf.json > bundle > macOS > frameworks configuration. The frameworks list can include either system or custom frameworks and dylib files.

tauri.conf.json

{
  "bundle": {
    "macOS": {
      +"frameworks": [
        +"CoreAudio",
        +"./libs/libmsodbcsql.18.dylib",
        +"./frameworks/MyApp.framework"
+      ]
    }
  }
}

Note

  • To reference a system framework you can just use its name (without the .framework extension) instead of absolute path
  • System frameworks must exist in either the $HOME/Library/Frameworks, /Library/Frameworks/, or /Network/Library/Frameworks/
  • To reference local frameworks and dylib files you must use the complete path to the framework, relative to the src-tauri directory

Adding custom files

You can use the tauri.conf.json > bundle > macOS > files configuration to add custom files to your application bundle, which maps the destination path to its source relative to the tauri.conf.json file. The files are added to the <product-name>.app/Contents folder.

tauri.conf.json

{
  "bundle": {
    "macOS": {
      +"files": {
        +"embedded.provisionprofile": "./profile-name.provisionprofile",
        +"SharedSupport/docs.md": "./docs/index.md"
+      }
    }
  }
}

In the above example, the profile-name.provisionprofile file is copied to <product-name>.app/Contents/embedded.provisionprofile and the docs/index.md file is copied to <product-name>.app/Contents/SharedSupport/docs.md.

Microsoft Store

Microsoft Store is the Windows app store operated by Microsoft.

This guide only covers details for distributing Windows Apps directly to the Microsoft Store. See the Windows Installer guide for more information on Windows installer distribution options and configurations.

Requirements

To publish apps on the Microsoft Store you must have a Microsoft account and enroll as a developer either as an individual or as a company.

Changing App Icon

The Tauri CLI can generate all icons your app needs, including Microsoft Store icons. Use the tauri icon command to generate app icons from a single PNG or SVG source:

  • npm

    npm run tauri icon /path/to/app-icon.png
    
  • yarn

    yarn tauri icon /path/to/app-icon.png
    
  • pnpm

    pnpm tauri icon /path/to/app-icon.png
    
  • deno

    deno task tauri icon /path/to/app-icon.png
    
  • bun

    bun tauri icon /path/to/app-icon.png
    
  • cargo

    cargo tauri icon /path/to/app-icon.png
    

Setting up

After you have enrolled as a developer with your Microsoft account you need to register your app in the Apps and Games page. Click New Product, select EXE or MSI app and reserve a unique name for your app.

Build and upload

Currently Tauri only generates EXE and MSI installers, so you must create a Microsoft Store application that only links to the unpacked application. The installer linked in the Microsoft Installer must be offline, handle auto-updates and be code signed.

See the official publish documentation for more information.

Offline Installer

The Windows installer distributed through the Microsoft Store must use the Offline Installer Webview2 installation option.

To only apply this installer configuration when bundling for Microsoft Store, you can define a separate Tauri configuration file:

"src-tauri/tauri.microsoftstore.conf.json

{
  "bundle": {
    "windows": {
      "webviewInstallMode": {
        "type": "offlineInstaller"
      }
    }
  }
}

Then merge that config file with the main one when bundling your Tauri app for Microsoft Store:

  • npm

    npm run tauri build -- --no-bundle
    npm run tauri bundle -- --config src-tauri/tauri.microsoftstore.conf.json
    
  • yarn

    yarn tauri build --no-bundle
    yarn tauri bundle --config src-tauri/tauri.microsoftstore.conf.json
    
  • pnpm

    pnpm tauri build --no-bundle
    pnpm tauri bundle --config src-tauri/tauri.microsoftstore.conf.json
    
  • deno

    deno task tauri build --no-bundle
    deno task tauri bundle --config src-tauri/tauri.microsoftstore.conf.json
    
  • bun

    bun tauri build --no-bundle
    bun tauri bundle --config src-tauri/tauri.microsoftstore.conf.json
    
  • cargo

    cargo tauri build --no-bundle
    cargo tauri bundle --config src-tauri/tauri.microsoftstore.conf.json
    

This is particularly useful when setting up your CI/CD to upload your app to the Microsoft Store while having a separate configuration for the Windows installer you distribute outside the app store.

Silent install

The Microsoft Store requires Win32 installers to support silent installation. If your installer does not install silently, your submission is rejected with an error such as:

10.2.9.2 Security - Package Submissions | Win32 products must install silently.

When you register your installer in Partner Center you must provide the silent install parameters so the Store can run it unattended. Tauris NSIS -setup.exe installer installs silently with the /S flag (note the uppercase S):

MyApp_x64-setup.exe /S

Enter /S as the silent install argument in the installer parameters of your Microsoft Store product. If you distribute the MSI installer instead, use the standard msiexec flag /quiet.

Publisher

Your application publisher name cannot match the application product name.

If the publisher configuration value is not set, Tauri derives it from the second part of your bundle identifier. Since the publisher name cannot match the product name, the following configuration is invalid:

tauri.conf.json

{
  "productName": "Example",
  "identifier": "com.example.app"
}

In this case you can define the publisher value separately to fix this conflict:

tauri.conf.json

{
  "productName": "Example",
  "identifier": "com.example.app",
  +"bundle": {
    +"publisher": "Example Inc."
+  }
}

Upload

After building the Windows installer for Microsoft Store, you can upload it to the distribution service of your choice and link it in your application page in the Microsoft Store website.

CrabNebula Cloud

Distributing with CrabNebula Cloud

CrabNebula is an official Tauri partner providing services and tooling for Tauri applications. The CrabNebula Cloud is a platform for application distribution that seamlessly integrates with the Tauri updater.

The Cloud offers a Content Delivery Network (CDN) that is capable of shipping your application installers and updates globally while being cost effective and exposing download metrics.

With the CrabNebula Cloud service it is simple to implement multiple release channels, download buttons for your application website and more.

Setting up your Tauri app to use the Cloud is easy: all you need to do is to sign in to the Cloud website using your GitHub account, create your organization and application and install its CLI to create a release and upload the Tauri bundles. Additionally, a GitHub Action is provided to simplify the process of using the CLI on GitHub workflows.

For more information, see the CrabNebula Cloud documentation.

GitHub

This guide will show you how to use tauri-action in GitHub Actions to easily build and upload your app, and how to make Tauris updater query the newly created GitHub release for updates.

Lastly, it will also show how to set up a more complicated build pipeline for Linux Arm AppImages.

Code Signing

To set up code signing for Windows and macOS in your workflow, follow the specific guide for each platform:

If you build a macOS app without an Apple signing certificate, configure an ad-hoc signing identity. This can avoid macOS treating Apple Silicon builds downloaded from GitHub releases as damaged.

Getting Started

To set up tauri-action you must first set up a GitHub repository. You can also use this action on a repository that does not have Tauri configured yet since it can automatically initialize Tauri for you, please see the actions readme for necessary configuration options.

Go to the Actions tab on your GitHub project page and select “New workflow”, then choose “Set up a workflow yourself”. Replace the file with the workflow from below or from one of the actions examples.

Configuration

Please see the tauri-action readme for all available configuration options.

When your app is not on the root of the repository, use the projectPath input.

You may freely modify the workflow name, change its triggers, and add more steps such as npm run lint or npm run test. The important part is that you keep the below line at the end of the workflow since this runs the build script and releases your app.

How to Trigger

The release workflow shown below and in the tauri-action examples is triggered by pushed to the release branch. The action automatically creates a git tag and a title for the GitHub release using the application version.

As another example, you can also change the trigger to run the workflow on the push of a version git tag such as app-v0.7.0:

name: 'publish'


on:
  push:
    tags:
      - 'app-v*'

For a full list of possible trigger configurations, check out the official GitHub documentation.

Example Workflow

Below is an example workflow that has been set up to run every time you push to the release branch.

This workflow will build and release your app for Windows x64, Linux x64, Linux Arm64, macOS x64 and macOS Arm64 (M1 and above).

The steps this workflow takes are:

  1. Checkout the repository using actions/checkout@v7.
  2. Install Linux system dependencies required to build the app.
  3. Set up Node.js LTS and a cache for global npm/yarn/pnpm package data using actions/setup-node@v6.
  4. Set up Rust and a cache for Rusts build artifacts using dtolnay/rust-toolchain@stable and swatinem/rust-cache@v2.
  5. Install the frontend dependencies and, if not configured as beforeBuildCommand, run the web apps build script.
  6. Lastly, it uses tauri-apps/tauri-action@v1 to run tauri build, generate the artifacts, and create a GitHub release.
name: 'publish'


on:
  workflow_dispatch:
  push:
    branches:
      - release


jobs:
  publish-tauri:
    permissions:
      contents: write
    strategy:
      fail-fast: false
      matrix:
        include:
          - platform: 'macos-latest' # for Arm based macs (M1 and above).
            args: '--target aarch64-apple-darwin'
          - platform: 'macos-latest' # for Intel based macs.
            args: '--target x86_64-apple-darwin'
          - platform: 'ubuntu-22.04'
            args: ''
          - platform: 'ubuntu-22.04-arm' # Only available in public repos.
            args: ''
          - platform: 'windows-latest'
            args: ''


    runs-on: ${{ matrix.platform }}
    steps:
      - uses: actions/checkout@v7


      - name: install dependencies (ubuntu only)
        if: matrix.platform == 'ubuntu-22.04' || matrix.platform == 'ubuntu-22.04-arm' # This must match the platform value defined above.
        run: |
          sudo apt-get update
          sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf xdg-utils


      - name: setup node
        uses: actions/setup-node@v6
        with:
          node-version: lts/*
          cache: 'npm' # Set this to npm, yarn or pnpm.


      - name: install Rust stable
        uses: dtolnay/rust-toolchain@stable
        with:
          # Those targets are only used on macos runners so it's in an `if` to slightly speed up windows and linux builds.
          targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}


      - name: Rust cache
        uses: swatinem/rust-cache@v2
        with:
          # This matches tauri's default project layout. Change this if you have a different layout.
          workspaces: './src-tauri -> target'


      - name: install frontend dependencies
        # If you don't have `beforeBuildCommand` configured you may want to build your frontend here too.
        run: npm install # change this to npm, yarn or pnpm depending on which one you use.


      - uses: tauri-apps/tauri-action@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tagName: app-v__VERSION__ # the action automatically replaces __VERSION__ with the app version.
          releaseName: 'App v__VERSION__'
          releaseBody: 'See the assets to download this version and install.'
          releaseDraft: true
          prerelease: false
          args: ${{ matrix.args }}

For more configuration options, check out the tauri-action repository and its examples.

Caution

Carefully read through the Usage limits, billing, and administration documentation for GitHub Actions.

Arm Runner Compilation

August 2025 Update

Github has released publicly available ubuntu-22.04-arm and ubuntu-24.04-arm runners. You can use these to build your app for Arm64 in public repos with the workflow example above.

This workflow uses pguyot/arm-runner-action to compile directly on an emulated Arm runner. This bridges the gap for missing cross-architecture build support in the AppImage tooling.

Danger

arm-runner-action is much slower than GitHubs standard runners, so be careful in private repositories where youre invoiced for build minutes. An uncached build for a fresh create-tauri-app project needs ~1 hour.

name: 'Publish Linux Arm builds'


on:
  workflow_dispatch:
  push:
    branches:
      - release


jobs:
  build:
    runs-on: ubuntu-22.04


    strategy:
      matrix:
        arch: [aarch64, armv7l]
        include:
          - arch: aarch64
            cpu: cortex-a72
            base_image: https://dietpi.com/downloads/images/DietPi_RPi5-ARMv8-Bookworm.img.xz
            deb: arm64
            rpm: aarch64
            appimage: aarch64
          - arch: armv7l
            cpu: cortex-a53
            deb: armhfp
            rpm: arm
            appimage: armhf
            base_image: https://dietpi.com/downloads/images/DietPi_RPi-ARMv7-Bookworm.img.xz


    steps:
      - uses: actions/checkout@v3


      - name: Cache rust build artifacts
        uses: Swatinem/rust-cache@v2
        with:
          workspaces: src-tauri
          cache-on-failure: true


      - name: Build app
        uses: pguyot/arm-runner-action@v2.6.5
        with:
          base_image: ${{ matrix.base_image }}
          cpu: ${{ matrix.cpu }}
          bind_mount_repository: true
          image_additional_mb: 10240
          optimize_image: no
          #exit_on_fail: no
          commands: |
            # Prevent Rust from complaining about $HOME not matching eid home
            export HOME=/root


            # Workaround to CI worker being stuck on Updating crates.io index
            export CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse


            # Install setup prerequisites
            apt-get update -y --allow-releaseinfo-change
            apt-get autoremove -y
            apt-get install -y --no-install-recommends --no-install-suggests curl libwebkit2gtk-4.1-dev build-essential libssl-dev libgtk-3-dev libayatana-appindicator3-dev librsvg2-dev patchelf libfuse2 file
            curl https://sh.rustup.rs -sSf | sh -s -- -y
            . "$HOME/.cargo/env"
            curl -fsSL https://deb.nodesource.com/setup_lts.x | bash
            apt-get install -y nodejs


            # Install frontend dependencies
            npm install


            # Build the application
            npm run tauri build -- --verbose


      - name: Get app version
        run: echo "APP_VERSION=$(jq -r .version src-tauri/tauri.conf.json)" >> $GITHUB_ENV


      # TODO: Combine this with the basic workflow and upload the files to the Release.
      - name: Upload deb bundle
        uses: actions/upload-artifact@v3
        with:
          name: Debian Bundle
          path: ${{ github.workspace }}/src-tauri/target/release/bundle/deb/appname_${{ env.APP_VERSION }}_${{ matrix.deb }}.deb


      - name: Upload rpm bundle
        uses: actions/upload-artifact@v3
        with:
          name: RPM Bundle
          path: ${{ github.workspace }}/src-tauri/target/release/bundle/rpm/appname-${{ env.APP_VERSION }}-1.${{ matrix.rpm }}.rpm


      - name: Upload appimage bundle
        uses: actions/upload-artifact@v3
        with:
          name: AppImage Bundle
          path: ${{ github.workspace }}/src-tauri/target/release/bundle/appimage/appname_${{ env.APP_VERSION }}_${{ matrix.appimage }}.AppImage

Troubleshooting

GitHub Environment Token

The GitHub Token is automatically issued by GitHub for each workflow run without further configuration, which means there is no risk of secret leakage. This token however only has read permissions by default and you may get a “Resource not accessible by integration” error when running the workflow. If this happens, you may need to add write permissions to this token. To do this, go to your GitHub project settings, select Actions, scroll down to Workflow permissions, and check “Read and write permissions”.

You can see the GitHub Token being passed to the workflow via this line in the workflow:

env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

RPM

Note

Some sections in this guide are optional. This includes configuring scripts and certain other steps. Feel free to adapt the instructions based on your specific needs and requirements.

This guide covers how to distribute and manage RPM packages, including retrieving package information, configuring scripts, setting dependencies, and signing packages.

Note

GUI apps on macOS and Linux do not inherit the $PATH from your shell dotfiles (.bashrc, .bash_profile, .zshrc, etc). Check out Tauris fix-path-env-rs crate to fix this issue.

Limitations

Core libraries such as glibc frequently break compatibility with older systems. For this reason, you must build your Tauri application using the oldest base system you intend to support that also provides Tauri v2s required WebKitGTK 4.1 packages. Ubuntu 22.04 and Debian 12 are suitable baseline examples because they provide libwebkit2gtk-4.1-dev from their standard package repositories. Building on a newer base system can raise the minimum glibc version required by your app, so when running on an older system, you may face a runtime error like /usr/lib/libc.so.6: version 'GLIBC_2.33' not found. We recommend using a Docker container or GitHub Actions to build your Tauri application for Linux.

See the issues tauri-apps/tauri#1355 and rust-lang/rust#57497, in addition to the AppImage guide for more information.

Configuring the RPM package

Tauri allows you to configure the RPM package by adding scripts, setting dependencies, adding a license, including custom files, and more. For detailed information about configurable options, please refer to: RpmConfig.

Add post, pre-install/remove script to the package

The RPM package manager allows you to run scripts before or after the installation or removal of the package. For example, you can use these scripts to start a service after the package is installed.

Heres an example of how to add these scripts:

  1. Create a folder named scripts in the src-tauri directory in your project.
mkdir src-tauri/scripts
  1. Create the script files in the folder.
touch src-tauri/scripts/postinstall.sh \
touch src-tauri/scripts/preinstall.sh \
touch src-tauri/scripts/preremove.sh \
touch src-tauri/scripts/postremove.sh

Now if we look inside /src-tauri/scripts we will see:

ls src-tauri/scripts/
postinstall.sh  postremove.sh  preinstall.sh  preremove.sh
  1. Add some content to the scripts

preinstall.sh

echo "-------------"
echo "This is pre"
echo "Install Value: $1"
echo "Upgrade Value: $1"
echo "Uninstall Value: $1"
echo "-------------"

postinstall.sh

echo "-------------"
echo "This is post"
echo "Install Value: $1"
echo "Upgrade Value: $1"
echo "Uninstall Value: $1"
echo "-------------"

preremove.sh

echo "-------------"
echo "This is preun"
echo "Install Value: $1"
echo "Upgrade Value: $1"
echo "Uninstall Value: $1"
echo "-------------"

postremove.sh

echo "-------------"
echo "This is postun"
echo "Install Value: $1"
echo "Upgrade Value: $1"
echo "Uninstall Value: $1"
echo "-------------"
  1. Add the scripts to thetauri.conf.json file

tauri.conf.json

{
  "bundle": {
    "linux": {
      "rpm": {
        "epoch": 0,
        "files": {},
        "release": "1",
        // add the script here
        "preInstallScript": "/path/to/your/project/src-tauri/scripts/prescript.sh",
        "postInstallScript": "/path/to/your/project/src-tauri/scripts/postscript.sh",
        "preRemoveScript": "/path/to/your/project/src-tauri/scripts/prescript.sh",
        "postRemoveScript": "/path/to/your/project/src-tauri/scripts/postscript.sh"
      }
    }
  }
}

Setting the Conflict, Provides, Depends, Files, Obsoletes, DesktopTemplate, and Epoch

  • conflict: Prevents the installation of the package if it conflicts with another package. For example, if you update an RPM package that your app depends on and the new version is incompatible with your app.

  • provides: Lists the RPM dependencies that your application provides.

  • depends: Lists the RPM dependencies that your application needs to run.

  • files: Specifies which files to include in the package.

  • obsoletes: Lists the RPM dependencies that your application obsoletes.

Note

If this package is installed, packages listed as “obsoletes” will be automatically removed if present.

  • desktopTemplate: Adds a custom desktop file to the package.

  • epoch: Defines weighted dependencies based on version numbers.

Caution

It is not recommended to use epoch unless necessary, as it alters how the package manager compares package versions. For more information about epoch, please check: RPM Packaging Guide.

To use these options, add the following to your tauri.conf.json :

tauri.conf.json

{
  "bundle": {
    "linux": {
      "rpm": {
        "postRemoveScript": "/path/to/your/project/src-tauri/scripts/postscript.sh",
        "conflicts": ["oldLib.rpm"],
        "depends": ["newLib.rpm"],
        "obsoletes": ["veryoldLib.rpm"],
        "provides": ["coolLib.rpm"],
        "desktopTemplate": "/path/to/your/project/src-tauri/desktop-template.desktop"
      }
    }
  }
}

Add a license to the package

To add a license to the package, add the following to the src-tauri/cargo.toml or in the src-tauri/tauri.conf.json file:

src-tauri/cargo.toml

[package]
name = "tauri-app"
version = "0.0.0"
description = "A Tauri App"
authors = ["you"]
edition = "2021"
license = "MIT" # add the license here
# ...  rest of the file

And for src-tauri/tauri.conf.json

src-tauri/tauri.conf.json

{
  "bundle": {
    "licenseFile": "../LICENSE", // put the path to the license file here
    "license": "MIT" // add the license here
  }
}

Building the RPM package

To build the RPM package, you can use the following command:

  • npm

    npm run tauri build
    
  • yarn

    yarn tauri build
    
  • pnpm

    pnpm tauri build
    
  • deno

    deno task tauri build
    
  • bun

    bun tauri build
    
  • cargo

    cargo tauri build
    

This command will build the RPM package in the src-tauri/target/release/bundle/rpm directory.

Signing the RPM package

Tauri allows you to sign the package with the key you have in your system during the build process. To do this, you will need to generate a GPG key.

Generate a GPG key

To generate a GPG key you can use the following command:

gpg --gen-key

Follow the instruction to generate the key.

Once the key is generated, you will need to add it to your environment variable. You can do this by adding the following to your .bashrc or .zshrc file or just export it in the terminal:

export TAURI_SIGNING_RPM_KEY=$(cat /home/johndoe/my_super_private.key)

If you have a passphrase for the key, you can add it to the environment variable:

export TAURI_SIGNING_RPM_KEY_PASSPHRASE=password

Now you can build the package with the following command:

  • npm

    npm run tauri build
    
  • yarn

    yarn tauri build
    
  • pnpm

    pnpm tauri build
    
  • deno

    deno task tauri build
    
  • bun

    bun tauri build
    
  • cargo

    cargo tauri build
    

Verify the signature

Note

This should be done only to test the signature locally.

Before verifying the signature, you will need to create and import the public key to the RPM database:

gpg --export -a 'Tauri-App' > RPM-GPG-KEY-Tauri-App
sudo rpm --import RPM-GPG-KEY-Tauri-App

Now that the key is imported, we have to edit the ~/.rpmmacros file to utilize the key.

~/.rpmmacros

%_signature gpg
%_gpg_path /home/johndoe/.gnupg
%_gpg_name Tauri-App
%_gpgbin /usr/bin/gpg2
%__gpg_sign_cmd %{__gpg} \
    gpg --force-v3-sigs --digest-algo=sha1 --batch --no-verbose --no-armor \
    --passphrase-fd 3 --no-secmem-warning -u "%{_gpg_name}" \
    -sbo %{__signature_filename} %{__plaintext_filename}

Finally, you can verify the package using the following command:

rpm  -v --checksig tauri-app-0.0.0-1.x86_64.rpm

Debugging the RPM package

In this section, we will see how to debug the RPM package by checking the content of the package and getting information about the package.

Getting information about the package

To get information about your package, such as the version, release, and architecture, use the following command:

rpm -qip package_name.rpm

Query specific information about the package

For example, if you want to get the name, version, release, architecture, and size of the package, use the following command:

rpm  -qp --queryformat '[%{NAME} %{VERSION} %{RELEASE} %{ARCH} %{SIZE}\n]' package_name.rpm

Note

--queryformat is a format string that can be used to get specific information about the package. The information that can be retrieved is from the rpm -qip command.

Checking the content of the package

To check the content of the package, use the following command:

rpm -qlp package_name.rpm

This command will list all the files that are included in the package.

Debugging scripts

To debug post/pre-install/remove scripts, use the following command:

rpm -qp --scripts package_name.rpm

This command will print the content of the scripts.

Checking dependencies

To check the dependencies of the package, use the following command:

rpm -qp --requires package_name.rpm

List packages that depend on a specific package

To list the packages that depend on a specific package, use the following command:

rpm -q --whatrequires package_name.rpm

Debugging Installation Issues

If you encounter issues during the installation of an RPM package, you can use the -vv (very verbose) option to get detailed output:

rpm -ivvh package_name.rpm

Or for an already installed package:

rpm -Uvvh package_name.rpm

Cross-Compiling for ARM-based Devices

This guide covers manual compilation. Check out our GitHub Action guide for an example workflow that leverages QEMU to build the app. This will be much slower but will also be able to build AppImages.

Manual compilation is suitable when you dont need to compile your application frequently and prefer a one-time setup. The following steps expect you to use a Linux distribution based on Debian/Ubuntu.

  1. Install Rust targets for your desired architecture

    • For ARMv7 (32-bit): rustup target add armv7-unknown-linux-gnueabihf
    • For ARMv8 (ARM64, 64-bit): rustup target add aarch64-unknown-linux-gnu
  2. Install the corresponding linker for your chosen architecture

    • For ARMv7: sudo apt install gcc-arm-linux-gnueabihf
    • For ARMv8 (ARM64): sudo apt install gcc-aarch64-linux-gnu
  3. Open or create the file <project-root>/.cargo/config.toml and add the following configurations accordingly

    [target.armv7-unknown-linux-gnueabihf]
    linker = "arm-linux-gnueabihf-gcc"
    
    
    [target.aarch64-unknown-linux-gnu]
    linker = "aarch64-linux-gnu-gcc"
    
  4. Enable the respective architecture in the package manager

    • For ARMv7: sudo dpkg --add-architecture armhf
    • For ARMv8 (ARM64): sudo dpkg --add-architecture arm64
  5. Adjusting Package Sources

    On Debian, this step should not be necessary, but on other distributions, you might need to edit /etc/apt/sources.list to include the ARM architecture variant. For example on Ubuntu 22.04 add these lines to the bottom of the file (Remember to replace jammy with the codename of your Ubuntu version):

    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy main restricted
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy universe
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates universe
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy multiverse
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates multiverse
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-backports main restricted universe multiverse
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security universe
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security multiverse
    

    Then, to prevent issues with the main packages, you have to add the correct main architecture to all other lines the file contained beforehand. For standard 64-bit systems you need to add [arch=amd64], the full file on Ubuntu 22.04 then looks similar to this:

    Show solution

    # See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
    # newer versions of the distribution.
    deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy main restricted
    # deb-src http://archive.ubuntu.com/ubuntu/ jammy main restricted
    
    
    ## Major bug fix updates produced after the final release of the
    ## distribution.
    deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted
    # deb-src http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted
    
    
    ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
    ## team. Also, please note that software in universe WILL NOT receive any
    ## review or updates from the Ubuntu security team.
    deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy universe
    # deb-src http://archive.ubuntu.com/ubuntu/ jammy universe
    deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-updates universe
    # deb-src http://archive.ubuntu.com/ubuntu/ jammy-updates universe
    
    
    ## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
    ## team, and may not be under a free licence. Please satisfy yourself as to
    ## your rights to use the software. Also, please note that software in
    ## multiverse WILL NOT receive any review or updates from the Ubuntu
    ## security team.
    deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy multiverse
    # deb-src http://archive.ubuntu.com/ubuntu/ jammy multiverse
    deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-updates multiverse
    
    
    ## N.B. software from this repository may not have been tested as
    ## extensively as that contained in the main release, although it includes
    ## newer versions of some applications which may provide useful features.
    ## Also, please note that software in backports WILL NOT receive any review
    ## or updates from the Ubuntu security team.
    deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse
    # deb-src http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse
    
    
    deb [arch=amd64] http://security.ubuntu.com/ubuntu/ jammy-security main restricted
    # deb-src http://security.ubuntu.com/ubuntu/ jammy-security main restricted
    deb [arch=amd64] http://security.ubuntu.com/ubuntu/ jammy-security universe
    # deb-src http://security.ubuntu.com/ubuntu/ jammy-security universe
    deb [arch=amd64] http://security.ubuntu.com/ubuntu/ jammy-security multiverse
    # deb-src http://security.ubuntu.com/ubuntu/ jammy-security multiverse
    
    
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy main restricted
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates main restricted
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy universe
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates universe
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy multiverse
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-updates multiverse
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-backports main restricted universe multiverse
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security main restricted
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security universe
    deb [arch=armhf,arm64] http://ports.ubuntu.com/ubuntu-ports jammy-security multiverse
    
  6. Update the package information: sudo apt-get update && sudo apt-get upgrade -y

  7. Install the required webkitgtk library for your chosen architecture

    • For ARMv7: sudo apt install libwebkit2gtk-4.1-dev:armhf
    • For ARMv8 (ARM64): sudo apt install libwebkit2gtk-4.1-dev:arm64
  8. Install OpenSSL or use a vendored version

    This is not always required so you may want to proceed first and check if you see errors like Failed to find OpenSSL development headers.

    • Either install the development headers system-wide:

      • For ARMv7: sudo apt install libssl-dev:armhf
      • For ARMv8 (ARM64): sudo apt install libssl-dev:arm64
    • Or enable the vendor feature for the OpenSSL Rust crate which will affect all other Rust dependencies using the same minor version. You can do so by adding this to the dependencies section in your Cargo.toml file:

    openssl-sys = {version = "0.9", features = ["vendored"]}
    
  9. Set the PKG_CONFIG_SYSROOT_DIR to the appropriate directory based on your chosen architecture

    • For ARMv7: export PKG_CONFIG_SYSROOT_DIR=/usr/arm-linux-gnueabihf/
    • For ARMv8 (ARM64): export PKG_CONFIG_SYSROOT_DIR=/usr/aarch64-linux-gnu/
  10. Build the app for your desired ARM version

    • For ARMv7: cargo tauri build target armv7-unknown-linux-gnueabihf
    • For ARMv8 (ARM64): cargo tauri build target aarch64-unknown-linux-gnu

    Choose the appropriate set of instructions based on whether you want to cross-compile your Tauri application for ARMv7 or ARMv8 (ARM64). Please note that the specific steps may vary depending on your Linux distribution and setup.

Android Code Signing

To publish on the Play Store, you need to sign your app with a digital certificate.

Android App Bundles and APKs must be signed before being uploaded for distribution.

Google also provides an additional signing mechanism for Android App Bundles distributed in the Play Store. See the official Play App Signing documentation for more information.

Creating a keystore and upload key

Android signing requires a Java Keystore file that can be generated using the official keytool CLI:

  • macOS/Linux

    keytool -genkey -v -keystore ~/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload
    
  • Windows

    keytool -genkey -v -keystore $env:USERPROFILE\upload-keystore.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias upload
    

This command stores the upload-keystore.jks file in your home directory. If you want to store it elsewhere, change the argument you pass to the -keystore parameter.

Tip

  • The keytool command might not be in your PATH. You may find it installed in the JDK that is installed with Android Studio:
  • Linux

    /opt/android-studio/jbr/bin/keytool ...args
    

    Android Studio directory path depends on your Linux distribution

  • macOS

    /Applications/Android\ Studio.app/Contents/jbr/Contents/Home/bin/keytool ...args
    
  • Windows

    C:\\Program Files\\Android\\Android Studio\\jbr\\bin\\keytool.exe ...args
    

Security Warning

Keep the keystore file private; dont check it into public source control!

See the official documentation for more information.

Configure the signing key

Create a file named [project]/src-tauri/gen/android/keystore.properties that contains a reference to your keystore:

password=<password defined when keytool was executed>
keyAlias=upload
storeFile=<location of the key store file, such as /Users/<user name>/upload-keystore.jks or C:\\Users\\<user name>\\upload-keystore.jks>

Security Warning

Keep the keystore.properties file private; dont check it into public source control.

You will usually generate this file in your CI/CD platform. The following snippet contains an example job step for GitHub Actions:

- name: setup Android signing
  run: |
    cd src-tauri/gen/android
    echo "keyAlias=${{ secrets.ANDROID_KEY_ALIAS }}" > keystore.properties
    echo "password=${{ secrets.ANDROID_KEY_PASSWORD }}" >> keystore.properties
    base64 -d <<< "${{ secrets.ANDROID_KEY_BASE64 }}" > $RUNNER_TEMP/keystore.jks
    echo "storeFile=$RUNNER_TEMP/keystore.jks" >> keystore.properties

In this example the keystore was exported to base64 with base64 -i /path/to/keystore.jks and set as the ANDROID_KEY_BASE64 secret.

Configure Gradle to use the signing key

Configure gradle to use your upload key when building your app in release mode by editing the [project]/src-tauri/gen/android/app/build.gradle.kts file.

Tip

There are multiple different build.gradle.kts files in a typical Android project. If there is no buildTypes block youre looking at the wrong file. The one you need is in the app/ directory relative to the keystore file from the prior step.

Click here for a screenshot showing its location in a typical file tree.

build.gradle.kts location in file tree

  1. Add the needed import at the beginning of the file:

    import java.io.FileInputStream
    
  2. Add the release signing config before the buildTypes block:

    signingConfigs {
        create("release") {
            val keystorePropertiesFile = rootProject.file("keystore.properties")
            val keystoreProperties = Properties()
            if (keystorePropertiesFile.exists()) {
                keystoreProperties.load(FileInputStream(keystorePropertiesFile))
            }
    
    
            keyAlias = keystoreProperties["keyAlias"] as String
            keyPassword = keystoreProperties["password"] as String
            storeFile = file(keystoreProperties["storeFile"] as String)
            storePassword = keystoreProperties["password"] as String
        }
    }
    
    
    buildTypes {
        ...
    }
    
  3. Use the new release signing config in the release config in buildTypes block:

    buildTypes {
        getByName("release") {
            signingConfig = signingConfigs.getByName("release")
        }
    }
    

Release builds of your app will now be signed automatically.

iOS Code Signing

Code signing on iOS is required to distribute your application through the official Apple App Store or possibly alternative marketplaces in the European Union and in general to install and execute on end user devices.

Prerequisites

Code signing on iOS requires enrolling to the Apple Developer program, which at the time of writing costs 99$ per year. You also need an Apple device where you perform the code signing. This is required by the signing process and due to Apples Terms and Conditions.

To distribute iOS applications you must have your bundle identifier registered in the App Store Connect, an appropriate iOS code signing certificate and a mobile provisioning profile that links them together and enables the iOS capabilities used by your app. These requirements can be either automatically managed by Xcode or provided manually.

Automatic Signing

Letting Xcode manage the signing and provisioning for your app is the most convenient way to export your iOS app to be distributed. It automatically registers your bundle identifier, manages iOS capabilities changes, and configures an appropriate certificate based on your export method.

Automatic signing is enabled by default, and uses the account configured in Xcode to authenticate when used on your local machine.
To register your account, open the Xcode application and open the Settings page in the Xcode > Settings menu, switch to the Accounts tab and click the + icon.

To use the automatic signing in CI/CD platforms you must create an App Store Connect API key and define the APPLE_API_ISSUER, APPLE_API_KEY and APPLE_API_KEY_PATH environment variables.
Open the App Store Connects Users and Access page, select the Integrations tab, click on the Add button and select a name and the Admin access. The APPLE_API_ISSUER (Issuer ID) is presented above the keys table, and the APPLE_API_KEY is the value on the Key ID column on that table. You also need to download the private key, which can only be done once and is only visible after a page reload (the button is shown on the table row for the newly created key). The private key file path must be set via the APPLE_API_KEY_PATH environment variable.

Manual Signing

To manually sign your iOS app you can provide the certificate and mobile provisioning profile via environment variables:

  • IOS_CERTIFICATE: base64 representation of the certificate exported from the Keychain.
  • IOS_CERTIFICATE_PASSWORD: password of the certificate set when exporting it from the Keychain.
  • IOS_MOBILE_PROVISION: base64 representation of the provisioning profile.

The following sections explain how to get these values.

Signing Certificate

After enrolling, navigate to the Certificates page to create a new Apple Distribution certificate. Download the new certificate and install it to the macOS Keychain.

To export the certificate key, open the “Keychain Access” app, expand the certificates entry, right-click on the key item and select “Export <key-name>” item. Select the path of the exported .p12 file and remember its password.

Run the following base64 command to convert the certificate to base64 and copy it to the clipboard:

base64 -i <path-to-certificate.p12> | pbcopy

The value in the clipboard is now the base64 representation of the signing certificate. Save it and use it as the IOS_CERTIFICATE environment variable value.

The certificate password must be set to the IOS_CERTIFICATE_PASSWORD variable.

Choose Certificate Type

You must use an appropriate certificate type for each export method:

  • debugging: Apple Development or iOS App Development
  • app-store-connect: Apple Distribution or iOS Distribution (App Store Connect and Ad Hoc)
  • ad-hoc: Apple Distribution or iOS Distribution (App Store Connect and Ad Hoc)

Provisioning Profile

Additionally, you must provide the provisioning profile for your application. In the Identifiers page, create a new App ID and make sure its “Bundle ID” value matches the identifier set in the identifier configuration.

Navigate to the Profiles page to create a new provisioning profile. For App Store distribution, it must be an “App Store Connect” profile. Select the appropriate App ID and link the certificate you previously created.

After creating the provisioning profile, download it and run the following base64 command to convert the profile and copy it to the clipboard:

base64 -i <path-to-profile.mobileprovision> | pbcopy

The value in the clipboard is now the base64 representation of the provisioning profile. Save it and use it as the IOS_MOBILE_PROVISION environment variable value.

Now you can build your iOS application and distribute on the App Store!

Linux Code Signing

This guide provides information on code signing for Linux packages. While artifact signing is not required for your application to be deployed on Linux, it can be used to increase trust into your deployed application. Signing the binaries allows your end user to verify that these are genuine and have not been modified by another untrusted entity.

Signing for AppImages

The AppImage can be signed using either gpg or gpg2.

Prerequisites

A key for signing must be prepared. A new one can be generated using:

gpg2 --full-gen-key

Please refer to the gpg or gpg2 documentation for additional information. You should take additional care to back up your private and public keys in a secure location.

Signing

You can embed a signature in the AppImage by setting the following environment variables:

  • SIGN: set to 1 to sign the AppImage.
  • SIGN_KEY: optional variable to use a specific GPG Key ID for signing.
  • APPIMAGETOOL_SIGN_PASSPHRASE: the signing key password. If unset, gpg shows a dialog so you can input it. You must set this when building in CI/CD platforms.
  • APPIMAGETOOL_FORCE_SIGN: by default the AppImage is generated even if signing fails. To exit on errors, you can set this variable to 1.

You can display the signature embedded in the AppImage by running the following command:

./src-tauri/target/release/bundle/appimage/$APPNAME_$VERSION_amd64.AppImage --appimage-signature

Note that you need to change the $APPNAME and $VERSION values with the correct ones based on your configuration.

Caution

The signature is not verified

AppImage does not validate the signature, so you cant rely on it to check whether the file has been tampered with or not. The user must manually verify the signature using the AppImage validate tool. This requires you to publish your key ID on an authenticated channel (e.g. your website served via TLS), so the end user can view and verify.

See the official AppImage documentation for additional information.

Validate the signature

The AppImage validate tool can be downloaded from here. Select one of the validate-$PLATFORM.AppImage files.

Run the following command to validate the signature:

chmod +x validate-$PLATFORM.AppImage
./validate-$PLATFORM.AppImage $TAURI_OUTPUT.AppImage

If the signature is valid, the output will be:

Validation result: validation successful
Signatures found with key fingerprints: $KEY_ID
====================
Validator report:
Signature checked for key with fingerprint $KEY_ID:
Validation successful

macOS Code Signing

Code signing is required on macOS to allow your application to be listed in the Apple App Store and to prevent a warning that your application is broken and can not be started, when downloaded from the browser.

Prerequisites

Code signing on macOS requires an Apple Developer account which is either paid (99$ per year) or on the free plan (only for testing and development purposes). You also need an Apple device where you perform the code signing. This is required by the signing process and due to Apples Terms and Conditions.

Note

Note when using a free Apple Developer account, you will not be able to notarize your application and it will still show up as not verified when opening the app.

Signing

To setup code signing for macOS you must create an Apple code signing certificate and install it to your Mac computer keychain or export it to be used in CI/CD platforms.

Creating a signing certificate

To create a new signing certificate, you must generate a Certificate Signing Request (CSR) file from your Mac computer. See creating a certificate signing request to learn how to create the CSR for code signing.

On your Apple Developer account, navigate to the Certificates, IDs & Profiles page and click on the Create a certificate button to open the interface to create a new certificate. Choose the appropriate certificate type (Apple Distribution to submit apps to the App Store, and Developer ID Application to ship apps outside the App Store). Upload your CSR, and the certificate will be created.

Note

Only the Apple Developer Account Holder can create Developer ID Application certificates. But it can be associated with a different Apple ID by creating a CSR with a different user email address.

Downloading the certificate

On the Certificates, IDs & Profiles page, click on the certificate you want to use and click on the Download button. It saves a .cer file that installs the certificate on the keychain once opened.

Configuring Tauri

You can configure Tauri to use your certificate when building macOS apps on your local machine or when using CI/CD platforms.

Signing locally

With the certificate installed in your Mac computer keychain, you can configure Tauri to use it for code signing.

The name of the certificates keychain entry represents the signing identity, which can also be found by executing:

security find-identity -v -p codesigning

This identity can be provided in the tauri.conf.json > bundle > macOS > signingIdentity configuration option or via the APPLE_SIGNING_IDENTITY environment variable.

Note

A signing certificate is only valid if associated with your Apple ID. An invalid certificate wont be listed on the Keychain Access > My Certificates tab or the security find-identity -v -p codesigning output. If the certificate does not download to the correct location, make sure the “login” option is selected in Keychain Access under “Default Keychains” when downloading the .cer file.

Signing in CI/CD platforms

To use the certificate in CI/CD platforms, you must export the certificate to a base64 string and configure the APPLE_CERTIFICATE and APPLE_CERTIFICATE_PASSWORD environment variables:

  1. Open the Keychain Access app, click the My Certificates tab in the login keychain and find your certificates entry.
  2. Expand the entry, right-click on the key item, and select Export "$KEYNAME".
  3. Select the path to save the certificates .p12 file and define a password for the exported certificate.
  4. Convert the .p12 file to base64 running the following script on the terminal:
openssl base64 -A -in /path/to/certificate.p12 -out certificate-base64.txt
  1. Set the contents of the certificate-base64.txt file to the APPLE_CERTIFICATE environment variable.
  2. Set the certificate password to the APPLE_CERTIFICATE_PASSWORD environment variable.

Example GitHub Actions configuration

Required secrets:

  • APPLE_ID - Your Apple ID email
  • APPLE_PASSWORD - Your Apple ID password
  • APPLE_CERTIFICATE - The base64 encoded .p12 file
  • APPLE_CERTIFICATE_PASSWORD - The password for your exported .p12 file
  • KEYCHAIN_PASSWORD - The password for your keychain

Check out the official GitHub guide to learn how to set up secrets.

name: 'build'


on:
  push:
    branches:
      - main


jobs:
  build-macos:
    needs: prepare
    strategy:
      matrix:
        include:
          - args: '--target aarch64-apple-darwin'
            arch: 'silicon'
          - args: '--target x86_64-apple-darwin'
            arch: 'intel'
    runs-on: macos-latest
    env:
      APPLE_ID: ${{ secrets.APPLE_ID }}
      APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
    steps:
      - name: Import Apple Developer Certificate
        env:
          APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
          APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
          KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
        run: |
          echo $APPLE_CERTIFICATE | base64 --decode > certificate.p12
          security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
          security default-keychain -s build.keychain
          security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
          security set-keychain-settings -t 3600 -u build.keychain
          security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
          security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain
          security find-identity -v -p codesigning build.keychain
      - name: Verify Certificate
        run: |
          CERT_INFO=$(security find-identity -v -p codesigning build.keychain | grep "Apple Development")
          CERT_ID=$(echo "$CERT_INFO" | awk -F'"' '{print $2}')
          echo "CERT_ID=$CERT_ID" >> $GITHUB_ENV
          echo "Certificate imported."
      - uses: tauri-apps/tauri-action@v0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
          APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
          APPLE_SIGNING_IDENTITY: ${{ env.CERT_ID }}
        with:
          args: ${{ matrix.args }}

Notarization

To notarize your application, you must provide credentials for Tauri to authenticate with Apple. This can be done via the App Store Connect API, or via your Apple ID.

  • App Store Connect

    1. Open the App Store Connects Users and Access page, select the Integrations tab, click on the Add button and select a name and the Developer access.
    2. Set the APPLE_API_ISSUER environment variable to the value presented above the keys table.
    3. Set the APPLE_API_KEY environment variable to the value on the Key ID column on that table.
    4. Download the private key, which can only be done once and is only visible after a page reload (the button is shown on the table row for the newly created key).
    5. Set the APPLE_API_KEY_PATH environment variable to the file path of the downloaded private key.
  • Apple ID

    1. Set the APPLE_ID environment variable to your Apple account email.
    2. Set the APPLE_PASSWORD environment variable to an app-specific password for your Apple account.
    3. Set the APPLE_TEAM_ID environment variable to your Apple Team ID. You can find your Team ID in your accounts membership page.

After setting these environment variables, rerun your Tauri build or bundle command. For example, to build a DMG with pnpm, run pnpm tauri build --bundles dmg again. If you need to skip stapling for an initial notarization pass, append --skip-stapling directly to the Tauri command, such as pnpm tauri build --bundles dmg --skip-stapling.

Note

Notarization is required when using a Developer ID Application certificate.

Ad-Hoc Signing

If you do not wish to provide an Apple-authenticated identity, but still wish to sign your application, you can configure an ad-hoc signature.

This is useful on ARM (Apple Silicon) devices, where code-signing is required for all apps from the Internet.

Caution

Ad-hoc code signing does not prevent MacOS from requiring users to whitelist the installation in their Privacy & Security settings.

To configure an ad-hoc signature, provide the pseudo-identity - to Tauri, e.g.

"signingIdentity": "-"

For details on configuring Tauris signing identity, see above.

Windows Code Signing

Code signing is required on Windows to allow your application to be listed in the Microsoft Store and to prevent a SmartScreen warning that your application is not trusted and can not be started, when downloaded from the browser.

It is not required to execute your application on Windows, as long as your end user is okay with ignoring the SmartScreen warning or your user does not download via the browser. This guide covers signing via OV (Organization Validated) certificates and Azure Key Vault. If you use any other signing mechanism not documented here, such as EV (Extended Validation) certificates, check out your certificate issuer documentation and refer to the custom sign command section.

OV Certificates

Danger

This guide only applies to OV code signing certificates acquired before June 1st 2023! For code signing with EV certificates and OV certificates received after that date please consult the documentation of your certificate issuer instead.

Note

If you sign the app with an EV Certificate, itll receive an immediate reputation with Microsoft SmartScreen and wont show any warnings to users.

If you opt for an OV Certificate, which is generally cheaper and available to individuals, Microsoft SmartScreen will still show a warning to users when they download the app. It might take some time until your certificate builds enough reputation. You may opt for submitting your app to Microsoft for manual review. Although not guaranteed, if the app does not contain any malicious code, Microsoft may grant additional reputation and potentially remove the warning for that specific uploaded file.

See the comparison to learn more about OV vs EV certificates.

Prerequisites

  • Windows - you can likely use other platforms, but this tutorial uses Powershell native features.
  • A working Tauri application
  • Code signing certificate - you can acquire one of these on services listed in Microsofts docs. There are likely additional authorities for non-EV certificates than included in that list, please compare them yourself and choose one at your own risk.
    • Please make sure to get a code signing certificate, SSL certificates do not work!

Getting Started

There are a few things we have to do to get Windows prepared for code signing. This includes converting our certificate to a specific format, installing this certificate, and decoding the required information from the certificate.

  1. Convert your .cer to .pfx

    • You will need the following:

      • certificate file (mine is cert.cer)
      • private key file (mine is private-key.key)
    • Open up a command prompt and change to your current directory using cd Documents/Certs

    • Convert your .cer to a .pfx using openssl pkcs12 -export -in cert.cer -inkey private-key.key -out certificate.pfx

    • You should be prompted to enter an export password DONT FORGET IT!

  2. Import your .pfx file into the keystore.

    • We now need to import our .pfx file.

    • Assign your export password to a variable using $WINDOWS_PFX_PASSWORD = 'MYPASSWORD'

    • Now Import the certificate using Import-PfxCertificate -FilePath certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $WINDOWS_PFX_PASSWORD -Force -AsPlainText)

  3. Prepare Variables

    • Start ➡️ certmgr.msc to open Personal Certificate Management, then open Personal/Certificates.

    • Find the certificate we just imported and double-click on it, then click on the Details tab.

    • The Signature hash algorithm will be our digestAlgorithm. (Hint: this is likely sha256)

    • Scroll down to Thumbprint. There should be a value like A1B1A2B2A3B3A4B4A5B5A6B6A7B7A8B8A9B9A0B0. This is our certificateThumbprint.

    • We also need a timestamp URL; this is a time server used to verify the time of the certificate signing. Im using http://timestamp.comodoca.com, but whoever you got your certificate from likely has one as well.

Prepare tauri.conf.json file

  1. Now that we have our certificateThumbprint, digestAlgorithm, & timestampUrl we will open up the tauri.conf.json.

  2. In the tauri.conf.json you will look for the tauri -> bundle -> windows section. There are three variables for the information we have captured. Fill it out like below.

"windows": {
        "certificateThumbprint": "A1B1A2B2A3B3A4B4A5B5A6B6A7B7A8B8A9B9A0B0",
        "digestAlgorithm": "sha256",
        "timestampUrl": "http://timestamp.comodoca.com"
}
  1. Save and run tauri build

  2. In the console output, you should see the following output.

info: signing app
info: running signtool "C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.19041.0\\x64\\signtool.exe"
info: "Done Adding Additional Store\r\nSuccessfully signed: APPLICATION FILE PATH HERE

Which shows you have successfully signed the .exe.

And thats it! You have successfully set up your Tauri application for Windows signing.

Sign your application with GitHub Actions.

We can also create a workflow to sign the application with GitHub actions.

GitHub Secrets

We need to add a few GitHub secrets for the proper configuration of the GitHub Action. These can be named however you would like.

The secrets we used are as follows

GitHub Secrets Value for Variable
WINDOWS_CERTIFICATE Base64 encoded version of your .pfx certificate, can be done using this command certutil -encode certificate.pfx base64cert.txt
WINDOWS_CERTIFICATE_PASSWORD Certificate export password used on creation of certificate .pfx

Workflow Modifications

  1. We need to add a step in the workflow to import the certificate into the Windows environment. This workflow accomplishes the following

    1. Assign GitHub secrets to environment variables
    2. Create a new certificate directory
    3. Import WINDOWS_CERTIFICATE into tempCert.txt
    4. Use certutil to decode the tempCert.txt from base64 into a .pfx file.
    5. Remove tempCert.txt
    6. Import the .pfx file into the Cert store of Windows & convert the WINDOWS_CERTIFICATE_PASSWORD to a secure string to be used in the import command.
  2. We will be using the tauri-action publish template.

name: 'publish'
on:
  push:
    branches:
      - release


jobs:
  publish-tauri:
    strategy:
      fail-fast: false
      matrix:
        platform: [macos-latest, ubuntu-latest, windows-latest]


    runs-on: ${{ matrix.platform }}
    steps:
      - uses: actions/checkout@v2
      - name: setup node
        uses: actions/setup-node@v1
        with:
          node-version: 12
      - name: install Rust stable
        uses: actions-rs/toolchain@v1
        with:
          toolchain: stable
      - name: install webkit2gtk (ubuntu only)
        if: matrix.platform == 'ubuntu-latest'
        run: |
          sudo apt-get update
          sudo apt-get install -y webkit2gtk-4.0
      - name: install app dependencies and build it
        run: yarn && yarn build
      - uses: tauri-apps/tauri-action@v0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tagName: app-v__VERSION__ # the action automatically replaces \_\_VERSION\_\_ with the app version
          releaseName: 'App v__VERSION__'
          releaseBody: 'See the assets to download this version and install.'
          releaseDraft: true
          prerelease: false
  1. Right above -name: install app dependencies and build it you will want to add the following step
- name: import windows certificate
  if: matrix.platform == 'windows-latest'
  env:
    WINDOWS_CERTIFICATE: ${{ secrets.WINDOWS_CERTIFICATE }}
    WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
  run: |
    New-Item -ItemType directory -Path certificate
    Set-Content -Path certificate/tempCert.txt -Value $env:WINDOWS_CERTIFICATE
    certutil -decode certificate/tempCert.txt certificate/certificate.pfx
    Remove-Item -path certificate -include tempCert.txt
    Import-PfxCertificate -FilePath certificate/certificate.pfx -CertStoreLocation Cert:\CurrentUser\My -Password (ConvertTo-SecureString -String $env:WINDOWS_CERTIFICATE_PASSWORD -Force -AsPlainText)
  1. Save and push to your repo.

  2. Your workflow can now import your windows certificate and import it into the GitHub runner, allowing for automated code signing!

Azure Key Vault

You can sign the Windows executables by providing an Azure Key Vault certificate and credentials.

Note

This guide uses relic due to its support to secret-based authentication, though you can configure alternative tools if you prefer. To download relic, check its releases page or run go install github.com/sassoftware/relic/v8@latest.

  1. Key Vault

In the Azure Portal navigate to the Key vaults service to create a new key vault by clicking the “Create” button. Remember the “Key vault name” as you will need that information to configure the certificate URL.

  1. Certificate

After creating a key vault, select it and go to the “Objects > Certificates” page to create a new certificate and click the “Generate/Import” button. Remember the “Certificate name” as you will need that information to configure the certificate URL.

  1. Tauri Configuration

relic uses a configuration file to determine which signing key it should use. For Azure Key Vault you also need the certificate URL. Create a relic.conf file in the src-tauri folder and configure relic to use your certificate:

src-tauri/relic.conf

tokens:
  azure:
    type: azure


keys:
  azure:
    token: azure
    id: https://\<KEY_VAULT_NAME\>.vault.azure.net/certificates/\<CERTIFICATE_NAME\>

Note that you must replace <KEY_VAULT_NAME> and <CERTIFICATE_NAME> with the appropriate names from the previous steps.

To configure Tauri to use your Azure Key Vault configuration for signing change the bundle > windows > signCommand config value:

tauri.conf.json

{
  "bundle": {
    "windows": {
      "signCommand": "relic sign --file %1 --key azure --config relic.conf"
    }
  }
}
  1. Credentials

relic must authenticate with Azure in order to load the certificate. In the Azure portal landing page, go to the “Microsoft Entra ID” service and head to the “Manage > App registrations” page. Click “New registration” to create a new app. After creating the app, you are redirected to the application details page where you can see the “Application (client) ID” and “Directory (tenant) ID” values. Set these IDs to the AZURE_CLIENT_ID and AZURE_TENANT_ID environment variables respectively.

In the “Manage > Certificates & secrets” page click the “New client secret” button and set the text in the “Value” column as the AZURE_CLIENT_SECRET environment variable.

After setting up all the credentials, head back to your key vaults page and navigate to the “Access control (IAM)” page. You must assign the “Key Vault Certificate User” and “Key Vault Crypto User” roles to your newly created application.

After setting up all these variables, running tauri build will produce signed Windows installers!

Custom Sign Command

In the Azure Key Vault documentation above we used a powerful Tauri Windows signing configuration to force the Tauri CLI to use a special shell command to sign Windows installer executables. The bundle > windows > signCommand configuration option can be used to use any codesign tool that can sign Windows executables.

Tip

When cross compiling Windows installers from Linux and macOS machines, you must use a custom sign command as the default implementation only works on Windows machines.

Azure Artifact Signing

You can sign the Windows executables by providing an Azure Artifact Signing (previously called Azure Code Signing/Azure Trusted Signing) certificate and credentials. If you dont have an Azure Artifact signing Account yet you can follow this tutorial.

Prerequisites

If you want to sign with Github Actions everything should be installed.

  1. Artifact Signing Account and permissions configured
  2. .NET (.NET 8 recommended)
  3. Azure CLI
  4. Signtool (Windows 11 SDK 10.0.26100.0 or later recommended)

Getting Started

You need to install artifact-signing-cli and configure your environment variables.

  1. Install artifact-signing-cli

    • cargo install artifact-signing-cli
  2. Configure environment variables

    • artifact-signing-cli needs the following environment variables to be set, dont forget to add these as Github Actions secrets:

  3. Modify your tauri.conf.json file

    • You can modify your tauri.conf.json or you can create a specific config file for Windows. Replace the URL and the certificate name with your own values.

      • -e: The endpoint of your Azure Artifact Signing account
      • -a: The name of your Azure Artifact Signing Account
      • -c: The name of your Certificate profile inside your Azure Artifact Signing Account
      • -d: The description of the signed content (optional). When signing a .msi installer, this description will appear as the installers name in the UAC prompt or will be a random string of characters if unset.

    tauri.conf.json

    {
      "bundle": {
        "windows": {
          "signCommand": "artifact-signing-cli -e https://wus2.codesigning.azure.net -a MyAccount -c MyProfile -d MyApp %1"
        }
      }
    }
    

Snapcraft

Prerequisites

1. Install snap

  • Debian

    sudo apt install snapd
    
  • Arch

    sudo pacman -S --needed git base-devel
    git clone https://aur.archlinux.org/snapd.git
    cd snapd
    makepkg -si
    sudo systemctl enable --now snapd.socket
    sudo systemctl start snapd.socket
    sudo systemctl enable --now snapd.apparmor.service
    
  • Fedora

    sudo dnf install snapd
    # Enable classic snap support
    sudo ln -s /var/lib/snapd/snap /snap
    

    Reboot your system afterwards.

2. Install a base snap

sudo snap install core22

3. Install snapcraft

sudo snap install snapcraft --classic

Configuration

  1. Create an UbuntuOne account.
  2. Go to the Snapcraft website and register an App name.
  3. Create a snapcraft.yaml file in your projects root.
  4. Adjust the names in the snapcraft.yaml file.
name: appname
base: core22
version: '0.1.0'
summary: Your summary # 79 char long summary
description: |
  Your description


grade: stable
confinement: strict


layout:
  /usr/lib/$SNAPCRAFT_ARCH_TRIPLET/webkit2gtk-4.1:
    bind: $SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/webkit2gtk-4.1


apps:
  appname:
    command: usr/bin/appname
    desktop: usr/share/applications/appname.desktop
    extensions: [gnome]
    #plugs:
    #  - network
    # Add whatever plugs you need here, see https://snapcraft.io/docs/snapcraft-interfaces for more info.
    # The gnome extension already includes [ desktop, desktop-legacy, gsettings, opengl, wayland, x11, mount-observe, calendar-service ]
    #  - single-instance-plug # add this if you're using the single-instance plugin
    #slots:
    # Add the slots you need to expose to other snaps
    #  - single-instance-plug # add this if you're using the single-instance plugin


# Add these lines only if you're using the single-instance plugin
# Check https://v2.tauri.app/plugin/single-instance/ for details
#slots:
#  single-instance:
#    interface: dbus
#    bus: session
#    name: org.net_mydomain_MyApp.SingleInstance # Remember to change net_mydomain_MyApp to your app ID with "_" instead of "." and "-"
#
#plugs:
#  single-instance-plug:
#    interface: dbus
#    bus: session
#    name: org.net_mydomain_MyApp.SingleInstance # Remember to change net_mydomain_MyApp to your app ID with "_" instead of "." and "-"


package-repositories:
  - type: apt
    components: [main]
    suites: [noble]
    key-id: 78E1918602959B9C59103100F1831DDAFC42E99D
    url: http://ppa.launchpad.net/snappy-dev/snapcraft-daily/ubuntu


parts:
  build-app:
    plugin: dump
    build-snaps:
      - node/20/stable
      - rustup/latest/stable
    build-packages:
      - libwebkit2gtk-4.1-dev
      - build-essential
      - curl
      - wget
      - file
      - libxdo-dev
      - libssl-dev
      - libayatana-appindicator3-dev
      - librsvg2-dev
      - dpkg
    stage-packages:
      - libwebkit2gtk-4.1-0
      - libayatana-appindicator3-1
    source: .
    override-build: |
      set -eu
      npm install
      npm run tauri build -- --bundles deb
      dpkg -x src-tauri/target/release/bundle/deb/*.deb $SNAPCRAFT_PART_INSTALL/
      sed -i -e "s|Icon=appname|Icon=/usr/share/icons/hicolor/32x32/apps/appname.png|g" $SNAPCRAFT_PART_INSTALL/usr/share/applications/appname.desktop

Explanation

  • The name variable defines the name of your app and is required to be set to the name that you have registered earlier.
  • The base variable defines which core you are using.
  • The version variable defines the version, and should be updated with each change to the source repository.
  • The apps section allows you to expose the desktop and binary files to allow the user to run your app.
  • The package-repositories section allows you to add a package repository to help you satisfy your dependencies.
  • build-packages/build-snaps defines the build dependencies for your snap.
  • stage-packages/stage-snaps defines the runtime dependencies for your snap.
  • The override-build section runs a series of commands after the sources were pulled.

Building

sudo snapcraft

Testing

snap run your-app

Releasing Manually

snapcraft login # Login with your UbuntuOne credentials
snapcraft upload --release=stable mysnap_latest_amd64.snap

Building automatically

  1. On your apps developer page click on the builds tab.
  2. Click login with github.
  3. Enter in your repositorys details.

Windows Installer

Tauri applications for Windows are either distributed as Microsoft Installers (.msi files) using the WiX Toolset v3 or as setup executables (-setup.exe files) using NSIS.

Please note that .msi installers can only be created on Windows as WiX can only run on Windows systems. Cross-compilation for NSIS installers is shown below.

This guide provides information about available customization options for the installer.

Building

To build and bundle your app into a Windows installer you can use the Tauri CLI and run the tauri build command in a Windows computer:

  • npm

    npm run tauri build
    
  • yarn

    yarn tauri build
    
  • pnpm

    pnpm tauri build
    
  • deno

    deno task tauri build
    
  • bun

    bun tauri build
    
  • cargo

    cargo tauri build
    

VBSCRIPT requirement for MSI packages

Building MSI packages ("targets": "msi" or "targets": "all" in tauri.conf.json) requires the VBSCRIPT optional feature to be enabled on Windows. This feature is enabled by default on most Windows installations, but if you encounter errors like failed to run light.exe, you may need to enable it manually through SettingsAppsOptional featuresMore Windows features. See the Prerequisites guide for detailed instructions.

Build Windows apps on Linux and macOS

Cross compiling Windows apps on Linux and macOS hosts is possible with caveats when using NSIS. It is not as straight forward as compiling on Windows directly and is not tested as much. Therefore it should only be used as a last resort if local VMs or CI solutions like GitHub Actions dont work for you.

Note

Signing cross compiled Windows installers requires an external signing tool. See the signing documentation for more information.

Since Tauri officially only supports the MSVC Windows target, the setup is a bit more involved.

Install NSIS

  • Linux

    Some Linux distributions have NSIS available in their repositories, for example on Ubuntu you can install NSIS by running this command:

    Ubuntu

    sudo apt install nsis
    

    But on many other distributions you have to compile NSIS yourself or download Stubs and Plugins manually that werent included in the distros binary package. Fedora for example only provides the binary but not the Stubs and Plugins:

    Fedora

    sudo dnf in mingw64-nsis
    wget https://github.com/tauri-apps/binary-releases/releases/download/nsis-3/nsis-3.zip
    unzip nsis-3.zip
    sudo cp nsis-3.08/Stubs/* /usr/share/nsis/Stubs/
    sudo cp -r nsis-3.08/Plugins/** /usr/share/nsis/Plugins/
    
  • macOS

    On macOS you will need [Homebrew] to install NSIS:

    macOS

    brew install nsis
    

Install LLVM and the LLD Linker

Since the default Microsoft linker only works on Windows we will also need to install a new linker. To compile the Windows Resource file which is used for setting the app icon among other things we will also need the llvm-rc binary which is part of the LLVM project.

  • Linux

    Ubuntu

    sudo apt install lld llvm
    

    On Linux you also need to install the clang package if you added dependencies that compile C/C++ dependencies as part of their build scripts. Default Tauri apps should not require this.

  • macOS

    macOS

    brew install llvm
    

    On macOS you also have to add /opt/homebrew/opt/llvm/bin to your $PATH as suggested in the install output.

Install the Windows Rust target

Assuming youre building for 64-bit Windows systems:

rustup target add x86_64-pc-windows-msvc

Install cargo-xwin

Instead of setting the Windows SDKs up manually we will use [cargo-xwin] as Tauris “runner”:

cargo install --locked cargo-xwin

By default cargo-xwin will download the Windows SDKs into a project-local folder. If you have multiple projects and want to share those files you can set the XWIN_CACHE_DIR environment variable with a path to the preferred location.

Building the App

Now it should be as simple as adding the runner and target to the tauri build command:

  • npm

    npm run tauri build -- --runner cargo-xwin --target x86_64-pc-windows-msvc
    
  • yarn

    yarn tauri build --runner cargo-xwin --target x86_64-pc-windows-msvc
    
  • pnpm

    pnpm tauri build --runner cargo-xwin --target x86_64-pc-windows-msvc
    
  • deno

    deno task tauri build --runner cargo-xwin --target x86_64-pc-windows-msvc
    
  • bun

    bun tauri build --runner cargo-xwin --target x86_64-pc-windows-msvc
    
  • cargo

    cargo tauri build --runner cargo-xwin --target x86_64-pc-windows-msvc
    

The build output will then be in target/x86_64-pc-windows-msvc/release/bundle/nsis/.

Building for 32-bit or ARM

The Tauri CLI compiles your executable using your machines architecture by default. Assuming that youre developing on a 64-bit machine, the CLI will produce 64-bit applications.

If you need to support 32-bit machines, you can compile your application with a different Rust target using the --target flag:

  • npm

    npm run tauri build -- --target i686-pc-windows-msvc
    
  • yarn

    yarn tauri build --target i686-pc-windows-msvc
    
  • pnpm

    pnpm tauri build --target i686-pc-windows-msvc
    
  • deno

    deno task tauri build --target i686-pc-windows-msvc
    
  • bun

    bun tauri build --target i686-pc-windows-msvc
    
  • cargo

    cargo tauri build --target i686-pc-windows-msvc
    

By default, Rust only installs toolchains for your machines target, so you need to install the 32-bit Windows toolchain first: rustup target add i686-pc-windows-msvc.

If you need to build for ARM64 you first need to install additional build tools. To do this, open Visual Studio Installer, click on “Modify”, and in the “Individual Components” tab install the “C++ ARM64 build tools”. At the time of writing, the exact name in VS2022 is MSVC v143 - VS 2022 C++ ARM64 build tools (Latest). Now you can add the rust target with rustup target add aarch64-pc-windows-msvc and then use the above-mentioned method to compile your app:

  • npm

    npm run tauri build -- --target aarch64-pc-windows-msvc
    
  • yarn

    yarn tauri build --target aarch64-pc-windows-msvc
    
  • pnpm

    pnpm tauri build --target aarch64-pc-windows-msvc
    
  • deno

    deno task tauri build --target aarch64-pc-windows-msvc
    
  • bun

    bun tauri build --target aarch64-pc-windows-msvc
    
  • cargo

    cargo tauri build --target aarch64-pc-windows-msvc
    

Note

Note that the NSIS installer itself will still be x86 running on the ARM machine via emulation. The app itself will be a native ARM64 binary.

Supporting Windows 7

By default, the Microsoft Installer (.msi) does not work on Windows 7 because it needs to download the WebView2 bootstrapper if not installed (which might fail if TLS 1.2 is not enabled in the operating system). Tauri includes an option to embed the WebView2 bootstrapper (see the Embedding the WebView2 Bootstrapper section below). The NSIS based installer (-setup.exe) also supports the downloadBootstrapper mode on Windows 7.

Additionally, to use the Notification API in Windows 7, you need to enable the windows7-compat Cargo feature:

Cargo.toml

[dependencies]
tauri-plugin-notification = { version = "2.0.0", features = [ "windows7-compat" ] }

FIPS Compliance

If your system requires the MSI bundle to be FIPS compliant you can set the TAURI_BUNDLER_WIX_FIPS_COMPLIANT environment variable to true before running tauri build. In PowerShell you can set it for the current terminal session like this:

$env:TAURI_BUNDLER_WIX_FIPS_COMPLIANT="true"

WebView2 Installation Options

The installers by default download the WebView2 bootstrapper and executes it if the runtime is not installed. Alternatively, you can embed the bootstrapper, embed the offline installer, or use a fixed WebView2 runtime version. See the following table for a comparison between these methods:

Installation Method Requires Internet Connection? Additional Installer Size Notes
downloadBootstrapper Yes 0MB Default Results in a smaller installer size, but is not recommended for Windows 7 deployment via .msi files.
embedBootstrapper Yes ~1.8MB Better support on Windows 7 for .msi installers.
offlineInstaller No ~127MB Embeds WebView2 installer. Recommended for offline environments.
fixedVersion No ~180MB Embeds a fixed WebView2 version.
skip No 0MB ⚠️ Not recommended Does not install the WebView2 as part of the Windows Installer.

Note

On Windows 10 (April 2018 release or later) and Windows 11, the WebView2 runtime is distributed as part of the operating system.

Downloaded Bootstrapper

This is the default setting for building the Windows Installer. It downloads the bootstrapper and runs it. Requires an internet connection but results in a smaller installer size. This is not recommended if youre going to be distributing to Windows 7 via .msi installers.

tauri.conf.json

{
  "bundle": {
    "windows": {
      "webviewInstallMode": {
        "type": "downloadBootstrapper"
      }
    }
  }
}

Embedded Bootstrapper

To embed the WebView2 Bootstrapper, set the webviewInstallMode to embedBootstrapper. This increases the installer size by around 1.8MB, but increases compatibility with Windows 7 systems.

tauri.conf.json

{
  "bundle": {
    "windows": {
      "webviewInstallMode": {
        "type": "embedBootstrapper"
      }
    }
  }
}

Offline Installer

To embed the WebView2 Bootstrapper, set the webviewInstallMode to offlineInstaller. This increases the installer size by around 127MB, but allows your application to be installed even if an internet connection is not available.

tauri.conf.json

{
  "bundle": {
    "windows": {
      "webviewInstallMode": {
        "type": "offlineInstaller"
      }
    }
  }
}

Fixed Version

Using the runtime provided by the system is great for security as the webview vulnerability patches are managed by Windows. If you want to control the WebView2 distribution on each of your applications (either to manage the release patches yourself or distribute applications on environments where an internet connection might not be available) Tauri can bundle the runtime files for you.

Caution

Distributing a fixed WebView2 Runtime version increases the Windows Installer by around 180MB.

  1. Download the WebView2 fixed version runtime from Microsofts website. In this example, the downloaded filename is Microsoft.WebView2.FixedVersionRuntime.128.0.2739.42.x64.cab
  2. Extract the file to the core folder:
Expand .\Microsoft.WebView2.FixedVersionRuntime.128.0.2739.42.x64.cab -F:* ./src-tauri
  1. Configure the WebView2 runtime path in tauri.conf.json:

tauri.conf.json

{
  "bundle": {
    "windows": {
      "webviewInstallMode": {
        "type": "fixedRuntime",
        "path": "./Microsoft.WebView2.FixedVersionRuntime.98.0.1108.50.x64/"
      }
    }
  }
}
  1. Run tauri build to produce the Windows Installer with the fixed WebView2 runtime.

Skipping Installation

You can remove the WebView2 Runtime download check from the installer by setting webviewInstallMode to skip. Your application WILL NOT work if the user does not have the runtime installed.

Your application WILL NOT work if the user does not have the runtime installed and wont attempt to install it.

tauri.conf.json

{
  "bundle": {
    "windows": {
      "webviewInstallMode": {
        "type": "skip"
      }
    }
  }
}

Minimum Webview2 version

If your app requires features only available in newer Webview2 versions (such as custom URI schemes), you can instruct the Windows installer to verify the current Webview2 version and run the Webview2 bootstrapper if it does not match the target version.

tauri.conf.json

{
  "bundle": {
    "windows": {
      "minimumWebview2Version": "110.0.1531.0"
    }
  }
}

Customizing the WiX Installer

See the WiX configuration for the complete list of customization options.

Installer Template

The .msi Windows Installer package is built using the WiX Toolset v3. Currently, apart from pre-defined configurations, you can change it by using a custom WiX source code (an XML file with a .wxs file extension) or through WiX fragments.

Replacing the Installer Code with a Custom WiX File

The Windows Installer XML defined by Tauri is configured to work for the common use case of simple webview-based applications (you can find it here). It uses handlebars so the Tauri CLI can brand your installer according to your tauri.conf.json definition. If you need a completely different installer, a custom template file can be configured on tauri.bundle.windows.wix.template.

Extending the Installer with WiX Fragments

A WiX fragment is a container where you can configure almost everything offered by WiX. In this example, we will define a fragment that writes two registry entries:

<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Fragment>
    <!-- these registry entries should be installed
     to the target user's machine -->
    <DirectoryRef Id="TARGETDIR">
      <!-- groups together the registry entries to be installed -->
      <!-- Note the unique `Id` we provide here -->
      <Component Id="MyFragmentRegistryEntries" Guid="*">
        <!-- the registry key will be under
       HKEY_CURRENT_USER\Software\MyCompany\MyApplicationName -->
        <!-- Tauri uses the second portion of the
       bundle identifier as the `MyCompany` name
       (e.g. `tauri-apps` in `com.tauri-apps.test`)  -->
        <RegistryKey
          Root="HKCU"
          Key="Software\MyCompany\MyApplicationName"
          Action="createAndRemoveOnUninstall"
        >
          <!-- values to persist on the registry -->
          <RegistryValue
            Type="integer"
            Name="SomeIntegerValue"
            Value="1"
            KeyPath="yes"
          />
          <RegistryValue Type="string" Value="Default Value" />
        </RegistryKey>
      </Component>
    </DirectoryRef>
  </Fragment>
</Wix>

Save the fragment file with the .wxs extension in the src-tauri/windows/fragments folder and reference it on tauri.conf.json:

tauri.conf.json

{
  "bundle": {
    "windows": {
      "wix": {
        "fragmentPaths": ["./windows/fragments/registry.wxs"],
        "componentRefs": ["MyFragmentRegistryEntries"]
      }
    }
  }
}

Note that ComponentGroup, Component, FeatureGroup, Feature and Merge element ids must be referenced on the wix object of tauri.conf.json on the componentGroupRefs, componentRefs, featureGroupRefs, featureRefs and mergeRefs respectively to be included in the installer.

Internationalization

The WiX Installer is built using the en-US language by default. Internationalization (i18n) can be configured using the tauri.bundle.windows.wix.language property, defining the languages Tauri should build an installer against. You can find the language names to use in the Language-Culture column on Microsofts website.

Compiling a WiX Installer for a Single Language

To create a single installer targeting a specific language, set the language value to a string:

tauri.conf.json

{
  "bundle": {
    "windows": {
      "wix": {
        "language": "fr-FR"
      }
    }
  }
}

Compiling a WiX Installer for Each Language in a List

To compile an installer targeting a list of languages, use an array. A specific installer for each language will be created, with the language key as a suffix:

tauri.conf.json

{
  "bundle": {
    "windows": {
      "wix": {
        "language": ["en-US", "pt-BR", "fr-FR"]
      }
    }
  }
}

Configuring the WiX Installer Strings for Each Language

A configuration object can be defined for each language to configure localization strings:

tauri.conf.json

{
  "bundle": {
    "windows": {
      "wix": {
        "language": {
          "en-US": null,
          "pt-BR": {
            "localePath": "./wix/locales/pt-BR.wxl"
          }
        }
      }
    }
  }
}

The localePath property defines the path to a language file, a XML configuring the language culture:

<WixLocalization
  Culture="en-US"
  xmlns="http://schemas.microsoft.com/wix/2006/localization"
>
  <String Id="LaunchApp"> Launch MyApplicationName </String>
  <String Id="DowngradeErrorMessage">
    A newer version of MyApplicationName is already installed.
  </String>
  <String Id="PathEnvVarFeature">
    Add the install location of the MyApplicationName executable to
    the PATH system environment variable. This allows the
    MyApplicationName executable to be called from any location.
  </String>
  <String Id="InstallAppFeature">
    Installs MyApplicationName.
  </String>
</WixLocalization>

Note

The WixLocalization elements Culture field must match the configured language.

Currently, Tauri references the following locale strings: LaunchApp, DowngradeErrorMessage, PathEnvVarFeature and InstallAppFeature. You can define your own strings and reference them on your custom template or fragments with "!(loc.TheStringId)". See the WiX localization documentation for more information.

Customizing the NSIS Installer

See the NSIS configuration for the complete list of customization options.

Installer Template

The NSIS Installers .nsi script defined by Tauri is configured to work for the common use case of simple webview-based applications (you can find it here). It uses handlebars so the Tauri CLI can brand your installer according to your tauri.conf.json definition. If you need a completely different installer, a custom template file can be configured on tauri.bundle.windows.nsis.template.

Extending the Installer

If you only need to extend some installation steps you might be able to use installer hooks instead of replacing the entire installer template.

Supported hooks are:

  • NSIS_HOOK_PREINSTALL: Runs before copying files, setting registry key values and creating shortcuts.
  • NSIS_HOOK_POSTINSTALL: Runs after the installer has finished copying all files, setting the registry keys and created shortcuts.
  • NSIS_HOOK_PREUNINSTALL: Runs before removing any files, registry keys and shortcuts.
  • NSIS_HOOK_POSTUNINSTALL: Runs after files, registry keys and shortcuts have been removed.

For example, create a hooks.nsh file in the src-tauri/windows folder and define the hooks you need:

!macro NSIS_HOOK_PREINSTALL
  MessageBox MB_OK "PreInstall"
!macroend


!macro NSIS_HOOK_POSTINSTALL
  MessageBox MB_OK "PostInstall"
!macroend


!macro NSIS_HOOK_PREUNINSTALL
  MessageBox MB_OK "PreUnInstall"
!macroend


!macro NSIS_HOOK_POSTUNINSTALL
  MessageBox MB_OK "PostUninstall"
!macroend

Then you must configure Tauri to use that hook file:

tauri.conf.json

{
  "bundle": {
    "windows": {
      "nsis": {
        "installerHooks": "./windows/hooks.nsh"
      }
    }
  }
}

Installing Dependencies with Hooks

You can use installer hooks to automatically install system dependencies that your application requires. This is particularly useful for runtime dependencies like Visual C++ Redistributables, DirectX, OpenSSL or other system libraries that may not be present on all Windows systems.

MSI Installer Example (Visual C++ Redistributable):

!macro NSIS_HOOK_POSTINSTALL
  ; Check if Visual C++ 2019 Redistributable is installed (via Windows Registry)
  ReadRegDWord $0 HKLM "SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x64" "Installed"


  ${If} $0 == 1
    DetailPrint "Visual C++ Redistributable already installed"
    Goto vcredist_done
  ${EndIf}


  ; Install from bundled MSI if not installed
  ${If} ${FileExists} "$INSTDIR\resources\vc_redist.x64.msi"
    DetailPrint "Installing Visual C++ Redistributable..."
    ; Copy to TEMP folder and then execute installer
    CopyFiles "$INSTDIR\resources\vc_redist.x64.msi" "$TEMP\vc_redist.x64.msi"
    ExecWait 'msiexec /i "$TEMP\vc_redist.x64.msi" /passive /norestart' $0


    ; Check wether installation process exited successfully (code 0) or not
    ${If} $0 == 0
      DetailPrint "Visual C++ Redistributable installed successfully"
    ${Else}
      MessageBox MB_ICONEXCLAMATION "Visual C++ installation failed. Some features may not work."
    ${EndIf}


    ; Clean up setup files from TEMP and your installed app
    Delete "$TEMP\vc_redist.x64.msi"
    Delete "$INSTDIR\resources\vc_redist.x64.msi"
  ${EndIf}


  vcredist_done:
!macroend

Key considerations:

  • A good practice is to always check if the dependency is already installed using registry keys or file existence or via Windows where command.
  • Use /passive, /quiet, or /silent flags to avoid interrupting the installation flow. Check out msiexec options for .msi files, or the setup manual for app-specific flags
  • Include /norestart to prevent automatic system reboots during installation for setups that restarts user devices
  • Clean up temporary files and bundled installers to avoid bloating the application
  • Consider that dependencies might be shared with other applications when uninstalling
  • Provide meaningful error messages if installation fails

Ensure to bundle the dependency installers in your src-tauri/resources folder and add to tauri.conf.json so they get bundled, and can be accessed during installation from $INSTDIR\resources\:

tauri.conf.json

{
  "bundle": {
    "resources": [
      "resources/my-dependency.exe",
      "resources/another-one.msi
    ]
  }
}

Install Modes

By default the installer will install your application for the current user only. The advantage of this option is that the installer does not require Administrator privileges to run, but the app is installed in the %LOCALAPPDATA% folder instead of C:/Program Files.

If you prefer your app installation to be available system-wide (which requires Administrator privileges) you can set installMode to perMachine:

tauri.conf.json

{
  "bundle": {
    "windows": {
      "nsis": {
        "installMode": "perMachine"
      }
    }
  }
}

Alternatively you can let the user choose whether the app should be installed for the current user only or system-wide by setting the installMode to both. Note that the installer will require Administrator privileges to execute.

See NSISInstallerMode for more information.

Internationalization

The NSIS Installer is a multi-language installer, which means you always have a single installer which contains all the selected translations.

You can specify which languages to include using the tauri.bundle.windows.nsis.languages property. A list of languages supported by NSIS is available in the NSIS GitHub project. There are a few Tauri-specific translations required, so if you see untranslated texts feel free to open a feature request in Tauris main repo. You can also provide custom translation files.

By default the operating system default language is used to determine the installer language. You can also configure the installer to display a language selector before the installer contents are rendered:

tauri.conf.json

{
  "bundle": {
    "windows": {
      "nsis": {
        "displayLanguageSelector": true
      }
    }
  }
}

Learn

Tutorials intended to provide end-to-end learning experiences to guide you through specific Tauri topics and help you apply knowledge from the guides and reference documentation

The Learning category is intended to provide end-to-end learning experiences on a Tauri related topic.

These tutorials will guide you through a specific topic and help you apply knowledge from the guides and reference documentation.

For security related topics, you can learn about the permissions system. You will get practical insight into how to use it, extend it, and write your own permissions.

Using Plugin Permissions

Capabilities for Different Windows and Platforms

Writing Plugin Permissions

To learn how to write your own splash screen, use a node.js sidecar, or set up mobile features, check out:

Splashcreen

Node.js as a Sidecar

Multi-Window on Mobile

File Associations on Mobile

More Resources

This section contains learning resources created by the Community that are not hosted on this website.

Have something to share?Open a pull request to show us your amazing resource.

Books

HTML, CSS, JavaScript, and Rust for Beginners Book Cover

HTML, CSS, JavaScript, and Rust for Beginners: A Guide to Application Development with Tauri

by James Alexander Rose

Paperback on Amazon: Buy Here

Free PDF version: Download (PDF 4MB)

Guides & Tutorials

Auto-Updates with Tauri v2Setup auto-updates with Tauri and CrabNebula Cloud.

Publish to Apples App StoreDetails all the steps needed to publish your Mac app to the app store. Includes a sample bash script.

Video Guides

Create Tauri App with ReactChris Biscardi shows how easy it is to wire up a Rust crate with a JS module and communicate between them.

Tauri & ReactJS - Creating Modern Desktop AppsCreating a modern desktop application with Tauri.

File Associations on Mobile

Tauri supports file associations on Android and iOS, allowing your app to be registered as a handler for specific file types. When a user opens a file that matches your declared associations, the operating system launches your app and delivers the file URL.

On Android, file associations are implemented using intent filters that the Tauri build system generates automatically from your configuration.

On iOS, file associations use CFBundleDocumentTypes and optionally UTExportedTypeDeclarations for custom file types.

Configuration

File associations are declared in tauri.conf.json under bundle.fileAssociations. The Tauri CLI uses this configuration to generate the appropriate platform-specific metadata (Android intent filters in AndroidManifest.xml, iOS document types in Info.plist).

Each entry in the array represents a file type your app can handle:

src-tauri/tauri.conf.json

{
  "bundle": {
    "fileAssociations": [
      {
        "ext": ["png"],
        "mimeType": "image/png"
      },
      {
        "ext": ["jpg", "jpeg"],
        "mimeType": "image/jpeg"
      }
    ]
  }
}

Configuration Options

  • ext — list of file extensions to associate (without leading dot).
  • mimeType — the MIME type for the file (e.g. image/png). Required on Android for intent filter matching. Tauri infers common MIME types from extensions when not specified.
  • role — the apps role with respect to the file type. Maps to CFBundleTypeRole on Apple platforms. Values: Editor (default), Viewer, Shell, QLGenerator, None.
  • rank — the ranking among apps that handle this file type. Maps to LSHandlerRank on Apple platforms. Values: Default (default), Owner, Alternate, None.
  • name — display name for the file type. Defaults to the first extension.
  • exportedType — defines a custom file type owned by your app. Required on Apple platforms when associating with non-standard file extensions.
  • androidIntentActionFilters — which Android intent actions to register. Values: Send, SendMultiple, View. All three are used by default.

Custom File Types

For non-standard file extensions, you should define an exportedType so Apple platforms can identify the file type. The identifier should be a reverse-DNS string unique to your app, and conformsTo lists the parent types:

src-tauri/tauri.conf.json

{
  "bundle": {
    "fileAssociations": [
      {
        "ext": ["mydata"],
        "mimeType": "application/octet-stream",
        "exportedType": {
          "identifier": "com.example.myapp.mydata",
          "conformsTo": ["public.data"]
        }
      }
    ]
  }
}

Common conformsTo values include public.data, public.image, public.json, and public.plain-text.

Handling Opened Files

When a file is opened with your app, Tauri emits a RunEvent::Opened event containing the file URLs. This event is available on macOS, iOS, and Android.

You need to handle two cases:

  1. App is already running — the event is delivered at runtime.
  2. App is launched by the file open — the event fires during startup, so you should store the URLs and make them available to your frontend.

Rust

Store incoming URLs in managed state, expose them with a command the frontend can call on startup, and emit a Tauri event whenever RunEvent::Opened fires so the frontend can react while the app is already running:

src-tauri/src/lib.rs

use std::sync::Mutex;
use tauri::Manager;


struct OpenedUrls(Mutex<Vec<tauri::Url>>);


#[tauri::command]
fn opened_urls(app: tauri::AppHandle) -> Vec<tauri::Url> {
    app.state::<OpenedUrls>().0.lock().unwrap().clone()
}


#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .manage(OpenedUrls(Mutex::new(vec![])))
        .invoke_handler(tauri::generate_handler![opened_urls])
        .build(tauri::generate_context!())
        .expect("error while running tauri application")
        .run(|app, event| {
            #[cfg(any(target_os = "macos", target_os = "ios", target_os = "android"))]
            if let tauri::RunEvent::Opened { urls } = event {
                use tauri::Emitter;
                app.state::<OpenedUrls>()
                    .0
                    .lock()
                    .unwrap()
                    .extend(urls.clone());
                app.emit("opened", urls).unwrap();
            }
        });
}

JavaScript

The frontend below is wired to that Rust code in two places:

  • invoke('opened_urls') calls the opened_urls command, so the webview can read URLs that were stored before the UI finished loading (cold start from a file open).
  • listen('opened', …) subscribes to the same event name passed to app.emit("opened", urls) in Rust, so file open events that are triggered while the app is already running are delivered immediately.
import { listen } from '@tauri-apps/api/event';
import { invoke } from '@tauri-apps/api/core';


// Cold start: URLs may already be in Rust state before the frontend loads
const initialUrls = await invoke('opened_urls');
if (initialUrls.length > 0) {
  handleFiles(initialUrls);
}


// Warm: Rust emits the "opened" event when RunEvent::Opened fires
await listen('opened', (event) => {
  handleFiles(event.payload);
});

Multi-Window on Mobile

Tauri supports multiple windows on Android and iOS, allowing your app to display content side-by-side on tablets or in separate scenes on iPad.

On Android, multi-window is implemented using Activity Embedding, which lets the system display two activities side by side on large screens.

On iOS, multi-window uses the UIScene API, which allows iPad users to open multiple instances of your app in separate windows.

On phones, the system usually does not lay out two windows side by side. On Android, creating another window still launches a separate activity, but on handset-sized displays it is typically pushed onto the activity back stack—so Back returns to the previous activity instead of closing a split. On iOS (especially iPhone), opening or creating another window often replaces the current UI with the new scenes content rather than keeping both visible at once; true concurrent windows remain an iPad (and Stage Manager) experience.

Note

Multi-window requires Android 12L (API 32)+ and iOS 13+. You can use the [app.supportsMultipleWindows] API to check availability at runtime.

Shared Setup

Both platforms require a capability permission to create new windows from the frontend.

Capabilities

Add the core:webview:allow-create-webview-window permission to your capability file so your frontend can create new windows.

If you are creating multiple windows, use a wildcard or list every window label in the windows array:

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "default",
  "description": "Capability for the main window",
  "windows": ["main"],
  +"permissions": ["core:default", "core:webview:allow-create-webview-window"]
}

Android

Android multi-window uses Activity Embedding to split activities side by side on large screens (tablets, foldables). You need to create an Android Activity for each window type, configure split rules, and register an initializer.

  1. Add Dependencies

    Add the required AndroidX libraries to your build.gradle.kts:

    src-tauri/gen/android/app/build.gradle.kts

    dependencies {
        // ... existing dependencies
        +implementation("androidx.window:window:1.5.0")
        +implementation("androidx.startup:startup-runtime:1.2.0")
    }
    
  2. Create a New Activity

    Create a Kotlin class for each additional window type. Each activity must extend TauriActivity:

    src-tauri/gen/android/app/src/main/java/com/example/app/DetailActivity.kt

    package com.example.app
    
    
    import android.os.Bundle
    import android.os.PersistableBundle
    
    
    class DetailActivity: TauriActivity() {
      override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
      }
    }
    
  3. Update AndroidManifest.xml

    Register the new activity and enable activity embedding by adding the tools namespace and the embedding property:

    src-tauri/gen/android/app/src/main/AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
      +xmlns:tools="http://schemas.android.com/tools">
    
    
      <application ...>
    
    
        <property
          +android:name="android.window.PROPERTY_ACTIVITY_EMBEDDING_SPLITS_ENABLED"
          +android:value="true" />
    
    
        <!-- Existing MainActivity -->
        <activity
          android:name=".MainActivity"
          android:exported="true"
          ...>
          ...
        </activity>
    
    
        <!-- New activity for the detail window -->
        <activity android:name=".DetailActivity" android:exported="true" />
    
    
        +<!-- Register the split initializer -->
        <provider android:name="androidx.startup.InitializationProvider"
          +android:authorities="${applicationId}.androidx-startup"
          +android:exported="false"
          +tools:node="merge">
          <meta-data android:name="${applicationId}.SplitInitializer"
            +android:value="androidx.startup" />
        </provider>
    
    
      </application>
    </manifest>
    
  4. Create the Split Initializer

    The initializer loads the split pair rules at app startup:

    src-tauri/gen/android/app/src/main/java/com/example/app/SplitInitializer.kt

    package com.example.app
    
    
    import android.content.Context
    import androidx.startup.Initializer
    import androidx.window.core.ExperimentalWindowApi
    import androidx.window.embedding.RuleController
    
    
    @OptIn(ExperimentalWindowApi::class)
    class SplitInitializer : Initializer<RuleController> {
      override fun create(context: Context): RuleController {
        return RuleController.getInstance(context).apply {
          setRules(RuleController.parseRules(context, R.xml.main_split_config))
        }
      }
    
    
      override fun dependencies(): List<Class<out Initializer<*>>> {
        return emptyList()
      }
    }
    
  5. Define Split Rules

    Create an XML resource that tells the system how to pair activities and split the screen:

    src-tauri/gen/android/app/src/main/res/xml/main_split_config.xml

    <resources
      xmlns:window="http://schemas.android.com/apk/res-auto">
    
    
      <SplitPairRule
        window:splitRatio="0.33"
        window:splitLayoutDirection="locale"
        window:splitMinWidthDp="840"
        window:splitMaxAspectRatioInPortrait="alwaysAllow"
        window:finishPrimaryWithSecondary="never"
        window:finishSecondaryWithPrimary="never"
        window:clearTop="false">
        <SplitPairFilter
          window:primaryActivityName=".MainActivity"
          window:secondaryActivityName=".DetailActivity"/>
      </SplitPairRule>
    
    
    </resources>
    

    Key attributes:

    • splitRatio — how the screen is divided (0.33 gives the primary activity one-third)
    • splitMinWidthDp — minimum screen width to activate the split (840dp targets tablets)
    • splitMaxAspectRatioInPortrait — set to alwaysAllow to enable split in portrait mode
    • primaryActivityName / secondaryActivityName — which activity pair triggers the split

iOS

On iOS, multi-window uses the UIScene API. iPad users can open new windows by long-pressing the app icon and selecting “New window”, or your app can create them programmatically.

  1. Enable Scene Support

    Create an Info.ios.plist file in your src-tauri directory to declare scene support:

    src-tauri/Info.ios.plist

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
      "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
      <key>UIApplicationSceneManifest</key>
      <dict>
        <key>UIApplicationSupportsMultipleScenes</key>
        <true/>
        <key>UISceneConfigurations</key>
        <dict/>
      </dict>
    </dict>
    </plist>
    
  2. Handle Scene Requests

    When a user requests a new window on iPad (for example by long-pressing the app icon), Tauri emits a RunEvent::SceneRequested event. Handle it to create a new window:

    src-tauri/src/lib.rs

    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
        #[cfg(target_os = "ios")]
        let mut counter = 0;
    
    
        tauri::Builder::default()
            .setup(|app| {
                tauri::WebviewWindowBuilder::new(
                    app, "main", tauri::WebviewUrl::default()
                ).build()?;
                Ok(())
            })
            .build(tauri::generate_context!())
            .expect("error while running tauri application")
            .run(move |app, event| {
                #[cfg(target_os = "ios")]
                if let tauri::RunEvent::SceneRequested { .. } = event {
                    counter += 1;
                    tauri::WebviewWindowBuilder::new(
                        app,
                        format!("main-{counter}"),
                        tauri::WebviewUrl::default(),
                    )
                    .build()
                    .unwrap();
                }
                #[cfg(not(target_os = "ios"))]
                let _ = (app, event);
            });
    }
    

    Note

    Since scene-requested windows use dynamic labels like main-1, main-2, etc., make sure your capabilities file includes a wildcard pattern to cover them — e.g. "windows": ["main", "main-*"].

Creating Windows

You can create additional windows from both Rust and the frontend JavaScript API. The WebviewWindowBuilder (Rust) and WebviewWindow (JavaScript) accept platform-specific options:

Android options:

  • activityName — the name of the Android Activity class to create for this window.
  • createdByActivityName — the name of the Activity that is creating this window. This determines which activity stack the new activity belongs to, which is important for the split rules to work correctly. When not set, it is automatically inherited from the manager (e.g. when building from a Window or Webview handle).

iOS options:

  • requestedBySceneIdentifier — sets the identifier of the UIScene that is requesting the creation of this new scene, establishing a relationship between the two scenes. By default the system uses the foreground scene. When not set, it is automatically inherited from the manager.
  • JavaScript

    import { WebviewWindow } from '@tauri-apps/api/webviewWindow';
    
    
    function openDetail(id) {
      const webview = new WebviewWindow(`detail-${id}`, {
        url: `detail/${id}`,
        activityName: 'DetailActivity',
      });
      webview.once('tauri://created', () => {
        console.log('window created');
      });
      webview.once('tauri://error', (e) => {
        console.error(e);
      });
    }
    
  • Rust

    use tauri::Manager;
    
    
    let main_window = app.get_webview_window("main").unwrap();
    // use the main_window instance so the relationships are determined automatically
    let builder = tauri::WebviewWindowBuilder::new(main_window, "detail", tauri::WebviewUrl::App("detail/1".into()));
    
    
    #[cfg(target_os = "android")]
    let builder = builder.activity_name("DetailActivity");
    
    
    let window = builder.build()?;
    

Tip

If you are using a frontend router, use a browser-history based router (e.g. createBrowserRouter in React Router) instead of a hash router so each window can navigate to a distinct URL path.

Window Instance APIs

Once a window has been created, you can retrieve its platform-specific identifier:

  • JavaScript

    const activityName = await window.activityName();
    const sceneId = await window.sceneIdentifier();
    
  • Rust

    #[cfg(target_os = "android")]
    let activity = window.activity_name()?;
    
    
    #[cfg(target_os = "ios")]
    let scene_id = window.scene_identifier()?;
    

These getters are useful for referencing a windows identity when creating related windows. For example, you can read a windows activityName to pass as createdByActivityName on a new window, or read sceneIdentifier to pass as requestedBySceneIdentifier.

Capabilities for Different Windows and Platforms

This guide will help you customize the capabilities of your Tauri app.

Content of this guide

  • Create multiple windows in a Tauri app
  • Use different capabilities for different windows
  • Use platform-specific capabilities

Prerequisites

This exercise is meant to be read after completing Using Plugin Permissions.

Guide

  1. Create Multiple Windows in a Tauri Application

    Here we create an app with two windows labelled first and second. There are multiple ways to create windows in your Tauri application.

    Create Windows with the Tauri Configuration File

    In the Tauri configuration file, usually named tauri.conf.json:

    Show solution

      "productName": "multiwindow",
      ...
      "app": {
        "windows": [
          {
            "label": "first",
            "title": "First",
            "width": 800,
            "height": 600
          },
          {
            "label": "second",
            "title": "Second",
            "width": 800,
            "height": 600
          }
        ],
      },
      ...
    }
    

    Create Windows Programmatically

    In the Rust code to create a Tauri app:

    Show solution

    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![greet])
        .setup(|app| {
            let webview_url = tauri::WebviewUrl::App("index.html".into());
            // First window
            tauri::WebviewWindowBuilder::new(app, "first", webview_url.clone())
                .title("First")
                .build()?;
            // Second window
            tauri::WebviewWindowBuilder::new(app, "second", webview_url)
                .title("Second")
                .build()?;
            Ok(())
        })
        .run(context)
        .expect("error while running tauri application");
    
  2. Apply Different Capabilities to Different Windows

    The windows of a Tauri app can use different features or plugins of the Tauri backend. For better security it is recommended to only give the necessary capabilities to each window. We simulate a scenario where the first windows uses filesystem and dialog functionalities and second only needs dialog functionalities.

    Separate capability files per category

    It is recommended to separate the capability files per category of actions they enable.

    Show solution

    JSON files in the src-tauri/capabilities will be taken into account for the capability system. Here we separate capabilities related to the filesystem and dialog window into filesystem.json and dialog.json.

    filetree of the Tauri project:

    /src
    /src-tauri
      /capabilities
        filesystem.json
        dialog.json
      tauri.conf.json
    package.json
    README.md
    

    Give filesystem capabilities to the first window

    We give the first window the capability to have read access to the content of the $HOME directory.

    Show solution

    Use the windows field in a capability file with one or multiple window labels.

    filesystem.json

    {
      "identifier": "fs-read-home",
      "description": "Allow access file access to home directory",
      "local": true,
      "windows": ["first"],
      "permissions": [
        "fs:allow-home-read",
      ]
    }
    

    Give dialog capabilities to the first and second window

    We give to first and second windows the capability to create a “Yes/No” dialog

    Show solution

    Use the windows field in a capability file with one or multiple window labels.

    dialog.json

    {
      "identifier": "dialog",
      "description": "Allow to open a dialog",
      "local": true,
      "windows": ["first", "second"],
      "permissions": ["dialog:allow-ask"]
    }
    
  3. Make Capabilities Platform Dependent

    We now want to customize the capabilities to be active only on certain platforms. We make our filesystem capabilities only active on linux and windows.

    Show solution

    Use the platforms field in a capability file to make it platform-specific.

    filesystem.json

    {
      "identifier": "fs-read-home",
      "description": "Allow access file access to home directory",
      "local": true,
      "windows": ["first"],
      "permissions": [
        "fs:allow-home-read",
      ],
      "platforms": ["linux", "windows"]
    }
    

    The currently available platforms are linux, windows, macos, android, and ios.

Conclusion and Resources

We have learned how to create multiple windows in a Tauri app and give them specific capabilities. Furthermore these capabilities can also be targeted to certain platforms.

An example application that used window capabilities can be found in the api example of the Tauri Github repository. The fields that can be used in a capability file are listed in the Capability reference.

Using Plugin Permissions

The goal of this exercise is to get a better understanding on how plugin permissions can be enabled or disabled, where they are described and how to use default permissions of plugins.

At the end you will have the ability to find and use permissions of arbitrary plugins and understand how to custom tailor existing permissions. You will have an example Tauri application where a plugin and plugin specific permissions are used.

  1. Create Tauri Application

    Create your Tauri application. In our example we will facilitate create-tauri-app:

    • Bash

      sh <(curl https://create.tauri.app/sh)
      
    • PowerShell

      irm https://create.tauri.app/ps | iex
      
    • Fish

      sh (curl -sSL https://create.tauri.app/sh | psub)
      
    • npm

      npm create tauri-app@latest
      
    • Yarn

      yarn create tauri-app
      
    • pnpm

      pnpm create tauri-app
      
    • deno

      deno run -A npm:create-tauri-app
      
    • bun

      bun create tauri-app
      
    • Cargo

      cargo install create-tauri-app --locked
      cargo create-tauri-app
      

    We will proceed in this step-by-step explanation with pnpm but you can choose another package manager and replace it in the commands accordingly.

    Show solution

    pnpm create tauri-app
    
    ✔ Project name · plugin-permission-demo
    ✔ Choose which language to use for your frontend · TypeScript / JavaScript - (pnpm, yarn, npm, bun)
    ✔ Choose your package manager · pnpm
    ✔ Choose your UI template · Vanilla
    ✔ Choose your UI flavor · TypeScript
    
    
    Template created! To get started run:
    cd plugin-permission-demo
    pnpm install
    pnpm tauri dev
    
  2. Add the file-system Plugin to Your Application

    To search for existing plugins you can use multiple resources.

    The most straight forward way would be to check out if your plugin is already in the Plugins section of the documentation and therefore part of Tauris maintained plugin set. The Filesystem plugin is part of the Tauri plugin workspace and you can add it to your project by following the instructions.

    If the plugin is part of the community effort you can most likely find it on crates.io when searching for tauri-plugin-<your plugin name>.

    Show solution

    If it is an existing plugin from our workspace you can use the automated way:

    pnpm tauri add fs
    

    If you have found it on crates.io you need to manually add it as a dependency and modify the Tauri builder to initialize the plugin:

    cargo add tauri-plugin-fs
    

    Modify lib.rs to initialize the plugin:

    src-tauri/src/lib.rs

    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    fn run() {
      tauri::Builder::default()
        +.plugin(tauri_plugin_fs::init())
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
    }
    
  3. Understand the Default Permissions of the fs Plugin

    Each plugin has a default permission set, which contains all permissions and scopes to use the plugin out of the box with a reasonable minimal feature set.

    In the case of official maintained plugins you can find a rendered description in the documentation (eg. fs default).

    In case you are figuring this out for a community plugin you need to check out the source code of the plugin. This should be defined in your-plugin/permissions/default.toml.

    Show solution

    "$schema" = "schemas/schema.json"
    
    
    [default]
    description = """
    # Tauri `fs` default permissions
    
    
    This configuration file defines the default permissions granted
    to the filesystem.
    
    
    ### Granted Permissions
    
    
    This default permission set enables all read-related commands and
    allows access to the `$APP` folder and sub directories created in it.
    The location of the `$APP` folder depends on the operating system,
    where the application is run.
    
    
    In general the `$APP` folder needs to be manually created
    by the application at runtime, before accessing files or folders
    in it is possible.
    
    
    ### Denied Permissions
    
    
    This default permission set prevents access to critical components
    of the Tauri application by default.
    On Windows the webview data folder access is denied.
    
    
    """
    permissions = ["read-all", "scope-app-recursive", "deny-default"]
    
  4. Find the Right Permissions

    This step is all about finding the permissions you need to for your commands to be exposed to the frontend with the minimal access to your system.

    The fs plugin has autogenerated permissions which will disable or enable individual commands and allow or disable global scopes.

    These can be found in the documentation or in the source code of the plugin (fs/permissions/autogenerated).

    Let us assume we want to enable writing to a text file test.txt located in the users $HOME folder.

    For this we would search in the autogenerated permissions for a permission to enable writing to text files like allow-write-text-file and then for a scope which would allow us to access the $HOME/test.txt file.

    We need to add these to our capabilities section in our src-tauri/tauri.conf.json or in a file in the src-tauri/capabilities/ folder. By default there is already a capability in src-tauri/capabilities/default.json we can modify.

    Show solution

    src-tauri/capabilities/default.json

    {
      "$schema": "../gen/schemas/desktop-schema.json",
      "identifier": "default",
      "description": "Capability for the main window",
      "windows": [
        "main"
      ],
      "permissions": [
        "path:default",
        "event:default",
        "window:default",
        "app:default",
        "image:default",
        "resources:default",
        "menu:default",
        "tray:default",
        "shell:allow-open",
        -"fs:default",
        +"fs:allow-write-text-file",
      ]
    }
    

    Since there are only autogenerated scopes in the fs plugin to access the full $HOME folder, we need to configure our own scope. This scope should be only enabled for the write-text-file command and should only expose our test.txt file.

    Show solution

    src-tauri/capabilities/default.json

       {
      "$schema": "../gen/schemas/desktop-schema.json",
      "identifier": "default",
      "description": "Capability for the main window",
      "windows": [
        "main"
      ],
      "permissions": [
        "path:default",
        "event:default",
        "window:default",
        "app:default",
        "image:default",
        "resources:default",
        "menu:default",
        "tray:default",
        "shell:allow-open",
        -"fs:allow-write-text-file",
    +    {
          +"identifier": "fs:allow-write-text-file",
          +"allow": [{ "path": "$HOME/test.txt" }]
    +    },
      ]
    }
    
  5. Test Permissions in Practice

    After we have added the necessary permission we want to confirm that our application can access the file and write its content.

    Show solution

    We can use this snippet in our application to write to the file:

    src/main.ts

    import { writeTextFile, BaseDirectory } from '@tauri-apps/plugin-fs';
    
    
    let greetInputEl: HTMLInputElement | null;
    
    
    async function write(message: string) {
        await writeTextFile('test.txt', message, { baseDir: BaseDirectory.Home });
    }
    
    
    window.addEventListener("DOMContentLoaded", () => {
      greetInputEl = document.querySelector("#greet-input");
      document.querySelector("#greet-form")?.addEventListener("submit", (e) => {
        e.preventDefault();
        if (!greetInputEl )
          return;
    
    
        write(greetInputEl.value == "" ? "No input provided": greetInputEl.value);
    
    
      });
    });
    

    Replacing the src/main.ts with this snippet means we do not need to modify the default index.html, when using the plain Vanilla+Typescript app. Entering any input into the input field of the running app will be written to the file on submit.

    Lets test now in practice:

    pnpm run tauri dev
    

    After writing into the input and clicking “Submit”, we can check via our terminal emulator or by manually opening the file in your home folder.

    cat $HOME/test.txt
    

    You should be presented with your input and finished learning about using permissions from plugins in Tauri applications. 🥳

    If you encountered this error:

    [Error] Unhandled Promise Rejection: fs.write_text_file not allowed. Permissions associated with this command: fs:allow-app-write, fs:allow-app-write-recursive, fs:allow-appcache-write, fs:allow-appcache-write-recursive, fs:allow-appconf...
    (anonymous function) (main.ts:5)
    

    Then you very likely did not properly follow the previous instructions.

Writing Plugin Permissions

The goal of this exercise is to get a better understanding on how plugin permissions can be created when writing your own plugin.

At the end you will have the ability to create simple permissions for your plugins. You will have an example Tauri plugin where permissions are partially autogenerated and hand crafted.

  1. Create a Tauri Plugin

    In our example we will facilitate the Tauri cli to bootstrap a Tauri plugin source code structure. Make sure you have installed all Prerequisites and verify you have the Tauri CLI in the correct version by running cargo tauri info.

    The output should indicate the tauri-cli version is 2.x. We will proceed in this step-by-step explanation with pnpm but you can choose another package manager and replace it in the commands accordingly.

    Once you have a recent version installed you can go ahead and create the plugin using the Tauri CLI.

    Show solution

    mkdir -p tauri-learning
    cd tauri-learning
    cargo tauri plugin new test
    cd tauri-plugin-test
    pnpm install
    pnpm build
    cargo build
    
  2. Create a New Command

    To showcase something practical and simple let us assume our command writes user input to a file in our temporary folder while adding some custom header to the file.

    Lets name our command write_custom_file, implement it in src/commands.rs and add it to our plugin builder to be exposed to the frontend.

    Tauris core utils will autogenerate allow and deny permissions for this command, so we do not need to care about this.

    Show solution

    The command implementation:

    src/commands.rs

    use tauri::{AppHandle, command, Runtime};
    
    
    use crate::models::*;
    use crate::Result;
    use crate::TestExt;
    
    
    #[command]
    pub(crate) async fn ping<R: Runtime>(
        app: AppHandle<R>,
        payload: PingRequest,
    ) -> Result<PingResponse> {
        app.test1().ping(payload)
    }
    
    
    +#[command]
    +pub(crate) async fn write_custom_file<R: Runtime>(
        +user_input: String,
        +app: AppHandle<R>,
    +) -> Result<String> {
    +    std::fs::write(app.path().temp_dir().unwrap(), user_input)?;
    +    Ok("success".to_string())
    +}
    

    Auto-Generate inbuilt permissions for your new command:

    src/build.rs

    const COMMANDS: &[&str] = &["ping", "write_custom_file"];
    

    These inbuilt permissions will be automatically generated by the Tauri build system and will be visible in the permissions/autogenerated/commands folder. By default an enable-<command> and deny-<command> permission will be created.

  3. Expose the New Command

    The previous step was to write the actual command implementation. Next we want to expose it to the frontend so it can be consumed.

    Show solution

    Configure the Tauri builder to generate the invoke handler to pass frontend IPC requests to the newly implemented command:

    src/lib.rs

    pub fn init<R: Runtime>() -> TauriPlugin<R> {
    Builder::new("test")
        .invoke_handler(tauri::generate_handler![
            commands::ping,
            commands::write_custom_file,
        ])
        .setup(|app, api| {
            #[cfg(mobile)]
            let test = mobile::init(app, api)?;
            #[cfg(desktop)]
            let test = desktop::init(app, api)?;
            app.manage(test);
    
    
            // manage state so it is accessible by the commands
            app.manage(MyState::default());
            Ok(())
        })
        .build()
    }
    

    Expose the new command in the frontend module.

    This step is essential for the example application to successfully import the frontend module. This is for convenience and has no security impact, as the command handler is already generated and the command can be manually invoked from the frontend.

    guest-js/index.ts

    import { invoke } from '@tauri-apps/api/core'
    
    
    export async function ping(value: string): Promise<string | null> {
      return await invoke<{value?: string}>('plugin:test|ping', {
        payload: {
          value,
        },
      }).then((r) => (r.value ? r.value : null));
    }
    
    
    +export async function writeCustomFile(user_input: string): Promise<string> {
     +return await invoke('plugin:test|write_custom_file',{userInput: user_input});
    +}
    

    Tip

    The invoke parameter needs to be CamelCase. In this example it is userInput instead of user_input.

    Make sure your package is built:

    pnpm build
    
  4. Define Default Plugin Permissions

    As our plugin should expose the write_custom_file command by default we should add this to our default.toml permission.

    Show solution

    Add this to our default permission set to allow the new command we just exposed.

    permissions/default.toml

    "$schema" = "schemas/schema.json"
    [default]
    description = "Default permissions for the plugin"
    permissions = ["allow-ping", "allow-write-custom-file"]
    
  5. Invoke Test Command from Example Application

    The created plugin directory structure contains an examples/tauri-app folder, which has a ready to use Tauri application to test out the plugin.

    Since we added a new command we need to slightly modify the frontend to invoke our new command instead.

    Show solution

    src/App.svelte

    <script>
      import Greet from './lib/Greet.svelte'
      import { ping, writeCustomFile } from 'tauri-plugin-test-api'
    
    
      let response = ''
    
    
      function updateResponse(returnValue) {
        response += `[${new Date().toLocaleTimeString()}]` + (typeof returnValue === 'string' ? returnValue : JSON.stringify(returnValue)) + '<br>'
      }
    
    
      -function _ping() {
        -ping("Pong!").then(updateResponse).catch(updateResponse)
    -  }
      +function _writeCustomFile() {
        +writeCustomFile("HELLO FROM TAURI PLUGIN").then(updateResponse).catch(updateResponse)
    +  }
    </script>
    
    
    <main class="container">
      <h1>Welcome to Tauri!</h1>
    
    
      <div class="row">
        <a href="https://vitejs.dev" target="_blank">
          <img src="/vite.svg" class="logo vite" alt="Vite Logo" />
        </a>
        <a href="https://tauri.app" target="_blank">
          <img src="/tauri.svg" class="logo tauri" alt="Tauri Logo" />
        </a>
        <a href="https://svelte.dev" target="_blank">
          <img src="/svelte.svg" class="logo svelte" alt="Svelte Logo" />
        </a>
      </div>
    
    
      <p>
        Click on the Tauri, Vite, and Svelte logos to learn more.
      </p>
    
    
      <div class="row">
        <Greet />
      </div>
    
    
      <div>
        <button on:click="{_ping}">Ping</button>
        <div>{@html response}</div>
      </div>
      <div>
        <button on:click="{_writeCustomFile}">Write</button>
        <div>{@html response}</div>
      </div>
    
    
    
    
    </main>
    
    
    <style>
      .logo.vite:hover {
        filter: drop-shadow(0 0 2em #747bff);
      }
    
    
      .logo.svelte:hover {
        filter: drop-shadow(0 0 2em #ff3e00);
      }
    </style>
    

    Running this and pressing the “Write” button you should be greeted with this:

    success
    

    And you should find a test.txt file in your temporary folder containing a message from our new implemented plugin command. 🥳

Node.js as a sidecar

In this guide we are going to package a Node.js application to a self contained binary to be used as a sidecar in a Tauri application without requiring the end user to have a Node.js installation. This example tutorial is applicable for desktop operating systems only.

We recommend reading the general sidecar guide first for a deeper understanding of how Tauri sidecars work.

Goals

  • Package a Node.js application as a binary.
  • Integrate this binary as a Tauri sidecar.

Implementation Details

  • For this we use the pkg tool, but any other tool that can compile JavaScript or Typescript into a binary application will work.
  • You can also embed the Node runtime itself into your Tauri application and ship bundled JavaScript as a resource, but this will ship the JavaScript content as readable-ish files and the runtime is usually larger than a pkg packaged application.

In this example we will create a Node.js application that reads input from the command line process.argv and writes output to stdout using console.log.
You can leverage alternative inter-process communication systems such as a localhost server, stdin/stdout or local sockets. Note that each has their own advantages, drawbacks and security concerns.

Prerequisites

An existing Tauri application set up with the shell plugin, that compiles and runs for you locally.

Create a lab app

If you are not an advanced user its highly recommended that you use the options and frameworks provided here. Its just a lab, you can delete the project when youre done.

  • Bash

    sh <(curl https://create.tauri.app/sh)
    
  • PowerShell

    irm https://create.tauri.app/ps | iex
    
  • Fish

    sh (curl -sSL https://create.tauri.app/sh | psub)
    
  • npm

    npm create tauri-app@latest
    
  • Yarn

    yarn create tauri-app
    
  • pnpm

    pnpm create tauri-app
    
  • deno

    deno run -A npm:create-tauri-app
    
  • bun

    bun create tauri-app
    
  • Cargo

    cargo install create-tauri-app --locked
    cargo create-tauri-app
    
  • Project name: node-sidecar-lab
  • Choose which language to use for your frontend: Typescript / Javascript
  • Choose your package manager: pnpm
  • Choose your UI template: Vanilla
  • Choose your UI flavor: Typescript

Note

Please follow the shell plugin guide first to set up and initialize the plugin correctly. Without the plugin being initialized and configured the example wont work.

Guide

  1. Initialize Sidecar Project

    Lets create a new Node.js project to contain our sidecar implementation. Create a new directory in your Tauri application root folder (in this example we will call it sidecar-app) and run the init command of your preferred Node.js package manager inside the directory:

    • npm

      npm init
      
    • yarn

      yarn init
      
    • pnpm

      pnpm init
      

    We will compile our Node.js application to a self container binary using pkg among other options. Lets install it as a development dependency into the new sidecar-app:

    • npm

      npm add @yao-pkg/pkg --save-dev
      
    • yarn

      yarn add @yao-pkg/pkg --dev
      
    • pnpm

      pnpm add @yao-pkg/pkg --save-dev
      
  2. Write Sidecar Logic

    Now we can start writing JavaScript code that will be executed by our Tauri application.

    In this example we will process a command from the command line argmuents and write output to stdout, which means our process will be short lived and only handle a single command at a time. If your application must be long lived, consider using alternative inter-process communication systems.

    Lets create a index.js file in our sidecar-app directory and write a basic Node.js app:

    sidecar-app/index.js

    const command = process.argv[2];
    
    
    switch (command) {
      case 'hello':
        const message = process.argv[3];
        console.log(`Hello ${message}!`);
        break;
      default:
        console.error(`unknown command ${command}`);
        process.exit(1);
    }
    
  3. Package the Sidecar

    To package our Node.js application into a self contained binary, create a script in package.json:

    sidecar-app/package.json

    {
      "scripts": {
        "build": "pkg index.ts --output my-sidecar"
      }
    }
    
    • npm

      npm run build
      
    • yarn

      yarn build
      
    • pnpm

      pnpm build
      

    This will create the sidecar-app/my-sidecar binary on Linux and macOS, and a sidecar-app/my-sidecar.exe executable on Windows.

    For sidecar applications, we need to ensure that the binary is named in the correct pattern, for more information read Embedding External Binaries To rename this file to the expected Tauri sidecar filename and also move to our Tauri project, we can use the following Node.js script as a starting example:

    sidecar-app/rename.js

    import { execSync } from 'child_process';
    import fs from 'fs';
    
    
    const ext = process.platform === 'win32' ? '.exe' : '';
    
    
    const targetTriple = execSync('rustc --print host-tuple').toString().trim();
    if (!targetTriple) {
      console.error('Failed to determine platform target triple');
    }
    // TODO: create `src-tauri/binaries` dir
    fs.renameSync(
      `my-sidecar${ext}`,
      `../src-tauri/binaries/my-sidecar-${targetTriple}${ext}`
    );
    

    Note

    The --print host-tuple flag was added in Rust 1.84.0. If youre using an older version, youll need to parse the output of rustc -Vv instead:

    const rustInfo = execSync('rustc -vV');
    const targetTriple = /host: (\S+)/g.exec(rustInfo)[1];
    

    And run node rename.js from the sidecar-app directory.

    At this step the /src-tauri/binaries directory should contain the renamed sidecar binary.

  4. Setup plugin-shell permission

    After installing the shell plugin make sure you configure the required capabilities.

    Note that we use "args": true but you can optionally provide an array ["hello"], read more.

    src-tauri/capabilities/default.json

    {
      "permissions": [
        "core:default",
        "opener:default",
        {
          "identifier": "shell:allow-execute",
          "allow": [
            {
              "args": true,
              "name": "binaries/my-sidecar",
              "sidecar": true
            }
          ]
        }
      ]
    }
    
  5. Configure the Sidecar in the Tauri Application

    Now that we have our Node.js application ready, we can connect it to our Tauri application by configuring the bundle > externalBin array:

    src-tauri/tauri.conf.json

    {
      "bundle": {
        "externalBin": ["binaries/my-sidecar"]
      }
    }
    

    The Tauri CLI will handle the bundling of the sidecar binary as long as it exists as src-tauri/binaries/my-sidecar-<target-triple>.

  6. Execute the Sidecar

    We can run the sidecar binary either from Rust code or directly from JavaScript.

    • JavaScript

      Lets execute the hello command in the Node.js sidecar directly:

      import { Command } from '@tauri-apps/plugin-shell';
      
      
      const message = 'Tauri';
      
      
      const command = Command.sidecar('binaries/my-sidecar', ['hello', message]);
      const output = await command.execute();
      // once everything is configured it should log "Hello Tauri" in the browser console.
      console.log(output.stdout)
      
    • Rust

      Lets pipe a hello Tauri command to the Node.js sidecar:

      use tauri_plugin_shell::ShellExt;
      
      
      #[tauri::command]
      async fn hello(app: tauri::AppHandle, cmd: String, message: String) -> String {
          let sidecar_command = app
              .shell()
              .sidecar("my-sidecar")
              .unwrap()
              .arg(cmd)
              .arg(message);
          let output = sidecar_command.output().await.unwrap();
          String::from_utf8(output.stdout).unwrap()
      }
      

      Register it in invoke_handler and call it in the frontend with:

      import { invoke } from "@tauri-apps/api/core";
      
      
      const message = "Tauri"
      console.log(await invoke("hello", { cmd: 'hello', message }))
      
  7. Running

    Lets test it

    • npm

      npm run tauri dev
      
    • yarn

      yarn tauri dev
      
    • pnpm

      pnpm tauri dev
      
    • deno

      deno task tauri dev
      
    • bun

      bun tauri dev
      
    • cargo

      cargo tauri dev
      

    Open the DevTools with F12 (or Cmd+Option+I on macOS) and you should see the output of the sidecar command.

    If you find any issues, please open an issue on GitHub.

Splashscreen

In this lab well be implementing a basic splashscreen functionality in a Tauri app. Doing so is quite straight forward, a splashscreen is effectively just a matter of creating a new window that displays some contents during the period your app is doing some heavy setup related tasks and then closing it when setting up is done.

Prerequisites

Create a lab app

If you are not an advanced user its highly recommended that you use the options and frameworks provided here. Its just a lab, you can delete the project when youre done.

  • Bash

    sh <(curl https://create.tauri.app/sh)
    
  • PowerShell

    irm https://create.tauri.app/ps | iex
    
  • Fish

    sh (curl -sSL https://create.tauri.app/sh | psub)
    
  • npm

    npm create tauri-app@latest
    
  • Yarn

    yarn create tauri-app
    
  • pnpm

    pnpm create tauri-app
    
  • deno

    deno run -A npm:create-tauri-app
    
  • bun

    bun create tauri-app
    
  • Cargo

    cargo install create-tauri-app --locked
    cargo create-tauri-app
    
  • Project name: splashscreen-lab
  • Choose which language to use for your frontend: Typescript / Javascript
  • Choose your package manager: pnpm
  • Choose your UI template: Vanilla
  • Choose your UI flavor: Typescript

Steps

  1. Install dependencies and run the project

    Before you start developing any project its important to build and run the initial template, just to validate your setup is working as intended.

    Show solution

    # Make sure you're in the right directory
    cd splashscreen-lab
    # Install dependencies
    pnpm install
    # Build and run the app
    pnpm tauri dev
    

    Successful run of the created template app.

  2. Register new windows in tauri.conf.json

    The easiest way of adding new windows is by adding them directly to tauri.conf.json. You can also create them dynamically at startup, but for the sake of simplicity lets just register them instead. Make sure you have a window with the label main thats being created as a hidden window and a window with the label splashscreen thats created as being shown directly. You can leave all other options as their defaults, or tweak them based on preference.

    Show solution

    src-tauri/tauri.conf.json

    {
        "windows": [
            {
                "label": "main",
                "visible": false
            },
            {
                "label": "splashscreen",
                "url": "/splashscreen"
            }
        ]
    }
    
  3. Create a new page to host your splashscreen

    Before you begin youll need to have some content to show. How you develop new pages depend on your chosen framework, most have the concept of a “router” that handles page navigation which should work just like normal in Tauri, in which case you just create a new splashscreen page. Or as were going to be doing here, create a new splashscreen.html file to host the contents.

    Whats important here is that you can navigate to a /splashscreen URL and be shown the contents you want for your splashscreen. Try running the app again after this step!

    Show solution

    /splashscreen.html

    <!doctype html>
    <html lang="en">
    <head>
        <meta charset="UTF-8" />
        <link rel="stylesheet" href="/src/styles.css" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Tauri App</title>
    </head>
    <body>
        <div class="container">
            <h1>Tauri used Splash!</h1>
            <div class="row">
                <h5>It was super effective!</h5>
            </div>
        </div>
    </body>
    </html>
    

    The splashscreen we just created.

  4. Start some setup tasks

    Since splashscreens are generally intended to be used for the sake of hiding heavy setup related tasks, lets fake giving the app something heavy to do, some in the frontend and some in the backend.

    To fake heavy setup in the frontend were going to be using a simple setTimeout function.

    The easiest way to fake heavy operations in the backend is by using the Tokio crate, which is the Rust crate that Tauri uses in the backend to provide an asynchronous runtime. While Tauri provides the runtime there are various utilities that Tauri doesnt re-export from it, so well need to add the crate to our project in order to access them. This is a perfectly normal practice within the Rust ecosystem.

    Dont use std::thread::sleep in async functions, they run cooperatively in a concurrent environment not in parallel, meaning that if you sleep the thread instead of the Tokio task youll be locking all tasks scheduled to run on that thread from being executed, causing your app to freeze.

    Show solution

    # Run this command where the `Cargo.toml` file is
    cd src-tauri
    # Add the Tokio crate
    cargo add tokio -F time
    # Optionally go back to the top folder to keep developing
    # `tauri dev` can figure out where to run automatically
    cd ..
    

    src/main.ts

    // These contents can be copy-pasted below the existing code, don't replace the entire file!!
    
    
    // Utility function to implement a sleep function in TypeScript
    function sleep(seconds: number): Promise<void> {
        return new Promise(resolve => setTimeout(resolve, seconds * 1000));
    }
    
    
    // Setup function
    async function setup() {
        // Fake perform some really heavy setup task
        console.log('Performing really heavy frontend setup task...')
        await sleep(3);
        console.log('Frontend setup task complete!')
        // Set the frontend task as being completed
        invoke('set_complete', {task: 'frontend'})
    }
    
    
    // Effectively a JavaScript main function
    window.addEventListener("DOMContentLoaded", () => {
        setup()
    });
    

    /src-tauri/src/lib.rs

    // Import functionalities we'll be using
    use std::sync::Mutex;
    use tauri::async_runtime::spawn;
    use tauri::{AppHandle, Manager, State};
    use tokio::time::{sleep, Duration};
    
    
    // Create a struct we'll use to track the completion of
    // setup related tasks
    struct SetupState {
        frontend_task: bool,
        backend_task: bool,
    }
    
    
    // Our main entrypoint in a version 2 mobile compatible app
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
        // Don't write code before Tauri starts, write it in the
        // setup hook instead!
        tauri::Builder::default()
            // Register a `State` to be managed by Tauri
            // We need write access to it so we wrap it in a `Mutex`
            .manage(Mutex::new(SetupState {
                frontend_task: false,
                backend_task: false,
            }))
            // Add a command we can use to check
            .invoke_handler(tauri::generate_handler![greet, set_complete])
            // Use the setup hook to execute setup related tasks
            // Runs before the main loop, so no windows are yet created
            .setup(|app| {
                // Spawn setup as a non-blocking task so the windows can be
                // created and ran while it executes
                spawn(setup(app.handle().clone()));
                // The hook expects an Ok result
                Ok(())
            })
            // Run the app
            .run(tauri::generate_context!())
            .expect("error while running tauri application");
    }
    
    
    #[tauri::command]
    fn greet(name: String) -> String {
        format!("Hello {name} from Rust!")
    }
    
    
    // A custom task for setting the state of a setup task
    #[tauri::command]
    async fn set_complete(
        app: AppHandle,
        state: State<'_, Mutex<SetupState>>,
        task: String,
    ) -> Result<(), ()> {
        // Lock the state without write access
        let mut state_lock = state.lock().unwrap();
        match task.as_str() {
            "frontend" => state_lock.frontend_task = true,
            "backend" => state_lock.backend_task = true,
            _ => panic!("invalid task completed!"),
        }
        // Check if both tasks are completed
        if state_lock.backend_task && state_lock.frontend_task {
            // Setup is complete, we can close the splashscreen
            // and unhide the main window!
            let splash_window = app.get_webview_window("splashscreen").unwrap();
            let main_window = app.get_webview_window("main").unwrap();
            splash_window.close().unwrap();
            main_window.show().unwrap();
        }
        Ok(())
    }
    
    
    // An async function that does some heavy setup task
    async fn setup(app: AppHandle) -> Result<(), ()> {
        // Fake performing some heavy action for 3 seconds
        println!("Performing really heavy backend setup task...");
        sleep(Duration::from_secs(3)).await;
        println!("Backend setup task completed!");
        // Set the backend task as being completed
        // Commands can be ran as regular functions as long as you take
        // care of the input arguments yourself
        set_complete(
            app.clone(),
            app.state::<Mutex<SetupState>>(),
            "backend".to_string(),
        )
        .await?;
        Ok(())
    }
    
  5. Run the application

    You should now see a splashscreen window pop up, both the frontend and backend will perform their respective heavy 3 second setup tasks, after which the splashscreen disappears and the main window is shown!

Discuss

Should you have a splashscreen?

In general having a splashscreen is an admittance of defeat that you couldnt make your app load fast enough to not need one. In fact it tends to be better to just go straight to a main window that then shows some little spinner somewhere in a corner informing the user theres still setup tasks happening in the background.

However, with that said, it can be a stylistic choice that you want to have a splashscreen, or you might have some very particular requirement that makes it impossible to start the app until some tasks are performed. Its definitely not wrong to have a splashscreen, it just tends to not be necessary and can make users feel like the app isnt very well optimized.

System Tray

Tauri allows you to create and customize a system tray for your application. This can enhance the user experience by providing quick access to common actions.

Configuration

First of all, update your Cargo.toml to include the necessary feature for the system tray.

src-tauri/Cargo.toml

tauri = { version = "2.0.0", features = [ "tray-icon" ] }

Usage

The tray API is available in both JavaScript and Rust.

Create a Tray Icon

  • JavaScript

    Use the TrayIcon.new static function to create a new tray icon:

    import { TrayIcon } from '@tauri-apps/api/tray';
    
    
    const options = {
      // here you can add a tray menu, title, tooltip, event handler, etc
    };
    
    
    const tray = await TrayIcon.new(options);
    

    See TrayIconOptions for more information on the customization options.

  • Rust

    use tauri::tray::TrayIconBuilder;
    
    
    tauri::Builder::default()
        .setup(|app| {
            let tray = TrayIconBuilder::new().build(app)?;
            Ok(())
        })
    

    See TrayIconBuilder for more information on customization options.

Change the Tray Icon

When creating the tray you can use the application icon as the tray icon:

  • JavaScript

    import { TrayIcon } from '@tauri-apps/api/tray';
    import { defaultWindowIcon } from '@tauri-apps/api/app';
    
    
    const options = {
      icon: await defaultWindowIcon(),
    };
    
    
    const tray = await TrayIcon.new(options);
    
  • Rust

    let tray = TrayIconBuilder::new()
      .icon(app.default_window_icon().unwrap().clone())
      .build(app)?;
    

Add a Menu

To attach a menu that is displayed when the tray is clicked, you can use the menu option.

Note

By default the menu is displayed on both left and right clicks.

To prevent the menu from popping up on left click, call the show_menu_on_left_click(false) Rust function or set the menuOnLeftClick JavaScript option to false.

  • JavaScript

    import { TrayIcon } from '@tauri-apps/api/tray';
    import { Menu } from '@tauri-apps/api/menu';
    
    
    const menu = await Menu.new({
      items: [
        {
          id: 'quit',
          text: 'Quit',
        },
      ],
    });
    
    
    const options = {
      menu,
      menuOnLeftClick: true,
    };
    
    
    const tray = await TrayIcon.new(options);
    
  • Rust

    use tauri::{
      menu::{Menu, MenuItem},
      tray::TrayIconBuilder,
    };
    
    
    let quit_i = MenuItem::with_id(app, "quit", "Quit", true, None::<&str>)?;
    let menu = Menu::with_items(app, &[&quit_i])?;
    
    
    let tray = TrayIconBuilder::new()
      .menu(&menu)
      .show_menu_on_left_click(true)
      .build(app)?;
    

Listen to Menu Events

  • JavaScript

    On JavaScript you can attach a menu click event listener directly to the menu item:

    • Using a shared menu click handler

      import { Menu } from '@tauri-apps/api/menu';
      
      
      function onTrayMenuClick(itemId) {
        // itemId === 'quit'
      }
      
      
      const menu = await Menu.new({
        items: [
          {
            id: 'quit',
            text: 'Quit',
            action: onTrayMenuClick,
          },
        ],
      });
      
    • Using a dedicated menu click handler

      import { Menu } from '@tauri-apps/api/menu';
      
      
      const menu = await Menu.new({
        items: [
          {
            id: 'quit',
            text: 'Quit',
            action: () => {
              console.log('quit pressed');
            },
          },
        ],
      });
      
  • Rust

    Use the TrayIconBuilder::on_menu_event method to attach a tray menu click event listener:

    use tauri::tray::TrayIconBuilder;
    
    
    TrayIconBuilder::new()
      .on_menu_event(|app, event| match event.id.as_ref() {
        "quit" => {
          println!("quit menu item was clicked");
          app.exit(0);
        }
        _ => {
          println!("menu item {:?} not handled", event.id);
        }
      })
    

Listen to Tray Events

The tray icon emits events for the following mouse events:

  • click: triggered when the cursor receives a single left, right or middle click, including information on whether the mouse press was released or not
  • Double click: triggered when the cursor receives a double left, right or middle click
  • Enter: triggered when the cursor enters the tray icon area
  • Move: triggered when the cursor moves around the tray icon area
  • Leave: triggered when the cursor leaves the tray icon area

Note

Linux: Unsupported. The event is not emitted even though the icon is shown and will still show a context menu on right click.

  • JavaScript

    import { TrayIcon } from '@tauri-apps/api/tray';
    
    
    const options = {
      action: (event) => {
        switch (event.type) {
          case 'Click':
            console.log(
              `mouse ${event.button} button pressed, state: ${event.buttonState}`
            );
            break;
          case 'DoubleClick':
            console.log(`mouse ${event.button} button pressed`);
            break;
          case 'Enter':
            console.log(
              `mouse hovered tray at ${event.rect.position.x}, ${event.rect.position.y}`
            );
            break;
          case 'Move':
            console.log(
              `mouse moved on tray at ${event.rect.position.x}, ${event.rect.position.y}`
            );
            break;
          case 'Leave':
            console.log(
              `mouse left tray at ${event.rect.position.x}, ${event.rect.position.y}`
            );
            break;
        }
      },
    };
    
    
    const tray = await TrayIcon.new(options);
    

    See TrayIconEvent for more information on the event payload.

  • Rust

    use tauri::{
        Manager,
        tray::{MouseButton, MouseButtonState, TrayIconBuilder, TrayIconEvent}
    };
    
    
    TrayIconBuilder::new()
      .on_tray_icon_event(|tray, event| match event {
        TrayIconEvent::Click {
          button: MouseButton::Left,
          button_state: MouseButtonState::Up,
          ..
        } => {
          println!("left click pressed and released");
          // in this example, let's show and focus the main window when the tray is clicked
          let app = tray.app_handle();
          if let Some(window) = app.get_webview_window("main") {
            let _ = window.unminimize();
            let _ = window.show();
            let _ = window.set_focus();
          }
        }
        _ => {
          println!("unhandled event {event:?}");
        }
      })
    

    See TrayIconEvent for more information on the event type.

For detailed information about creating menus, including menu items, submenus, and dynamic updates, see the Window Menu documentation.

Window Customization

Tauri provides lots of options for customizing the look and feel of your apps window. You can create custom titlebars, have transparent windows, enforce size constraints, and more.

Configuration

There are three ways to change the window configuration:

Usage

Creating a Custom Titlebar

A common use of these window features is creating a custom titlebar. This short tutorial will guide you through that process.

Note

For macOS, using a custom titlebar will also lose some features provided by the system, such as moving or aligning the window. Another approach to customizing the titlebar but keeping native functions could be making the titlebar transparent and setting the window background color. See the usage (macOS) Transparent Titlebar with Custom Window Background Color.

tauri.conf.json

Set decorations to false in your tauri.conf.json:

tauri.conf.json

"tauri": {
  "windows": [
    {
      "decorations": false
    }
  ]
}

Permissions

Add window permissions in capability file.

By default, all plugin commands are blocked and cannot be accessed. You must define a list of permissions in your capabilities configuration.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    +"core:window:default",
    +"core:window:allow-close",
    +"core:window:allow-minimize",
    +"core:window:allow-toggle-maximize",
    +"core:window:allow-start-dragging"
  ]
}
Permission Description
core:window:default Default permissions for the plugin. This includes core:window:allow-internal-toggle-maximize.
core:window:allow-close Enables the close command without any pre-configured scope.
core:window:allow-minimize Enables the minimize command without any pre-configured scope.
core:window:allow-start-dragging Enables the start_dragging command without any pre-configured scope.
core:window:allow-toggle-maximize Enables the toggle_maximize command without any pre-configured scope.
core:window:allow-internal-toggle-maximize Enables the internal_toggle_maximize command without any pre-configured scope.

CSS

Add this CSS sample to keep it at the top of the screen and style the buttons:

.titlebar {
  height: 30px;
  background: #329ea3;
  user-select: none;
  display: grid;
  grid-template-columns: auto max-content;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
}
.titlebar > .controls {
  display: flex;
}
.titlebar button {
  appearance: none;
  padding: 0;
  margin: 0;
  border: none;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  width: 30px;
  background-color: transparent;
}
.titlebar button:hover {
  background: #5bbec3;
}

HTML

Put this at the top of your <body> tag:

<div class="titlebar">
  <div data-tauri-drag-region></div>
  <div class="controls">
    <button id="titlebar-minimize" title="minimize">
      <!-- https://api.iconify.design/mdi:window-minimize.svg -->
      <svg
        xmlns="http://www.w3.org/2000/svg"
        width="24"
        height="24"
        viewBox="0 0 24 24"
      >
        <path fill="currentColor" d="M19 13H5v-2h14z" />
      </svg>
    </button>
    <button id="titlebar-maximize" title="maximize">
      <!-- https://api.iconify.design/mdi:window-maximize.svg -->
      <svg
        xmlns="http://www.w3.org/2000/svg"
        width="24"
        height="24"
        viewBox="0 0 24 24"
      >
        <path fill="currentColor" d="M4 4h16v16H4zm2 4v10h12V8z" />
      </svg>
    </button>
    <button id="titlebar-close" title="close">
      <!-- https://api.iconify.design/mdi:close.svg -->
      <svg
        xmlns="http://www.w3.org/2000/svg"
        width="24"
        height="24"
        viewBox="0 0 24 24"
      >
        <path
          fill="currentColor"
          d="M13.46 12L19 17.54V19h-1.46L12 13.46L6.46 19H5v-1.46L10.54 12L5 6.46V5h1.46L12 10.54L17.54 5H19v1.46z"
        />
      </svg>
    </button>
  </div>
</div>

Note that you may need to move the rest of your content down so that the titlebar doesnt cover it.

Tip

On Windows, if you just want a title bar that doesnt need custom interactions, you can use

*[data-tauri-drag-region] {
  app-region: drag;
}

to make the title bar work with touch and pen inputs

JavaScript

Use this code snippet to make the buttons work:

import { getCurrentWindow } from '@tauri-apps/api/window';


// when using `"withGlobalTauri": true`, you may use
// const { getCurrentWindow } = window.__TAURI__.window;


const appWindow = getCurrentWindow();


document
  .getElementById('titlebar-minimize')
  ?.addEventListener('click', () => appWindow.minimize());
document
  .getElementById('titlebar-maximize')
  ?.addEventListener('click', () => appWindow.toggleMaximize());
document
  .getElementById('titlebar-close')
  ?.addEventListener('click', () => appWindow.close());

Note that if you are using a Rust-based frontend, you can copy the code above into a <script> element in your index.html file.

Note

data-tauri-drag-region will only work on the element to which it is directly applied. If you want the drag behavior to apply to child elements as well, youll need to add it to each child individually.

This behavior is preserved so that interactive elements like buttons and inputs can function properly.

Manual Implementation of data-tauri-drag-region

For use cases where you customize the drag behavior, you can manually add an event listener with window.startDragging instead of using data-tauri-drag-region.

HTML

From the code in the previous section, we remove data-tauri-drag-region and add an id:

<div data-tauri-drag-region class="titlebar">
  <div id="titlebar" class="titlebar">
    <!-- ... -->
  </div>
</div>

Javascript

Add an event listener to the titlebar element:

// ...
document.getElementById('titlebar')?.addEventListener('mousedown', (e) => {
  if (e.buttons === 1) {
    // Primary (left) button
    e.detail === 2
      ? appWindow.toggleMaximize() // Maximize on double click
      : appWindow.startDragging(); // Else start dragging
  }
});

(macOS) Transparent Titlebar with Custom Window Background Color

We are going to create the main window and change its background color from the Rust side.

Remove the main window from the tauri.conf.json file:

tauri.conf.json

"tauri": {
  "windows": [
-    {
      -"title": "Transparent Titlebar Window",
      -"width": 800,
      -"height": 600
-    }
  ],
}

Add cocoa crate to dependencies so that we can use it to call the macOS native API:

src-tauri/Cargo.toml

[target."cfg(target_os = \"macos\")".dependencies]
objc2-app-kit = { version = "0.3.2", features = ["NSColor", "NSWindow", "objc2-core-foundation"] }

Create the main window and change its background color:

src-tauri/src/lib.rs

use tauri::{TitleBarStyle, WebviewUrl, WebviewWindowBuilder};


pub fn run() {
  tauri::Builder::default()
    .setup(|app| {
      let win_builder =
        WebviewWindowBuilder::new(app, "main", WebviewUrl::default())
          .title("Transparent Titlebar Window")
          .inner_size(800.0, 600.0);


      // set transparent title bar only when building for macOS
      #[cfg(target_os = "macos")]
      let win_builder = win_builder.title_bar_style(TitleBarStyle::Transparent);


      let window = win_builder.build().unwrap();


      // set background color only when building for macOS
      #[cfg(target_os = "macos")]
      {
        use objc2_app_kit::{NSColor, NSWindow};


        let ns_window_ptr = window.ns_window().unwrap() as *mut NSWindow;
        let ns_window = unsafe { &*ns_window_ptr };
        let bg_color = NSColor::colorWithRed_green_blue_alpha(
          50.0 / 255.0,
          158.0 / 255.0,
          163.5 / 255.0,
          1.0,
        );
        ns_window.setBackgroundColor(Some(&bg_color));
      }


      Ok(())
    })
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

Window Menu

Native application menus can be attached to both to a window or system tray. Available on desktop.

Creating a base-level menu

To create a base-level native window menu, and attach to a window. You can create various types of menu items including basic items, check items, and separators:

  • JavaScript

    Use the Menu.new static function to create a window menu:

    import { Menu } from '@tauri-apps/api/menu';
    
    
    const menu = await Menu.new({
      items: [
        {
          id: 'quit',
          text: 'Quit',
          action: () => {
            console.log('quit pressed');
          },
        },
        {
          id: 'check_item',
          text: 'Check Item',
          checked: true,
        },
        {
          item: 'Separator',
        },
        {
          id: 'disabled_item',
          text: 'Disabled Item',
          enabled: false,
        },
        {
          id: 'status',
          text: 'Status: Processing...',
        },
      ],
    });
    
    
    // If a window was not created with an explicit menu or had one set explicitly,
    // this menu will be assigned to it.
    menu.setAsAppMenu().then(async (res) => {
      console.log('menu set success', res);
    
    
      // Update individual menu item text
      const statusItem = await menu.get('status');
      if (statusItem) {
        await statusItem.setText('Status: Ready');
      }
    });
    
  • Rust

    use tauri::menu::MenuBuilder;
    
    
    fn main() {
        tauri::Builder::default()
            .setup(|app| {
                let menu = MenuBuilder::new(app)
                    .text("open", "Open")
                    .text("close", "Close")
                    .check("check_item", "Check Item")
                    .separator()
                    .text("disabled_item", "Disabled Item")
                    .text("status", "Status: Processing...")
                    .build()?;
    
    
                app.set_menu(menu.clone())?;
    
    
                // Update individual menu item text
                menu
                    .get("status")
                    .unwrap()
                    .as_menuitem_unchecked()
                    .set_text("Status: Ready")?;
    
    
                Ok(())
            })
            .run(tauri::generate_context!());
    }
    

Listening to events on custom menu items

Each custom menu item triggers an event when clicked. Use the on_menu_event API to handle them.

  • JavaScript

    import { Menu } from '@tauri-apps/api/menu';
    
    
    const menu = await Menu.new({
      items: [
        {
          id: 'Open',
          text: 'open',
          action: () => {
            console.log('open pressed');
          },
        },
        {
          id: 'Close',
          text: 'close',
          action: () => {
            console.log('close pressed');
          },
        },
      ],
    });
    
    
    await menu.setAsAppMenu();
    
  • Rust

    #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
    use tauri::menu::{MenuBuilder};
    
    
    fn main() {
      tauri::Builder::default()
            .setup(|app| {
                let menu = MenuBuilder::new(app)
                    .text("open", "Open")
                    .text("close", "Close")
                    .build()?;
    
    
                app.set_menu(menu)?;
    
    
                app.on_menu_event(move |app_handle: &tauri::AppHandle, event| {
    
    
                    println!("menu event: {:?}", event.id());
    
    
                    match event.id().0.as_str() {
                        "open" => {
                            println!("open event");
                        }
                        "close" => {
                            println!("close event");
                        }
                        _ => {
                            println!("unexpected menu event");
                        }
                    }
                });
    
    
                Ok(())
            })
    }
    

Creating a multi-level menu

Multi-level menus allow you to group menu items under categories like “File,” “Edit,” etc. These will appear as part of the application window for Windows or Linux, or in the menu bar on MacOS.

Note: When using submenus on MacOS, all items must be grouped under a submenu. Top-level items will be ignored. Additionally, the first submenu will be placed under the applications about menu by default, regardless of the text label. You should include a submenu as the first entry (say, an “About” submenu) to fill this space.

Note

Icon support for submenus is available since Tauri 2.8.0.

  • JavaScript

    import { Menu, MenuItem, Submenu } from '@tauri-apps/api/menu';
    
    
    // Will become the application submenu on MacOS
    const aboutSubmenu = await Submenu.new({
      text: 'About',
      items: [
        await MenuItem.new({
          id: 'quit',
          text: 'Quit',
          action: () => {
            console.log('Quit pressed');
          },
        }),
      ],
    });
    
    
    const fileSubmenu = await Submenu.new({
      text: 'File',
      icon: 'folder', // Optional: Add an icon to the submenu
      items: [
        await MenuItem.new({
          id: 'new',
          text: 'New',
          action: () => {
            console.log('New clicked');
          },
        }),
        await MenuItem.new({
          id: 'open',
          text: 'Open',
          action: () => {
            console.log('Open clicked');
          },
        }),
        await MenuItem.new({
          id: 'save_as',
          text: 'Save As...',
          action: () => {
            console.log('Save As clicked');
          },
        }),
      ],
    });
    
    
    const editSubmenu = await Submenu.new({
      text: 'Edit',
      items: [
        await MenuItem.new({
          id: 'undo',
          text: 'Undo',
          action: () => {
            console.log('Undo clicked');
          },
        }),
        await MenuItem.new({
          id: 'redo',
          text: 'Redo',
          action: () => {
            console.log('Redo clicked');
          },
        }),
      ],
    });
    
    
    const menu = await Menu.new({
      items: [aboutSubmenu, fileSubmenu, editSubmenu],
    });
    
    
    menu.setAsAppMenu();
    
    
    // You can also update the submenu icon dynamically
    fileSubmenu.setIcon('document');
    // Or set a native icon (only one type applies per platform)
    fileSubmenu.setNativeIcon('NSFolder');
    
  • Rust

    use tauri::{
        image::Image,
        menu::{CheckMenuItemBuilder, IconMenuItemBuilder, MenuBuilder, SubmenuBuilder},
    };
    
    
    fn main() {
        tauri::Builder::default()
            .setup(|app| {
                let menu_image = Image::from_bytes(include_bytes!("../icons/menu.png")).unwrap();
                let file_menu = SubmenuBuilder::new(app, "File")
                    .submenu_icon(menu_image) // Optional: Add an icon to the submenu
                    .text("open", "Open")
                    .text("quit", "Quit")
                    .build()?;
    
    
                let lang_str = "en";
                let check_sub_item_1 = CheckMenuItemBuilder::new("English")
                    .id("en")
                    .checked(lang_str == "en")
                    .build(app)?;
    
    
                let check_sub_item_2 = CheckMenuItemBuilder::new("Chinese")
                    .id("zh")
                    .checked(lang_str == "zh")
                    .enabled(false)
                    .build(app)?;
    
    
                // Load icon from path
                let icon_image = Image::from_bytes(include_bytes!("../icons/icon.png")).unwrap();
    
    
                let icon_item = IconMenuItemBuilder::new("icon")
                    .icon(icon_image)
                    .build(app)?;
    
    
                let other_item = SubmenuBuilder::new(app, "language")
                    .item(&check_sub_item_1)
                    .item(&check_sub_item_2)
                    .build()?;
    
    
                let menu = MenuBuilder::new(app)
                    .items(&[&file_menu, &other_item, &icon_item])
                    .build()?;
    
    
                app.set_menu(menu)?;
    
    
                let menu_image_update =
                    Image::from_bytes(include_bytes!("../icons/menu_update.png")).unwrap();
                // You can also update the submenu icon dynamically
                file_menu.set_icon(Some(menu_image_update))?;
                // Or set a native icon (only one type applies per platform)
                file_menu.set_native_icon(Some(tauri::menu::NativeIcon::Folder))?;
    
    
                Ok(())
            })
            .run(tauri::generate_context!());
    }
    

    Note that you need to enable image-ico or image-png feature to use this API:

    src-tauri/Cargo.toml

    [dependencies]
    tauri = { version = "...", features = ["...", "image-png"] }
    

Creating predefined menu

To use built-in (native) menu items that has predefined behavior by the operating system or Tauri:

  • JavaScript

    import { Menu, PredefinedMenuItem } from '@tauri-apps/api/menu';
    
    
    const copy = await PredefinedMenuItem.new({
      text: 'copy-text',
      item: 'Copy',
    });
    
    
    const separator = await PredefinedMenuItem.new({
      text: 'separator-text',
      item: 'Separator',
    });
    
    
    const undo = await PredefinedMenuItem.new({
      text: 'undo-text',
      item: 'Undo',
    });
    
    
    const redo = await PredefinedMenuItem.new({
      text: 'redo-text',
      item: 'Redo',
    });
    
    
    const cut = await PredefinedMenuItem.new({
      text: 'cut-text',
      item: 'Cut',
    });
    
    
    const paste = await PredefinedMenuItem.new({
      text: 'paste-text',
      item: 'Paste',
    });
    
    
    const select_all = await PredefinedMenuItem.new({
      text: 'select_all-text',
      item: 'SelectAll',
    });
    
    
    const menu = await Menu.new({
      items: [copy, separator, undo, redo, cut, paste, select_all],
    });
    
    
    await menu.setAsAppMenu();
    
  • Rust

    #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
    use tauri::menu::{MenuBuilder, PredefinedMenuItem};
    
    
    fn main() {
      tauri::Builder::default()
            .setup(|app| {
          let menu = MenuBuilder::new(app)
                    .copy()
                    .separator()
                    .undo()
                    .redo()
                    .cut()
                    .paste()
                    .select_all()
                    .item(&PredefinedMenuItem::copy(app, Some("custom text"))?)
                    .build()?;
                app.set_menu(menu)?;
    
    
                Ok(())
            })
    }
    

    For more preset capabilities, please refer to the documentation PredefinedMenuItem.

    Tip

    The menu builder has dedicated methods to add each predefined menu item so you can call .copy() instead of .item(&PredefinedMenuItem::copy(app, None)?).

Change menu status

If you want to change the status of the menu, such as text, icon, or check status, you can set_menu again:

  • JavaScript

    import {
      Menu,
      CheckMenuItem,
      IconMenuItem,
      MenuItem,
    } from '@tauri-apps/api/menu';
    import { Image } from '@tauri-apps/api/image';
    
    
    let currentLanguage = 'en';
    
    
    const check_sub_item_en = await CheckMenuItem.new({
      id: 'en',
      text: 'English',
      checked: currentLanguage === 'en',
      action: () => {
        currentLanguage = 'en';
        check_sub_item_en.setChecked(currentLanguage === 'en');
        check_sub_item_zh.setChecked(currentLanguage === 'cn');
        console.log('English pressed');
      },
    });
    
    
    const check_sub_item_zh = await CheckMenuItem.new({
      id: 'zh',
      text: 'Chinese',
      checked: currentLanguage === 'zh',
      action: () => {
        currentLanguage = 'zh';
        check_sub_item_en.setChecked(currentLanguage === 'en');
        check_sub_item_zh.setChecked(currentLanguage === 'zh');
        check_sub_item_zh.setAccelerator('Ctrl+L');
        console.log('Chinese pressed');
      },
    });
    
    
    // Load icon from path
    const icon = await Image.fromPath('../src/icon.png');
    const icon2 = await Image.fromPath('../src/icon-2.png');
    
    
    const icon_item = await IconMenuItem.new({
      id: 'icon_item',
      text: 'Icon Item',
      icon: icon,
      action: () => {
        icon_item.setIcon(icon2);
        console.log('icon pressed');
      },
    });
    
    
    const text_item = await MenuItem.new({
      id: 'text_item',
      text: 'Text Item',
      action: () => {
        text_item.setText('Text Item Changed');
        console.log('text pressed');
      },
    });
    
    
    const menu = await Menu.new({
      items: [
        {
          id: 'change menu',
          text: 'change_menu',
          items: [text_item, check_sub_item_en, check_sub_item_zh, icon_item],
        },
      ],
    });
    
    
    await menu.setAsAppMenu();
    
  • Rust

    // change-menu-status
    #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
    
    
    use tauri::{
        image::Image,
        menu::{CheckMenuItemBuilder, IconMenuItem, MenuBuilder, MenuItem, SubmenuBuilder},
    };
    
    
    fn main() {
        tauri::Builder::default()
            .setup(|app| {
                let check_sub_item_en = CheckMenuItemBuilder::with_id("en", "EN")
                    .checked(true)
                    .build(app)?;
    
    
                let check_sub_item_zh = CheckMenuItemBuilder::with_id("zh", "ZH")
                    .checked(false)
                    .build(app)?;
    
    
                let text_menu = MenuItem::with_id(
                    app,
                    "change_text",
                    &"Change menu".to_string(),
                    true,
                    Some("Ctrl+Z"),
                )
                .unwrap();
    
    
                let icon_menu = IconMenuItem::with_id(
                    app,
                    "change_icon",
                    &"Change icon menu",
                    true,
                    Some(Image::from_bytes(include_bytes!("../icons/icon.png")).unwrap()),
                    Some("Ctrl+F"),
                )
                .unwrap();
    
    
                let menu_item = SubmenuBuilder::new(app, "Change menu")
                    .item(&text_menu)
                    .item(&icon_menu)
                    .items(&[&check_sub_item_en, &check_sub_item_zh])
                    .build()?;
                let menu = MenuBuilder::new(app).items(&[&menu_item]).build()?;
                app.set_menu(menu)?;
                app.on_menu_event(move |_app_handle: &tauri::AppHandle, event| {
                    match event.id().0.as_str() {
                        "change_text" => {
                            text_menu
                                .set_text("changed menu text")
                                .expect("Change text error");
    
    
                            text_menu
                                .set_text("changed menu text")
                                .expect("Change text error");
                        }
                        "change_icon" => {
                            icon_menu
                                .set_text("changed menu-icon text")
                                .expect("Change text error");
                            icon_menu
                                .set_icon(Some(
                                    Image::from_bytes(include_bytes!("../icons/icon-2.png")).unwrap(),
                                ))
                                .expect("Change icon error");
                        }
    
    
                        "en" | "zh" => {
                            check_sub_item_en
                                .set_checked(event.id().0.as_str() == "en")
                                .expect("Change check error");
                            check_sub_item_zh
                                .set_checked(event.id().0.as_str() == "zh")
                                .expect("Change check error");
                            check_sub_item_zh.set_accelerator(Some("Ctrl+L"))
                            .expect("Change accelerator error");
                        }
                        _ => {
                            println!("unexpected menu event");
                        }
                    }
                });
    
    
                Ok(())
            })
            .run(tauri::generate_context!())
            .expect("error while running tauri application");
    }
    

Features & Recipes

Information on the extensibility of Tauri from built-in Tauri features and functionality to provided plugins and recipes built by the Tauri community

Tauri comes with extensibility in mind. On this page youll find:

Use the search and filter functionality to find features or community resources:

Official Features

Autostart

Automatically launch your app at system startup.

Barcode Scanner

Allows your mobile application to use the camera to scan QR codes, EAN-13 and other types of barcodes.

Biometric

Prompt the user for biometric authentication on Android and iOS.

Clipboard

Read and write to the system clipboard.

Command Line Interface (CLI)

Parse arguments from the command line interface.

Deep Linking

Set your Tauri application as the default handler for an URL.

Dialog

Native system dialogs for opening and saving files along with message dialogs.

File System

Access the file system.

Geolocation

Get and track the device's current position, including information about altitude, heading, and speed (if available).

Global Shortcut

Register global shortcuts.

Haptics

Haptic feedback and vibrations on Android and iOS

HTTP Client

Access the HTTP client written in Rust.

Localhost

Use a localhost server in production apps.

Logging

Configurable logging.

NFC

Read and write NFC tags on Android and iOS.

Notifications

Send native notifications to the user.

Opener

Open files and URLs in external applications.

OS Information

Read information about the operating system.

Persisted Scope

Persist runtime scope changes on the filesystem.

Positioner

Move windows to common locations.

Process

Access the current process.

Shell

Access the system shell to spawn child processes.

Single Instance

Ensure that a single instance of your Tauri app is running at a time.

SQL

Tauri Plugin providing an interface for the frontend to communicate with SQL databases through sqlx.

Store

Persistent key value storage.

Stronghold

Encrypted, secure database.

Updater

In-app updates for Tauri applications.

Upload

File uploads through HTTP.

Websocket

Open a WebSocket connection using a Rust client in JavaScript.

Window State

Persist window sizes and positions.

Community Plugins

sentry-tauriCapture JavaScript errors, Rust panics and native crash minidumps to Sentry.

tauri-awesome-rpcCustom invoke system that leverages WebSocket.

tauri-nspanelConvert a window to panel.

tauri-nspopover-pluginNative NSPopover view for use in the status bar in macOS.

tauri-plugin-android-battery-optimizationCheck and request battery optimization exemptions on Android.

tauri-plugin-android-fsAccess the file system on Android.

tauri-plugin-aptabasePrivacy-first and minimalist analytics for desktop and mobile apps.

tauri-plugin-authAuth plugin for iOS that uses ASWebAuthenticationSession for authentication, which allows keychain access

tauri-plugin-blecCross platform Bluetooth Low Energy client based on btleplug.

tauri-plugin-cacheAdvanced disk caching solution with memory layer, TTL management, compression support, and cross-platform compatibility for desktop and mobile.

tauri-plugin-clipboardClipboard plugin for reading/writing clipboard text/image/html/rtf/files, and monitoring clipboard update.

tauri-plugin-context-menuNative context menu.

tauri-plugin-desktop-underlayAttach a window to desktop, below icons and above wallpaper.

tauri-plugin-device-infoAccess comprehensive device information including battery, network, storage, display, and system details across desktop and mobile.

tauri-plugin-dragoutNative macOS drag-out (file promise) support.

tauri-plugin-drpcDiscord RPC support.

tauri-plugin-fs-proExtended with additional methods for files and directories.

tauri-plugin-graphqlType-safe IPC for Tauri using GraphQL.

tauri-plugin-iapPlugin that enables full In-App Purchases flow for Android, macOS, iOS and Windows.

tauri-plugin-iapIn-app-purchase plugin for iOS that allows fetching, purchasing, and restoring of products.

tauri-plugin-in-app-reviewIn-app app rating prompts using native platform APIs.

tauri-plugin-ios-photosiOS Photos album and asset management via native APIs.

tauri-plugin-jsGive your app Electron-like JS backends with type-safe RPC powered by kkrpc. Supports Bun, Node.js, and Deno.

tauri-plugin-keep-screen-onDisable screen timeout on Android and iOS.

tauri-plugin-macos-permissionsSupport for checking and requesting macOS system permissions.

tauri-plugin-mobile-sharetargetHandle mobile Share Intents with a FIFO queue

tauri-plugin-mqttMQTT client support.

tauri-plugin-networkTools for reading network information and scanning network.

tauri-plugin-nosleepBlock the power save functionality in the OS.

tauri-plugin-otaOTA plugin for applications that just want to continuously deliever new JavaScript code based on a manfiest.

tauri-plugin-piniaPersistent Pinia stores for Vue.

tauri-plugin-prevent-defaultDisable default browser shortcuts.

tauri-plugin-pythonUse python in your backend.

tauri-plugin-screenshotsGet screenshots of windows and monitors.

tauri-plugin-serialportCross-compatible serialport communication tool.

tauri-plugin-serialpluginCross-compatible serialport communication tool for tauri 2.

tauri-plugin-sharesheetShare content to other apps via the Android Sharesheet or iOS Share Pane.

tauri-plugin-sveltePersistent Svelte stores.

tauri-plugin-system-infoDetailed system information.

tauri-plugin-tcpTCP socket support.

tauri-plugin-themeDynamically change Tauri App theme.

tauri-plugin-thermal-printerAdd support to handle thermal printers.

tauri-plugin-tracingStructured logging with the tracing crate, featuring JS-to-Rust log bridging, file rotation, and flamegraph profiling.

tauri-plugin-udpUDP socket support.

tauri-plugin-velesdbNative vector database plugin. 70µs semantic search, ≥95% recall, hybrid BM25+vector, offline-first, full ecosystem integrations and more.

tauri-plugin-viewView and share files on mobile.

tauri-remote-uiMake you web app bundle available as web page for test and development.

taurpcTypesafe IPC wrapper for Tauri commands and events.

Community Integrations

AstrodonMake Tauri desktop apps with Deno.

axios-tauri-adapteraxios adapter for the @tauri-apps/api/http module.

axios-tauri-api-adapterMakes it easy to use Axios in Tauri, axios adapter for the @tauri-apps/api/http module.

Deno in TauriRun JS/TS code with Deno Core Engine, in Tauri apps.

faynosync-update-serverSelf-hosted Dynamic Update Server with statistics, supporting Tauri and other platforms. Flexible features for seamless app updates and insights.

kkrpcSeamless RPC communication between a Tauri app and node/deno/bun processes, just like Electron.

ngx-tauriSmall lib to wrap around functions from tauri modules, to integrate easier with Angular.

svelte-tauri-filedropFile drop handling component for Svelte.

Tauri SpectaCompletely typesafe Tauri commands.

tauri-htmx-extensionExtention for using htmx with Tauri apis.

tauri-macos-menubar-app-exampleExample macOS Menubar app project.

tauri-macos-spotlight-exampleExample macOS Spotlight app project.

tauri-mcp-serverMCP server and plugin for rapid development and debugging.

tauri-update-cloudflareOne-click deploy a Tauri Update Server to Cloudflare.

tauri-update-serverAutomatically interface the Tauri updater with git repository releases.

vite-plugin-tauriIntegrate Tauri in a Vite project to build cross-platform apps.

Support Table

Hover “*” to see notes. For more details visit the plugin page

Plugin Rust Version android ios linux macos windows
autostart 1.77.2
barcode-scanner 1.77.2
biometric 1.77.2
cli 1.77.2
clipboard-manager 1.77.2 * *
deep-link 1.77.2 * * *
dialog 1.77.2 * *
fs 1.77.2 * * * * *
geolocation 1.77.2
global-shortcut 1.77.2
haptics 1.77.2
http 1.77.2
localhost 1.77.2
log 1.77.2
nfc 1.77.2
notification 1.77.2 *
opener 1.77.2 * *
os 1.77.2
persisted-scope 1.77.2
positioner 1.77.2
process 1.77.2
shell 1.77.2 * *
single-instance 1.77.2
sql 1.77.2
store 1.77.2
stronghold 1.77.2
updater 1.77.2
upload 1.77.2
websocket 1.77.2
window-state 1.77.2
system-tray 1.77.2
window-customization 1.77.2

Autostart

Automatically launch your app at system startup.

GitHubnpmcrates.io

API Reference:

Automatically launch your application at system startup.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the autostart plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add autostart
      
    • yarn

      yarn run tauri add autostart
      
    • pnpm

      pnpm tauri add autostart
      
    • deno

      deno task tauri add autostart
      
    • bun

      bun tauri add autostart
      
    • cargo

      cargo tauri add autostart
      
  • Manual

    npm run tauri add autostart
    
  • npm

    yarn run tauri add autostart
    
  • yarn

    pnpm tauri add autostart
    
  • pnpm

    deno task tauri add autostart
    
  • deno

    bun tauri add autostart
    
  • bun

    cargo tauri add autostart
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-autostart --target 'cfg(any(target_os = "macos", windows, target_os = "linux"))'
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              .setup(|app| {
      +            #[cfg(desktop)]
                  +app.handle().plugin(tauri_plugin_autostart::init(tauri_plugin_autostart::MacosLauncher::LaunchAgent, Some(vec!["--flag1", "--flag2"]) /* arbitrary number of args to pass to your app */));
                  Ok(())
              })
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. You can install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-autostart
        
      • yarn

        yarn add @tauri-apps/plugin-autostart
        
      • pnpm

        pnpm add @tauri-apps/plugin-autostart
        
      • deno

        deno add npm:@tauri-apps/plugin-autostart
        
      • bun

        bun add @tauri-apps/plugin-autostart
        
  • npm

    npm install @tauri-apps/plugin-autostart
    
  • yarn

    yarn add @tauri-apps/plugin-autostart
    
  • pnpm

    pnpm add @tauri-apps/plugin-autostart
    
  • deno

    deno add npm:@tauri-apps/plugin-autostart
    
  • bun

    bun add @tauri-apps/plugin-autostart
    

Usage

The autostart plugin is available in both JavaScript and Rust.

  • JavaScript

    import { enable, isEnabled, disable } from '@tauri-apps/plugin-autostart';
    // when using `"withGlobalTauri": true`, you may use
    // const { enable, isEnabled, disable } = window.__TAURI__.autostart;
    
    
    // Enable autostart
    await enable();
    // Check enable state
    console.log(`registered for autostart? ${await isEnabled()}`);
    // Disable autostart
    disable();
    
  • Rust

    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
        tauri::Builder::default()
            .setup(|app| {
                #[cfg(desktop)]
                {
                    use tauri_plugin_autostart::MacosLauncher;
                    use tauri_plugin_autostart::ManagerExt;
    
    
                    app.handle().plugin(tauri_plugin_autostart::init(
                        MacosLauncher::LaunchAgent,
                        Some(vec!["--flag1", "--flag2"]),
                    ));
    
    
                    // Get the autostart manager
                    let autostart_manager = app.autolaunch();
                    // Enable autostart
                    let _ = autostart_manager.enable();
                    // Check enable state
                    println!("registered for autostart? {}", autostart_manager.is_enabled().unwrap());
                    // Disable autostart
                    let _ = autostart_manager.disable();
                }
                Ok(())
            })
            .run(tauri::generate_context!())
            .expect("error while running tauri application");
    }
    

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "permissions": [
    ...,
    "autostart:allow-enable",
    "autostart:allow-disable",
    "autostart:allow-is-enabled"
  ]
}

Default Permission

This permission set configures if your application can enable or disable auto starting the application on boot.

Granted Permissions

It allows all to check, enable and disable the automatic start on boot.

This default permission set includes the following:

  • allow-enable
  • allow-disable
  • allow-is-enabled

Permission Table

Identifier Description
autostart:allow-disable Enables the disable command without any pre-configured scope.
autostart:deny-disable Denies the disable command without any pre-configured scope.
autostart:allow-enable Enables the enable command without any pre-configured scope.
autostart:deny-enable Denies the enable command without any pre-configured scope.
autostart:allow-is-enabled Enables the is_enabled command without any pre-configured scope.
autostart:deny-is-enabled Denies the is_enabled command without any pre-configured scope.

Barcode Scanner

Allows your mobile application to use the camera to scan QR codes, EAN-13 and other types of barcodes.

GitHubnpmcrates.io

API Reference:

Allows your mobile application to use the camera to scan QR codes, EAN-13 and other kinds of barcodes.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the barcode-scanner plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add barcode-scanner
      
    • yarn

      yarn run tauri add barcode-scanner
      
    • pnpm

      pnpm tauri add barcode-scanner
      
    • deno

      deno task tauri add barcode-scanner
      
    • bun

      bun tauri add barcode-scanner
      
    • cargo

      cargo tauri add barcode-scanner
      
  • Manual

    npm run tauri add barcode-scanner
    
  • npm

    yarn run tauri add barcode-scanner
    
  • yarn

    pnpm tauri add barcode-scanner
    
  • pnpm

    deno task tauri add barcode-scanner
    
  • deno

    bun tauri add barcode-scanner
    
  • bun

    cargo tauri add barcode-scanner
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-barcode-scanner --target 'cfg(any(target_os = "android", target_os = "ios"))'
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              .setup(|app| {
      +            #[cfg(mobile)]
                  +app.handle().plugin(tauri_plugin_barcode_scanner::init());
                  Ok(())
              })
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-barcode-scanner
        
      • yarn

        yarn add @tauri-apps/plugin-barcode-scanner
        
      • pnpm

        pnpm add @tauri-apps/plugin-barcode-scanner
        
      • deno

        deno add npm:@tauri-apps/plugin-barcode-scanner
        
      • bun

        bun add @tauri-apps/plugin-barcode-scanner
        
  • npm

    npm install @tauri-apps/plugin-barcode-scanner
    
  • yarn

    yarn add @tauri-apps/plugin-barcode-scanner
    
  • pnpm

    pnpm add @tauri-apps/plugin-barcode-scanner
    
  • deno

    deno add npm:@tauri-apps/plugin-barcode-scanner
    
  • bun

    bun add @tauri-apps/plugin-barcode-scanner
    

Configuration

On iOS the barcode scanner plugin requires the NSCameraUsageDescription information property list value, which should describe why your app needs to use the camera.

In the src-tauri/Info.ios.plist file, add the following snippet:

src-tauri/Info.ios.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>NSCameraUsageDescription</key>
    <string>Read QR codes</string>
  </dict>
</plist>

Usage

The barcode scanner plugin is available in JavaScript.

import { scan, Format } from '@tauri-apps/plugin-barcode-scanner';
// when using `"withGlobalTauri": true`, you may use
// const { scan, Format } = window.__TAURI__.barcodeScanner;


// `windowed: true` actually sets the webview to transparent
// instead of opening a separate view for the camera
// make sure your user interface is ready to show what is underneath with a transparent element
scan({ windowed: true, formats: [Format.QRCode] });

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/mobile.json

{
  "$schema": "../gen/schemas/mobile-schema.json",
  "identifier": "mobile-capability",
  "windows": ["main"],
  "platforms": ["iOS", "android"],
  "permissions": ["barcode-scanner:allow-scan", "barcode-scanner:allow-cancel"]
}

Default Permission

This permission set configures which barcode scanning features are by default exposed.

Granted Permissions

It allows all barcode related features.

This default permission set includes the following:

  • allow-cancel
  • allow-check-permissions
  • allow-open-app-settings
  • allow-request-permissions
  • allow-scan
  • allow-vibrate

Permission Table

Identifier Description
barcode-scanner:allow-cancel Enables the cancel command without any pre-configured scope.
barcode-scanner:deny-cancel Denies the cancel command without any pre-configured scope.
barcode-scanner:allow-check-permissions Enables the check_permissions command without any pre-configured scope.
barcode-scanner:deny-check-permissions Denies the check_permissions command without any pre-configured scope.
barcode-scanner:allow-open-app-settings Enables the open_app_settings command without any pre-configured scope.
barcode-scanner:deny-open-app-settings Denies the open_app_settings command without any pre-configured scope.
barcode-scanner:allow-request-permissions Enables the request_permissions command without any pre-configured scope.
barcode-scanner:deny-request-permissions Denies the request_permissions command without any pre-configured scope.
barcode-scanner:allow-scan Enables the scan command without any pre-configured scope.
barcode-scanner:deny-scan Denies the scan command without any pre-configured scope.
barcode-scanner:allow-vibrate Enables the vibrate command without any pre-configured scope.
barcode-scanner:deny-vibrate Denies the vibrate command without any pre-configured scope.

Biometric

Prompt the user for biometric authentication on Android and iOS.

GitHubnpmcrates.io

API Reference:

Prompt the user for biometric authentication on Android and iOS.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the biometric plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add biometric
      
    • yarn

      yarn run tauri add biometric
      
    • pnpm

      pnpm tauri add biometric
      
    • deno

      deno task tauri add biometric
      
    • bun

      bun tauri add biometric
      
    • cargo

      cargo tauri add biometric
      
  • Manual

    npm run tauri add biometric
    
  • npm

    yarn run tauri add biometric
    
  • yarn

    pnpm tauri add biometric
    
  • pnpm

    deno task tauri add biometric
    
  • deno

    bun tauri add biometric
    
  • bun

    cargo tauri add biometric
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-biometric --target 'cfg(any(target_os = "android", target_os = "ios"))'
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              .setup(|app| {
      +            #[cfg(mobile)]
                  +app.handle().plugin(tauri_plugin_biometric::Builder::new().build());
                  Ok(())
              })
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-biometric
        
      • yarn

        yarn add @tauri-apps/plugin-biometric
        
      • pnpm

        pnpm add @tauri-apps/plugin-biometric
        
      • deno

        deno add npm:@tauri-apps/plugin-biometric
        
      • bun

        bun add @tauri-apps/plugin-biometric
        
  • npm

    npm install @tauri-apps/plugin-biometric
    
  • yarn

    yarn add @tauri-apps/plugin-biometric
    
  • pnpm

    pnpm add @tauri-apps/plugin-biometric
    
  • deno

    deno add npm:@tauri-apps/plugin-biometric
    
  • bun

    bun add @tauri-apps/plugin-biometric
    

Configuration

On iOS the biometric plugin requires the NSFaceIDUsageDescription information property list value, which should describe why your app needs to use biometric authentication.

In the src-tauri/Info.ios.plist file, add the following snippet:

src-tauri/Info.ios.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>NSFaceIDUsageDescription</key>
    <string>Authenticate with biometric</string>
  </dict>
</plist>

Usage

This plugin enables you to verify the availability of Biometric Authentication on a device, prompt the user for biometric authentication, and check the result to determine if the authentication was successful or not.

Check Status

You can check the status of Biometric Authentication, including its availability and the types of biometric authentication methods supported.

  • JavaScript

    import { checkStatus } from '@tauri-apps/plugin-biometric';
    
    
    const status = await checkStatus();
    if (status.isAvailable) {
      console.log('Yes! Biometric Authentication is available');
    } else {
      console.log(
        'No! Biometric Authentication is not available due to ' + status.error
      );
    }
    
  • Rust

    use tauri_plugin_biometric::BiometricExt;
    
    
    fn check_biometric(app_handle: tauri::AppHandle) {
        let status = app_handle.biometric().status().unwrap();
        if status.is_available {
            println!("Yes! Biometric Authentication is available");
        } else {
            println!("No! Biometric Authentication is not available due to: {}", status.error.unwrap());
        }
    }
    

Authenticate

To prompt the user for Biometric Authentication, utilize the authenticate() method.

  • JavaScript

    import { authenticate } from '@tauri-apps/plugin-biometric';
    
    
    const options = {
      // Set true if you want the user to be able to authenticate using phone password
      allowDeviceCredential: false,
      cancelTitle: "Feature won't work if Canceled",
    
    
      // iOS only feature
      fallbackTitle: 'Sorry, authentication failed',
    
    
      // Android only features
      title: 'Tauri feature',
      subtitle: 'Authenticate to access the locked Tauri function',
      confirmationRequired: true,
    };
    
    
    try {
      +await authenticate('This feature is locked', options);
      console.log(
        'Hooray! Successfully Authenticated! We can now perform the locked Tauri function!'
      );
    } catch (err) {
      console.log('Oh no! Authentication failed because ' + err.message);
    }
    
  • Rust

    use tauri_plugin_biometric::{BiometricExt, AuthOptions};
    
    
    fn bio_auth(app_handle: tauri::AppHandle) {
    
    
        let options = AuthOptions {
            // Set True if you want the user to be able to authenticate using phone password
            allow_device_credential:false,
            cancel_title: Some("Feature won't work if Canceled".to_string()),
    
    
            // iOS only feature
            fallback_title: Some("Sorry, authentication failed".to_string()),
    
    
            // Android only features
            title: Some("Tauri feature".to_string()),
            subtitle: Some("Authenticate to access the locked Tauri function".to_string()),
            confirmation_required: Some(true),
        };
    
    
        // if the authentication was successful, the function returns Result::Ok()
        // otherwise returns Result::Error()
        +match app_handle.biometric().authenticate("This feature is locked".to_string(), options) {
            Ok(_) => {
                println!("Hooray! Successfully Authenticated! We can now perform the locked Tauri function!");
            }
            Err(e) => {
                println!("Oh no! Authentication failed because : {e}");
            }
        }
    }
    

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  +"permissions": ["biometric:default"]
}

Default Permission

This permission set configures which biometric features are by default exposed.

Granted Permissions

It allows acccess to all biometric commands.

This default permission set includes the following:

  • allow-authenticate
  • allow-status

Permission Table

Identifier Description
biometric:allow-authenticate Enables the authenticate command without any pre-configured scope.
biometric:deny-authenticate Denies the authenticate command without any pre-configured scope.
biometric:allow-status Enables the status command without any pre-configured scope.
biometric:deny-status Denies the status command without any pre-configured scope.

Command Line Interface (CLI)

Parse arguments from the command line interface.

GitHubnpmcrates.io

API Reference:

Tauri enables your app to have a CLI through clap, a robust command line argument parser. With a simple CLI definition in your tauri.conf.json file, you can define your interface and read its argument matches map on JavaScript and/or Rust.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios
  • Windows
    • Due to an OS limitation, production apps are not able to write text back to the calling console by default. Please check out tauri#8305 for a workaround.

Setup

Install the CLI plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add cli
      
    • yarn

      yarn run tauri add cli
      
    • pnpm

      pnpm tauri add cli
      
    • deno

      deno task tauri add cli
      
    • bun

      bun tauri add cli
      
    • cargo

      cargo tauri add cli
      
  • Manual

    npm run tauri add cli
    
  • npm

    yarn run tauri add cli
    
  • yarn

    pnpm tauri add cli
    
  • pnpm

    deno task tauri add cli
    
  • deno

    bun tauri add cli
    
  • bun

    cargo tauri add cli
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-cli --target 'cfg(any(target_os = "macos", windows, target_os = "linux"))'
      
      1. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              .setup(|app| {
      +            #[cfg(desktop)]
                  +app.handle().plugin(tauri_plugin_cli::init());
                  Ok(())
              })
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
      1. Install the JavaScript Guest bindings using your preferred JavaScript package manager:
      • npm

        npm install @tauri-apps/plugin-cli
        
      • yarn

        yarn add @tauri-apps/plugin-cli
        
      • pnpm

        pnpm add @tauri-apps/plugin-cli
        
      • deno

        deno add npm:@tauri-apps/plugin-cli
        
      • bun

        bun add @tauri-apps/plugin-cli
        
  • npm

    npm install @tauri-apps/plugin-cli
    
  • yarn

    yarn add @tauri-apps/plugin-cli
    
  • pnpm

    pnpm add @tauri-apps/plugin-cli
    
  • deno

    deno add npm:@tauri-apps/plugin-cli
    
  • bun

    bun add @tauri-apps/plugin-cli
    

Base Configuration

Under tauri.conf.json, you have the following structure to configure the interface:

src-tauri/tauri.conf.json

{
  "plugins": {
    "cli": {
      "description": "Tauri CLI Plugin Example",
      "args": [
        {
          "short": "v",
          "name": "verbose",
          "description": "Verbosity level"
        }
      ],
      "subcommands": {
        "run": {
          "description": "Run the application",
          "args": [
            {
              "name": "debug",
              "description": "Run application in debug mode"
            },
            {
              "name": "release",
              "description": "Run application in release mode"
            }
          ]
        }
      }
    }
  }
}

Note

All JSON configurations here are just samples, many other fields have been omitted for the sake of clarity.

Adding Arguments

The args array represents the list of arguments accepted by its command or subcommand.

Positional Arguments

A positional argument is identified by its position in the list of arguments. With the following configuration:

src-tauri/tauri.conf.json

{
  "args": [
    {
      "name": "source",
      "index": 1,
      "takesValue": true
    },
    {
      "name": "destination",
      "index": 2,
      "takesValue": true
    }
  ]
}

Users can run your app as ./app tauri.txt dest.txt and the arg matches map will define source as "tauri.txt" and destination as "dest.txt".

Named Arguments

A named argument is a (key, value) pair where the key identifies the value. With the following configuration:

tauri-src/tauri.conf.json

{
  "args": [
    {
      "name": "type",
      "short": "t",
      "takesValue": true,
      "multiple": true,
      "possibleValues": ["foo", "bar"]
    }
  ]
}

Users can run your app as ./app --type foo bar, ./app -t foo -t bar or ./app --type=foo,bar and the arg matches map will define type as ["foo", "bar"].

Flag Arguments

A flag argument is a standalone key whose presence or absence provides information to your application. With the following configuration:

tauri-src/tauri.conf.json

{
  "args": [
    {
      "name": "verbose",
      "short": "v"
    }
  ]
}

Users can run your app as ./app -v -v -v, ./app --verbose --verbose --verbose or ./app -vvv and the arg matches map will define verbose as true, with occurrences = 3.

Subcommands

Some CLI applications have additional interfaces as subcommands. For instance, the git CLI has git branch, git commit and git push. You can define additional nested interfaces with the subcommands array:

tauri-src/tauri.conf.json

{
  "cli": {
    ...
    "subcommands": {
      "branch": {
        "args": []
      },
      "push": {
        "args": []
      }
    }
  }
}

Its configuration is the same as the root application configuration, with the description, longDescription, args, etc.

Usage

The CLI plugin is available in both JavaScript and Rust.

  • JavaScript

    import { getMatches } from '@tauri-apps/plugin-cli';
    // when using `"withGlobalTauri": true`, you may use
    // const { getMatches } = window.__TAURI__.cli;
    
    
    const matches = await getMatches();
    if (matches.subcommand?.name === 'run') {
      // `./your-app run $ARGS` was executed
      const args = matches.subcommand.matches.args;
      if (args.debug?.value === true) {
        // `./your-app run --debug` was executed
      }
      if (args.release?.value === true) {
        // `./your-app run --release` was executed
      }
    }
    
  • Rust

    src-tauri/src/lib.rs

    use tauri_plugin_cli::CliExt;
    
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
       tauri::Builder::default()
           .plugin(tauri_plugin_cli::init())
           .setup(|app| {
               match app.cli().matches() {
                   // `matches` here is a Struct with { args, subcommand }.
                   // `args` is `HashMap<String, ArgData>` where `ArgData` is a struct with { value, occurrences }.
                   // `subcommand` is `Option<Box<SubcommandMatches>>` where `SubcommandMatches` is a struct with { name, matches }.
                   Ok(matches) => {
                       println!("{:?}", matches)
                   }
                   Err(_) => {}
               }
               Ok(())
           })
           .run(tauri::generate_context!())
           .expect("error while running tauri application");
    }
    

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  +"permissions": ["cli:default"]
}

Default Permission

Allows reading the CLI matches

This default permission set includes the following:

  • allow-cli-matches

Permission Table

Identifier Description
cli:allow-cli-matches Enables the cli_matches command without any pre-configured scope.
cli:deny-cli-matches Denies the cli_matches command without any pre-configured scope.

Clipboard

Read and write to the system clipboard.

GitHubnpmcrates.io

API Reference:

Read and write to the system clipboard using the clipboard plugin.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android Only plain-text content support
ios Only plain-text content support

Setup

Install the clipboard plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add clipboard-manager
      
    • yarn

      yarn run tauri add clipboard-manager
      
    • pnpm

      pnpm tauri add clipboard-manager
      
    • deno

      deno task tauri add clipboard-manager
      
    • bun

      bun tauri add clipboard-manager
      
    • cargo

      cargo tauri add clipboard-manager
      
  • Manual

    npm run tauri add clipboard-manager
    
  • npm

    yarn run tauri add clipboard-manager
    
  • yarn

    pnpm tauri add clipboard-manager
    
  • pnpm

    deno task tauri add clipboard-manager
    
  • deno

    bun tauri add clipboard-manager
    
  • bun

    cargo tauri add clipboard-manager
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-clipboard-manager
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_clipboard_manager::init())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. If youd like to manage the clipboard in JavaScript then install the npm package as well:

      • npm

        npm install @tauri-apps/plugin-clipboard-manager
        
      • yarn

        yarn add @tauri-apps/plugin-clipboard-manager
        
      • pnpm

        pnpm add @tauri-apps/plugin-clipboard-manager
        
      • deno

        deno add npm:@tauri-apps/plugin-clipboard-manager
        
      • bun

        bun add @tauri-apps/plugin-clipboard-manager
        
  • npm

    npm install @tauri-apps/plugin-clipboard-manager
    
  • yarn

    yarn add @tauri-apps/plugin-clipboard-manager
    
  • pnpm

    pnpm add @tauri-apps/plugin-clipboard-manager
    
  • deno

    deno add npm:@tauri-apps/plugin-clipboard-manager
    
  • bun

    bun add @tauri-apps/plugin-clipboard-manager
    

Usage

The clipboard plugin is available in both JavaScript and Rust.

  • JavaScript

    import { writeText, readText } from '@tauri-apps/plugin-clipboard-manager';
    // when using `"withGlobalTauri": true`, you may use
    // const { writeText, readText } = window.__TAURI__.clipboardManager;
    
    
    // Write content to clipboard
    await writeText('Tauri is awesome!');
    
    
    // Read content from clipboard
    const content = await readText();
    console.log(content);
    // Prints "Tauri is awesome!" to the console
    
  • Rust

    use tauri_plugin_clipboard_manager::ClipboardExt;
    
    
    app.clipboard().write_text("Tauri is awesome!".to_string()).unwrap();
    
    
    // Read content from clipboard
    let content = app.clipboard().read_text();
    println!("{:?}", content.unwrap());
    // Prints "Tauri is awesome!" to the terminal
    

Default Permission

No features are enabled by default, as we believe the clipboard can be inherently dangerous and it is application specific if read and/or write access is needed.

Clipboard interaction needs to be explicitly enabled.

Permission Table

Identifier Description
clipboard-manager:allow-clear Enables the clear command without any pre-configured scope.
clipboard-manager:deny-clear Denies the clear command without any pre-configured scope.
clipboard-manager:allow-read-image Enables the read_image command without any pre-configured scope.
clipboard-manager:deny-read-image Denies the read_image command without any pre-configured scope.
clipboard-manager:allow-read-text Enables the read_text command without any pre-configured scope.
clipboard-manager:deny-read-text Denies the read_text command without any pre-configured scope.
clipboard-manager:allow-write-html Enables the write_html command without any pre-configured scope.
clipboard-manager:deny-write-html Denies the write_html command without any pre-configured scope.
clipboard-manager:allow-write-image Enables the write_image command without any pre-configured scope.
clipboard-manager:deny-write-image Denies the write_image command without any pre-configured scope.
clipboard-manager:allow-write-text Enables the write_text command without any pre-configured scope.
clipboard-manager:deny-write-text Denies the write_text command without any pre-configured scope.

Deep Linking

Set your Tauri application as the default handler for an URL.

GitHubnpmcrates.io

API Reference:

Set your Tauri application as the default handler for an URL.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos Deep links must be registered in config. Dynamic registration at runtime is not supported.
android Deep links must be registered in config. Dynamic registration at runtime is not supported.
ios Deep links must be registered in config. Dynamic registration at runtime is not supported.

Setup

Install the deep-link plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add deep-link
      
    • yarn

      yarn run tauri add deep-link
      
    • pnpm

      pnpm tauri add deep-link
      
    • deno

      deno task tauri add deep-link
      
    • bun

      bun tauri add deep-link
      
    • cargo

      cargo tauri add deep-link
      
  • Manual

    npm run tauri add deep-link
    
  • npm

    yarn run tauri add deep-link
    
  • yarn

    pnpm tauri add deep-link
    
  • pnpm

    deno task tauri add deep-link
    
  • deno

    bun tauri add deep-link
    
  • bun

    cargo tauri add deep-link
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-deep-link@2.0.0
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_deep_link::init())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-deep-link
        
      • yarn

        yarn add @tauri-apps/plugin-deep-link
        
      • pnpm

        pnpm add @tauri-apps/plugin-deep-link
        
      • deno

        deno add npm:@tauri-apps/plugin-deep-link
        
      • bun

        bun add @tauri-apps/plugin-deep-link
        
  • npm

    npm install @tauri-apps/plugin-deep-link
    
  • yarn

    yarn add @tauri-apps/plugin-deep-link
    
  • pnpm

    pnpm add @tauri-apps/plugin-deep-link
    
  • deno

    deno add npm:@tauri-apps/plugin-deep-link
    
  • bun

    bun add @tauri-apps/plugin-deep-link
    

Setting up

Android

There are two ways to open your app from links on Android:

  1. App Links (http/https + host, verified) For app links, you need a server with a .well-known/assetlinks.json endpoint that must return a text response in the given format:

.well-known/assetlinks.json

[
  {
    "relation": ["delegate_permission/common.handle_all_urls"],
    "target": {
      "namespace": "android_app",
      "package_name": "$APP_BUNDLE_ID",
      "sha256_cert_fingerprints": [
        $CERT_FINGERPRINT
      ]
    }
  }
]

Where $APP_BUNDLE_ID is the value defined on tauri.conf.json > identifier with - replaced with _ and $CERT_FINGERPRINT is a list of SHA256 fingerprints of your apps signing certificates, see verify Android applinks for more information.

  1. Custom URI schemes (no host required, no verification) For URIs like myapp://..., you can declare a custom scheme without hosting any files. Use the scheme field in the mobile configuration and omit the host.

iOS

There are two ways to open your app from links on iOS:

  1. Universal Links (https + host, verified) For universal links, you need a server with a .well-known/apple-app-site-association endpoint that must return a JSON response in the given format:

.well-known/apple-app-site-association

{
  "applinks": {
    "details": [
      {
        "appIDs": ["$DEVELOPMENT_TEAM_ID.$APP_BUNDLE_ID"],
        "components": [
          {
            "/": "/open/*",
            "comment": "Matches any URL whose path starts with /open/"
          }
        ]
      }
    ]
  }
}

Note

The response Content-Type header must be application/json.

The .well-known/apple-app-site-association endpoint must be served over HTTPS. To test localhost you can either use a self-signed TLS certificate and install it on the iOS simulator or use services like ngrok.

Where $DEVELOPMENT_TEAM_ID is the value defined on tauri.conf.json > bundle > iOS > developmentTeam or the TAURI_APPLE_DEVELOPMENT_TEAM environment variable and $APP_BUNDLE_ID is the value defined on tauri.conf.json > identifier.

To verify if your domain has been properly configured to expose the app associations, you can run the following command, replacing <host> with your actual host:

curl -v https://app-site-association.cdn-apple.com/a/v1/<host>

See applinks.details for more information.

  1. Custom URI schemes (no host, no verification) For URIs like myapp://..., you can declare a custom scheme under mobile configuration with "appLink": false (or omit it). The plugin generates the appropriate CFBundleURLTypes entries in your apps Info.plist. No .well-known files or HTTPS host are needed.

Desktop

On Linux and Windows deep links are delivered as a command line argument to a new app process. The deep link plugin has integration with the single instance plugin if you prefer having a unique app instance receiving the events.

  • First you must add the deep-link feature to the single instance plugin:

src-tauri/Cargo.toml

[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\"))".dependencies]
tauri-plugin-single-instance = { version = "2.0.0", features = ["deep-link"] }
  • Then configure the single instance plugin which should always be the first plugin you register:

src-tauri/lib.rs

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    let mut builder = tauri::Builder::default();


    #[cfg(desktop)]
    {
        builder = builder.plugin(tauri_plugin_single_instance::init(|_app, argv, _cwd| {
          println!("a new app instance was opened with {argv:?} and the deep link event was already triggered");
          // when defining deep link schemes at runtime, you must also check `argv` here
        }));
    }


    builder = builder.plugin(tauri_plugin_deep_link::init());
}

Caution

The user could trigger a fake deep link manually by including the URL as argument. Tauri matches the command line argument against the configured schemes to mitigate this, but you should still check if the URL matches the format you expect.

This means Tauri only handles deep links for schemes that were statically configured, and schemes registered at runtime must be manually checked using Env::args_os.

Configuration

Under tauri.conf.json > plugins > deep-link, configure mobile domains/schemes and desktop schemes you want to associate with your application.

Examples

Custom scheme on mobile (no server required):

tauri.conf.json

{
  "plugins": {
    "deep-link": {
      "mobile": [
        {
          "scheme": ["ovi"],
          "appLink": false
        }
      ]
    }
  }
}

This registers the ovi://* scheme on Android and iOS.

App Link / Universal Link (verified https + host):

{
  "plugins": {
    "deep-link": {
      "mobile": [
        {
          "scheme": ["https"],
          "host": "your.website.com",
          "pathPrefix": ["/open"],
          "appLink": true
        }
      ]
    }
  }
}

This registers https://your.website.com/open/* as an app/universal link.

Desktop custom schemes:

{
  "plugins": {
    "deep-link": {
      "desktop": {
        "schemes": ["something", "my-tauri-app"]
      }
    }
  }
}

Usage

The deep-link plugin is available in both JavaScript and Rust.

  • JavaScript

    When a deep link triggers your app while its running, the onOpenUrl callback is called. To detect whether your app was opened via a deep link, use getCurrent on app start.

    import { getCurrent, onOpenUrl } from '@tauri-apps/plugin-deep-link';
    // when using `"withGlobalTauri": true`, you may use
    // const { getCurrent, onOpenUrl } = window.__TAURI__.deepLink;
    
    
    const startUrls = await getCurrent();
    if (startUrls) {
      // App was likely started via a deep link
      // Note that getCurrent's return value will also get updated every time onOpenUrl gets triggered.
    }
    
    
    await onOpenUrl((urls) => {
      console.log('deep link:', urls);
    });
    
  • Rust

    When a deep link triggers your app while its running, the plugins on_open_url closure is called. To detect whether your app was opened via a deep link, use get_current on app start.

    src-tauri/src/lib.rs

    use tauri_plugin_deep_link::DeepLinkExt;
    
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
        tauri::Builder::default()
            .plugin(tauri_plugin_deep_link::init())
            .setup(|app| {
                // Note that get_current's return value will also get updated every time on_open_url gets triggered.
                let start_urls = app.deep_link().get_current()?;
                if let Some(urls) = start_urls {
                    // app was likely started by a deep link
                    println!("deep link URLs: {:?}", urls);
                }
    
    
                app.deep_link().on_open_url(|event| {
                    println!("deep link URLs: {:?}", event.urls());
                });
                Ok(())
            })
            .run(tauri::generate_context!())
            .expect("error while running tauri application");
    }
    

Note

The open URL event is triggered with a list of URLs that were requested to be compatible with the macOS API for deep links, but in most cases your app will only receive a single URL.

The configuration section describes how to define static deep link schemes for your application.

On Linux and Windows it is possible to also associate schemes with your application at runtime via the register Rust function.

In the following snippet, we will register the my-app scheme at runtime. After executing the app for the first time, the operating system will open my-app://* URLs with our application:

src-tauri/src/lib.rs

use tauri_plugin_deep_link::DeepLinkExt;


#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_deep_link::init())
        .setup(|app| {
            #[cfg(desktop)]
            app.deep_link().register("my-app")?;
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Note

Registering the deep links at runtime can be useful for developing on Linux and Windows as by default the deep link is only registered when your app is installed.

Installing an AppImage can be complicated as it requires an AppImage launcher.

Registering the deep links at runtime might be preferred, so Tauri also includes a helper function to force register all statically configured deep links at runtime. Calling this function also ensures the deep links is registered for development mode:

#[cfg(any(target_os = "linux", all(debug_assertions, windows)))]
{
  use tauri_plugin_deep_link::DeepLinkExt;
  app.deep_link().register_all()?;
}

Testing

There are some caveats to test deep links for your application.

Desktop

Deep links are only triggered for installed applications on desktop. On Linux and Windows you can circumvent this using the register_all Rust function, which registers all configured schemes to trigger the current executable:

src-tauri/src/lib.rs

use tauri_plugin_deep_link::DeepLinkExt;


#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_deep_link::init())
        .setup(|app| {
            #[cfg(any(windows, target_os = "linux"))]
            {
                use tauri_plugin_deep_link::DeepLinkExt;
                app.deep_link().register_all()?;
            }
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Note

Installing an AppImage that supports deep links on Linux requires an AppImage launcher to integrate the AppImage with the operating system. Using the register_all function you can support deep links out of the box, without requiring your users to use external tools.

When the AppImage is moved to a different location in the file system, the deep link is invalidated since it leverages an absolute path to the executable, which makes registering the schemes at runtime even more important.

See the Registering Desktop Deep Links at Runtime section for more information.

Caution

Registering deep links at runtime is not possible on macOS, so deep links can only be tested on the bundled application, which must be installed in the /Applications directory.

Windows

To trigger a deep link on Windows you can either open <scheme>://url in the browser or run the following command in the terminal:

start <scheme>://url

Linux

To trigger a deep link on Linux you can either open <scheme>://url in the browser or run xdg-open in the terminal:

xdg-open <scheme>://url

iOS

To trigger an app link on iOS you can open the https://<host>/path URL in the browser. For simulators you can leverage the simctl CLI to directly open a link from the terminal:

xcrun simctl openurl booted https://<host>/path

Android

To trigger an app link on Android you can open the https://<host>/path URL in the browser. For emulators you can leverage the adb CLI to directly open a link from the terminal:

adb shell am start -a android.intent.action.VIEW -d https://<host>/path <bundle-identifier>

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/mobile-schema.json",
  "identifier": "mobile-capability",
  "windows": ["main"],
  "platforms": ["iOS", "android"],
  "permissions": [
    // Usually you will need core:event:default to listen to the deep-link event
    "core:event:default",
    +"deep-link:default"
  ]
}

Default Permission

Allows reading the opened deep link via the get_current command

This default permission set includes the following:

  • allow-get-current

Permission Table

Identifier Description
deep-link:allow-get-current Enables the get_current command without any pre-configured scope.
deep-link:deny-get-current Denies the get_current command without any pre-configured scope.
deep-link:allow-is-registered Enables the is_registered command without any pre-configured scope.
deep-link:deny-is-registered Denies the is_registered command without any pre-configured scope.
deep-link:allow-register Enables the register command without any pre-configured scope.
deep-link:deny-register Denies the register command without any pre-configured scope.
deep-link:allow-unregister Enables the unregister command without any pre-configured scope.
deep-link:deny-unregister Denies the unregister command without any pre-configured scope.

Dialog

Native system dialogs for opening and saving files along with message dialogs.

GitHubnpmcrates.io

API Reference:

Native system dialogs for opening and saving files along with message dialogs.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android Does not support folder picker
ios Does not support folder picker

Setup

Install the dialog plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add dialog
      
    • yarn

      yarn run tauri add dialog
      
    • pnpm

      pnpm tauri add dialog
      
    • deno

      deno task tauri add dialog
      
    • bun

      bun tauri add dialog
      
    • cargo

      cargo tauri add dialog
      
  • Manual

    npm run tauri add dialog
    
  • npm

    yarn run tauri add dialog
    
  • yarn

    pnpm tauri add dialog
    
  • pnpm

    deno task tauri add dialog
    
  • deno

    bun tauri add dialog
    
  • bun

    cargo tauri add dialog
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-dialog
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_dialog::init())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. If youd like create dialogs in JavaScript, install the npm package as well:

      • npm

        npm install @tauri-apps/plugin-dialog
        
      • yarn

        yarn add @tauri-apps/plugin-dialog
        
      • pnpm

        pnpm add @tauri-apps/plugin-dialog
        
      • deno

        deno add npm:@tauri-apps/plugin-dialog
        
      • bun

        bun add @tauri-apps/plugin-dialog
        
  • npm

    npm install @tauri-apps/plugin-dialog
    
  • yarn

    yarn add @tauri-apps/plugin-dialog
    
  • pnpm

    pnpm add @tauri-apps/plugin-dialog
    
  • deno

    deno add npm:@tauri-apps/plugin-dialog
    
  • bun

    bun add @tauri-apps/plugin-dialog
    

Usage

The dialog plugin is available in both JavaScript and Rust. Heres how you can use it:

in JavaScript:

in Rust:

Note

The file dialog APIs returns file system paths on Linux, Windows and macOS.

On iOS, a file://<path> URIs are returned.

On Android, content URIs are returned.

The filesystem plugin works with any path format out of the box.

JavaScript

See all Dialog Options at the JavaScript API reference.

Create Yes/No Dialog

Shows a question dialog with Yes and No buttons.

import { ask } from '@tauri-apps/plugin-dialog';
// when using `"withGlobalTauri": true`, you may use
// const { ask } = window.__TAURI__.dialog;


// Create a Yes/No dialog
const answer = await ask('This action cannot be reverted. Are you sure?', {
  title: 'Tauri',
  kind: 'warning',
});


console.log(answer);
// Prints boolean to the console

Create Ok/Cancel Dialog

Shows a question dialog with Ok and Cancel buttons.

import { confirm } from '@tauri-apps/plugin-dialog';
// when using `"withGlobalTauri": true`, you may use
// const { confirm } = window.__TAURI__.dialog;


// Creates a confirmation Ok/Cancel dialog
const confirmation = await confirm(
  'This action cannot be reverted. Are you sure?',
  { title: 'Tauri', kind: 'warning' }
);


console.log(confirmation);
// Prints boolean to the console

Create Message Dialog

Shows a message dialog with an Ok button. Keep in mind that if the user closes the dialog it will return false.

import { message } from '@tauri-apps/plugin-dialog';
// when using `"withGlobalTauri": true`, you may use
// const { message } = window.__TAURI__.dialog;


// Shows message
await message('File not found', { title: 'Tauri', kind: 'error' });

Open a File Selector Dialog

Open a file/directory selection dialog.

The multiple option controls whether the dialog allows multiple selection or not, while the directory, whether is a directory selection or not.

import { open } from '@tauri-apps/plugin-dialog';
// when using `"withGlobalTauri": true`, you may use
// const { open } = window.__TAURI__.dialog;


// Open a dialog
const file = await open({
  multiple: false,
  directory: false,
});
console.log(file);
// Prints file path or URI

Save to File Dialog

Open a file/directory save dialog.

import { save } from '@tauri-apps/plugin-dialog';
// when using `"withGlobalTauri": true`, you may use
// const { save } = window.__TAURI__.dialog;


// Prompt to save a 'My Filter' with extension .png or .jpeg
const path = await save({
  filters: [
    {
      name: 'My Filter',
      extensions: ['png', 'jpeg'],
    },
  ],
});
console.log(path);
// Prints the chosen path

Rust

Refer to the Rust API reference to see all available options.

Build an Ask Dialog

Shows a question dialog with Absolutely and Totally buttons.

use tauri_plugin_dialog::{DialogExt, MessageDialogButtons};


let answer = app.dialog()
        .message("Tauri is Awesome")
        .title("Tauri is Awesome")
        .buttons(MessageDialogButtons::OkCancelCustom("Absolutely", "Totally"))
        .blocking_show();

If you need a non blocking operation you can use show() instead:

use tauri_plugin_dialog::{DialogExt, MessageDialogButtons};


app.dialog()
    .message("Tauri is Awesome")
    .title("Tauri is Awesome")
   .buttons(MessageDialogButtons::OkCancelCustom("Absolutely", "Totally"))
    .show(|result| match result {
        true => // do something,
        false =>// do something,
    });

Build a Message Dialog

Shows a message dialog with an Ok button. Keep in mind that if the user closes the dialog it will return false.

use tauri_plugin_dialog::{DialogExt, MessageDialogKind};


let ans = app.dialog()
    .message("File not found")
    .kind(MessageDialogKind::Error)
    .title("Warning")
    .blocking_show();

If you need a non blocking operation you can use show() instead:

use tauri_plugin_dialog::{DialogExt, MessageDialogButtons, MessageDialogKind};


app.dialog()
    .message("Tauri is Awesome")
    .kind(MessageDialogKind::Info)
    .title("Information")
    .buttons(MessageDialogButtons::OkCustom("Absolutely"))
    .show(|result| match result {
        true => // do something,
        false => // do something,
    });

Build a File Selector Dialog

Pick Files

use tauri_plugin_dialog::DialogExt;


let file_path = app.dialog().file().blocking_pick_file();
// return a file_path `Option`, or `None` if the user closes the dialog

If you need a non blocking operation you can use pick_file() instead:

use tauri_plugin_dialog::DialogExt;


app.dialog().file().pick_file(|file_path| {
    // return a file_path `Option`, or `None` if the user closes the dialog
    })

Save Files

use tauri_plugin_dialog::DialogExt;


let file_path = app
    .dialog()
    .file()
    .add_filter("My Filter", &["png", "jpeg"])
    .blocking_save_file();
    // do something with the optional file path here
    // the file path is `None` if the user closed the dialog

or, alternatively:

use tauri_plugin_dialog::DialogExt;


app.dialog()
    .file()
    .add_filter("My Filter", &["png", "jpeg"])
    .pick_file(|file_path| {
        // return a file_path `Option`, or `None` if the user closes the dialog
    });

Default Permission

This permission set configures the types of dialogs available from the dialog plugin.

Granted Permissions

All dialog types are enabled.

This default permission set includes the following:

  • allow-message
  • allow-save
  • allow-open

Permission Table

Identifier Description
dialog:allow-ask Enables the ask command without any pre-configured scope. (DEPRECATED: This is now an alias to allow-message and will be removed in v3)
dialog:deny-ask Denies the ask command without any pre-configured scope. (DEPRECATED: This is now an alias to deny-message and will be removed in v3)
dialog:allow-message Enables the message command without any pre-configured scope.
dialog:deny-message Denies the message command without any pre-configured scope.
dialog:allow-open Enables the open command without any pre-configured scope.
dialog:deny-open Denies the open command without any pre-configured scope.
dialog:allow-save Enables the save command without any pre-configured scope.
dialog:deny-save Denies the save command without any pre-configured scope.
dialog:allow-confirm Enables the confirm command without any pre-configured scope. (DEPRECATED: This is now an alias to allow-message and will be removed in v3)
dialog:deny-confirm Denies the confirm command without any pre-configured scope. (DEPRECATED: This is now an alias to deny-message and will be removed in v3)

File System

Access the file system.

GitHubnpmcrates.io

API Reference:

Access the file system.

Use std::fs or tokio::fs on the Rust side

If you want to manipulate files/directories through Rust, use traditional Rusts libs (std::fs, tokio::fs, etc).

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows Apps installed via MSI or NSIS in perMachine and both mode require admin permissions for write access in $RESOURCES folder
linux No write access to $RESOURCES folder
macos No write access to $RESOURCES folder
android Access is restricted to Application folder by default
ios Access is restricted to Application folder by default

Setup

Install the fs plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add fs
      
    • yarn

      yarn run tauri add fs
      
    • pnpm

      pnpm tauri add fs
      
    • deno

      deno task tauri add fs
      
    • bun

      bun tauri add fs
      
    • cargo

      cargo tauri add fs
      
  • Manual

    npm run tauri add fs
    
  • npm

    yarn run tauri add fs
    
  • yarn

    pnpm tauri add fs
    
  • pnpm

    deno task tauri add fs
    
  • deno

    bun tauri add fs
    
  • bun

    cargo tauri add fs
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-fs
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
        tauri::Builder::default()
          +.plugin(tauri_plugin_fs::init())
          .run(tauri::generate_context!())
          .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-fs
        
      • yarn

        yarn add @tauri-apps/plugin-fs
        
      • pnpm

        pnpm add @tauri-apps/plugin-fs
        
      • deno

        deno add npm:@tauri-apps/plugin-fs
        
      • bun

        bun add @tauri-apps/plugin-fs
        
  • npm

    npm install @tauri-apps/plugin-fs
    
  • yarn

    yarn add @tauri-apps/plugin-fs
    
  • pnpm

    pnpm add @tauri-apps/plugin-fs
    
  • deno

    deno add npm:@tauri-apps/plugin-fs
    
  • bun

    bun add @tauri-apps/plugin-fs
    

Configuration

Android

When using the audio, cache, documents, downloads, picture, public or video directories your app must have access to the external storage.

Include the following permissions to the manifest tag in the gen/android/app/src/main/AndroidManifest.xml file:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

iOS

Apple requires app developers to specify approved reasons for API usage to enhance user privacy.

You must create a PrivacyInfo.xcprivacy file in the src-tauri/gen/apple folder with the required NSPrivacyAccessedAPICategoryFileTimestamp key and the C617.1 recommended reason.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>NSPrivacyAccessedAPITypes</key>
    <array>
      <dict>
        <key>NSPrivacyAccessedAPIType</key>
        <string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
        <key>NSPrivacyAccessedAPITypeReasons</key>
        <array>
          <string>C617.1</string>
        </array>
      </dict>
    </array>
  </dict>
</plist>

Usage

The fs plugin is available in both JavaScript and Rust.

Different APIs

Although this plugin has a file manipulation API on the frontend, in the backend it offers only the methods to change permission of some resources (files, directories, etc).

In the Rust side you can use the traditional file manipulation libraries, std::fs, tokio::fs or others.

  • JavaScript

    import { exists, BaseDirectory } from '@tauri-apps/plugin-fs';
    // when using `"withGlobalTauri": true`, you may use
    // const { exists, BaseDirectory } = window.__TAURI__.fs;
    
    
    // Check if the `$APPDATA/avatar.png` file exists
    await exists('avatar.png', { baseDir: BaseDirectory.AppData });
    
  • Rust

    src-tauri/src/lib.rs

    use tauri_plugin_fs::FsExt;
    
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
      tauri::Builder::default()
          .plugin(tauri_plugin_fs::init())
          .setup(|app| {
              // allowed the given directory
              let scope = app.fs_scope();
              scope.allow_directory("/path/to/directory", false);
              dbg!(scope.allowed());
    
    
              Ok(())
           })
           .run(tauri::generate_context!())
           .expect("error while running tauri application");
    }
    

Security

This module prevents path traversal, not allowing parent directory accessors to be used (i.e. “/usr/path/to/../file” or “../path/to/file” paths are not allowed). Paths accessed with this API must be either relative to one of the base directories or created with the path API.

See @tauri-apps/plugin-fs - Security for more information.

Paths

The file system plugin offers two ways of manipulating paths: the base directory and the path API.

  • base directory

    Every API has an options argument that lets you define a baseDir that acts as the working directory of the operation.

    import { readFile } from '@tauri-apps/plugin-fs';
    const contents = await readFile('avatars/tauri.png', {
      baseDir: BaseDirectory.Home,
    });
    

    In the above example the ~/avatars/tauri.png file is read since we are using the Home base directory.

  • path API

    Alternatively you can use the path APIs to perform path manipulations.

    import { readFile } from '@tauri-apps/plugin-fs';
    import * as path from '@tauri-apps/api/path';
    const home = await path.homeDir();
    const contents = await readFile(await path.join(home, 'avatars/tauri.png'));
    

Files

Create

Creates a file and returns a handle to it. If the file already exists, it is truncated.

import { create, BaseDirectory } from '@tauri-apps/plugin-fs';
const file = await create('foo/bar.txt', { baseDir: BaseDirectory.AppData });
await file.write(new TextEncoder().encode('Hello world'));
await file.close();

Note

Always call file.close() when you are done manipulating the file.

Write

The plugin offers separate APIs for writing text and binary files for performance.

  • text files

    import { writeTextFile, BaseDirectory } from '@tauri-apps/plugin-fs';
    const contents = JSON.stringify({ notifications: true });
    await writeTextFile('config.json', contents, {
      baseDir: BaseDirectory.AppConfig,
    });
    
  • binary files

    import { writeFile, BaseDirectory } from '@tauri-apps/plugin-fs';
    const contents = new Uint8Array(); // fill a byte array
    await writeFile('config', contents, {
      baseDir: BaseDirectory.AppConfig,
    });
    

Open

Opens a file and returns a handle to it. With this API you have more control over how the file should be opened (read-only mode, write-only mode, append instead of overwrite, only create if it does not exist, etc).

Note

Always call file.close() when you are done manipulating the file.

  • read-only

    This is the default mode.

    import { open, BaseDirectory } from '@tauri-apps/plugin-fs';
    const file = await open('foo/bar.txt', {
      read: true,
      baseDir: BaseDirectory.AppData,
    });
    
    
    const stat = await file.stat();
    const buf = new Uint8Array(stat.size);
    await file.read(buf);
    const textContents = new TextDecoder().decode(buf);
    await file.close();
    
  • write-only

    import { open, BaseDirectory } from '@tauri-apps/plugin-fs';
    const file = await open('foo/bar.txt', {
      write: true,
      baseDir: BaseDirectory.AppData,
    });
    await file.write(new TextEncoder().encode('Hello world'));
    await file.close();
    

    By default the file is truncated on any file.write() call. See the following example to learn how to append to the existing contents instead.

  • append

    import { open, BaseDirectory } from '@tauri-apps/plugin-fs';
    const file = await open('foo/bar.txt', {
      append: true,
      baseDir: BaseDirectory.AppData,
    });
    await file.write(new TextEncoder().encode('world'));
    await file.close();
    

    Note that { append: true } has the same effect as { write: true, append: true }.

  • truncate

    When the truncate option is set and the file already exists, it will be truncated to length 0.

    import { open, BaseDirectory } from '@tauri-apps/plugin-fs';
    const file = await open('foo/bar.txt', {
      write: true,
      truncate: true,
      baseDir: BaseDirectory.AppData,
    });
    await file.write(new TextEncoder().encode('world'));
    await file.close();
    

    This option requires write to be true.

    You can use it along the append option if you want to rewrite an existing file using multiple file.write() calls.

  • create

    By default the open API only opens existing files. To create the file if it does not exist, opening it if it does, set create to true:

    import { open, BaseDirectory } from '@tauri-apps/plugin-fs';
    const file = await open('foo/bar.txt', {
      write: true,
      create: true,
      baseDir: BaseDirectory.AppData,
    });
    await file.write(new TextEncoder().encode('world'));
    await file.close();
    

    In order for the file to be created, write or append must also be set to true.

    To fail if the file already exists, see createNew.

  • createNew

    createNew works similarly to create, but will fail if the file already exists.

    import { open, BaseDirectory } from '@tauri-apps/plugin-fs';
    const file = await open('foo/bar.txt', {
      write: true,
      createNew: true,
      baseDir: BaseDirectory.AppData,
    });
    await file.write(new TextEncoder().encode('world'));
    await file.close();
    

    In order for the file to be created, write must also be set to true.

Read

The plugin offers separate APIs for reading text and binary files for performance.

  • text files

    import { readTextFile, BaseDirectory } from '@tauri-apps/plugin-fs';
    const configToml = await readTextFile('config.toml', {
      baseDir: BaseDirectory.AppConfig,
    });
    

    If the file is large you can stream its lines with the readTextFileLines API:

    import { readTextFileLines, BaseDirectory } from '@tauri-apps/plugin-fs';
    const lines = await readTextFileLines('app.logs', {
      baseDir: BaseDirectory.AppLog,
    });
    for await (const line of lines) {
      console.log(line);
    }
    
  • binary files

    import { readFile, BaseDirectory } from '@tauri-apps/plugin-fs';
    const icon = await readFile('icon.png', {
      baseDir: BaseDirectory.Resources,
    });
    

Remove

Call remove() to delete a file. If the file does not exist, an error is returned.

import { remove, BaseDirectory } from '@tauri-apps/plugin-fs';
await remove('user.db', { baseDir: BaseDirectory.AppLocalData });

Copy

The copyFile function takes the source and destination paths. Note that you must configure each base directory separately.

import { copyFile, BaseDirectory } from '@tauri-apps/plugin-fs';
await copyFile('user.db', 'user.db.bk', {
  fromPathBaseDir: BaseDirectory.AppLocalData,
  toPathBaseDir: BaseDirectory.Temp,
});

In the above example the <app-local-data>/user.db file is copied to $TMPDIR/user.db.bk.

Exists

Use the exists() function to check if a file exists:

import { exists, BaseDirectory } from '@tauri-apps/plugin-fs';
const tokenExists = await exists('token', {
  baseDir: BaseDirectory.AppLocalData,
});

Metadata

File metadata can be retrieved with the stat and the lstat functions. stat follows symlinks (and returns an error if the actual file it points to is not allowed by the scope) and lstat does not follow symlinks, returning the information of the symlink itself.

import { stat, BaseDirectory } from '@tauri-apps/plugin-fs';
const metadata = await stat('app.db', {
  baseDir: BaseDirectory.AppLocalData,
});

Rename

The rename function takes the source and destination paths. Note that you must configure each base directory separately.

import { rename, BaseDirectory } from '@tauri-apps/plugin-fs';
await rename('user.db.bk', 'user.db', {
  fromPathBaseDir: BaseDirectory.AppLocalData,
  toPathBaseDir: BaseDirectory.Temp,
});

In the above example the <app-local-data>/user.db.bk file is renamed to $TMPDIR/user.db.

Truncate

Truncates or extends the specified file to reach the specified file length (defaults to 0).

  • truncate to 0 length
import { truncate } from '@tauri-apps/plugin-fs';
await truncate('my_file.txt', 0, { baseDir: BaseDirectory.AppLocalData });
  • truncate to a specific length
import {
  truncate,
  readTextFile,
  writeTextFile,
  BaseDirectory,
} from '@tauri-apps/plugin-fs';


const filePath = 'file.txt';
await writeTextFile(filePath, 'Hello World', {
  baseDir: BaseDirectory.AppLocalData,
});
await truncate(filePath, 7, {
  baseDir: BaseDirectory.AppLocalData,
});
const data = await readTextFile(filePath, {
  baseDir: BaseDirectory.AppLocalData,
});
console.log(data); // "Hello W"

Directories

Create

To create a directory, call the mkdir function:

import { mkdir, BaseDirectory } from '@tauri-apps/plugin-fs';
await mkdir('images', {
  baseDir: BaseDirectory.AppLocalData,
});

Read

The readDir function recursively lists the entries of a directory:

import { readDir, BaseDirectory } from '@tauri-apps/plugin-fs';
const entries = await readDir('users', { baseDir: BaseDirectory.AppLocalData });

Remove

Call remove() to delete a directory. If the directory does not exist, an error is returned.

import { remove, BaseDirectory } from '@tauri-apps/plugin-fs';
await remove('images', { baseDir: BaseDirectory.AppLocalData });

If the directory is not empty, the recursive option must be set to true:

import { remove, BaseDirectory } from '@tauri-apps/plugin-fs';
await remove('images', {
  baseDir: BaseDirectory.AppLocalData,
  recursive: true,
});

Exists

Use the exists() function to check if a directory exists:

import { exists, BaseDirectory } from '@tauri-apps/plugin-fs';
const tokenExists = await exists('images', {
  baseDir: BaseDirectory.AppLocalData,
});

Metadata

Directory metadata can be retrieved with the stat and the lstat functions. stat follows symlinks (and returns an error if the actual file it points to is not allowed by the scope) and lstat does not follow symlinks, returning the information of the symlink itself.

import { stat, BaseDirectory } from '@tauri-apps/plugin-fs';
const metadata = await stat('databases', {
  baseDir: BaseDirectory.AppLocalData,
});

Watching changes

To watch a directory or file for changes, use the watch or watchImmediate functions.

  • watch

    watch is debounced so it only emits events after a certain delay:

    import { watch, BaseDirectory } from '@tauri-apps/plugin-fs';
    await watch(
      'app.log',
      (event) => {
        console.log('app.log event', event);
      },
      {
        baseDir: BaseDirectory.AppLog,
        delayMs: 500,
      }
    );
    
  • watchImmediate

    watchImmediate immediately notifies listeners of an event:

    import { watchImmediate, BaseDirectory } from '@tauri-apps/plugin-fs';
    await watchImmediate(
      'logs',
      (event) => {
        console.log('logs directory event', event);
      },
      {
        baseDir: BaseDirectory.AppLog,
        recursive: true,
      }
    );
    

By default watch operations on a directory are not recursive. Set the recursive option to true to recursively watch for changes on all sub-directories.

Note

The watch functions require the watch feature flag:

src-tauri/Cargo.toml

[dependencies]
tauri-plugin-fs = { version = "2.0.0", features = ["watch"] }

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    +"fs:default",
+    {
      +"identifier": "fs:allow-exists",
      +"allow": [{ "path": "$APPDATA/*" }]
+    }
  ]
}

Default Permission

This set of permissions describes the what kind of file system access the fs plugin has enabled or denied by default.

Granted Permissions

This default permission set enables read access to the application specific directories (AppConfig, AppData, AppLocalData, AppCache, AppLog) and all files and sub directories created in it. The location of these directories depends on the operating system, where the application is run.

In general these directories need to be manually created by the application at runtime, before accessing files or folders in it is possible.

Therefore, it is also allowed to create all of these folders via the mkdir command.

Denied Permissions

This default permission set prevents access to critical components of the Tauri application by default. On Windows the webview data folder access is denied.

This default permission set includes the following:

  • create-app-specific-dirs
  • read-app-specific-dirs-recursive
  • deny-default

Permission Table

Identifier Description
fs:allow-app-read-recursive This allows full recursive read access to the complete application folders, files and subdirectories.
fs:allow-app-write-recursive This allows full recursive write access to the complete application folders, files and subdirectories.
fs:allow-app-read This allows non-recursive read access to the application folders.
fs:allow-app-write This allows non-recursive write access to the application folders.
fs:allow-app-meta-recursive This allows full recursive read access to metadata of the application folders, including file listing and statistics.
fs:allow-app-meta This allows non-recursive read access to metadata of the application folders, including file listing and statistics.
fs:scope-app-recursive This scope permits recursive access to the complete application folders, including sub directories and files.
fs:scope-app This scope permits access to all files and list content of top level directories in the application folders.
fs:scope-app-index This scope permits to list all files and folders in the application directories.
fs:allow-appcache-read-recursive This allows full recursive read access to the complete $APPCACHE folder, files and subdirectories.
fs:allow-appcache-write-recursive This allows full recursive write access to the complete $APPCACHE folder, files and subdirectories.
fs:allow-appcache-read This allows non-recursive read access to the $APPCACHE folder.
fs:allow-appcache-write This allows non-recursive write access to the $APPCACHE folder.
fs:allow-appcache-meta-recursive This allows full recursive read access to metadata of the $APPCACHE folder, including file listing and statistics.
fs:allow-appcache-meta This allows non-recursive read access to metadata of the $APPCACHE folder, including file listing and statistics.
fs:scope-appcache-recursive This scope permits recursive access to the complete $APPCACHE folder, including sub directories and files.
fs:scope-appcache This scope permits access to all files and list content of top level directories in the $APPCACHE folder.
fs:scope-appcache-index This scope permits to list all files and folders in the $APPCACHEfolder.
fs:allow-appconfig-read-recursive This allows full recursive read access to the complete $APPCONFIG folder, files and subdirectories.
fs:allow-appconfig-write-recursive This allows full recursive write access to the complete $APPCONFIG folder, files and subdirectories.
fs:allow-appconfig-read This allows non-recursive read access to the $APPCONFIG folder.
fs:allow-appconfig-write This allows non-recursive write access to the $APPCONFIG folder.
fs:allow-appconfig-meta-recursive This allows full recursive read access to metadata of the $APPCONFIG folder, including file listing and statistics.
fs:allow-appconfig-meta This allows non-recursive read access to metadata of the $APPCONFIG folder, including file listing and statistics.
fs:scope-appconfig-recursive This scope permits recursive access to the complete $APPCONFIG folder, including sub directories and files.
fs:scope-appconfig This scope permits access to all files and list content of top level directories in the $APPCONFIG folder.
fs:scope-appconfig-index This scope permits to list all files and folders in the $APPCONFIGfolder.
fs:allow-appdata-read-recursive This allows full recursive read access to the complete $APPDATA folder, files and subdirectories.
fs:allow-appdata-write-recursive This allows full recursive write access to the complete $APPDATA folder, files and subdirectories.
fs:allow-appdata-read This allows non-recursive read access to the $APPDATA folder.
fs:allow-appdata-write This allows non-recursive write access to the $APPDATA folder.
fs:allow-appdata-meta-recursive This allows full recursive read access to metadata of the $APPDATA folder, including file listing and statistics.
fs:allow-appdata-meta This allows non-recursive read access to metadata of the $APPDATA folder, including file listing and statistics.
fs:scope-appdata-recursive This scope permits recursive access to the complete $APPDATA folder, including sub directories and files.
fs:scope-appdata This scope permits access to all files and list content of top level directories in the $APPDATA folder.
fs:scope-appdata-index This scope permits to list all files and folders in the $APPDATAfolder.
fs:allow-applocaldata-read-recursive This allows full recursive read access to the complete $APPLOCALDATA folder, files and subdirectories.
fs:allow-applocaldata-write-recursive This allows full recursive write access to the complete $APPLOCALDATA folder, files and subdirectories.
fs:allow-applocaldata-read This allows non-recursive read access to the $APPLOCALDATA folder.
fs:allow-applocaldata-write This allows non-recursive write access to the $APPLOCALDATA folder.
fs:allow-applocaldata-meta-recursive This allows full recursive read access to metadata of the $APPLOCALDATA folder, including file listing and statistics.
fs:allow-applocaldata-meta This allows non-recursive read access to metadata of the $APPLOCALDATA folder, including file listing and statistics.
fs:scope-applocaldata-recursive This scope permits recursive access to the complete $APPLOCALDATA folder, including sub directories and files.
fs:scope-applocaldata This scope permits access to all files and list content of top level directories in the $APPLOCALDATA folder.
fs:scope-applocaldata-index This scope permits to list all files and folders in the $APPLOCALDATAfolder.
fs:allow-applog-read-recursive This allows full recursive read access to the complete $APPLOG folder, files and subdirectories.
fs:allow-applog-write-recursive This allows full recursive write access to the complete $APPLOG folder, files and subdirectories.
fs:allow-applog-read This allows non-recursive read access to the $APPLOG folder.
fs:allow-applog-write This allows non-recursive write access to the $APPLOG folder.
fs:allow-applog-meta-recursive This allows full recursive read access to metadata of the $APPLOG folder, including file listing and statistics.
fs:allow-applog-meta This allows non-recursive read access to metadata of the $APPLOG folder, including file listing and statistics.
fs:scope-applog-recursive This scope permits recursive access to the complete $APPLOG folder, including sub directories and files.
fs:scope-applog This scope permits access to all files and list content of top level directories in the $APPLOG folder.
fs:scope-applog-index This scope permits to list all files and folders in the $APPLOGfolder.
fs:allow-audio-read-recursive This allows full recursive read access to the complete $AUDIO folder, files and subdirectories.
fs:allow-audio-write-recursive This allows full recursive write access to the complete $AUDIO folder, files and subdirectories.
fs:allow-audio-read This allows non-recursive read access to the $AUDIO folder.
fs:allow-audio-write This allows non-recursive write access to the $AUDIO folder.
fs:allow-audio-meta-recursive This allows full recursive read access to metadata of the $AUDIO folder, including file listing and statistics.
fs:allow-audio-meta This allows non-recursive read access to metadata of the $AUDIO folder, including file listing and statistics.
fs:scope-audio-recursive This scope permits recursive access to the complete $AUDIO folder, including sub directories and files.
fs:scope-audio This scope permits access to all files and list content of top level directories in the $AUDIO folder.
fs:scope-audio-index This scope permits to list all files and folders in the $AUDIOfolder.
fs:allow-cache-read-recursive This allows full recursive read access to the complete $CACHE folder, files and subdirectories.
fs:allow-cache-write-recursive This allows full recursive write access to the complete $CACHE folder, files and subdirectories.
fs:allow-cache-read This allows non-recursive read access to the $CACHE folder.
fs:allow-cache-write This allows non-recursive write access to the $CACHE folder.
fs:allow-cache-meta-recursive This allows full recursive read access to metadata of the $CACHE folder, including file listing and statistics.
fs:allow-cache-meta This allows non-recursive read access to metadata of the $CACHE folder, including file listing and statistics.
fs:scope-cache-recursive This scope permits recursive access to the complete $CACHE folder, including sub directories and files.
fs:scope-cache This scope permits access to all files and list content of top level directories in the $CACHE folder.
fs:scope-cache-index This scope permits to list all files and folders in the $CACHEfolder.
fs:allow-config-read-recursive This allows full recursive read access to the complete $CONFIG folder, files and subdirectories.
fs:allow-config-write-recursive This allows full recursive write access to the complete $CONFIG folder, files and subdirectories.
fs:allow-config-read This allows non-recursive read access to the $CONFIG folder.
fs:allow-config-write This allows non-recursive write access to the $CONFIG folder.
fs:allow-config-meta-recursive This allows full recursive read access to metadata of the $CONFIG folder, including file listing and statistics.
fs:allow-config-meta This allows non-recursive read access to metadata of the $CONFIG folder, including file listing and statistics.
fs:scope-config-recursive This scope permits recursive access to the complete $CONFIG folder, including sub directories and files.
fs:scope-config This scope permits access to all files and list content of top level directories in the $CONFIG folder.
fs:scope-config-index This scope permits to list all files and folders in the $CONFIGfolder.
fs:allow-data-read-recursive This allows full recursive read access to the complete $DATA folder, files and subdirectories.
fs:allow-data-write-recursive This allows full recursive write access to the complete $DATA folder, files and subdirectories.
fs:allow-data-read This allows non-recursive read access to the $DATA folder.
fs:allow-data-write This allows non-recursive write access to the $DATA folder.
fs:allow-data-meta-recursive This allows full recursive read access to metadata of the $DATA folder, including file listing and statistics.
fs:allow-data-meta This allows non-recursive read access to metadata of the $DATA folder, including file listing and statistics.
fs:scope-data-recursive This scope permits recursive access to the complete $DATA folder, including sub directories and files.
fs:scope-data This scope permits access to all files and list content of top level directories in the $DATA folder.
fs:scope-data-index This scope permits to list all files and folders in the $DATAfolder.
fs:allow-desktop-read-recursive This allows full recursive read access to the complete $DESKTOP folder, files and subdirectories.
fs:allow-desktop-write-recursive This allows full recursive write access to the complete $DESKTOP folder, files and subdirectories.
fs:allow-desktop-read This allows non-recursive read access to the $DESKTOP folder.
fs:allow-desktop-write This allows non-recursive write access to the $DESKTOP folder.
fs:allow-desktop-meta-recursive This allows full recursive read access to metadata of the $DESKTOP folder, including file listing and statistics.
fs:allow-desktop-meta This allows non-recursive read access to metadata of the $DESKTOP folder, including file listing and statistics.
fs:scope-desktop-recursive This scope permits recursive access to the complete $DESKTOP folder, including sub directories and files.
fs:scope-desktop This scope permits access to all files and list content of top level directories in the $DESKTOP folder.
fs:scope-desktop-index This scope permits to list all files and folders in the $DESKTOPfolder.
fs:allow-document-read-recursive This allows full recursive read access to the complete $DOCUMENT folder, files and subdirectories.
fs:allow-document-write-recursive This allows full recursive write access to the complete $DOCUMENT folder, files and subdirectories.
fs:allow-document-read This allows non-recursive read access to the $DOCUMENT folder.
fs:allow-document-write This allows non-recursive write access to the $DOCUMENT folder.
fs:allow-document-meta-recursive This allows full recursive read access to metadata of the $DOCUMENT folder, including file listing and statistics.
fs:allow-document-meta This allows non-recursive read access to metadata of the $DOCUMENT folder, including file listing and statistics.
fs:scope-document-recursive This scope permits recursive access to the complete $DOCUMENT folder, including sub directories and files.
fs:scope-document This scope permits access to all files and list content of top level directories in the $DOCUMENT folder.
fs:scope-document-index This scope permits to list all files and folders in the $DOCUMENTfolder.
fs:allow-download-read-recursive This allows full recursive read access to the complete $DOWNLOAD folder, files and subdirectories.
fs:allow-download-write-recursive This allows full recursive write access to the complete $DOWNLOAD folder, files and subdirectories.
fs:allow-download-read This allows non-recursive read access to the $DOWNLOAD folder.
fs:allow-download-write This allows non-recursive write access to the $DOWNLOAD folder.
fs:allow-download-meta-recursive This allows full recursive read access to metadata of the $DOWNLOAD folder, including file listing and statistics.
fs:allow-download-meta This allows non-recursive read access to metadata of the $DOWNLOAD folder, including file listing and statistics.
fs:scope-download-recursive This scope permits recursive access to the complete $DOWNLOAD folder, including sub directories and files.
fs:scope-download This scope permits access to all files and list content of top level directories in the $DOWNLOAD folder.
fs:scope-download-index This scope permits to list all files and folders in the $DOWNLOADfolder.
fs:allow-exe-read-recursive This allows full recursive read access to the complete $EXE folder, files and subdirectories.
fs:allow-exe-write-recursive This allows full recursive write access to the complete $EXE folder, files and subdirectories.
fs:allow-exe-read This allows non-recursive read access to the $EXE folder.
fs:allow-exe-write This allows non-recursive write access to the $EXE folder.
fs:allow-exe-meta-recursive This allows full recursive read access to metadata of the $EXE folder, including file listing and statistics.
fs:allow-exe-meta This allows non-recursive read access to metadata of the $EXE folder, including file listing and statistics.
fs:scope-exe-recursive This scope permits recursive access to the complete $EXE folder, including sub directories and files.
fs:scope-exe This scope permits access to all files and list content of top level directories in the $EXE folder.
fs:scope-exe-index This scope permits to list all files and folders in the $EXEfolder.
fs:allow-font-read-recursive This allows full recursive read access to the complete $FONT folder, files and subdirectories.
fs:allow-font-write-recursive This allows full recursive write access to the complete $FONT folder, files and subdirectories.
fs:allow-font-read This allows non-recursive read access to the $FONT folder.
fs:allow-font-write This allows non-recursive write access to the $FONT folder.
fs:allow-font-meta-recursive This allows full recursive read access to metadata of the $FONT folder, including file listing and statistics.
fs:allow-font-meta This allows non-recursive read access to metadata of the $FONT folder, including file listing and statistics.
fs:scope-font-recursive This scope permits recursive access to the complete $FONT folder, including sub directories and files.
fs:scope-font This scope permits access to all files and list content of top level directories in the $FONT folder.
fs:scope-font-index This scope permits to list all files and folders in the $FONTfolder.
fs:allow-home-read-recursive This allows full recursive read access to the complete $HOME folder, files and subdirectories.
fs:allow-home-write-recursive This allows full recursive write access to the complete $HOME folder, files and subdirectories.
fs:allow-home-read This allows non-recursive read access to the $HOME folder.
fs:allow-home-write This allows non-recursive write access to the $HOME folder.
fs:allow-home-meta-recursive This allows full recursive read access to metadata of the $HOME folder, including file listing and statistics.
fs:allow-home-meta This allows non-recursive read access to metadata of the $HOME folder, including file listing and statistics.
fs:scope-home-recursive This scope permits recursive access to the complete $HOME folder, including sub directories and files.
fs:scope-home This scope permits access to all files and list content of top level directories in the $HOME folder.
fs:scope-home-index This scope permits to list all files and folders in the $HOMEfolder.
fs:allow-localdata-read-recursive This allows full recursive read access to the complete $LOCALDATA folder, files and subdirectories.
fs:allow-localdata-write-recursive This allows full recursive write access to the complete $LOCALDATA folder, files and subdirectories.
fs:allow-localdata-read This allows non-recursive read access to the $LOCALDATA folder.
fs:allow-localdata-write This allows non-recursive write access to the $LOCALDATA folder.
fs:allow-localdata-meta-recursive This allows full recursive read access to metadata of the $LOCALDATA folder, including file listing and statistics.
fs:allow-localdata-meta This allows non-recursive read access to metadata of the $LOCALDATA folder, including file listing and statistics.
fs:scope-localdata-recursive This scope permits recursive access to the complete $LOCALDATA folder, including sub directories and files.
fs:scope-localdata This scope permits access to all files and list content of top level directories in the $LOCALDATA folder.
fs:scope-localdata-index This scope permits to list all files and folders in the $LOCALDATAfolder.
fs:allow-log-read-recursive This allows full recursive read access to the complete $LOG folder, files and subdirectories.
fs:allow-log-write-recursive This allows full recursive write access to the complete $LOG folder, files and subdirectories.
fs:allow-log-read This allows non-recursive read access to the $LOG folder.
fs:allow-log-write This allows non-recursive write access to the $LOG folder.
fs:allow-log-meta-recursive This allows full recursive read access to metadata of the $LOG folder, including file listing and statistics.
fs:allow-log-meta This allows non-recursive read access to metadata of the $LOG folder, including file listing and statistics.
fs:scope-log-recursive This scope permits recursive access to the complete $LOG folder, including sub directories and files.
fs:scope-log This scope permits access to all files and list content of top level directories in the $LOG folder.
fs:scope-log-index This scope permits to list all files and folders in the $LOGfolder.
fs:allow-picture-read-recursive This allows full recursive read access to the complete $PICTURE folder, files and subdirectories.
fs:allow-picture-write-recursive This allows full recursive write access to the complete $PICTURE folder, files and subdirectories.
fs:allow-picture-read This allows non-recursive read access to the $PICTURE folder.
fs:allow-picture-write This allows non-recursive write access to the $PICTURE folder.
fs:allow-picture-meta-recursive This allows full recursive read access to metadata of the $PICTURE folder, including file listing and statistics.
fs:allow-picture-meta This allows non-recursive read access to metadata of the $PICTURE folder, including file listing and statistics.
fs:scope-picture-recursive This scope permits recursive access to the complete $PICTURE folder, including sub directories and files.
fs:scope-picture This scope permits access to all files and list content of top level directories in the $PICTURE folder.
fs:scope-picture-index This scope permits to list all files and folders in the $PICTUREfolder.
fs:allow-public-read-recursive This allows full recursive read access to the complete $PUBLIC folder, files and subdirectories.
fs:allow-public-write-recursive This allows full recursive write access to the complete $PUBLIC folder, files and subdirectories.
fs:allow-public-read This allows non-recursive read access to the $PUBLIC folder.
fs:allow-public-write This allows non-recursive write access to the $PUBLIC folder.
fs:allow-public-meta-recursive This allows full recursive read access to metadata of the $PUBLIC folder, including file listing and statistics.
fs:allow-public-meta This allows non-recursive read access to metadata of the $PUBLIC folder, including file listing and statistics.
fs:scope-public-recursive This scope permits recursive access to the complete $PUBLIC folder, including sub directories and files.
fs:scope-public This scope permits access to all files and list content of top level directories in the $PUBLIC folder.
fs:scope-public-index This scope permits to list all files and folders in the $PUBLICfolder.
fs:allow-resource-read-recursive This allows full recursive read access to the complete $RESOURCE folder, files and subdirectories.
fs:allow-resource-write-recursive This allows full recursive write access to the complete $RESOURCE folder, files and subdirectories.
fs:allow-resource-read This allows non-recursive read access to the $RESOURCE folder.
fs:allow-resource-write This allows non-recursive write access to the $RESOURCE folder.
fs:allow-resource-meta-recursive This allows full recursive read access to metadata of the $RESOURCE folder, including file listing and statistics.
fs:allow-resource-meta This allows non-recursive read access to metadata of the $RESOURCE folder, including file listing and statistics.
fs:scope-resource-recursive This scope permits recursive access to the complete $RESOURCE folder, including sub directories and files.
fs:scope-resource This scope permits access to all files and list content of top level directories in the $RESOURCE folder.
fs:scope-resource-index This scope permits to list all files and folders in the $RESOURCEfolder.
fs:allow-runtime-read-recursive This allows full recursive read access to the complete $RUNTIME folder, files and subdirectories.
fs:allow-runtime-write-recursive This allows full recursive write access to the complete $RUNTIME folder, files and subdirectories.
fs:allow-runtime-read This allows non-recursive read access to the $RUNTIME folder.
fs:allow-runtime-write This allows non-recursive write access to the $RUNTIME folder.
fs:allow-runtime-meta-recursive This allows full recursive read access to metadata of the $RUNTIME folder, including file listing and statistics.
fs:allow-runtime-meta This allows non-recursive read access to metadata of the $RUNTIME folder, including file listing and statistics.
fs:scope-runtime-recursive This scope permits recursive access to the complete $RUNTIME folder, including sub directories and files.
fs:scope-runtime This scope permits access to all files and list content of top level directories in the $RUNTIME folder.
fs:scope-runtime-index This scope permits to list all files and folders in the $RUNTIMEfolder.
fs:allow-temp-read-recursive This allows full recursive read access to the complete $TEMP folder, files and subdirectories.
fs:allow-temp-write-recursive This allows full recursive write access to the complete $TEMP folder, files and subdirectories.
fs:allow-temp-read This allows non-recursive read access to the $TEMP folder.
fs:allow-temp-write This allows non-recursive write access to the $TEMP folder.
fs:allow-temp-meta-recursive This allows full recursive read access to metadata of the $TEMP folder, including file listing and statistics.
fs:allow-temp-meta This allows non-recursive read access to metadata of the $TEMP folder, including file listing and statistics.
fs:scope-temp-recursive This scope permits recursive access to the complete $TEMP folder, including sub directories and files.
fs:scope-temp This scope permits access to all files and list content of top level directories in the $TEMP folder.
fs:scope-temp-index This scope permits to list all files and folders in the $TEMPfolder.
fs:allow-template-read-recursive This allows full recursive read access to the complete $TEMPLATE folder, files and subdirectories.
fs:allow-template-write-recursive This allows full recursive write access to the complete $TEMPLATE folder, files and subdirectories.
fs:allow-template-read This allows non-recursive read access to the $TEMPLATE folder.
fs:allow-template-write This allows non-recursive write access to the $TEMPLATE folder.
fs:allow-template-meta-recursive This allows full recursive read access to metadata of the $TEMPLATE folder, including file listing and statistics.
fs:allow-template-meta This allows non-recursive read access to metadata of the $TEMPLATE folder, including file listing and statistics.
fs:scope-template-recursive This scope permits recursive access to the complete $TEMPLATE folder, including sub directories and files.
fs:scope-template This scope permits access to all files and list content of top level directories in the $TEMPLATE folder.
fs:scope-template-index This scope permits to list all files and folders in the $TEMPLATEfolder.
fs:allow-video-read-recursive This allows full recursive read access to the complete $VIDEO folder, files and subdirectories.
fs:allow-video-write-recursive This allows full recursive write access to the complete $VIDEO folder, files and subdirectories.
fs:allow-video-read This allows non-recursive read access to the $VIDEO folder.
fs:allow-video-write This allows non-recursive write access to the $VIDEO folder.
fs:allow-video-meta-recursive This allows full recursive read access to metadata of the $VIDEO folder, including file listing and statistics.
fs:allow-video-meta This allows non-recursive read access to metadata of the $VIDEO folder, including file listing and statistics.
fs:scope-video-recursive This scope permits recursive access to the complete $VIDEO folder, including sub directories and files.
fs:scope-video This scope permits access to all files and list content of top level directories in the $VIDEO folder.
fs:scope-video-index This scope permits to list all files and folders in the $VIDEOfolder.
fs:allow-copy-file Enables the copy_file command without any pre-configured scope.
fs:deny-copy-file Denies the copy_file command without any pre-configured scope.
fs:allow-create Enables the create command without any pre-configured scope.
fs:deny-create Denies the create command without any pre-configured scope.
fs:allow-exists Enables the exists command without any pre-configured scope.
fs:deny-exists Denies the exists command without any pre-configured scope.
fs:allow-fstat Enables the fstat command without any pre-configured scope.
fs:deny-fstat Denies the fstat command without any pre-configured scope.
fs:allow-ftruncate Enables the ftruncate command without any pre-configured scope.
fs:deny-ftruncate Denies the ftruncate command without any pre-configured scope.
fs:allow-lstat Enables the lstat command without any pre-configured scope.
fs:deny-lstat Denies the lstat command without any pre-configured scope.
fs:allow-mkdir Enables the mkdir command without any pre-configured scope.
fs:deny-mkdir Denies the mkdir command without any pre-configured scope.
fs:allow-open Enables the open command without any pre-configured scope.
fs:deny-open Denies the open command without any pre-configured scope.
fs:allow-read Enables the read command without any pre-configured scope.
fs:deny-read Denies the read command without any pre-configured scope.
fs:allow-read-dir Enables the read_dir command without any pre-configured scope.
fs:deny-read-dir Denies the read_dir command without any pre-configured scope.
fs:allow-read-file Enables the read_file command without any pre-configured scope.
fs:deny-read-file Denies the read_file command without any pre-configured scope.
fs:allow-read-text-file Enables the read_text_file command without any pre-configured scope.
fs:deny-read-text-file Denies the read_text_file command without any pre-configured scope.
fs:allow-read-text-file-lines Enables the read_text_file_lines command without any pre-configured scope.
fs:deny-read-text-file-lines Denies the read_text_file_lines command without any pre-configured scope.
fs:allow-read-text-file-lines-next Enables the read_text_file_lines_next command without any pre-configured scope.
fs:deny-read-text-file-lines-next Denies the read_text_file_lines_next command without any pre-configured scope.
fs:allow-remove Enables the remove command without any pre-configured scope.
fs:deny-remove Denies the remove command without any pre-configured scope.
fs:allow-rename Enables the rename command without any pre-configured scope.
fs:deny-rename Denies the rename command without any pre-configured scope.
fs:allow-seek Enables the seek command without any pre-configured scope.
fs:deny-seek Denies the seek command without any pre-configured scope.
fs:allow-size Enables the size command without any pre-configured scope.
fs:deny-size Denies the size command without any pre-configured scope.
fs:allow-start-accessing-security-scoped-resource Enables the start_accessing_security_scoped_resource command without any pre-configured scope.
fs:deny-start-accessing-security-scoped-resource Denies the start_accessing_security_scoped_resource command without any pre-configured scope.
fs:allow-stat Enables the stat command without any pre-configured scope.
fs:deny-stat Denies the stat command without any pre-configured scope.
fs:allow-stop-accessing-security-scoped-resource Enables the stop_accessing_security_scoped_resource command without any pre-configured scope.
fs:deny-stop-accessing-security-scoped-resource Denies the stop_accessing_security_scoped_resource command without any pre-configured scope.
fs:allow-truncate Enables the truncate command without any pre-configured scope.
fs:deny-truncate Denies the truncate command without any pre-configured scope.
fs:allow-unwatch Enables the unwatch command without any pre-configured scope.
fs:deny-unwatch Denies the unwatch command without any pre-configured scope.
fs:allow-watch Enables the watch command without any pre-configured scope.
fs:deny-watch Denies the watch command without any pre-configured scope.
fs:allow-write Enables the write command without any pre-configured scope.
fs:deny-write Denies the write command without any pre-configured scope.
fs:allow-write-file Enables the write_file command without any pre-configured scope.
fs:deny-write-file Denies the write_file command without any pre-configured scope.
fs:allow-write-text-file Enables the write_text_file command without any pre-configured scope.
fs:deny-write-text-file Denies the write_text_file command without any pre-configured scope.
fs:create-app-specific-dirs This permissions allows to create the application specific directories.
fs:deny-default This denies access to dangerous Tauri relevant files and folders by default.
fs:deny-webview-data-linux This denies read access to the $APPLOCALDATA folder on linux as the webview data and configuration values are stored here. Allowing access can lead to sensitive information disclosure and should be well considered.
fs:deny-webview-data-windows This denies read access to the $APPLOCALDATA/EBWebView folder on windows as the webview data and configuration values are stored here. Allowing access can lead to sensitive information disclosure and should be well considered.
fs:read-all This enables all read related commands without any pre-configured accessible paths.
fs:read-app-specific-dirs-recursive This permission allows recursive read functionality on the application specific base directories.
fs:read-dirs This enables directory read and file metadata related commands without any pre-configured accessible paths.
fs:read-files This enables file read related commands without any pre-configured accessible paths.
fs:read-meta This enables all index or metadata related commands without any pre-configured accessible paths.
fs:scope An empty permission you can use to modify the global scope.## Example```
{
"identifier": "read-documents",
"windows": ["main"],
"permissions": [
"fs:allow-read",
{
"identifier": "fs:scope",
"allow": [
"$APPDATA/documents/**/*"
],
"deny": [
"$APPDATA/documents/secret.txt"
]
}
]
}
| `fs:write-all`                                      | This enables all write related commands without any pre-configured accessible paths.                                                                                                                                                                                                                                                                          |
| `fs:write-files`                                    | This enables all file write related commands without any pre-configured accessible paths.                                                                                                                                                                                                                                                                     |

### Scopes

This plugin permissions includes scopes for defining which paths are allowed or explicitly rejected. For more information on scopes, see the [Command Scopes](/security/scope/).

Each `allow` or `deny` scope must include an array listing all paths that should be allowed or denied. The scope entries are in the `{ path: string }` format.

Note

`deny` take precedence over `allow` so if a path is denied by a scope, it will be blocked at runtime even if it is allowed by another scope.

Scope entries can use `$<path>` variables to reference common system paths such as the home directory, the app resources directory and the config directory. The following table lists all common paths you can reference:

| Path                                                                                            | Variable      |
| ----------------------------------------------------------------------------------------------- | ------------- |
| [appConfigDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#appconfigdir)       | $APPCONFIG    |
| [appDataDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#appdatadir)           | $APPDATA      |
| [appLocalDataDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#appLocaldatadir) | $APPLOCALDATA |
| [appcacheDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#appcachedir)         | $APPCACHE     |
| [applogDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#applogdir)             | $APPLOG       |
| [audioDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#audiodir)               | $AUDIO        |
| [cacheDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#cachedir)               | $CACHE        |
| [configDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#configdir)             | $CONFIG       |
| [dataDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#datadir)                 | $DATA         |
| [localDataDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#localdatadir)       | $LOCALDATA    |
| [desktopDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#desktopdir)           | $DESKTOP      |
| [documentDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#documentdir)         | $DOCUMENT     |
| [downloadDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#downloaddir)         | $DOWNLOAD     |
| [executableDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#executabledir)     | $EXE          |
| [fontDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#fontdir)                 | $FONT         |
| [homeDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#homedir)                 | $HOME         |
| [pictureDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#picturedir)           | $PICTURE      |
| [publicDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#publicdir)             | $PUBLIC       |
| [runtimeDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#runtimedir)           | $RUNTIME      |
| [templateDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#templatedir)         | $TEMPLATE     |
| [videoDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#videodir)               | $VIDEO        |
| [resourceDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#resourcedir)         | $RESOURCE     |
| [tempDir](https://v2.tauri.app/reference/javascript/api/namespacepath/#tempdir)                 | $TEMP         |

#### Examples

* global scope

To apply a scope to any `fs` command, use the `fs:scope` permission:

src-tauri/capabilities/default.json

```json
{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    {
      "identifier": "fs:scope",
      "allow": [{ "path": "$APPDATA" }, { "path": "$APPDATA/**/*" }]
    }
  ]
}

To apply a scope to a specific fs command, use the the object form of permissions { "identifier": string, "allow"?: [], "deny"?: [] }:

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    {
      "identifier": "fs:allow-rename",
      "allow": [{ "path": "$HOME/**/*" }]
    },
    {
      "identifier": "fs:allow-rename",
      "deny": [{ "path": "$HOME/.config/**/*" }]
    },
    {
      "identifier": "fs:allow-exists",
      "allow": [{ "path": "$APPDATA/*" }]
    }
  ]
}

In the above example you can use the exists API using any $APPDATA sub path (does not include sub-directories) and the rename

Tip

If you are trying to access dotfiles (e.g. .gitignore) or dotfolders (e.g. .ssh) on Unix based systems, then you need to specify either the full path /home/user/.ssh/example or the glob after the dotfolder path component /home/user/.ssh/*.

If that does not work in your use case then you can configure the plugin to treat any component as a valid path literal.

src-tauri/tauri.conf.json

 "plugins": {
    "fs": {
      "requireLiteralLeadingDot": false
    }
  }

The same option exists for app.security.assetProtocol.scope when you use the object form (not the array-only form). For real-world cases involving dot-directories, see tauri#13788.

Geolocation

Get and track the device's current position, including information about altitude, heading, and speed (if available).

GitHubnpmcrates.io

API Reference:

Get and track the devices current position, including information about altitude, heading, and speed (if available).

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the geolocation plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add geolocation
      
    • yarn

      yarn run tauri add geolocation
      
    • pnpm

      pnpm tauri add geolocation
      
    • deno

      deno task tauri add geolocation
      
    • bun

      bun tauri add geolocation
      
    • cargo

      cargo tauri add geolocation
      
  • Manual

    npm run tauri add geolocation
    
  • npm

    yarn run tauri add geolocation
    
  • yarn

    pnpm tauri add geolocation
    
  • pnpm

    deno task tauri add geolocation
    
  • deno

    bun tauri add geolocation
    
  • bun

    cargo tauri add geolocation
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-geolocation --target 'cfg(any(target_os = "android", target_os = "ios"))'
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              .setup(|app| {
      +            #[cfg(mobile)]
                  +app.handle().plugin(tauri_plugin_geolocation::init());
                  Ok(())
              })
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-geolocation
        
      • yarn

        yarn add @tauri-apps/plugin-geolocation
        
      • pnpm

        pnpm add @tauri-apps/plugin-geolocation
        
      • deno

        deno add npm:@tauri-apps/plugin-geolocation
        
      • bun

        bun add @tauri-apps/plugin-geolocation
        
  • npm

    npm install @tauri-apps/plugin-geolocation
    
  • yarn

    yarn add @tauri-apps/plugin-geolocation
    
  • pnpm

    pnpm add @tauri-apps/plugin-geolocation
    
  • deno

    deno add npm:@tauri-apps/plugin-geolocation
    
  • bun

    bun add @tauri-apps/plugin-geolocation
    

Configuration

iOS

Apple requires privacy descriptions to be specified in Info.plist for location information, where you should describe why your app needs to access it. Illustrated below is an example description:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>NSLocationWhenInUseUsageDescription</key>
        <string>Required to do XY</string>
    </dict>
</plist>

Android

This plugin automatically adds the following permissions to your AndroidManifest.xml file:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

If your app requires GPS functionality to function, you should add the following to your AndroidManifest.xml file:

<uses-feature android:name="android.hardware.location.gps" android:required="true" />

The Google Play Store uses this property to decide whether it should show the app to devices without GPS capabilities.

Usage

The geolocation plugin is available in JavaScript.

import {
  checkPermissions,
  requestPermissions,
  getCurrentPosition,
  watchPosition,
} from '@tauri-apps/plugin-geolocation';


let permissions = await checkPermissions();
if (
  permissions.location === 'prompt' ||
  permissions.location === 'prompt-with-rationale'
) {
  permissions = await requestPermissions(['location']);
}


if (permissions.location === 'granted') {
  const pos = await getCurrentPosition();


  await watchPosition(
    { enableHighAccuracy: true, timeout: 10000, maximumAge: 0 },
    (pos) => {
      console.log(pos);
    }
  );
}

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/mobile.json

{
  "$schema": "../gen/schemas/mobile-schema.json",
  "identifier": "mobile-capability",
  "windows": ["main"],
  "platforms": ["iOS", "android"],
  "permissions": [
    +"core:default",
    +"geolocation:allow-check-permissions",
    +"geolocation:allow-request-permissions",
    +"geolocation:allow-get-current-position",
    +"geolocation:allow-watch-position"
  ]
}

Permission Table

Identifier Description
geolocation:allow-check-permissions Enables the check_permissions command without any pre-configured scope.
geolocation:deny-check-permissions Denies the check_permissions command without any pre-configured scope.
geolocation:allow-clear-permissions Enables the clear_permissions command without any pre-configured scope.
geolocation:deny-clear-permissions Denies the clear_permissions command without any pre-configured scope.
geolocation:allow-clear-watch Enables the clear_watch command without any pre-configured scope.
geolocation:deny-clear-watch Denies the clear_watch command without any pre-configured scope.
geolocation:allow-get-current-position Enables the get_current_position command without any pre-configured scope.
geolocation:deny-get-current-position Denies the get_current_position command without any pre-configured scope.
geolocation:allow-request-permissions Enables the request_permissions command without any pre-configured scope.
geolocation:deny-request-permissions Denies the request_permissions command without any pre-configured scope.
geolocation:allow-watch-position Enables the watch_position command without any pre-configured scope.
geolocation:deny-watch-position Denies the watch_position command without any pre-configured scope.

Global Shortcut

Register global shortcuts.

GitHubnpmcrates.io

API Reference:

Register global shortcuts.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the global-shortcut plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add global-shortcut
      
    • yarn

      yarn run tauri add global-shortcut
      
    • pnpm

      pnpm tauri add global-shortcut
      
    • deno

      deno task tauri add global-shortcut
      
    • bun

      bun tauri add global-shortcut
      
    • cargo

      cargo tauri add global-shortcut
      
  • Manual

    npm run tauri add global-shortcut
    
  • npm

    yarn run tauri add global-shortcut
    
  • yarn

    pnpm tauri add global-shortcut
    
  • pnpm

    deno task tauri add global-shortcut
    
  • deno

    bun tauri add global-shortcut
    
  • bun

    cargo tauri add global-shortcut
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-global-shortcut --target 'cfg(any(target_os = "macos", windows, target_os = "linux"))'
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      pub fn run() {
          tauri::Builder::default()
              .setup(|app| {
      +            #[cfg(desktop)]
                  +app.handle().plugin(tauri_plugin_global_shortcut::Builder::new().build());
                  Ok(())
              })
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-global-shortcut
        
      • yarn

        yarn add @tauri-apps/plugin-global-shortcut
        
      • pnpm

        pnpm add @tauri-apps/plugin-global-shortcut
        
      • deno

        deno add npm:@tauri-apps/plugin-global-shortcut
        
      • bun

        bun add @tauri-apps/plugin-global-shortcut
        
  • npm

    npm install @tauri-apps/plugin-global-shortcut
    
  • yarn

    yarn add @tauri-apps/plugin-global-shortcut
    
  • pnpm

    pnpm add @tauri-apps/plugin-global-shortcut
    
  • deno

    deno add npm:@tauri-apps/plugin-global-shortcut
    
  • bun

    bun add @tauri-apps/plugin-global-shortcut
    

Usage

The global-shortcut plugin is available in both JavaScript and Rust.

  • JavaScript

    import { register } from '@tauri-apps/plugin-global-shortcut';
    // when using `"withGlobalTauri": true`, you may use
    // const { register } = window.__TAURI__.globalShortcut;
    
    
    await register('CommandOrControl+Shift+C', () => {
      console.log('Shortcut triggered');
    });
    
  • Rust

    src-tauri/src/lib.rs

    pub fn run() {
        tauri::Builder::default()
            .setup(|app| {
                #[cfg(desktop)]
                {
                    use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, Modifiers, Shortcut, ShortcutState};
    
    
                    let ctrl_n_shortcut = Shortcut::new(Some(Modifiers::CONTROL), Code::KeyN);
                    app.handle().plugin(
                        tauri_plugin_global_shortcut::Builder::new().with_handler(move |_app, shortcut, event| {
                            println!("{:?}", shortcut);
                            if shortcut == &ctrl_n_shortcut {
                                match event.state() {
                                  ShortcutState::Pressed => {
                                    println!("Ctrl-N Pressed!");
                                  }
                                  ShortcutState::Released => {
                                    println!("Ctrl-N Released!");
                                  }
                                }
                            }
                        })
                        .build(),
                    )?;
    
    
                    app.global_shortcut().register(ctrl_n_shortcut)?;
                }
                Ok(())
            })
            .run(tauri::generate_context!())
            .expect("error while running tauri application");
    }
    

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    +"global-shortcut:allow-is-registered",
    +"global-shortcut:allow-register",
    +"global-shortcut:allow-unregister"
  ]
}

Default Permission

No features are enabled by default, as we believe the shortcuts can be inherently dangerous and it is application specific if specific shortcuts should be registered or unregistered.

Permission Table

Identifier Description
global-shortcut:allow-is-registered Enables the is_registered command without any pre-configured scope.
global-shortcut:deny-is-registered Denies the is_registered command without any pre-configured scope.
global-shortcut:allow-register Enables the register command without any pre-configured scope.
global-shortcut:deny-register Denies the register command without any pre-configured scope.
global-shortcut:allow-register-all Enables the register_all command without any pre-configured scope.
global-shortcut:deny-register-all Denies the register_all command without any pre-configured scope.
global-shortcut:allow-unregister Enables the unregister command without any pre-configured scope.
global-shortcut:deny-unregister Denies the unregister command without any pre-configured scope.
global-shortcut:allow-unregister-all Enables the unregister_all command without any pre-configured scope.
global-shortcut:deny-unregister-all Denies the unregister_all command without any pre-configured scope.

Haptics

Haptic feedback and vibrations on Android and iOS

GitHubnpmcrates.io

API Reference:

Haptic feedback and vibrations on Android and iOS.

There are no standards/requirements for vibration support on Android, so the feedback APIs may not work correctly on more affordable phones, including recently released ones.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the haptics plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add haptics
      
    • yarn

      yarn run tauri add haptics
      
    • pnpm

      pnpm tauri add haptics
      
    • deno

      deno task tauri add haptics
      
    • bun

      bun tauri add haptics
      
    • cargo

      cargo tauri add haptics
      
  • Manual

    npm run tauri add haptics
    
  • npm

    yarn run tauri add haptics
    
  • yarn

    pnpm tauri add haptics
    
  • pnpm

    deno task tauri add haptics
    
  • deno

    bun tauri add haptics
    
  • bun

    cargo tauri add haptics
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-haptics --target 'cfg(any(target_os = "android", target_os = "ios"))'
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              .setup(|app| {
      +            #[cfg(mobile)]
                  +app.handle().plugin(tauri_plugin_haptics::init());
                  Ok(())
              })
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-haptics
        
      • yarn

        yarn add @tauri-apps/plugin-haptics
        
      • pnpm

        pnpm add @tauri-apps/plugin-haptics
        
      • deno

        deno add npm:@tauri-apps/plugin-haptics
        
      • bun

        bun add @tauri-apps/plugin-haptics
        
  • npm

    npm install @tauri-apps/plugin-haptics
    
  • yarn

    yarn add @tauri-apps/plugin-haptics
    
  • pnpm

    pnpm add @tauri-apps/plugin-haptics
    
  • deno

    deno add npm:@tauri-apps/plugin-haptics
    
  • bun

    bun add @tauri-apps/plugin-haptics
    

Usage

The haptics plugin is available in JavaScript.

import {
  vibrate,
  impactFeedback,
  notificationFeedback,
  selectionFeedback,
} from '@tauri-apps/plugin-haptics';


await vibrate(1);
await impactFeedback('medium');
await notificationFeedback('warning');
await selectionFeedback();

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/mobile.json

{
  "$schema": "../gen/schemas/mobile-schema.json",
  "identifier": "mobile-capability",
  "windows": ["main"],
  "platforms": ["iOS", "android"],
  "permissions": [
    +"haptics:allow-impact-feedback",
    +"haptics:allow-notification-feedback",
    +"haptics:allow-selection-feedback",
    +"haptics:allow-vibrate"
  ]
}

Permission Table

Identifier Description
haptics:allow-impact-feedback Enables the impact_feedback command without any pre-configured scope.
haptics:deny-impact-feedback Denies the impact_feedback command without any pre-configured scope.
haptics:allow-notification-feedback Enables the notification_feedback command without any pre-configured scope.
haptics:deny-notification-feedback Denies the notification_feedback command without any pre-configured scope.
haptics:allow-selection-feedback Enables the selection_feedback command without any pre-configured scope.
haptics:deny-selection-feedback Denies the selection_feedback command without any pre-configured scope.
haptics:allow-vibrate Enables the vibrate command without any pre-configured scope.
haptics:deny-vibrate Denies the vibrate command without any pre-configured scope.

HTTP Client

Access the HTTP client written in Rust.

GitHubnpmcrates.io

API Reference:

Make HTTP requests with the http plugin.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the http plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add http
      
    • yarn

      yarn run tauri add http
      
    • pnpm

      pnpm tauri add http
      
    • deno

      deno task tauri add http
      
    • bun

      bun tauri add http
      
    • cargo

      cargo tauri add http
      
  • Manual

    npm run tauri add http
    
  • npm

    yarn run tauri add http
    
  • yarn

    pnpm tauri add http
    
  • pnpm

    deno task tauri add http
    
  • deno

    bun tauri add http
    
  • bun

    cargo tauri add http
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-http
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_http::init())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. If youd like to make http requests in JavaScript then install the npm package as well:

      • npm

        npm install @tauri-apps/plugin-http
        
      • yarn

        yarn add @tauri-apps/plugin-http
        
      • pnpm

        pnpm add @tauri-apps/plugin-http
        
      • deno

        deno add npm:@tauri-apps/plugin-http
        
      • bun

        bun add @tauri-apps/plugin-http
        
  • npm

    npm install @tauri-apps/plugin-http
    
  • yarn

    yarn add @tauri-apps/plugin-http
    
  • pnpm

    pnpm add @tauri-apps/plugin-http
    
  • deno

    deno add npm:@tauri-apps/plugin-http
    
  • bun

    bun add @tauri-apps/plugin-http
    

Usage

The HTTP plugin is available in both Rust as a reqwest re-export and JavaScript.

JavaScript

  1. Configure the allowed URLs

    src-tauri/capabilities/default.json

    {
      "permissions": [
        {
          "identifier": "http:default",
          "allow": [{ "url": "https://*.tauri.app" }],
          "deny": [{ "url": "https://private.tauri.app" }]
        }
      ]
    }
    

    For more information, please see the documentation for Permissions Overview

  2. Send a request

    The fetch method tries to be as close and compliant to the fetch Web API as possible.

    import { fetch } from '@tauri-apps/plugin-http';
    
    
    // Send a GET request
    const response = await fetch('http://test.tauri.app/data.json', {
      method: 'GET',
    });
    console.log(response.status); // e.g. 200
    console.log(response.statusText); // e.g. "OK"
    

    Note

    Forbidden request headers are ignored by default. To use them you must enable the unsafe-headers feature flag:

    src-tauri/Cargo.toml

    [dependencies]
    tauri-plugin-http = { version = "2", features = ["unsafe-headers"] }
    

Rust

In Rust you can utilize the reqwest crate re-exported by the plugin. For more details refer to reqwest docs.

use tauri_plugin_http::reqwest;


let res = reqwest::get("http://my.api.host/data.json").await;
println!("{:?}", res.status()); // e.g. 200
println!("{:?}", res.text().await); // e.g Ok("{ Content }")

Default Permission

This permission set configures what kind of fetch operations are available from the http plugin.

This enables all fetch operations but does not allow explicitly any origins to be fetched. This needs to be manually configured before usage.

Granted Permissions

All fetch operations are enabled.

This default permission set includes the following:

  • allow-fetch
  • allow-fetch-cancel
  • allow-fetch-send
  • allow-fetch-read-body
  • allow-fetch-cancel-body

Permission Table

Identifier Description
http:allow-fetch Enables the fetch command without any pre-configured scope.
http:deny-fetch Denies the fetch command without any pre-configured scope.
http:allow-fetch-cancel Enables the fetch_cancel command without any pre-configured scope.
http:deny-fetch-cancel Denies the fetch_cancel command without any pre-configured scope.
http:allow-fetch-cancel-body Enables the fetch_cancel_body command without any pre-configured scope.
http:deny-fetch-cancel-body Denies the fetch_cancel_body command without any pre-configured scope.
http:allow-fetch-read-body Enables the fetch_read_body command without any pre-configured scope.
http:deny-fetch-read-body Denies the fetch_read_body command without any pre-configured scope.
http:allow-fetch-send Enables the fetch_send command without any pre-configured scope.
http:deny-fetch-send Denies the fetch_send command without any pre-configured scope.

Localhost

Use a localhost server in production apps.

GitHubcrates.io

API Reference:

Expose your apps assets through a localhost server instead of the default custom protocol.

Caution

This plugin brings considerable security risks and you should only use it if you know what you are doing. If in doubt, use the default custom protocol implementation.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the localhost plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add localhost
      
    • yarn

      yarn run tauri add localhost
      
    • pnpm

      pnpm tauri add localhost
      
    • deno

      deno task tauri add localhost
      
    • bun

      bun tauri add localhost
      
    • cargo

      cargo tauri add localhost
      
  • Manual

    npm run tauri add localhost
    
  • npm

    yarn run tauri add localhost
    
  • yarn

    pnpm tauri add localhost
    
  • pnpm

    deno task tauri add localhost
    
  • deno

    bun tauri add localhost
    
  • bun

    cargo tauri add localhost
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-localhost
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_localhost::Builder::new().build())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      

Usage

The localhost plugin is available in Rust.

src-tauri/src/lib.rs

use tauri::{webview::WebviewWindowBuilder, WebviewUrl};


pub fn run() {
  let port: u16 = 9527;


  tauri::Builder::default()
      .plugin(tauri_plugin_localhost::Builder::new(port).build())
      .setup(move |app| {
          let url = format!("http://localhost:{}", port).parse().unwrap();
          WebviewWindowBuilder::new(app, "main".to_string(), WebviewUrl::External(url))
              .title("Localhost Example")
              .build()?;
          Ok(())
      })
      .run(tauri::generate_context!())
      .expect("error while running tauri application");
}

Logging

Configurable logging.

GitHubnpmcrates.io

API Reference:

Configurable logging for your Tauri app.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the log plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add log
      
    • yarn

      yarn run tauri add log
      
    • pnpm

      pnpm tauri add log
      
    • deno

      deno task tauri add log
      
    • bun

      bun tauri add log
      
    • cargo

      cargo tauri add log
      
  • Manual

    npm run tauri add log
    
  • npm

    yarn run tauri add log
    
  • yarn

    pnpm tauri add log
    
  • pnpm

    deno task tauri add log
    
  • deno

    bun tauri add log
    
  • bun

    cargo tauri add log
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-log
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_log::Builder::new().build())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-log
        
      • yarn

        yarn add @tauri-apps/plugin-log
        
      • pnpm

        pnpm add @tauri-apps/plugin-log
        
      • deno

        deno add npm:@tauri-apps/plugin-log
        
      • bun

        bun add @tauri-apps/plugin-log
        
  • npm

    npm install @tauri-apps/plugin-log
    
  • yarn

    yarn add @tauri-apps/plugin-log
    
  • pnpm

    pnpm add @tauri-apps/plugin-log
    
  • deno

    deno add npm:@tauri-apps/plugin-log
    
  • bun

    bun add @tauri-apps/plugin-log
    

Usage

  1. First, you need to register the plugin with Tauri.

    src-tauri/src/lib.rs

    use tauri_plugin_log::{Target, TargetKind};
    
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
        tauri::Builder::default()
            .plugin(tauri_plugin_log::Builder::new().build())
            .run(tauri::generate_context!())
            .expect("error while running tauri application");
    }
    
  2. Afterwards, all the plugins APIs are available through the JavaScript guest bindings:

    import {
      warn,
      debug,
      trace,
      info,
      error,
      attachConsole,
      attachLogger,
    } from '@tauri-apps/plugin-log';
    // when using `"withGlobalTauri": true`, you may use
    // const { warn, debug, trace, info, error, attachConsole, attachLogger } = window.__TAURI__.log;
    

Logging

  • JavaScript

    Use one of the plugins warn, debug, trace, info or error APIs to produce a log record from JavaScript code:

    import { warn, debug, trace, info, error } from '@tauri-apps/plugin-log';
    
    
    trace('Trace');
    info('Info');
    error('Error');
    

    To automatically forward all console messages to the log plugin you can rewrite them:

    import { warn, debug, trace, info, error } from '@tauri-apps/plugin-log';
    
    
    function forwardConsole(
      fnName: 'log' | 'debug' | 'info' | 'warn' | 'error',
      logger: (message: string) => Promise<void>
    ) {
      const original = console[fnName];
      console[fnName] = (message) => {
        original(message);
        logger(message);
      };
    }
    
    
    forwardConsole('log', trace);
    forwardConsole('debug', debug);
    forwardConsole('info', info);
    forwardConsole('warn', warn);
    forwardConsole('error', error);
    
  • Rust

    To create your own logs on the Rust side you can use the log crate:

    log::error!("something bad happened!");
    log::info!("Tauri is awesome!");
    

    Note that the log crate must be added to your Cargo.toml file:

    [dependencies]
    log = "0.4"
    

Log targets

The log plugin builder has a targets function that lets you configure common destination of all your application logs.

Note

By default the plugin logs to stdout and to a file in the application logs directory. To only use your own log targets, call clear_targets:

tauri_plugin_log::Builder::new()
.clear_targets()
.build()

Printing logs to the terminal

To forward all your logs to the terminal, enable the Stdout or Stderr targets:

tauri_plugin_log::Builder::new()
  .target(tauri_plugin_log::Target::new(
    tauri_plugin_log::TargetKind::Stdout,
  ))
  .build()

This target is enabled by default.

Logging to the webview console

To view all your Rust logs in the webview console, enable the Webview target and run attachConsole in your frontend:

tauri_plugin_log::Builder::new()
  .target(tauri_plugin_log::Target::new(
    tauri_plugin_log::TargetKind::Webview,
  ))
  .build()
import { attachConsole } from '@tauri-apps/plugin-log';
const detach = await attachConsole();
// call detach() if you do not want to print logs to the console anymore

Persisting logs

To write all logs to a file, you can use either the LogDir or the Folder targets.

  • LogDir:
tauri_plugin_log::Builder::new()
  .target(tauri_plugin_log::Target::new(
    tauri_plugin_log::TargetKind::LogDir {
      file_name: Some("logs".to_string()),
    },
  ))
  .build()

When using the LogDir target, all logs are stored in the recommended log directory. The following table describes the location of the logs per platform:

Platform Value Example
Linux $XDG_DATA_HOME/{bundleIdentifier}/logs or $HOME/.local/share/{bundleIdentifier}/logs /home/alice/.local/share/com.tauri.dev/logs
macOS {homeDir}/Library/Logs/{bundleIdentifier} /Users/Alice/Library/Logs/com.tauri.dev
Windows {FOLDERID_LocalAppData}/{bundleIdentifier}/logs C:\Users\Alice\AppData\Local\com.tauri.dev\logs
  • Folder:

The Folder target lets you write logs to a custom location in the filesystem.

tauri_plugin_log::Builder::new()
  .target(tauri_plugin_log::Target::new(
    tauri_plugin_log::TargetKind::Folder {
      path: std::path::PathBuf::from("/path/to/logs"),
      file_name: None,
    },
  ))
  .build()

The default file_name is the application name.

Configuring log file behavior

By default the log file gets discarded when it reaches the maximum size. The maximum file size can be configured via the builders max_file_size function:

tauri_plugin_log::Builder::new()
  .max_file_size(50_000 /* bytes */)
  .build()

Tauri can automatically rotate your log file when it reaches the size limit instead of discarding the previous file. This behavior can be configured using rotation_strategy:

tauri_plugin_log::Builder::new()
  .rotation_strategy(tauri_plugin_log::RotationStrategy::KeepAll)
  .build()

Filtering

By default all logs are processed. There are some mechanisms to reduce the amount of logs and filter only relevant information.

Maximum log level

To set a maximum log level, use the level function:

tauri_plugin_log::Builder::new()
  .level(log::LevelFilter::Info)
  .build()

In this example, debug and trace logs are discarded as they have a lower level than info.

It is also possible to define separate maximum levels for individual modules:

tauri_plugin_log::Builder::new()
  .level(log::LevelFilter::Info)
  // verbose logs only for the commands module
  .level_for("my_crate_name::commands", log::LevelFilter::Trace)
  .build()

Note that these APIs use the log crate, which must be added to your Cargo.toml file:

[dependencies]
log = "0.4"

Target filter

A filter function can be defined to discard unwanted logs by checking their metadata:

tauri_plugin_log::Builder::new()
  // exclude logs with target `"hyper"`
  .filter(|metadata| metadata.target() != "hyper")
  .build()

Formatting

The log plugin formats each log record as DATE[TARGET][LEVEL] MESSAGE. A custom format function can be provided with format:

tauri_plugin_log::Builder::new()
  .format(|out, message, record| {
    out.finish(format_args!(
      "[{} {}] {}",
      record.level(),
      record.target(),
      message
    ))
  })
  .build()

Applying a different format to targets

You can specify your own log format for specific targets by using the format method on tauri_plugin_log::Target. You may also wish to call clear_format on the builder to remove the default formatter, which is applied to all targets:

tauri_plugin_log::Builder::new()
    .clear_format()
    .targets([
        tauri_plugin_log::Target::new(
            tauri_plugin_log::TargetKind::Stdout
        )
        .format(move |out, message, record| {
            // custom formatter for stdout
        }),
        tauri_plugin_log::Target::new(
            tauri_plugin_log::TargetKind::LogDir { file_name: None }
        )
        .format(move |out, message, record| {
            // custom formatter for log files
        }),
    ])
    .build(),

Log dates

By default the log plugin uses the UTC timezone to format dates but you can configure it to use the local timezone with timezone_strategy:

tauri_plugin_log::Builder::new()
  .timezone_strategy(tauri_plugin_log::TimezoneStrategy::UseLocal)
  .build()

Permissions

By default, all plugin commands are blocked and cannot be accessed. You must define a list of permissions in your capabilities configuration.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  +"permissions": ["log:default"]
}

Default Permission

Allows the log command

This default permission set includes the following:

  • allow-log

Permission Table

Identifier Description
log:allow-log Enables the log command without any pre-configured scope.
log:deny-log Denies the log command without any pre-configured scope.

NFC

Read and write NFC tags on Android and iOS.

GitHubnpmcrates.io

API Reference:

Read and write NFC tags on Android and iOS.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the nfc plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add nfc
      
    • yarn

      yarn run tauri add nfc
      
    • pnpm

      pnpm tauri add nfc
      
    • bun

      bun tauri add nfc
      
    • cargo

      cargo tauri add nfc
      
  • Manual

    npm run tauri add nfc
    
  • npm

    yarn run tauri add nfc
    
  • yarn

    pnpm tauri add nfc
    
  • pnpm

    bun tauri add nfc
    
  • bun

    cargo tauri add nfc
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-nfc --target 'cfg(any(target_os = "android", target_os = "ios"))'
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              .setup(|app| {
      +            #[cfg(mobile)]
                  +app.handle().plugin(tauri_plugin_nfc::init());
                  Ok(())
              })
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-nfc
        
      • yarn

        yarn add @tauri-apps/plugin-nfc
        
      • pnpm

        pnpm add @tauri-apps/plugin-nfc
        
      • deno

        deno add npm:@tauri-apps/plugin-nfc
        
      • bun

        bun add @tauri-apps/plugin-nfc
        
  • npm

    npm install @tauri-apps/plugin-nfc
    
  • yarn

    yarn add @tauri-apps/plugin-nfc
    
  • pnpm

    pnpm add @tauri-apps/plugin-nfc
    
  • deno

    deno add npm:@tauri-apps/plugin-nfc
    
  • bun

    bun add @tauri-apps/plugin-nfc
    

Configuration

The NFC plugin requires native configuration for iOS.

iOS

To access the NFC APIs on iOS you must adjust the target iOS version, configure a usage description on the Info.plist file and add the NFC capability to your application.

Target IOS version

The NFC plugin requires iOS 14+. This is the default for Tauri applications created with Tauri CLI v2.8 and above, but you can edit your Xcode project to configure it.

In the src-tauri/gen/apple/<project-name>.xcodeproj/project.pbxproj file, set all IPHONEOS_DEPLOYMENT_TARGET properties to 14.0:

src-tauri/gen/apple/<project-name>.xcodeproj/project.pbxproj

/* Begin XCBuildConfiguration section */
    1234567890ABCDEF12345678 /* release */ = {
      isa = XCBuildConfiguration;
      buildSettings = {
        /* ... */
        IPHONEOS_DEPLOYMENT_TARGET = 14.0;
      };
      name = release;
    };
    ABCDEF1234567890ABCDEF12 /* debug */ = {
      isa = XCBuildConfiguration;
      buildSettings = {
        /* ... */
        IPHONEOS_DEPLOYMENT_TARGET = 14.0;
      };
      name = debug;
    };

Alternatively you can set the deployment target from Xcode in the General > Minimum Deployments > iOS configuration.

Info.plist

On iOS the NFC plugin requires the NFCReaderUsageDescription information property list value, which should describe why your app needs to scan or write to NFC tags.

In the src-tauri/Info.ios.plist file, add the following snippet:

src-tauri/Info.ios.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>NFCReaderUsageDescription</key>
    <string>Read and write various NFC tags</string>
  </dict>
</plist>

NFC Capability

Additionally iOS requires the NFC capability to be associated with your application.

The capability can be added in Xcode in the project configurations “Signing & Capabilities” tab by clicking the “+ Capability” button and selecting the “Near Field Communication Tag Reading” capability (see Add a capability to a target for more information) or by adding the following configuration to the gen/apple/<app-name>_iOS/<app-name>_iOS.entitlements file:

gen/apple/<app-name>_iOS/<app-name>_iOS.entitlements

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>com.apple.developer.nfc.readersession.formats</key>
  <array>
    <string>TAG</string>
  </array>
</dict>
</plist>

Usage

The NFC plugin is available in both JavaScript and Rust, allowing you to scan and write to NFC tags.

Checking if NFC is supported

Not every mobile device has the capability to scan NFC tags, so you should check for availability before using the scan and write APIs.

  • JavaScript

    import { isAvailable } from '@tauri-apps/plugin-nfc';
    
    
    const canScanNfc = await isAvailable();
    
  • Rust

    tauri::Builder::default()
      .setup(|app| {
        #[cfg(mobile)]
        {
          use tauri_plugin_nfc::NfcExt;
    
    
          app.handle().plugin(tauri_plugin_nfc::init());
    
    
          let can_scan_nfc = app.nfc().is_available()?;
        }
        Ok(())
      })
    

Scanning NFC tags

The plugin can scan either generic NFC tags or NFC tags with a NDEF (NFC Data Exchange Format) message, which is a standard format to encapsulate typed data in an NFC tag.

  • JavaScript

    import { scan } from '@tauri-apps/plugin-nfc';
    
    
    const scanType = {
      type: 'ndef', // or 'tag',
    };
    
    
    const options = {
      keepSessionAlive: false,
      // configure the messages displayed in the "Scan NFC" dialog on iOS
      message: 'Scan a NFC tag',
      successMessage: 'NFC tag successfully scanned',
    };
    
    
    const tag = await scan(scanType, options);
    
  • Rust

    tauri::Builder::default()
      .setup(|app| {
        #[cfg(mobile)]
        {
          use tauri_plugin_nfc::NfcExt;
    
    
          app.handle().plugin(tauri_plugin_nfc::init());
    
    
          let tag = app
            .nfc()
            .scan(tauri_plugin_nfc::ScanRequest {
                kind: tauri_plugin_nfc::ScanKind::Ndef {
                    mime_type: None,
                    uri: None,
                    tech_list: None,
                },
                keep_session_alive: false,
            })?
            .tag;
        }
        Ok(())
      })
    

Note

The keepSessionAlive option can be used to directly write to the scanned NFC tag later.

If you do not provide that option, the session is recreated on the next write() call, which means the app will try to rescan the tag.

Filters

The NFC scanner can also filter tags with a specific URI format, mime type or NFC tag technologies. In this case, the scan will only detect tags that matches the provided filters.

Note

Filtering is only available on Android, so you should always check the scanned NFC tag contents.

The mime type is case sensitive and must be provided with lower case letters.

  • JavaScript

    import { scan, TechKind } from '@tauri-apps/plugin-nfc';
    
    
    const techLists = [
      // capture anything using NfcF
      [TechKind.NfcF],
      // capture all MIFARE Classics with NDEF payloads
      [TechKind.NfcA, TechKind.MifareClassic, TechKind.Ndef],
    ];
    
    
    const tag = await scan({
      type: 'ndef', // or 'tag'
      mimeType: 'text/plain',
      uri: {
        scheme: 'https',
        host: 'my.domain.com',
        pathPrefix: '/app',
      },
      techLists,
    });
    
  • Rust

    tauri::Builder::default()
      .setup(|app| {
        #[cfg(mobile)]
        {
          use tauri_plugin_nfc::NfcExt;
    
    
          app.handle().plugin(tauri_plugin_nfc::init());
    
    
          let tag = app
            .nfc()
            .scan(tauri_plugin_nfc::ScanRequest {
                kind: tauri_plugin_nfc::ScanKind::Ndef {
                    mime_type: Some("text/plain".to_string()),
                    uri: Some(tauri_plugin_nfc::UriFilter {
                      scheme: Some("https".to_string()),
                      host: Some("my.domain.com".to_string()),
                      path_prefix: Some("/app".to_string()),
                    }),
                    tech_list: Some(vec![
                      vec![tauri_plugin_nfc::TechKind::Ndef],
                    ]),
                },
            })?
            .tag;
        }
        Ok(())
      })
    

Writing to NFC tags

The write API can be used to write a payload to a NFC tag. If theres no scanned tag with keepSessionAlive: true, the application will first scan an NFC tag.

  • JavaScript

    import { write, textRecord, uriRecord } from '@tauri-apps/plugin-nfc';
    
    
    const payload = [uriRecord('https://tauri.app'), textRecord('some payload')];
    
    
    const options = {
      // the kind is only required if you do not have a scanned tag session alive
      // its format is the same as the argument provided to scan()
      kind: {
        type: 'ndef',
      },
      // configure the messages displayed in the "Scan NFC" dialog on iOS
      message: 'Scan a NFC tag',
      successfulReadMessage: 'NFC tag successfully scanned',
      successMessage: 'NFC tag successfully written',
    };
    
    
    await write(payload, options);
    
  • Rust

    Caution

    The Rust API currently only provides a low level interface for writing NFC payloads.

    The API will be enhanced soon.

    tauri::Builder::default()
      .setup(|app| {
        #[cfg(mobile)]
        {
          use tauri_plugin_nfc::NfcExt;
    
    
          app.handle().plugin(tauri_plugin_nfc::init());
    
    
          app
            .nfc()
            .write(vec![
              tauri_plugin_nfc::NfcRecord {
                format: tauri_plugin_nfc::NFCTypeNameFormat::NfcWellKnown,
                kind: vec![0x55], // URI record
                id: vec![],
                payload: vec![], // insert payload here
              }
            ])?;
        }
        Ok(())
      })
    

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "permissions": [
    ...,
    +"nfc:default",
  ]
}

Default Permission

This permission set configures what kind of operations are available from the nfc plugin.

Granted Permissions

Checking if the NFC functionality is available and scanning nearby tags is allowed. Writing to tags needs to be manually enabled.

This default permission set includes the following:

  • allow-is-available
  • allow-scan

Permission Table

Identifier Description
nfc:allow-is-available Enables the is_available command without any pre-configured scope.
nfc:deny-is-available Denies the is_available command without any pre-configured scope.
nfc:allow-scan Enables the scan command without any pre-configured scope.
nfc:deny-scan Denies the scan command without any pre-configured scope.
nfc:allow-write Enables the write command without any pre-configured scope.
nfc:deny-write Denies the write command without any pre-configured scope.

Notifications

Send native notifications to the user.

GitHubnpmcrates.io

API Reference:

Send native notifications to your user using the notification plugin.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows Only works for installed apps. Shows powershell name & icon in development.
linux
macos
android
ios

Setup

Install the notifications plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add notification
      
    • yarn

      yarn run tauri add notification
      
    • pnpm

      pnpm tauri add notification
      
    • deno

      deno task tauri add notification
      
    • bun

      bun tauri add notification
      
    • cargo

      cargo tauri add notification
      
  • Manual

    npm run tauri add notification
    
  • npm

    yarn run tauri add notification
    
  • yarn

    pnpm tauri add notification
    
  • pnpm

    deno task tauri add notification
    
  • deno

    bun tauri add notification
    
  • bun

    cargo tauri add notification
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-notification
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_notification::init())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. If youd like to use notifications in JavaScript then install the npm package as well:

      • npm

        npm install @tauri-apps/plugin-notification
        
      • yarn

        yarn add @tauri-apps/plugin-notification
        
      • pnpm

        pnpm add @tauri-apps/plugin-notification
        
      • deno

        deno add npm:@tauri-apps/plugin-notification
        
      • bun

        bun add @tauri-apps/plugin-notification
        
  • npm

    npm install @tauri-apps/plugin-notification
    
  • yarn

    yarn add @tauri-apps/plugin-notification
    
  • pnpm

    pnpm add @tauri-apps/plugin-notification
    
  • deno

    deno add npm:@tauri-apps/plugin-notification
    
  • bun

    bun add @tauri-apps/plugin-notification
    

Usage

Here are a few examples of how to use the notification plugin:

The notification plugin is available in both JavaScript and Rust.

Send Notification

Follow these steps to send a notification:

  1. Check if permission is granted

  2. Request permission if not granted

  3. Send the notification

  • JavaScript

    import {
      isPermissionGranted,
      requestPermission,
      sendNotification,
    } from '@tauri-apps/plugin-notification';
    // when using `"withGlobalTauri": true`, you may use
    // const { isPermissionGranted, requestPermission, sendNotification, } = window.__TAURI__.notification;
    
    
    // Do you have permission to send a notification?
    let permissionGranted = await isPermissionGranted();
    
    
    // If not we need to request it
    if (!permissionGranted) {
      const permission = await requestPermission();
      permissionGranted = permission === 'granted';
    }
    
    
    // Once permission has been granted we can send the notification
    if (permissionGranted) {
      sendNotification({ title: 'Tauri', body: 'Tauri is awesome!' });
    }
    
  • Rust

    tauri::Builder::default()
        .plugin(tauri_plugin_notification::init())
        .setup(|app| {
            use tauri_plugin_notification::NotificationExt;
            app.notification()
                .builder()
                .title("Tauri")
                .body("Tauri is awesome")
                .show()
                .unwrap();
    
    
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
    

Actions

Mobile Only

The Actions API is only available on mobile platforms.

Actions add interactive buttons and inputs to notifications. Use them to create a responsive experience for your users.

Register Action Types

Register action types to define interactive elements:

import { registerActionTypes } from '@tauri-apps/plugin-notification';


await registerActionTypes([
  {
    id: 'messages',
    actions: [
      {
        id: 'reply',
        title: 'Reply',
        input: true,
        inputButtonTitle: 'Send',
        inputPlaceholder: 'Type your reply...',
      },
      {
        id: 'mark-read',
        title: 'Mark as Read',
        foreground: false,
      },
    ],
  },
]);

Action Properties

Property Description
id Unique identifier for the action
title Display text for the action button
requiresAuthentication Requires device authentication
foreground Brings app to foreground when triggered
destructive Shows action in red on iOS
input Enables text input
inputButtonTitle Text for input submit button
inputPlaceholder Placeholder text for input field

Listen for Actions

Listen to user interactions with notification actions:

import { onAction } from '@tauri-apps/plugin-notification';


await onAction((notification) => {
  console.log('Action performed:', notification);
});

Attachments

Attachments add media content to notifications. Support varies by platform.

import { sendNotification } from '@tauri-apps/plugin-notification';


sendNotification({
  title: 'New Image',
  body: 'Check out this picture',
  attachments: [
    {
      id: 'image-1',
      url: 'asset:///notification-image.jpg',
    },
  ],
});

Attachment Properties

Property Description
id Unique identifier
url Content URL using asset:// or file:// protocol

Note: Test attachments on your target platforms to ensure compatibility.

Channels

Channels organize notifications into categories with different behaviors. While primarily used on Android, they provide a consistent API across platforms.

Create a Channel

import {
  createChannel,
  Importance,
  Visibility,
} from '@tauri-apps/plugin-notification';


await createChannel({
  id: 'messages',
  name: 'Messages',
  description: 'Notifications for new messages',
  importance: Importance.High,
  visibility: Visibility.Private,
  lights: true,
  lightColor: '#ff0000',
  vibration: true,
  sound: 'notification_sound',
});

Channel Properties

Property Description
id Unique identifier
name Display name
description Purpose description
importance Priority level (None, Min, Low, Default, High)
visibility Privacy setting (Secret, Private, Public)
lights Enable notification LED (Android)
lightColor LED color (Android)
vibration Enable vibrations
sound Custom sound filename

Managing Channels

List existing channels:

import { channels } from '@tauri-apps/plugin-notification';


const existingChannels = await channels();

Remove a channel:

import { removeChannel } from '@tauri-apps/plugin-notification';


await removeChannel('messages');

Using Channels

Send a notification using a channel:

import { sendNotification } from '@tauri-apps/plugin-notification';


sendNotification({
  title: 'New Message',
  body: 'You have a new message',
  channelId: 'messages',
});

Note: Create channels before sending notifications that reference them. Invalid channel IDs prevent notifications from displaying.

Security Considerations

Aside from normal sanitization procedures of user input there are currently no known security considerations.

Default Permission

This permission set configures which notification features are by default exposed.

Granted Permissions

It allows all notification related features.

This default permission set includes the following:

  • allow-is-permission-granted
  • allow-request-permission
  • allow-notify
  • allow-register-action-types
  • allow-register-listener
  • allow-cancel
  • allow-get-pending
  • allow-remove-active
  • allow-get-active
  • allow-check-permissions
  • allow-show
  • allow-batch
  • allow-list-channels
  • allow-delete-channel
  • allow-create-channel
  • allow-permission-state

Permission Table

Identifier Description
notification:allow-batch Enables the batch command without any pre-configured scope.
notification:deny-batch Denies the batch command without any pre-configured scope.
notification:allow-cancel Enables the cancel command without any pre-configured scope.
notification:deny-cancel Denies the cancel command without any pre-configured scope.
notification:allow-check-permissions Enables the check_permissions command without any pre-configured scope.
notification:deny-check-permissions Denies the check_permissions command without any pre-configured scope.
notification:allow-create-channel Enables the create_channel command without any pre-configured scope.
notification:deny-create-channel Denies the create_channel command without any pre-configured scope.
notification:allow-delete-channel Enables the delete_channel command without any pre-configured scope.
notification:deny-delete-channel Denies the delete_channel command without any pre-configured scope.
notification:allow-get-active Enables the get_active command without any pre-configured scope.
notification:deny-get-active Denies the get_active command without any pre-configured scope.
notification:allow-get-pending Enables the get_pending command without any pre-configured scope.
notification:deny-get-pending Denies the get_pending command without any pre-configured scope.
notification:allow-is-permission-granted Enables the is_permission_granted command without any pre-configured scope.
notification:deny-is-permission-granted Denies the is_permission_granted command without any pre-configured scope.
notification:allow-list-channels Enables the list_channels command without any pre-configured scope.
notification:deny-list-channels Denies the list_channels command without any pre-configured scope.
notification:allow-notify Enables the notify command without any pre-configured scope.
notification:deny-notify Denies the notify command without any pre-configured scope.
notification:allow-permission-state Enables the permission_state command without any pre-configured scope.
notification:deny-permission-state Denies the permission_state command without any pre-configured scope.
notification:allow-register-action-types Enables the register_action_types command without any pre-configured scope.
notification:deny-register-action-types Denies the register_action_types command without any pre-configured scope.
notification:allow-register-listener Enables the register_listener command without any pre-configured scope.
notification:deny-register-listener Denies the register_listener command without any pre-configured scope.
notification:allow-remove-active Enables the remove_active command without any pre-configured scope.
notification:deny-remove-active Denies the remove_active command without any pre-configured scope.
notification:allow-request-permission Enables the request_permission command without any pre-configured scope.
notification:deny-request-permission Denies the request_permission command without any pre-configured scope.
notification:allow-show Enables the show command without any pre-configured scope.
notification:deny-show Denies the show command without any pre-configured scope.

Opener

Open files and URLs in external applications.

GitHubnpmcrates.io

API Reference:

This plugin allows you to open files and URLs in a specified, or the default, application. It also supports “revealing” files in the systems file explorer.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android Only allows to open URLs via open
ios Only allows to open URLs via open

Setup

Install the opener plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add opener
      
    • yarn

      yarn run tauri add opener
      
    • pnpm

      pnpm tauri add opener
      
    • deno

      deno task tauri add opener
      
    • bun

      bun tauri add opener
      
    • cargo

      cargo tauri add opener
      
  • Manual

    npm run tauri add opener
    
  • npm

    yarn run tauri add opener
    
  • yarn

    pnpm tauri add opener
    
  • pnpm

    deno task tauri add opener
    
  • deno

    bun tauri add opener
    
  • bun

    cargo tauri add opener
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-opener
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_opener::init())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-opener
        
      • yarn

        yarn add @tauri-apps/plugin-opener
        
      • pnpm

        pnpm add @tauri-apps/plugin-opener
        
      • deno

        deno add npm:@tauri-apps/plugin-opener
        
      • bun

        bun add @tauri-apps/plugin-opener
        
  • npm

    npm install @tauri-apps/plugin-opener
    
  • yarn

    yarn add @tauri-apps/plugin-opener
    
  • pnpm

    pnpm add @tauri-apps/plugin-opener
    
  • deno

    deno add npm:@tauri-apps/plugin-opener
    
  • bun

    bun add @tauri-apps/plugin-opener
    

Usage

The opener plugin is available in both JavaScript and Rust.

  • JavaScript

    import { openPath, openUrl } from '@tauri-apps/plugin-opener';
    // when using `"withGlobalTauri": true`, you may use
    // const { openPath } = window.__TAURI__.opener;
    
    
    // opens a file using the default program:
    await openPath('/path/to/file');
    // opens a file using `vlc` command on Windows:
    await openPath('C:/path/to/file', 'vlc');
    // opens a URL using the default program:
    await openUrl('https://tauri.app');
    
  • Rust

    Note that app is an instance of App or AppHandle.

    use tauri_plugin_opener::OpenerExt;
    
    
    // opens a file using the default program:
    app.opener().open_path("/path/to/file", None::<&str>);
    // opens a file using `vlc` command on Windows:
    app.opener().open_path("C:/path/to/file", Some("vlc"));
    // opens a URL using the default program:
    app.opener().open_url("https://tauri.app", None::<&str>);
    

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

Below are two example scope configurations. Both path and url use the glob pattern syntax to define allowed file paths and URLs.

First, an example on how to add permissions to specific paths for the openPath() function:

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  +"permissions": [
+    {
      +"identifier": "opener:allow-open-path",
      +"allow": [
+        {
          +"path": "/path/to/file"
+        },
+        {
          +"path": "$APPDATA/file"
+        }
      ]
    }
  ]
}

Lastly, an example on how to add permissions for the exact https://tauri.app URL and all URLs on a custom protocol (must be known to the OS) for the openUrl() function:

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  +"permissions": [
+    {
      +"identifier": "opener:allow-open-url",
      +"allow": [
+        {
          +"url": "https://tauri.app"
+        },
+        {
          +"url": "custom:*"
+        }
      ]
    }
  ]
}

Default Permission

This permission set allows opening mailto:, tel:, https:// and http:// urls using their default application as well as reveal file in directories using default file explorer

This default permission set includes the following:

  • allow-open-url
  • allow-reveal-item-in-dir
  • allow-default-urls

Permission Table

Identifier Description
opener:allow-default-urls This enables opening mailto:, tel:, https:// and http:// urls using their default application.
opener:allow-open-path Enables the open_path command without any pre-configured scope.
opener:deny-open-path Denies the open_path command without any pre-configured scope.
opener:allow-open-url Enables the open_url command without any pre-configured scope.
opener:deny-open-url Denies the open_url command without any pre-configured scope.
opener:allow-reveal-item-in-dir Enables the reveal_item_in_dir command without any pre-configured scope.
opener:deny-reveal-item-in-dir Denies the reveal_item_in_dir command without any pre-configured scope.

OS Information

Read information about the operating system.

GitHubnpmcrates.io

API Reference:

Read information about the operating system using the OS Information plugin.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the OS Information plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add os
      
    • yarn

      yarn run tauri add os
      
    • pnpm

      pnpm tauri add os
      
    • deno

      deno task tauri add os
      
    • bun

      bun tauri add os
      
    • cargo

      cargo tauri add os
      
  • Manual

    npm run tauri add os
    
  • npm

    yarn run tauri add os
    
  • yarn

    pnpm tauri add os
    
  • pnpm

    deno task tauri add os
    
  • deno

    bun tauri add os
    
  • bun

    cargo tauri add os
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-os
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_os::init())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. If youd like to use in JavaScript then install the npm package as well:

      • npm

        npm install @tauri-apps/plugin-os
        
      • yarn

        yarn add @tauri-apps/plugin-os
        
      • pnpm

        pnpm add @tauri-apps/plugin-os
        
      • deno

        deno add npm:@tauri-apps/plugin-os
        
      • bun

        bun add @tauri-apps/plugin-os
        
  • npm

    npm install @tauri-apps/plugin-os
    
  • yarn

    yarn add @tauri-apps/plugin-os
    
  • pnpm

    pnpm add @tauri-apps/plugin-os
    
  • deno

    deno add npm:@tauri-apps/plugin-os
    
  • bun

    bun add @tauri-apps/plugin-os
    

Usage

With this plugin you can query multiple information from current operational system. See all available functions in the JavaScript API or Rust API references.

Example: OS Platform

platform returns a string describing the specific operating system in use. The value is set at compile time. Possible values are linux, macos, ios, freebsd, dragonfly, netbsd, openbsd, solaris, android, windows.

  • JavaScript

    import { platform } from '@tauri-apps/plugin-os';
    // when using `"withGlobalTauri": true`, you may use
    // const { platform } = window.__TAURI__.os;
    
    
    const currentPlatform = platform();
    console.log(currentPlatform);
    // Prints "windows" to the console
    
  • Rust

    let platform = tauri_plugin_os::platform();
    println!("Platform: {}", platform);
    // Prints "windows" to the terminal
    

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "permissions": [
    ...,
    +"os:default"
  ]
}

Default Permission

This permission set configures which operating system information are available to gather from the frontend.

Granted Permissions

All information except the host name are available.

This default permission set includes the following:

  • allow-arch
  • allow-exe-extension
  • allow-family
  • allow-locale
  • allow-os-type
  • allow-platform
  • allow-version

Permission Table

Identifier Description
os:allow-arch Enables the arch command without any pre-configured scope.
os:deny-arch Denies the arch command without any pre-configured scope.
os:allow-exe-extension Enables the exe_extension command without any pre-configured scope.
os:deny-exe-extension Denies the exe_extension command without any pre-configured scope.
os:allow-family Enables the family command without any pre-configured scope.
os:deny-family Denies the family command without any pre-configured scope.
os:allow-hostname Enables the hostname command without any pre-configured scope.
os:deny-hostname Denies the hostname command without any pre-configured scope.
os:allow-locale Enables the locale command without any pre-configured scope.
os:deny-locale Denies the locale command without any pre-configured scope.
os:allow-os-type Enables the os_type command without any pre-configured scope.
os:deny-os-type Denies the os_type command without any pre-configured scope.
os:allow-platform Enables the platform command without any pre-configured scope.
os:deny-platform Denies the platform command without any pre-configured scope.
os:allow-version Enables the version command without any pre-configured scope.
os:deny-version Denies the version command without any pre-configured scope.

Persisted Scope

Persist runtime scope changes on the filesystem.

GitHubcrates.io

API Reference:

Save filesystem and asset scopes and restore them when the app is reopened.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the persisted-scope plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add persisted-scope
      
    • yarn

      yarn run tauri add persisted-scope
      
    • pnpm

      pnpm tauri add persisted-scope
      
    • deno

      deno task tauri add persisted-scope
      
    • bun

      bun tauri add persisted-scope
      
    • cargo

      cargo tauri add persisted-scope
      
  • Manual

    npm run tauri add persisted-scope
    
  • npm

    yarn run tauri add persisted-scope
    
  • yarn

    pnpm tauri add persisted-scope
    
  • pnpm

    deno task tauri add persisted-scope
    
  • deno

    bun tauri add persisted-scope
    
  • bun

    cargo tauri add persisted-scope
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-persisted-scope
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_persisted_scope::init())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      

Caution

The persisted-scope plugin must be registered and initialized after the fs plugin, as illustrated by the example below:

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_fs::init()) // fs MUST BE before persisted scope!
        .plugin(tauri_plugin_persisted_scope::init())
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Not doing so will result in the persisted scope not working! You should also see a warning message upon launching your app in dev mode, similar to this:

Please make sure to register the `fs` plugin before the `persisted-scope` plugin!

Usage

After setup the plugin will automatically save and restore filesystem and asset scopes.

Positioner

Move windows to common locations.

GitHubnpmcrates.io

API Reference:

Position your windows at well-known locations.

This plugin is a port of electron-positioner for Tauri.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the positioner plugin to get started.

Note

If you only intend on moving the window from Rust code, you only need the dependency in src-tauri/Cargo.toml, and can remove the plugin registration from lib.rs if you choose to setup automatically.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add positioner
      
    • yarn

      yarn run tauri add positioner
      
    • pnpm

      pnpm tauri add positioner
      
    • deno

      deno task tauri add positioner
      
    • bun

      bun tauri add positioner
      
    • cargo

      cargo tauri add positioner
      
  • Manual

    npm run tauri add positioner
    
  • npm

    yarn run tauri add positioner
    
  • yarn

    pnpm tauri add positioner
    
  • pnpm

    deno task tauri add positioner
    
  • deno

    bun tauri add positioner
    
  • bun

    cargo tauri add positioner
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-positioner --target 'cfg(any(target_os = "macos", windows, target_os = "linux"))'
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.setup(|app| {
                  #[cfg(desktop)]
                  app.handle().plugin(tauri_plugin_positioner::init());
                  Ok(())
              })
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-positioner
        
      • yarn

        yarn add @tauri-apps/plugin-positioner
        
      • pnpm

        pnpm add @tauri-apps/plugin-positioner
        
      • deno

        deno add npm:@tauri-apps/plugin-positioner
        
      • bun

        bun add @tauri-apps/plugin-positioner
        
  • npm

    npm install @tauri-apps/plugin-positioner
    
  • yarn

    yarn add @tauri-apps/plugin-positioner
    
  • pnpm

    pnpm add @tauri-apps/plugin-positioner
    
  • deno

    deno add npm:@tauri-apps/plugin-positioner
    
  • bun

    bun add @tauri-apps/plugin-positioner
    

Additional setup is required to get tray-relative positions to work.

  1. Add tray-icon feature to your Cargo.toml file:

    src-tauri/Cargo.toml

    [dependencies]
    +tauri-plugin-positioner = { version = "2.0.0", features = ["tray-icon"] }
    
  2. Setup on_tray_event for positioner plugin:

    src-tauri/src/lib.rs

    pub fn run() {
      tauri::Builder::default()
        // This is required to get tray-relative positions to work
        +.setup(|app| {
    +        #[cfg(desktop)]
    +        {
              +app.handle().plugin(tauri_plugin_positioner::init());
    +            tauri::tray::TrayIconBuilder::new()
                  +.on_tray_icon_event(|tray_handle, event| {
    +                tauri_plugin_positioner::on_tray_event(tray_handle.app_handle(), &event);
    +              })
                  +.build(app)?;
            }
          Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
    }
    

Usage

The plugins APIs are available through the JavaScript guest bindings:

import { moveWindow, Position } from '@tauri-apps/plugin-positioner';
// when using `"withGlobalTauri": true`, you may use
// const { moveWindow, Position } = window.__TAURI__.positioner;


moveWindow(Position.TopRight);

You can import and use the Window trait extension directly through Rust:

use tauri_plugin_positioner::{WindowExt, Position};


let mut win = app.get_webview_window("main").unwrap();
let _ = win.as_ref().window().move_window(Position::TopRight);

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "permissions": [
    ...,
    +"positioner:default",
  ]
}

Default Permission

Allows the moveWindow and handleIconState APIs

This default permission set includes the following:

  • allow-move-window
  • allow-move-window-constrained
  • allow-set-tray-icon-state

Permission Table

Identifier Description
positioner:allow-move-window Enables the move_window command without any pre-configured scope.
positioner:deny-move-window Denies the move_window command without any pre-configured scope.
positioner:allow-move-window-constrained Enables the move_window_constrained command without any pre-configured scope.
positioner:deny-move-window-constrained Denies the move_window_constrained command without any pre-configured scope.
positioner:allow-set-tray-icon-state Enables the set_tray_icon_state command without any pre-configured scope.
positioner:deny-set-tray-icon-state Denies the set_tray_icon_state command without any pre-configured scope.

Process

Access the current process.

GitHubnpmcrates.io

API Reference:

This plugin provides APIs to access the current process. To spawn child processes, see the shell plugin.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the plugin-process to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add process
      
    • yarn

      yarn run tauri add process
      
    • pnpm

      pnpm tauri add process
      
    • deno

      deno task tauri add process
      
    • bun

      bun tauri add process
      
    • cargo

      cargo tauri add process
      
  • Manual

    npm run tauri add process
    
  • npm

    yarn run tauri add process
    
  • yarn

    pnpm tauri add process
    
  • pnpm

    deno task tauri add process
    
  • deno

    bun tauri add process
    
  • bun

    cargo tauri add process
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-process
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_process::init())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. If youd like to utilize the plugin in JavaScript then install the npm package as well:

      • npm

        npm install @tauri-apps/plugin-process
        
      • yarn

        yarn add @tauri-apps/plugin-process
        
      • pnpm

        pnpm add @tauri-apps/plugin-process
        
      • deno

        deno add npm:@tauri-apps/plugin-process
        
      • bun

        bun add @tauri-apps/plugin-process
        
  • npm

    npm install @tauri-apps/plugin-process
    
  • yarn

    yarn add @tauri-apps/plugin-process
    
  • pnpm

    pnpm add @tauri-apps/plugin-process
    
  • deno

    deno add npm:@tauri-apps/plugin-process
    
  • bun

    bun add @tauri-apps/plugin-process
    

Usage

The process plugin is available in both JavaScript and Rust.

  • JavaScript

    import { exit, relaunch } from '@tauri-apps/plugin-process';
    // when using `"withGlobalTauri": true`, you may use
    // const { exit, relaunch } = window.__TAURI__.process;
    
    
    // exits the app with the given status code
    await exit(0);
    
    
    // restarts the app
    await relaunch();
    
  • Rust

    Note that app is an instance of AppHandle.

    // exits the app with the given status code
    app.exit(0);
    
    
    // restarts the app
    app.restart();
    

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "permissions": [
    ...,
    +"process:default",
  ]
}

Default Permission

This permission set configures which process features are by default exposed.

Granted Permissions

This enables to quit via allow-exit and restart via allow-restart the application.

This default permission set includes the following:

  • allow-exit
  • allow-restart

Permission Table

Identifier Description
process:allow-exit Enables the exit command without any pre-configured scope.
process:deny-exit Denies the exit command without any pre-configured scope.
process:allow-restart Enables the restart command without any pre-configured scope.
process:deny-restart Denies the restart command without any pre-configured scope.

Shell

Access the system shell to spawn child processes.

GitHubnpmcrates.io

API Reference:

Access the system shell. Allows you to spawn child processes.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android Only allows to open URLs via open
ios Only allows to open URLs via open

Opener

If youre looking for documentation for the shell.open API, check out the new Opener plugin instead.

Setup

Install the shell plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add shell
      
    • yarn

      yarn run tauri add shell
      
    • pnpm

      pnpm tauri add shell
      
    • deno

      deno task tauri add shell
      
    • bun

      bun tauri add shell
      
    • cargo

      cargo tauri add shell
      
  • Manual

    npm run tauri add shell
    
  • npm

    yarn run tauri add shell
    
  • yarn

    pnpm tauri add shell
    
  • pnpm

    deno task tauri add shell
    
  • deno

    bun tauri add shell
    
  • bun

    cargo tauri add shell
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-shell
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_shell::init())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-shell
        
      • yarn

        yarn add @tauri-apps/plugin-shell
        
      • pnpm

        pnpm add @tauri-apps/plugin-shell
        
      • deno

        deno add npm:@tauri-apps/plugin-shell
        
      • bun

        bun add @tauri-apps/plugin-shell
        
  • npm

    npm install @tauri-apps/plugin-shell
    
  • yarn

    yarn add @tauri-apps/plugin-shell
    
  • pnpm

    pnpm add @tauri-apps/plugin-shell
    
  • deno

    deno add npm:@tauri-apps/plugin-shell
    
  • bun

    bun add @tauri-apps/plugin-shell
    

Usage

The shell plugin is available in both JavaScript and Rust.

  • JavaScript

    import { Command } from '@tauri-apps/plugin-shell';
    // when using `"withGlobalTauri": true`, you may use
    // const { Command } = window.__TAURI__.shell;
    
    
    let result = await Command.create('exec-sh', [
      '-c',
      "echo 'Hello World!'",
    ]).execute();
    console.log(result);
    
  • Rust

    use tauri_plugin_shell::ShellExt;
    
    
    let shell = app_handle.shell();
    let output = tauri::async_runtime::block_on(async move {
        shell
            .command("echo")
            .args(["Hello from Rust!"])
            .output()
            .await
            .unwrap()
    });
    if output.status.success() {
        println!("Result: {:?}", String::from_utf8(output.stdout));
    } else {
        println!("Exit with code: {}", output.status.code().unwrap());
    }
    

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  +"permissions": [
+    {
      +"identifier": "shell:allow-execute",
      +"allow": [
+        {
          +"name": "exec-sh",
          +"cmd": "sh",
          +"args": [
            +"-c",
+            {
              +"validator": "\\S+"
+            }
+          ],
          +"sidecar": false
+        }
+      ]
+    }
+  ]
}

Default Permission

This permission set configures which shell functionality is exposed by default.

Granted Permissions

It allows to use the open functionality with a reasonable scope pre-configured. It will allow opening http(s)://, tel: and mailto: links.

This default permission set includes the following:

  • allow-open

Permission Table

Identifier Description
shell:allow-execute Enables the execute command without any pre-configured scope.
shell:deny-execute Denies the execute command without any pre-configured scope.
shell:allow-kill Enables the kill command without any pre-configured scope.
shell:deny-kill Denies the kill command without any pre-configured scope.
shell:allow-open Enables the open command without any pre-configured scope.
shell:deny-open Denies the open command without any pre-configured scope.
shell:allow-spawn Enables the spawn command without any pre-configured scope.
shell:deny-spawn Denies the spawn command without any pre-configured scope.
shell:allow-stdin-write Enables the stdin_write command without any pre-configured scope.
shell:deny-stdin-write Denies the stdin_write command without any pre-configured scope.

Single Instance

Ensure that a single instance of your Tauri app is running at a time.

GitHubcrates.io

API Reference:

Ensure that a single instance of your tauri app is running at a time using the Single Instance Plugin.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the Single Instance plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add single-instance
      
    • yarn

      yarn run tauri add single-instance
      
    • pnpm

      pnpm tauri add single-instance
      
    • deno

      deno task tauri add single-instance
      
    • bun

      bun tauri add single-instance
      
    • cargo

      cargo tauri add single-instance
      
  • Manual

    npm run tauri add single-instance
    
  • npm

    yarn run tauri add single-instance
    
  • yarn

    pnpm tauri add single-instance
    
  • pnpm

    deno task tauri add single-instance
    
  • deno

    bun tauri add single-instance
    
  • bun

    cargo tauri add single-instance
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-single-instance --target 'cfg(any(target_os = "macos", windows, target_os = "linux"))'
      
    2. Modify lib.rs to initialize the plugin:

      lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              .setup(|app| {
      +            #[cfg(desktop)]
                  +app.handle().plugin(tauri_plugin_single_instance::init(|app, args, cwd| {}));
                  Ok(())
              })
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      

Note

The Single Instance plugin must be the first one to be registered to work well. This assures that it runs before other plugins can interfere.

Usage

The plugin is already installed and initialized, and it should be functioning correctly right away. Nevertheless, we can also enhance its functionality with the init() method.

The plugin init() method takes a closure that is invoked when a new app instance was started, but closed by the plugin. The closure has three arguments:

  1. app: The AppHandle of the application.
  2. args: The list of arguments, that was passed by the user to initiate this new instance.
  3. cwd: The Current Working Directory denotes the directory from which the new application instance was launched.

So, the closure should look like below

.plugin(tauri_plugin_single_instance::init(|app, args, cwd| {
  // Write your code here...
}))

Focusing on New Instance

By default, when you initiate a new instance while the application is already running, no action is taken. To focus the window of the running instance when user tries to open a new instance, alter the callback closure as follows:

src-tauri/src/lib.rs

use tauri::{AppHandle, Manager};


pub fn run() {
    let mut builder = tauri::Builder::default();
    #[cfg(desktop)]
    {
        builder = builder.plugin(tauri_plugin_single_instance::init(|app, args, cwd| {
            let _ = app.get_webview_window("main")
                       .expect("no main window")
                       .set_focus();
        }));
    }


    builder
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Usage in Snap and Flatpak

On Linux the Single Instance plugin uses DBus to ensure that there will be only one instance running. It does so by publishing a service to DBus when the first instance starts running. Then, the following instances will try to publish the same service and, if it is already published, they will send a request to the service to notify the first instance, and exit right away.

Despite this working pretty well when your app is bundled as a deb or rpm package or an AppImage, it wont work as intended for snap or flatpak packages by default because these packages run in a constrained sandboxed environment, where most of the communication to DBus services will be blocked if not explicitly declared on the packaging manifest.

Heres a guide that shows how to declare the needed permissions to enable the Single Instance for snap and flatpak packages:

Getting your app ID

The Single Instance plugin will publish a service named org.{id}.SingleInstance.

{id} will be the identifier from your tauri.conf.json file, but with with dots (.) and dashes (-) replaced by underline (_).

For example, if your identifier is net.mydomain.MyApp:

  • net_mydomain_MyApp will be your app {id}
  • org.net_mydomain_MyApp.SingleInstance will be your app SingleInstance service name

You will need the service name to authorize your app to use the DBus service on snap and flatpak manifests, as seen below.

Snap

In your snapcraft.yml file, declare a plug and a slot for the single instance service, and use both on your app declaration:

snapcraft.yml

# ...
slots:
  single-instance:
    interface: dbus
    bus: session
    name: org.net_mydomain_MyApp.SingleInstance # Remember to change net_mydomain_MyApp to your app ID


plugs:
  single-instance-plug:
    interface: dbus
    bus: session
    name: org.net_mydomain_MyApp.SingleInstance # Remember to change net_mydomain_MyApp to your app ID


# .....
apps:
  my-app:
    # ...
    plugs:
      # ....
      - single-instance-plug
    slots:
      # ...
      - single-instance


    # ....

This will allow your app to send and receive requests from/to the DBus service as expected by the Single Instance plugin.

Flatpak

In your flatpak manifest file (your.app.id.yml or your.app.id.json), declare a --talk-name and a --own-name finish args with the service name:

net.mydomain.MyApp.yml

# ...
finish-args:
  - --socket=wayland
  - --socket=fallback-x11
  - --device=dri
  - --share=ipc
  # ....
  - --talk-name=org.net_mydomain_MyApp.SingleInstance # Remember to change net_mydomain_MyApp to your app ID
  - --own-name=org.net_mydomain_MyApp.SingleInstance # Remember to change net_mydomain_MyApp to your app ID
# ...

This will allow your app to send and receive requests from/to the DBus service as expected by the Single Instance plugin.

Permissions

Because this Plugin currently does not have JavaScript APIs you do not have to configure capabilities to use it.

SQL

Tauri Plugin providing an interface for the frontend to communicate with SQL databases through sqlx.

GitHubnpmcrates.io

API Reference:

Plugin providing an interface for the frontend to communicate with SQL databases through sqlx. It supports the SQLite, MySQL and PostgreSQL drivers, enabled by a Cargo feature.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the SQL plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add sql
      
    • yarn

      yarn run tauri add sql
      
    • pnpm

      pnpm tauri add sql
      
    • deno

      deno task tauri add sql
      
    • bun

      bun tauri add sql
      
    • cargo

      cargo tauri add sql
      
  • Manual

    npm run tauri add sql
    
  • npm

    yarn run tauri add sql
    
  • yarn

    pnpm tauri add sql
    
  • pnpm

    deno task tauri add sql
    
  • deno

    bun tauri add sql
    
  • bun

    cargo tauri add sql
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-sql
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
          pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_sql::Builder::default().build())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-sql
        
      • yarn

        yarn add @tauri-apps/plugin-sql
        
      • pnpm

        pnpm add @tauri-apps/plugin-sql
        
      • deno

        deno add npm:@tauri-apps/plugin-sql
        
      • bun

        bun add @tauri-apps/plugin-sql
        
  • npm

    npm install @tauri-apps/plugin-sql
    
  • yarn

    yarn add @tauri-apps/plugin-sql
    
  • pnpm

    pnpm add @tauri-apps/plugin-sql
    
  • deno

    deno add npm:@tauri-apps/plugin-sql
    
  • bun

    bun add @tauri-apps/plugin-sql
    

After installing the plugin, you must select the supported database engine. The available engines are Sqlite, MySQL and PostgreSQL. Run the following command in the src-tauri folder to enable your preferred engine:

  • SQLite

    cargo add tauri-plugin-sql --features sqlite
    
  • MySQL

    cargo add tauri-plugin-sql --features mysql
    
  • PostgreSQL

    cargo add tauri-plugin-sql --features postgres
    

Usage

All the plugins APIs are available through the JavaScript guest bindings:

  • SQLite

    The path is relative to tauri::api::path::BaseDirectory::AppConfig.

    import Database from '@tauri-apps/plugin-sql';
    // when using `"withGlobalTauri": true`, you may use
    // const Database = window.__TAURI__.sql;
    
    
    const db = await Database.load('sqlite:test.db');
    await db.execute('INSERT INTO ...');
    
  • MySQL

    import Database from '@tauri-apps/plugin-sql';
    // when using `"withGlobalTauri": true`, you may use
    // const Database = window.__TAURI__.sql;
    
    
    const db = await Database.load('mysql://user:password@host/test');
    await db.execute('INSERT INTO ...');
    
  • PostgreSQL

    import Database from '@tauri-apps/plugin-sql';
    // when using `"withGlobalTauri": true`, you may use
    // const Database = window.__TAURI__.sql;
    
    
    const db = await Database.load('postgres://user:password@host/test');
    await db.execute('INSERT INTO ...');
    

Syntax

We use sqlx as the underlying library and adopt their query syntax.

  • SQLite

    Use the “$#” syntax when substituting query data

    const result = await db.execute(
      'INSERT into todos (id, title, status) VALUES ($1, $2, $3)',
      [todos.id, todos.title, todos.status]
    );
    
    
    const result = await db.execute(
      'UPDATE todos SET title = $1, status = $2 WHERE id = $3',
      [todos.title, todos.status, todos.id]
    );
    
  • MySQL

    Use “?” when substituting query data

    const result = await db.execute(
      'INSERT into todos (id, title, status) VALUES (?, ?, ?)',
      [todos.id, todos.title, todos.status]
    );
    
    
    const result = await db.execute(
      'UPDATE todos SET title = ?, status = ? WHERE id = ?',
      [todos.title, todos.status, todos.id]
    );
    
  • PostgreSQL

    Use the “$#” syntax when substituting query data

    const result = await db.execute(
      'INSERT into todos (id, title, status) VALUES ($1, $2, $3)',
      [todos.id, todos.title, todos.status]
    );
    
    
    const result = await db.execute(
      'UPDATE todos SET title = $1, status = $2 WHERE id = $3',
      [todos.title, todos.status, todos.id]
    );
    

Migrations

This plugin supports database migrations, allowing you to manage database schema evolution over time.

Defining Migrations

Migrations are defined in Rust using the Migration struct. Each migration should include a unique version number, a description, the SQL to be executed, and the type of migration (Up or Down).

Example of a migration:

use tauri_plugin_sql::{Migration, MigrationKind};


let migration = Migration {
    version: 1,
    description: "create_initial_tables",
    sql: "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);",
    kind: MigrationKind::Up,
};

Or if you want to use SQL from a file, you can include it by using include_str!:

use tauri_plugin_sql::{Migration, MigrationKind};


let migration = Migration {
    version: 1,
    description: "create_initial_tables",
    sql: include_str!("../drizzle/0000_graceful_boomer.sql"),
    kind: MigrationKind::Up,
};

Adding Migrations to the Plugin Builder

Migrations are registered with the Builder struct provided by the plugin. Use the add_migrations method to add your migrations to the plugin for a specific database connection.

Example of adding migrations:

src-tauri/src/main.rs

use tauri_plugin_sql::{Builder, Migration, MigrationKind};


fn main() {
    let migrations = vec![
        // Define your migrations here
        Migration {
            version: 1,
            description: "create_initial_tables",
            sql: "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT);",
            kind: MigrationKind::Up,
        }
    ];


    tauri::Builder::default()
        .plugin(
            tauri_plugin_sql::Builder::default()
                .add_migrations("sqlite:mydatabase.db", migrations)
                .build(),
        )
        ...
}

Applying Migrations

To apply the migrations when the plugin is initialized, add the connection string to the tauri.conf.json file:

src-tauri/tauri.conf.json

{
  "plugins": {
    "sql": {
      "preload": ["sqlite:mydatabase.db"]
    }
  }
}

Alternatively, the client side load() also runs the migrations for a given connection string:

import Database from '@tauri-apps/plugin-sql';
const db = await Database.load('sqlite:mydatabase.db');

Ensure that the migrations are defined in the correct order and are safe to run multiple times.

Note

All migrations are executed within a transaction, ensuring atomicity. If any migration fails, the entire transaction is rolled back, leaving the database in a consistent state.

Migration Management

  • Version Control: Each migration must have a unique version number. This is crucial for ensuring the migrations are applied in the correct order.
  • Idempotency: Write migrations in a way that they can be safely re-run without causing errors or unintended consequences.
  • Testing: Thoroughly test migrations to ensure they work as expected and do not compromise the integrity of your database.

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "permissions": [
    ...,
    +"sql:default",
    +"sql:allow-execute",
  ]
}

Default Permission

Default Permissions

This permission set configures what kind of database operations are available from the sql plugin.

Granted Permissions

All reading related operations are enabled. Also allows to load or close a connection.

This default permission set includes the following:

  • allow-close
  • allow-load
  • allow-select

Permission Table

Identifier Description
sql:allow-close Enables the close command without any pre-configured scope.
sql:deny-close Denies the close command without any pre-configured scope.
sql:allow-execute Enables the execute command without any pre-configured scope.
sql:deny-execute Denies the execute command without any pre-configured scope.
sql:allow-load Enables the load command without any pre-configured scope.
sql:deny-load Denies the load command without any pre-configured scope.
sql:allow-select Enables the select command without any pre-configured scope.
sql:deny-select Denies the select command without any pre-configured scope.

Store

Persistent key value storage.

GitHubnpmcrates.io

API Reference:

This plugin provides a persistent key-value store. This is one of many options to handle state in your application. See the state management overview for more information on additional options.

This store will allow you to persist state to a file which can be saved and loaded on demand including between app restarts. Note that this process is asynchronous which will require handling it within your code. It can be used both in the webview or within Rust.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the store plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add store
      
    • yarn

      yarn run tauri add store
      
    • pnpm

      pnpm tauri add store
      
    • deno

      deno task tauri add store
      
    • bun

      bun tauri add store
      
    • cargo

      cargo tauri add store
      
  • Manual

    npm run tauri add store
    
  • npm

    yarn run tauri add store
    
  • yarn

    pnpm tauri add store
    
  • pnpm

    deno task tauri add store
    
  • deno

    bun tauri add store
    
  • bun

    cargo tauri add store
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-store
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_store::Builder::new().build())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-store
        
      • yarn

        yarn add @tauri-apps/plugin-store
        
      • pnpm

        pnpm add @tauri-apps/plugin-store
        
      • deno

        deno add npm:@tauri-apps/plugin-store
        
      • bun

        bun add @tauri-apps/plugin-store
        
  • npm

    npm install @tauri-apps/plugin-store
    
  • yarn

    yarn add @tauri-apps/plugin-store
    
  • pnpm

    pnpm add @tauri-apps/plugin-store
    
  • deno

    deno add npm:@tauri-apps/plugin-store
    
  • bun

    bun add @tauri-apps/plugin-store
    

Usage

  • JavaScript

    import { load } from '@tauri-apps/plugin-store';
    // when using `"withGlobalTauri": true`, you may use
    // const { load } = window.__TAURI__.store;
    
    
    // Create a new store or load the existing one,
    // note that the options will be ignored if a `Store` with that path has already been created
    const store = await load('store.json', { autoSave: false });
    
    
    // Set a value.
    await store.set('some-key', { value: 5 });
    
    
    // Get a value.
    const val = await store.get<{ value: number }>('some-key');
    console.log(val); // { value: 5 }
    
    
    // You can manually save the store after making changes.
    // Otherwise, it will save upon graceful exit
    // And if you set `autoSave` to a number or left empty,
    // it will save the changes to disk after a debounce delay, 100ms by default.
    await store.save();
    
  • Rust

    src-tauri/src/lib.rs

    use tauri::Wry;
    use tauri_plugin_store::StoreExt;
    use serde_json::json;
    
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
        tauri::Builder::default()
            .plugin(tauri_plugin_store::Builder::default().build())
            .setup(|app| {
                // Create a new store or load the existing one
                // this also put the store in the app's resource table
                // so your following `store` calls (from both Rust and JS)
                // will reuse the same store.
    
    
                let store = app.store("store.json")?;
    
    
                // Note that values must be serde_json::Value instances,
                // otherwise, they will not be compatible with the JavaScript bindings.
                store.set("some-key", json!({ "value": 5 }));
    
    
                // Get a value from the store.
                let value = store.get("some-key").expect("Failed to get value from store");
                println!("{}", value); // {"value":5}
    
    
                // Remove the store from the resource table
                store.close_resource();
    
    
                Ok(())
            })
            .run(tauri::generate_context!())
            .expect("error while running tauri application");
    }
    

LazyStore

Theres also a high level JavaScript API LazyStore which only loads the store on first access

import { LazyStore } from '@tauri-apps/plugin-store';


const store = new LazyStore('settings.json');

Migrating from v1 and v2 beta/rc

  • JavaScript

    import { Store } from '@tauri-apps/plugin-store';
    import { LazyStore } from '@tauri-apps/plugin-store';
    
  • Rust

    with_store(app.handle().clone(), stores, path, |store| {
        store.insert("some-key".to_string(), json!({ "value": 5 }))?;
        Ok(())
    });
    let store = app.store(path)?;
    store.set("some-key".to_string(), json!({ "value": 5 }));
    

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "permissions": [
    ...,
    +"store:default",
  ]
}

Default Permission

This permission set configures what kind of operations are available from the store plugin.

Granted Permissions

All operations are enabled by default.

This default permission set includes the following:

  • allow-load
  • allow-get-store
  • allow-set
  • allow-get
  • allow-has
  • allow-delete
  • allow-clear
  • allow-reset
  • allow-keys
  • allow-values
  • allow-entries
  • allow-length
  • allow-reload
  • allow-save

Permission Table

Identifier Description
store:allow-clear Enables the clear command without any pre-configured scope.
store:deny-clear Denies the clear command without any pre-configured scope.
store:allow-delete Enables the delete command without any pre-configured scope.
store:deny-delete Denies the delete command without any pre-configured scope.
store:allow-entries Enables the entries command without any pre-configured scope.
store:deny-entries Denies the entries command without any pre-configured scope.
store:allow-get Enables the get command without any pre-configured scope.
store:deny-get Denies the get command without any pre-configured scope.
store:allow-get-store Enables the get_store command without any pre-configured scope.
store:deny-get-store Denies the get_store command without any pre-configured scope.
store:allow-has Enables the has command without any pre-configured scope.
store:deny-has Denies the has command without any pre-configured scope.
store:allow-keys Enables the keys command without any pre-configured scope.
store:deny-keys Denies the keys command without any pre-configured scope.
store:allow-length Enables the length command without any pre-configured scope.
store:deny-length Denies the length command without any pre-configured scope.
store:allow-load Enables the load command without any pre-configured scope.
store:deny-load Denies the load command without any pre-configured scope.
store:allow-reload Enables the reload command without any pre-configured scope.
store:deny-reload Denies the reload command without any pre-configured scope.
store:allow-reset Enables the reset command without any pre-configured scope.
store:deny-reset Denies the reset command without any pre-configured scope.
store:allow-save Enables the save command without any pre-configured scope.
store:deny-save Denies the save command without any pre-configured scope.
store:allow-set Enables the set command without any pre-configured scope.
store:deny-set Denies the set command without any pre-configured scope.
store:allow-values Enables the values command without any pre-configured scope.
store:deny-values Denies the values command without any pre-configured scope.

Stronghold

Encrypted, secure database.

GitHubnpmcrates.io

API Reference:

Store secrets and keys using the IOTA Stronghold secret management engine.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the stronghold plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add stronghold
      
    • yarn

      yarn run tauri add stronghold
      
    • pnpm

      pnpm tauri add stronghold
      
    • deno

      deno task tauri add stronghold
      
    • bun

      bun tauri add stronghold
      
    • cargo

      cargo tauri add stronghold
      
  • Manual

    npm run tauri add stronghold
    
  • npm

    yarn run tauri add stronghold
    
  • yarn

    pnpm tauri add stronghold
    
  • pnpm

    deno task tauri add stronghold
    
  • deno

    bun tauri add stronghold
    
  • bun

    cargo tauri add stronghold
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-stronghold
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_stronghold::Builder::new(|password| {}).build())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-stronghold
        
      • yarn

        yarn add @tauri-apps/plugin-stronghold
        
      • pnpm

        pnpm add @tauri-apps/plugin-stronghold
        
      • deno

        deno add npm:@tauri-apps/plugin-stronghold
        
      • bun

        bun add @tauri-apps/plugin-stronghold
        
  • npm

    npm install @tauri-apps/plugin-stronghold
    
  • yarn

    yarn add @tauri-apps/plugin-stronghold
    
  • pnpm

    pnpm add @tauri-apps/plugin-stronghold
    
  • deno

    deno add npm:@tauri-apps/plugin-stronghold
    
  • bun

    bun add @tauri-apps/plugin-stronghold
    

Due to an upstream bug we also recommend that you add this to your Cargo.toml file:

[profile.dev.package.scrypt]
opt-level = 3

Usage

The plugin must be initialized with a password hash function, which takes the password string and must return a 32 bytes hash derived from it.

Initialize with argon2 password hash function

The Stronghold plugin offers a default hash function using the argon2 algorithm.

src-tauri/src/lib.rs

use tauri::Manager;


pub fn run() {
    tauri::Builder::default()
        .setup(|app| {
            let salt_path = app
                .path()
                .app_local_data_dir()
                .expect("could not resolve app local data path")
                .join("salt.txt");
            app.handle().plugin(tauri_plugin_stronghold::Builder::with_argon2(&salt_path).build())?;
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Initialize with custom password hash function

Alternatively you can provide your own hash algorithm by using the tauri_plugin_stronghold::Builder::new constructor.

Note

The password hash must contain exactly 32 bytes. This is a Stronghold requirement.

src-tauri/src/lib.rs

pub fn run() {
    tauri::Builder::default()
        .plugin(
            tauri_plugin_stronghold::Builder::new(|password| {
                // Hash the password here with e.g. argon2, blake2b or any other secure algorithm
                // Here is an example implementation using the `rust-argon2` crate for hashing the password
                use argon2::{hash_raw, Config, Variant, Version};


                let config = Config {
                    lanes: 4,
                    mem_cost: 10_000,
                    time_cost: 10,
                    variant: Variant::Argon2id,
                    version: Version::Version13,
                    ..Default::default()
                };
                let salt = "your-salt".as_bytes();
                let key = hash_raw(password.as_ref(), salt, &config).expect("failed to hash password");


                key.to_vec()
            })
            .build(),
        )
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

Usage from JavaScript

The stronghold plugin is available in JavaScript.

import { Client, Stronghold } from '@tauri-apps/plugin-stronghold';
// when using `"withGlobalTauri": true`, you may use
// const { Client, Stronghold } = window.__TAURI__.stronghold;
import { appDataDir } from '@tauri-apps/api/path';
// when using `"withGlobalTauri": true`, you may use
// const { appDataDir } = window.__TAURI__.path;


const initStronghold = async () => {
  const vaultPath = `${await appDataDir()}/vault.hold`;
  const vaultPassword = 'vault password';
  const stronghold = await Stronghold.load(vaultPath, vaultPassword);


  let client: Client;
  const clientName = 'name your client';
  try {
    client = await stronghold.loadClient(clientName);
  } catch {
    client = await stronghold.createClient(clientName);
  }


  return {
    stronghold,
    client,
  };
};


// Insert a record to the store
async function insertRecord(store: any, key: string, value: string) {
  const data = Array.from(new TextEncoder().encode(value));
  await store.insert(key, data);
}


// Read a record from store
async function getRecord(store: any, key: string): Promise<string> {
  const data = await store.get(key);
  return new TextDecoder().decode(new Uint8Array(data));
}


const { stronghold, client } = await initStronghold();


const store = client.getStore();
const key = 'my_key';


// Insert a record to the store
insertRecord(store, key, 'secret value');


// Read a record from store
const value = await getRecord(store, key);
console.log(value); // 'secret value'


// Save your updates
await stronghold.save();


// Remove a record from store
await store.remove(key);

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  ...,
  "permissions": [
    +"stronghold:default",
  ]
}

Default Permission

This permission set configures what kind of operations are available from the stronghold plugin.

Granted Permissions

All non-destructive operations are enabled by default.

This default permission set includes the following:

  • allow-create-client
  • allow-get-store-record
  • allow-initialize
  • allow-execute-procedure
  • allow-load-client
  • allow-save-secret
  • allow-save-store-record
  • allow-save

Permission Table

Identifier Description
stronghold:allow-create-client Enables the create_client command without any pre-configured scope.
stronghold:deny-create-client Denies the create_client command without any pre-configured scope.
stronghold:allow-destroy Enables the destroy command without any pre-configured scope.
stronghold:deny-destroy Denies the destroy command without any pre-configured scope.
stronghold:allow-execute-procedure Enables the execute_procedure command without any pre-configured scope.
stronghold:deny-execute-procedure Denies the execute_procedure command without any pre-configured scope.
stronghold:allow-get-store-record Enables the get_store_record command without any pre-configured scope.
stronghold:deny-get-store-record Denies the get_store_record command without any pre-configured scope.
stronghold:allow-initialize Enables the initialize command without any pre-configured scope.
stronghold:deny-initialize Denies the initialize command without any pre-configured scope.
stronghold:allow-load-client Enables the load_client command without any pre-configured scope.
stronghold:deny-load-client Denies the load_client command without any pre-configured scope.
stronghold:allow-remove-secret Enables the remove_secret command without any pre-configured scope.
stronghold:deny-remove-secret Denies the remove_secret command without any pre-configured scope.
stronghold:allow-remove-store-record Enables the remove_store_record command without any pre-configured scope.
stronghold:deny-remove-store-record Denies the remove_store_record command without any pre-configured scope.
stronghold:allow-save Enables the save command without any pre-configured scope.
stronghold:deny-save Denies the save command without any pre-configured scope.
stronghold:allow-save-secret Enables the save_secret command without any pre-configured scope.
stronghold:deny-save-secret Denies the save_secret command without any pre-configured scope.
stronghold:allow-save-store-record Enables the save_store_record command without any pre-configured scope.
stronghold:deny-save-store-record Denies the save_store_record command without any pre-configured scope.

Updater

In-app updates for Tauri applications.

GitHubnpmcrates.io

API Reference:

Automatically update your Tauri app with an update server or a static JSON.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the Tauri updater plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add updater
      
    • yarn

      yarn run tauri add updater
      
    • pnpm

      pnpm tauri add updater
      
    • deno

      deno task tauri add updater
      
    • bun

      bun tauri add updater
      
    • cargo

      cargo tauri add updater
      
  • Manual

    npm run tauri add updater
    
  • npm

    yarn run tauri add updater
    
  • yarn

    pnpm tauri add updater
    
  • pnpm

    deno task tauri add updater
    
  • deno

    bun tauri add updater
    
  • bun

    cargo tauri add updater
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-updater --target 'cfg(any(target_os = "macos", windows, target_os = "linux"))'
      
    2. Modify lib.rs to initialize the plugin:

      lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              .setup(|app| {
      +            #[cfg(desktop)]
                  +app.handle().plugin(tauri_plugin_updater::Builder::new().build());
                  Ok(())
              })
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. You can install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-updater
        
      • yarn

        yarn add @tauri-apps/plugin-updater
        
      • pnpm

        pnpm add @tauri-apps/plugin-updater
        
      • deno

        deno add npm:@tauri-apps/plugin-updater
        
      • bun

        bun add @tauri-apps/plugin-updater
        
  • npm

    npm install @tauri-apps/plugin-updater
    
  • yarn

    yarn add @tauri-apps/plugin-updater
    
  • pnpm

    pnpm add @tauri-apps/plugin-updater
    
  • deno

    deno add npm:@tauri-apps/plugin-updater
    
  • bun

    bun add @tauri-apps/plugin-updater
    

Signing updates

Tauris updater needs a signature to verify that the update is from a trusted source. This cannot be disabled.

To sign your updates you need two keys:

  1. The public key, which will be set in the tauri.conf.json to validate the artifacts before the installation. This public key can be uploaded and shared safely as long as your private key is secure.
  2. The private key, which is used to sign your installer files. You should NEVER share this key with anyone. Also, if you lose this key you will NOT be able to publish new updates to the users that have the app already installed. It is important to store this key in a safe place!

To generate the keys the Tauri CLI provides the signer generate command. You can run this to create the keys in the home folder:

  • npm

    npm run tauri signer generate -- -w ~/.tauri/myapp.key
    
  • yarn

    yarn tauri signer generate -w ~/.tauri/myapp.key
    
  • pnpm

    pnpm tauri signer generate -w ~/.tauri/myapp.key
    
  • deno

    deno task tauri signer generate -w ~/.tauri/myapp.key
    
  • bun

    bunx tauri signer generate -w ~/.tauri/myapp.key
    
  • cargo

    cargo tauri signer generate -w ~/.tauri/myapp.key
    

Building

While building your update artifacts, you need to have the private key you generated above in your environment variables. .env files do not work!

  • Mac/Linux

    export TAURI_SIGNING_PRIVATE_KEY="Path or content of your private key"
    # optionally also add a password
    export TAURI_SIGNING_PRIVATE_KEY_PASSWORD=""
    
  • Windows

    Run this in PowerShell:

    $env:TAURI_SIGNING_PRIVATE_KEY="Path or content of your private key"
    <# optionally also add a password #>
    $env:TAURI_SIGNING_PRIVATE_KEY_PASSWORD=""
    

After that, you can run Tauri build as usual and Tauri will generate the update bundles and their signatures. The generated files depend on the createUpdaterArtifacts configuration value configured below.

  • v2

    {
      "bundle": {
        "createUpdaterArtifacts": true
      }
    }
    

    On Linux, Tauri will create the normal AppImage inside the target/release/bundle/appimage/ folder:

    • myapp.AppImage - The standard app bundle. It will be re-used by the updater.
    • myapp.AppImage.sig - The signature of the updater bundle.

    On macOS, Tauri will create a .tar.gz archive from the application bundle inside the target/release/bundle/macos/ folder:

    • myapp.app - The standard app bundle.
    • myapp.app.tar.gz - The updater bundle.
    • myapp.app.tar.gz.sig - The signature of the update bundle.

    On Windows, Tauri will create the normal MSI and NSIS installers inside the target/release/bundle/msi/ and target/release/bundle/nsis folders:

    • myapp-setup.exe - The standard app bundle. It will be re-used by the updater.
    • myapp-setup.exe.sig - The signature of the update bundle.
    • myapp.msi - The standard app bundle. It will be re-used by the updater.
    • myapp.msi.sig - The signature of the update bundle.
  • v1 compatible

    {
      "bundle": {
        "createUpdaterArtifacts": "v1Compatible"
      }
    }
    

    On Linux, Tauri will create a .tar.gz archive from the AppImage inside the target/release/bundle/appimage/ folder:

    • myapp.AppImage - The standard app bundle.
    • myapp.AppImage.tar.gz - The updater bundle.
    • myapp.AppImage.tar.gz.sig - The signature of the update bundle.

    On macOS, Tauri will create a .tar.gz archive from the application bundle inside the target/release/bundle/macos/ folder:

    • myapp.app - The standard app bundle.
    • myapp.app.tar.gz - The updater bundle.
    • myapp.app.tar.gz.sig - The signature of the update bundle.

    On Windows, Tauri will create .zip archives from the MSI and NSIS installers inside the target/release/bundle/msi/ and target/release/bundle/nsis folders:

    • myapp-setup.exe - The standard app bundle.
    • myapp-setup.nsis.zip - The updater bundle.
    • myapp-setup.nsis.zip.sig - The signature of the update bundle.
    • myapp.msi - The standard app bundle.
    • myapp.msi.zip - The updater bundle.
    • myapp.msi.zip.sig - The signature of the update bundle.

Tauri Configuration

Set up the tauri.conf.json in this format for the updater to start working.

Keys Description
createUpdaterArtifacts Setting this to true tells Tauris app bundler to create updater artifacts. If youre migrating your app from an older Tauri version, set it to "v1Compatible" instead. This setting will be removed in v3 so make sure to change it to true once all your users are migrated to v2.
pubkey This has to be the public key generated from the Tauri CLI in the step above. It cannot be a file path!
endpoints This must be an array of endpoint URLs as strings. TLS is enforced in production mode. Tauri will only continue to the next url if a non-2XX status code is returned!
dangerousInsecureTransportProtocol Setting this to true allows the updater to accept non-HTTPS endpoints. Use this configuration with caution!

Each updater URL can contain the following dynamic variables, allowing you to determine server-side if an update is available.

  • {{current_version}}: The version of the app that is requesting the update.
  • {{target}}: The operating system name (one of linux, windows or darwin).
  • {{arch}}: The architecture of the machine (one of x86_64, i686, aarch64 or armv7).

tauri.conf.json

{
  "bundle": {
    "createUpdaterArtifacts": true
  },
  "plugins": {
    "updater": {
      "pubkey": "CONTENT FROM PUBLICKEY.PEM",
      "endpoints": [
        "https://releases.myapp.com/{{target}}/{{arch}}/{{current_version}}",
        // or a static github json file
        "https://github.com/user/repo/releases/latest/download/latest.json"
      ]
    }
  }
}

Tip

Custom variables are not supported, but you can define a custom {{target}}.

installMode on Windows

On Windows there is an additional optional "installMode" config to change how the update is installed.

tauri.conf.json

{
  "plugins": {
    "updater": {
      "windows": {
        "installMode": "passive"
      }
    }
  }
}
  • "passive": There will be a small window with a progress bar. The update will be installed without requiring any user interaction. Generally recommended and the default mode.
  • "basicUi": There will be a basic user interface shown which requires user interaction to finish the installation.
  • "quiet": There will be no progress feedback to the user. With this mode the installer cannot request admin privileges by itself so it only works in user-wide installations or when your app itself already runs with admin privileges. Generally not recommended.

Server Support

The updater plugin can be used in two ways. Either with a dynamic update server or a static JSON file (to use on services like S3 or GitHub gists).

Static JSON File

When using static, you just need to return a JSON containing the required information.

Keys Description
version Must be a valid SemVer, with or without a leading v, meaning that both 1.0.0 and v1.0.0 are valid.
notes Notes about the update.
pub_date The date must be formatted according to RFC 3339 if present.
platforms Each platform key is in the OS-ARCH format, where OS is one of linux, darwin or windows, and ARCH is one of x86_64, aarch64, i686 or armv7.
signature The content of the generated .sig file, which may change with each build. A path or URL does not work!

Note

When using custom targets the provided target string is matched against the platforms key instead of the default OS-ARCH value.

The required keys are "version", "platforms.[target].url" and "platforms.[target].signature"; the others are optional.

{
  "version": "",
  "notes": "",
  "pub_date": "",
  "platforms": {
    "linux-x86_64": {
      "signature": "",
      "url": ""
    },
    "windows-x86_64": {
      "signature": "",
      "url": ""
    },
    "darwin-x86_64": {
      "signature": "",
      "url": ""
    }
  }
}

Note that Tauri will validate the whole file before checking the version field, so make sure all existing platform configurations are valid and complete.

Tip

Tauri Action generates a static JSON file for you to use on CDNs such as GitHub Releases.

Dynamic Update Server

When using a dynamic update server, Tauri will follow the servers instructions. To disable the internal version check you can overwrite the plugins version comparison, this will install the version sent by the server (useful if you need to roll back your app).

Your server can use variables defined in the endpoint URL above to determine if an update is required. If you need more data, you can include additional request headers in Rust to your liking.

Your server should respond with a status code of 204 No Content if there is no update available.

If an update is required, your server should respond with a status code of 200 OK and a JSON response in this format:

Keys Description
version This Must be a valid SemVer, with or without a leading v, meaning that both 1.0.0 and v1.0.0 are valid.
notes Notes about the update.
pub_date The date must be formatted according to RFC 3339 if present.
url This Must be a valid URL to the update bundle.
signature The content of the generated .sig file, which may change with each build. A path or URL does not work!

The required keys are "url", "version" and "signature"; the others are optional.

{
  "version": "",
  "pub_date": "",
  "url": "",
  "signature": "",
  "notes": ""
}

Tip

CrabNebula, an official Tauri partner, offers a dynamic update server. For more information, see the Distributing with CrabNebula Cloud documentation.

Checking for Updates

The default API for checking updates and installing them leverages the configured endpoints and can be accessed by both JavaScript and Rust code.

  • JavaScript

    import { check } from '@tauri-apps/plugin-updater';
    import { relaunch } from '@tauri-apps/plugin-process';
    
    
    const update = await check();
    if (update) {
      console.log(
        `found update ${update.version} from ${update.date} with notes ${update.body}`
      );
      let downloaded = 0;
      let contentLength = 0;
      // alternatively we could also call update.download() and update.install() separately
      await update.downloadAndInstall((event) => {
        switch (event.event) {
          case 'Started':
            contentLength = event.data.contentLength;
            console.log(`started downloading ${event.data.contentLength} bytes`);
            break;
          case 'Progress':
            downloaded += event.data.chunkLength;
            console.log(`downloaded ${downloaded} from ${contentLength}`);
            break;
          case 'Finished':
            console.log('download finished');
            break;
        }
      });
    
    
      console.log('update installed');
      await relaunch();
    }
    

    For more information see the JavaScript API documentation.

  • Rust

    src-tauri/src/lib.rs

    use tauri_plugin_updater::UpdaterExt;
    
    
    pub fn run() {
      tauri::Builder::default()
        .setup(|app| {
          let handle = app.handle().clone();
          tauri::async_runtime::spawn(async move {
            update(handle).await.unwrap();
          });
          Ok(())
        })
        .run(tauri::generate_context!())
        .unwrap();
    }
    
    
    async fn update(app: tauri::AppHandle) -> tauri_plugin_updater::Result<()> {
      if let Some(update) = app.updater()?.check().await? {
        let mut downloaded = 0;
    
    
        // alternatively we could also call update.download() and update.install() separately
        update
          .download_and_install(
            |chunk_length, content_length| {
              downloaded += chunk_length;
              println!("downloaded {downloaded} from {content_length:?}");
            },
            || {
              println!("download finished");
            },
          )
          .await?;
    
    
        println!("update installed");
        app.restart();
      }
    
    
      Ok(())
    }
    

    Tip

    To notify the frontend of the download progress consider using a command with a channel.

    Updater command

    #[cfg(desktop)]
    mod app_updates {
        use std::sync::Mutex;
        use serde::Serialize;
        use tauri::{ipc::Channel, AppHandle, State};
        use tauri_plugin_updater::{Update, UpdaterExt};
    
    
        #[derive(Debug, thiserror::Error)]
        pub enum Error {
            #[error(transparent)]
            Updater(#[from] tauri_plugin_updater::Error),
            #[error("there is no pending update")]
            NoPendingUpdate,
        }
    
    
        impl Serialize for Error {
            fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
            where
                S: serde::Serializer,
            {
                serializer.serialize_str(self.to_string().as_str())
            }
        }
    
    
        type Result<T> = std::result::Result<T, Error>;
    
    
        #[derive(Clone, Serialize)]
        #[serde(tag = "event", content = "data")]
        pub enum DownloadEvent {
            #[serde(rename_all = "camelCase")]
            Started {
                content_length: Option<u64>,
            },
            #[serde(rename_all = "camelCase")]
            Progress {
                chunk_length: usize,
            },
            Finished,
        }
    
    
        #[derive(Serialize)]
        #[serde(rename_all = "camelCase")]
        pub struct UpdateMetadata {
            version: String,
            current_version: String,
        }
    
    
        #[tauri::command]
        pub async fn fetch_update(
            app: AppHandle,
            pending_update: State<'_, PendingUpdate>,
        ) -> Result<Option<UpdateMetadata>> {
            let channel = "stable";
            let url = url::Url::parse(&format!(
                "https://cdn.myupdater.com/{{{{target}}}}-{{{{arch}}}}/{{{{current_version}}}}?channel={channel}",
            )).expect("invalid URL");
    
    
          let update = app
              .updater_builder()
              .endpoints(vec![url])?
              .build()?
              .check()
              .await?;
    
    
          let update_metadata = update.as_ref().map(|update| UpdateMetadata {
              version: update.version.clone(),
              current_version: update.current_version.clone(),
          });
    
    
          *pending_update.0.lock().unwrap() = update;
    
    
          Ok(update_metadata)
        }
    
    
        #[tauri::command]
        pub async fn install_update(pending_update: State<'_, PendingUpdate>, on_event: Channel<DownloadEvent>) -> Result<()> {
            let Some(update) = pending_update.0.lock().unwrap().take() else {
                return Err(Error::NoPendingUpdate);
            };
    
    
            let started = false;
    
    
            update
                .download_and_install(
                    |chunk_length, content_length| {
                        if !started {
                            let _ = on_event.send(DownloadEvent::Started { content_length });
                            started = true;
                        }
    
    
                        let _ = on_event.send(DownloadEvent::Progress { chunk_length });
                    },
                    || {
                        let _ = on_event.send(DownloadEvent::Finished);
                    },
                )
                .await?;
    
    
            Ok(())
        }
    
    
        struct PendingUpdate(Mutex<Option<Update>>);
    }
    
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
        tauri::Builder::default()
            .plugin(tauri_plugin_process::init())
            .setup(|app| {
                #[cfg(desktop)]
                {
                    app.handle().plugin(tauri_plugin_updater::Builder::new().build());
                    app.manage(app_updates::PendingUpdate(Mutex::new(None)));
                }
                Ok(())
            })
            .invoke_handler(tauri::generate_handler![
                #[cfg(desktop)]
                app_updates::fetch_update,
                #[cfg(desktop)]
                app_updates::install_update
            ])
    }
    

    For more information see the Rust API documentation.

Note that restarting your app immediately after installing an update is not required and you can choose how to handle the update by either waiting until the user manually restarts the app, or prompting them to select when to do so.

Note

On Windows the application is automatically exited when the install step is executed due to a limitation of Windows installers.

When checking and downloading updates it is possible to define a custom request timeout, a proxy and request headers.

  • JavaScript

    import { check } from '@tauri-apps/plugin-updater';
    
    
    const update = await check({
      proxy: '<proxy url>',
      timeout: 30000 /* milliseconds */,
      headers: {
        Authorization: 'Bearer <token>',
      },
    });
    
  • Rust

    use tauri_plugin_updater::UpdaterExt;
    let update = app
      .updater_builder()
      .timeout(std::time::Duration::from_secs(30))
      .proxy("<proxy-url>".parse().expect("invalid URL"))
      .header("Authorization", "Bearer <token>")
      .build()?
      .check()
      .await?;
    

Runtime Configuration

The updater APIs also allows the updater to be configured at runtime for more flexibility. For security reasons some APIs are only available for Rust.

Endpoints

Setting the URLs that should be requested to check updates at runtime allows more dynamic updates such as separate release channels:

use tauri_plugin_updater::UpdaterExt;
let channel = if beta { "beta" } else { "stable" };
let update_url = format!("https://{channel}.myserver.com/{{{{target}}}}-{{{{arch}}}}/{{{{current_version}}}}");


let update = app
  .updater_builder()
  .endpoints(vec![update_url])?
  .build()?
  .check()
  .await?;

Tip

Note that when using format!() to interpolate the update URL you need double escapes for the variables e.g. {{{{target}}}}.

Public key

Setting the public key at runtime can be useful to implement a key rotation logic. It can be set by either the plugin builder or updater builder:

tauri_plugin_updater::Builder::new().pubkey("<your public key>").build()
use tauri_plugin_updater::UpdaterExt;


let update = app
  .updater_builder()
  .pubkey("<your public key>")
  .build()?
  .check()
  .await?;

Custom target

By default the updater lets you use the {{target}} and {{arch}} variables to determine which update asset must be delivered. If you need more information on your updates (e.g. when distributing a Universal macOS binary option or having more build flavors) you can set a custom target.

  • JavaScript

    import { check } from '@tauri-apps/plugin-updater';
    
    
    const update = await check({
      target: 'macos-universal',
    });
    
  • Rust

    Custom targets can be set by either the plugin builder or updater builder:

    tauri_plugin_updater::Builder::new().target("macos-universal").build()
    
    use tauri_plugin_updater::UpdaterExt;
    let update = app
      .updater_builder()
      .target("macos-universal")
      .build()?
      .check()
      .await?;
    

    Tip

    The default $target-$arch key can be retrieved using tauri_plugin_updater::target() which returns an Option<String> that is None when the updater is not supported on the current platform.

Note

  • When using a custom target it might be easier to use it exclusively to determine the update platform, so you could remove the {{arch}} variable.
  • The value provided as target is the key that is matched against the platform key when using a Static JSON file.

Allowing downgrades

By default Tauri checks if the update version is greater than the current app version to verify if it should update or not. To allow downgrades, you must use the updater builders version_comparator API:

use tauri_plugin_updater::UpdaterExt;


let update = app
  .updater_builder()
  .version_comparator(|current, update| {
    // default comparison: `update.version > current`
    update.version != current
  })
  .build()?
  .check()
  .await?;

Windows before exit hook

Due to a limitation of Windows installers, Tauri will automatically quit your application before installing updates on Windows. To perform an action before that happens, use the on_before_exit function:

use tauri_plugin_updater::UpdaterExt;


let update = app
  .updater_builder()
  .on_before_exit(|| {
    println!("app is about to exit on Windows!");
  })
  .build()?
  .check()
  .await?;

Note

The values from the configuration are used as fallback if any of the builder values are not set.

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "permissions": [
    ...,
    +"updater:default",
  ]
}

Default Permission

This permission set configures which kind of updater functions are exposed to the frontend.

Granted Permissions

The full workflow from checking for updates to installing them is enabled.

This default permission set includes the following:

  • allow-check
  • allow-download
  • allow-install
  • allow-download-and-install

Permission Table

Identifier Description
updater:allow-check Enables the check command without any pre-configured scope.
updater:deny-check Denies the check command without any pre-configured scope.
updater:allow-download Enables the download command without any pre-configured scope.
updater:deny-download Denies the download command without any pre-configured scope.
updater:allow-download-and-install Enables the download_and_install command without any pre-configured scope.
updater:deny-download-and-install Denies the download_and_install command without any pre-configured scope.
updater:allow-install Enables the install command without any pre-configured scope.
updater:deny-install Denies the install command without any pre-configured scope.

Upload

File uploads through HTTP.

GitHubnpmcrates.io

API Reference:

Upload files from disk to a remote server over HTTP. Download files from a remote HTTP server to disk.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add upload
      
    • yarn

      yarn run tauri add upload
      
    • pnpm

      pnpm tauri add upload
      
    • deno

      deno task tauri add upload
      
    • bun

      bun tauri add upload
      
    • cargo

      cargo tauri add upload
      
  • Manual

    npm run tauri add upload
    
  • npm

    yarn run tauri add upload
    
  • yarn

    pnpm tauri add upload
    
  • pnpm

    deno task tauri add upload
    
  • deno

    bun tauri add upload
    
  • bun

    cargo tauri add upload
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-upload
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
        tauri::Builder::default()
          +.plugin(tauri_plugin_upload::init())
            .run(tauri::generate_context!())
            .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-upload
        
      • yarn

        yarn add @tauri-apps/plugin-upload
        
      • pnpm

        pnpm add @tauri-apps/plugin-upload
        
      • deno

        deno add npm:@tauri-apps/plugin-upload
        
      • bun

        bun add @tauri-apps/plugin-upload
        
  • npm

    npm install @tauri-apps/plugin-upload
    
  • yarn

    yarn add @tauri-apps/plugin-upload
    
  • pnpm

    pnpm add @tauri-apps/plugin-upload
    
  • deno

    deno add npm:@tauri-apps/plugin-upload
    
  • bun

    bun add @tauri-apps/plugin-upload
    

Usage

Once youve completed the registration and setup process for the plugin, you can access all of its APIs through the JavaScript guest bindings.

Heres an example of how you can use the plugin to upload and download files:

import { upload } from '@tauri-apps/plugin-upload';
// when using `"withGlobalTauri": true`, you may use
// const { upload } = window.__TAURI__.upload;


upload(
  'https://example.com/file-upload',
  './path/to/my/file.txt',
  ({ progress, total }) =>
    console.log(`Uploaded ${progress} of ${total} bytes`), // a callback that will be called with the upload progress
  { 'Content-Type': 'text/plain' } // optional headers to send with the request
);
import { download } from '@tauri-apps/plugin-upload';
// when using `"withGlobalTauri": true`, you may use
// const { download } = window.__TAURI__.upload;


download(
  'https://example.com/file-download-link',
  './path/to/save/my/file.txt',
  ({ progress, total }) =>
    console.log(`Downloaded ${progress} of ${total} bytes`), // a callback that will be called with the download progress
  { 'Content-Type': 'text/plain' } // optional headers to send with the request
);

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "permissions": [
    ...,
    +"upload:default",
  ]
}

Default Permission

This permission set configures what kind of operations are available from the upload plugin.

Granted Permissions

All operations are enabled by default.

This default permission set includes the following:

  • allow-upload
  • allow-download

Permission Table

Identifier Description
upload:allow-download Enables the download command without any pre-configured scope.
upload:deny-download Denies the download command without any pre-configured scope.
upload:allow-upload Enables the upload command without any pre-configured scope.
upload:deny-upload Denies the upload command without any pre-configured scope.

Websocket

Open a WebSocket connection using a Rust client in JavaScript.

GitHubnpmcrates.io

API Reference:

Open a WebSocket connection using a Rust client in JavaScript.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the websocket plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add websocket
      
    • yarn

      yarn run tauri add websocket
      
    • pnpm

      pnpm tauri add websocket
      
    • deno

      deno task tauri add websocket
      
    • bun

      bun tauri add websocket
      
    • cargo

      cargo tauri add websocket
      
  • Manual

    npm run tauri add websocket
    
  • npm

    yarn run tauri add websocket
    
  • yarn

    pnpm tauri add websocket
    
  • pnpm

    deno task tauri add websocket
    
  • deno

    bun tauri add websocket
    
  • bun

    cargo tauri add websocket
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-websocket
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.plugin(tauri_plugin_websocket::init())
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-websocket
        
      • yarn

        yarn add @tauri-apps/plugin-websocket
        
      • pnpm

        pnpm add @tauri-apps/plugin-websocket
        
      • deno

        deno add npm:@tauri-apps/plugin-websocket
        
      • bun

        bun add @tauri-apps/plugin-websocket
        
  • npm

    npm install @tauri-apps/plugin-websocket
    
  • yarn

    yarn add @tauri-apps/plugin-websocket
    
  • pnpm

    pnpm add @tauri-apps/plugin-websocket
    
  • deno

    deno add npm:@tauri-apps/plugin-websocket
    
  • bun

    bun add @tauri-apps/plugin-websocket
    

Usage

The websocket plugin is available in JavaScript.

import WebSocket from '@tauri-apps/plugin-websocket';
// when using `"withGlobalTauri": true`, you may use
// const WebSocket = window.__TAURI__.websocket;


const ws = await WebSocket.connect('ws://127.0.0.1:8080');


const removeListener = ws.addListener((msg) => {
  console.log('Received Message:', msg);
});


await ws.send('Hello World!');


// optionally remove the listener
removeListener();


await ws.disconnect();

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  +"permissions": ["websocket:default"]
}

Default Permission

Allows connecting and sending data to a WebSocket server

This default permission set includes the following:

  • allow-connect
  • allow-send

Permission Table

Identifier Description
websocket:allow-connect Enables the connect command without any pre-configured scope.
websocket:deny-connect Denies the connect command without any pre-configured scope.
websocket:allow-send Enables the send command without any pre-configured scope.
websocket:deny-send Denies the send command without any pre-configured scope.

Window State

Persist window sizes and positions.

GitHubnpmcrates.io

API Reference:

Save window positions and sizes and restore them when the app is reopened.

Supported Platforms

This plugin requires a Rust version of at least 1.77.2

Platform Level Notes
windows
linux
macos
android
ios

Setup

Install the window-state plugin to get started.

  • Automatic

    Use your projects package manager to add the dependency:

    • npm

      npm run tauri add window-state
      
    • yarn

      yarn run tauri add window-state
      
    • pnpm

      pnpm tauri add window-state
      
    • deno

      deno task tauri add window-state
      
    • bun

      bun tauri add window-state
      
    • cargo

      cargo tauri add window-state
      
  • Manual

    npm run tauri add window-state
    
  • npm

    yarn run tauri add window-state
    
  • yarn

    pnpm tauri add window-state
    
  • pnpm

    deno task tauri add window-state
    
  • deno

    bun tauri add window-state
    
  • bun

    cargo tauri add window-state
    
  • cargo

    1. Run the following command in the src-tauri folder to add the plugin to the projects dependencies in Cargo.toml:

      cargo add tauri-plugin-window-state --target 'cfg(any(target_os = "macos", windows, target_os = "linux"))'
      
    2. Modify lib.rs to initialize the plugin:

      src-tauri/src/lib.rs

      #[cfg_attr(mobile, tauri::mobile_entry_point)]
      pub fn run() {
          tauri::Builder::default()
              +.setup(|app| {
                  #[cfg(desktop)]
                  app.handle().plugin(tauri_plugin_window_state::Builder::default().build());
                  Ok(())
              })
              .run(tauri::generate_context!())
              .expect("error while running tauri application");
      }
      
    3. Install the JavaScript Guest bindings using your preferred JavaScript package manager:

      • npm

        npm install @tauri-apps/plugin-window-state
        
      • yarn

        yarn add @tauri-apps/plugin-window-state
        
      • pnpm

        pnpm add @tauri-apps/plugin-window-state
        
      • deno

        deno add npm:@tauri-apps/plugin-window-state
        
      • bun

        bun add @tauri-apps/plugin-window-state
        
  • npm

    npm install @tauri-apps/plugin-window-state
    
  • yarn

    yarn add @tauri-apps/plugin-window-state
    
  • pnpm

    pnpm add @tauri-apps/plugin-window-state
    
  • deno

    deno add npm:@tauri-apps/plugin-window-state
    
  • bun

    bun add @tauri-apps/plugin-window-state
    

Usage

After adding the window-state plugin, all windows will remember their state when the app is being closed and will restore to their previous state on the next launch.

You can also access the window-state plugin in both JavaScript and Rust.

Tip

Restoring the state will happen after window creation, so to prevent the window from flashing, you can set visible to false when creating the window, the plugin will show the window when it restores the state

JavaScript

You can use saveWindowState to manually save the window state:

import { saveWindowState, StateFlags } from '@tauri-apps/plugin-window-state';
// when using `"withGlobalTauri": true`, you may use
// const { saveWindowState, StateFlags } = window.__TAURI__.windowState;


saveWindowState(StateFlags.ALL);

Similarly you can manually restore a windows state from disk:

import {
  restoreStateCurrent,
  StateFlags,
} from '@tauri-apps/plugin-window-state';
// when using `"withGlobalTauri": true`, you may use
// const { restoreStateCurrent, StateFlags } = window.__TAURI__.windowState;


restoreStateCurrent(StateFlags.ALL);

Rust

You can use the save_window_state() method exposed by the AppHandleExt trait:

use tauri_plugin_window_state::{AppHandleExt, StateFlags};


// `tauri::AppHandle` now has the following additional method
app.save_window_state(StateFlags::all()); // will save the state of all open windows to disk

Similarly you can manually restore a windows state from disk using the restore_state() method exposed by the WindowExt trait:

use tauri_plugin_window_state::{WindowExt, StateFlags};


// all `Window` types now have the following additional method
window.restore_state(StateFlags::all()); // will restore the window's state from disk

Permissions

By default all potentially dangerous plugin commands and scopes are blocked and cannot be accessed. You must modify the permissions in your capabilities configuration to enable these.

See the Capabilities Overview for more information and the step by step guide to use plugin permissions.

src-tauri/capabilities/default.json

{
  "permissions": [
    ...,
    +"window-state:default",
  ]
}

Default Permission

This permission set configures what kind of operations are available from the window state plugin.

Granted Permissions

All operations are enabled by default.

This default permission set includes the following:

  • allow-filename
  • allow-restore-state
  • allow-save-window-state

Permission Table

Identifier Description
window-state:allow-filename Enables the filename command without any pre-configured scope.
window-state:deny-filename Denies the filename command without any pre-configured scope.
window-state:allow-restore-state Enables the restore_state command without any pre-configured scope.
window-state:deny-restore-state Denies the restore_state command without any pre-configured scope.
window-state:allow-save-window-state Enables the save_window_state command without any pre-configured scope.
window-state:deny-save-window-state Denies the save_window_state command without any pre-configured scope.

Capability

A grouping and boundary mechanism developers can use to isolate access to the IPC layer.

It controls application windows and webviews fine grained access to the Tauri core, application, or plugin commands. If a webview or its window is not matching any capability then it has no access to the IPC layer at all.

This can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. main-window) or glob patterns like * or admin-*. A Window can have none, one, or multiple associated capabilities.

Example

{
  "identifier": "main-user-files-write",
  "description": "This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.",
  "windows": [
    "main"
  ],
  "permissions": [
    "core:default",
    "dialog:open",
    {
      "identifier": "fs:allow-write-text-file",
      "allow": [{ "path": "$HOME/test.txt" }]
    },
  ],
  "platforms": ["macOS","windows"]
}

Object Properties:

  • description
  • identifier (required)
  • local
  • permissions (required)
  • platforms
  • remote
  • webviews
  • windows

description

string

Description of what the capability is intended to allow on associated windows.

It should contain a description of what the grouped permissions should allow.

Example

This capability allows the main window access to filesystem write related commands and dialog commands to enable programmatic access to files selected by the user.

identifier

string

Identifier of the capability.

Example

main-user-files-write

local

boolean

Whether this capability is enabled for local app URLs or not. Defaults to true.

Default: true

permissions

PermissionEntry[] each item must be unique

List of permissions attached to this capability.

Must include the plugin name as prefix in the form of ${plugin-name}:${permission-name}. For commands directly implemented in the application itself only ${permission-name} is required.

Example

[
  "core:default",
  "shell:allow-open",
  "dialog:open",
  {
    "identifier": "fs:allow-write-text-file",
    "allow": [{ "path": "$HOME/test.txt" }]
  }
]

platforms

Target[] | null

Limit which target platforms this capability applies to.

By default all platforms are targeted.

Example

["macOS","windows"]

remote

CapabilityRemote | null

Configure remote URLs that can use the capability permissions.

This setting is optional and defaults to not being set, as our default use case is that the content is served from our local application.

Caution

Make sure you understand the security implications of providing remote sources with local system access.

Example

{
  "urls": ["https://*.mydomain.dev"]
}

webviews

string[]

List of webviews that are affected by this capability. Can be a glob pattern.

The capability will be enabled on all the webviews whose label matches any of the patterns in this list, regardless of whether the webviews window label matches a pattern in [Self::windows].

Example

["sub-webview-one", "sub-webview-two"]

windows

string[]

List of windows that are affected by this capability. Can be a glob pattern.

If a window label matches any of the patterns in this list, the capability will be enabled on all the webviews of that window, regardless of the value of [Self::webviews].

On multiwebview windows, prefer specifying [Self::webviews] and omitting [Self::windows] for a fine grained access control.

Example

["main"]

Definitions

CapabilityRemote

Configuration for remote URLs that are associated with the capability.

Object Properties:

  • urls (required)
urls

string[]

Remote domains this capability refers to using the URLPattern standard.

Examples

Identifier

string

Number

Any of the following:

  • integer formatted as int64 Represents an [i64].
  • number formatted as double Represents a [f64].

A valid ACL number.

PermissionEntry

Any of the following:

  • Identifier Reference a permission or permission set by identifier.
  • Reference a permission or permission set by identifier and extends its scope. Object Properties: - allow - deny - identifier (required) ##### allow Value[] | null Data that defines what is allowed by the scope. ##### deny Value[] | null Data that defines what is denied by the scope. This should be prioritized by validation logic. ##### identifier Identifier Identifier of the permission or permission set.

An entry for a permission value in a [Capability] can be either a raw permission [Identifier] or an object that references a permission and extends its scope.

Target

One of the following:

  • "macOS" MacOS.
  • "windows" Windows.
  • "linux" Linux.
  • "android" Android.
  • "iOS" iOS.

Platform target.

Value

Any of the following:

  • null Represents a null JSON value.
  • boolean Represents a [bool].
  • Number Represents a valid ACL [Number].
  • string Represents a [String].
  • Value[] Represents a list of other [Value]s.
  • Represents a map of [String] keys to [Value]s. Allows additional properties: Value

All supported ACL values.

Core Permissions

A list of all permissions that can be used with the core of the Tauri framework.

If you are looking for permissions to specific Tauri plugins, please refer to the Plugins section of the documentation.

Default Permissions

The core:default permission in Tauri automatically adds:

  • core:app:default
  • core:event:default
  • core:image:default
  • core:menu:default
  • core:path:default
  • core:resources:default
  • core:tray:default
  • core:webview:default
  • core:window:default

App

Default Permission

The default permission, core:app:default, includes the following:

  • allow-version
  • allow-name
  • allow-tauri-version
  • allow-identifier
  • allow-bundle-type
  • allow-register-listener
  • allow-remove-listener
  • allow-supports-multiple-windows

Permission Table

Identifier Description
core:app:allow-app-hide Enables the app_hide command without any pre-configured scope.
core:app:deny-app-hide Denies the app_hide command without any pre-configured scope.
core:app:allow-app-show Enables the app_show command without any pre-configured scope.
core:app:deny-app-show Denies the app_show command without any pre-configured scope.
core:app:allow-bundle-type Enables the bundle_type command without any pre-configured scope.
core:app:deny-bundle-type Denies the bundle_type command without any pre-configured scope.
core:app:allow-default-window-icon Enables the default_window_icon command without any pre-configured scope.
core:app:deny-default-window-icon Denies the default_window_icon command without any pre-configured scope.
core:app:allow-fetch-data-store-identifiers Enables the fetch_data_store_identifiers command without any pre-configured scope.
core:app:deny-fetch-data-store-identifiers Denies the fetch_data_store_identifiers command without any pre-configured scope.
core:app:allow-identifier Enables the identifier command without any pre-configured scope.
core:app:deny-identifier Denies the identifier command without any pre-configured scope.
core:app:allow-name Enables the name command without any pre-configured scope.
core:app:deny-name Denies the name command without any pre-configured scope.
core:app:allow-register-listener Enables the register_listener command without any pre-configured scope.
core:app:deny-register-listener Denies the register_listener command without any pre-configured scope.
core:app:allow-remove-data-store Enables the remove_data_store command without any pre-configured scope.
core:app:deny-remove-data-store Denies the remove_data_store command without any pre-configured scope.
core:app:allow-remove-listener Enables the remove_listener command without any pre-configured scope.
core:app:deny-remove-listener Denies the remove_listener command without any pre-configured scope.
core:app:allow-set-app-theme Enables the set_app_theme command without any pre-configured scope.
core:app:deny-set-app-theme Denies the set_app_theme command without any pre-configured scope.
core:app:allow-set-dock-visibility Enables the set_dock_visibility command without any pre-configured scope.
core:app:deny-set-dock-visibility Denies the set_dock_visibility command without any pre-configured scope.
core:app:allow-supports-multiple-windows Enables the supports_multiple_windows command without any pre-configured scope.
core:app:deny-supports-multiple-windows Denies the supports_multiple_windows command without any pre-configured scope.
core:app:allow-tauri-version Enables the tauri_version command without any pre-configured scope.
core:app:deny-tauri-version Denies the tauri_version command without any pre-configured scope.
core:app:allow-version Enables the version command without any pre-configured scope.
core:app:deny-version Denies the version command without any pre-configured scope.

Event

Default Permission

The default permission, core:event:default, includes the following:

  • allow-listen
  • allow-unlisten
  • allow-emit
  • allow-emit-to

Permission Table

Identifier Description
core:event:allow-emit Enables the emit command without any pre-configured scope.
core:event:deny-emit Denies the emit command without any pre-configured scope.
core:event:allow-emit-to Enables the emit_to command without any pre-configured scope.
core:event:deny-emit-to Denies the emit_to command without any pre-configured scope.
core:event:allow-listen Enables the listen command without any pre-configured scope.
core:event:deny-listen Denies the listen command without any pre-configured scope.
core:event:allow-unlisten Enables the unlisten command without any pre-configured scope.
core:event:deny-unlisten Denies the unlisten command without any pre-configured scope.

Image

Default Permission

The default permission, core:image:default, includes the following:

  • allow-new
  • allow-from-bytes
  • allow-from-path
  • allow-rgba
  • allow-size

Permission Table

Identifier Description
core:image:allow-from-bytes Enables the from_bytes command without any pre-configured scope.
core:image:deny-from-bytes Denies the from_bytes command without any pre-configured scope.
core:image:allow-from-path Enables the from_path command without any pre-configured scope.
core:image:deny-from-path Denies the from_path command without any pre-configured scope.
core:image:allow-new Enables the new command without any pre-configured scope.
core:image:deny-new Denies the new command without any pre-configured scope.
core:image:allow-rgba Enables the rgba command without any pre-configured scope.
core:image:deny-rgba Denies the rgba command without any pre-configured scope.
core:image:allow-size Enables the size command without any pre-configured scope.
core:image:deny-size Denies the size command without any pre-configured scope.

Menu

Default Permission

The default permission, core:menu:default, includes the following:

  • allow-new
  • allow-append
  • allow-prepend
  • allow-insert
  • allow-remove
  • allow-remove-at
  • allow-items
  • allow-get
  • allow-popup
  • allow-create-default
  • allow-set-as-app-menu
  • allow-set-as-window-menu
  • allow-text
  • allow-set-text
  • allow-is-enabled
  • allow-set-enabled
  • allow-set-accelerator
  • allow-set-as-windows-menu-for-nsapp
  • allow-set-as-help-menu-for-nsapp
  • allow-is-checked
  • allow-set-checked
  • allow-set-icon

Permission Table

Identifier Description
core:menu:allow-append Enables the append command without any pre-configured scope.
core:menu:deny-append Denies the append command without any pre-configured scope.
core:menu:allow-create-default Enables the create_default command without any pre-configured scope.
core:menu:deny-create-default Denies the create_default command without any pre-configured scope.
core:menu:allow-get Enables the get command without any pre-configured scope.
core:menu:deny-get Denies the get command without any pre-configured scope.
core:menu:allow-insert Enables the insert command without any pre-configured scope.
core:menu:deny-insert Denies the insert command without any pre-configured scope.
core:menu:allow-is-checked Enables the is_checked command without any pre-configured scope.
core:menu:deny-is-checked Denies the is_checked command without any pre-configured scope.
core:menu:allow-is-enabled Enables the is_enabled command without any pre-configured scope.
core:menu:deny-is-enabled Denies the is_enabled command without any pre-configured scope.
core:menu:allow-items Enables the items command without any pre-configured scope.
core:menu:deny-items Denies the items command without any pre-configured scope.
core:menu:allow-new Enables the new command without any pre-configured scope.
core:menu:deny-new Denies the new command without any pre-configured scope.
core:menu:allow-popup Enables the popup command without any pre-configured scope.
core:menu:deny-popup Denies the popup command without any pre-configured scope.
core:menu:allow-prepend Enables the prepend command without any pre-configured scope.
core:menu:deny-prepend Denies the prepend command without any pre-configured scope.
core:menu:allow-remove Enables the remove command without any pre-configured scope.
core:menu:deny-remove Denies the remove command without any pre-configured scope.
core:menu:allow-remove-at Enables the remove_at command without any pre-configured scope.
core:menu:deny-remove-at Denies the remove_at command without any pre-configured scope.
core:menu:allow-set-accelerator Enables the set_accelerator command without any pre-configured scope.
core:menu:deny-set-accelerator Denies the set_accelerator command without any pre-configured scope.
core:menu:allow-set-as-app-menu Enables the set_as_app_menu command without any pre-configured scope.
core:menu:deny-set-as-app-menu Denies the set_as_app_menu command without any pre-configured scope.
core:menu:allow-set-as-help-menu-for-nsapp Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.
core:menu:deny-set-as-help-menu-for-nsapp Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.
core:menu:allow-set-as-window-menu Enables the set_as_window_menu command without any pre-configured scope.
core:menu:deny-set-as-window-menu Denies the set_as_window_menu command without any pre-configured scope.
core:menu:allow-set-as-windows-menu-for-nsapp Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.
core:menu:deny-set-as-windows-menu-for-nsapp Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.
core:menu:allow-set-checked Enables the set_checked command without any pre-configured scope.
core:menu:deny-set-checked Denies the set_checked command without any pre-configured scope.
core:menu:allow-set-enabled Enables the set_enabled command without any pre-configured scope.
core:menu:deny-set-enabled Denies the set_enabled command without any pre-configured scope.
core:menu:allow-set-icon Enables the set_icon command without any pre-configured scope.
core:menu:deny-set-icon Denies the set_icon command without any pre-configured scope.
core:menu:allow-set-text Enables the set_text command without any pre-configured scope.
core:menu:deny-set-text Denies the set_text command without any pre-configured scope.
core:menu:allow-text Enables the text command without any pre-configured scope.
core:menu:deny-text Denies the text command without any pre-configured scope.

Path

Default Permission

The default permission, core:path:default, includes the following:

  • allow-resolve-directory
  • allow-resolve
  • allow-normalize
  • allow-join
  • allow-dirname
  • allow-extname
  • allow-basename
  • allow-is-absolute

Permission Table

Identifier Description
core:path:allow-basename Enables the basename command without any pre-configured scope.
core:path:deny-basename Denies the basename command without any pre-configured scope.
core:path:allow-dirname Enables the dirname command without any pre-configured scope.
core:path:deny-dirname Denies the dirname command without any pre-configured scope.
core:path:allow-extname Enables the extname command without any pre-configured scope.
core:path:deny-extname Denies the extname command without any pre-configured scope.
core:path:allow-is-absolute Enables the is_absolute command without any pre-configured scope.
core:path:deny-is-absolute Denies the is_absolute command without any pre-configured scope.
core:path:allow-join Enables the join command without any pre-configured scope.
core:path:deny-join Denies the join command without any pre-configured scope.
core:path:allow-normalize Enables the normalize command without any pre-configured scope.
core:path:deny-normalize Denies the normalize command without any pre-configured scope.
core:path:allow-resolve Enables the resolve command without any pre-configured scope.
core:path:deny-resolve Denies the resolve command without any pre-configured scope.
core:path:allow-resolve-directory Enables the resolve_directory command without any pre-configured scope.
core:path:deny-resolve-directory Denies the resolve_directory command without any pre-configured scope.

Resources

Default Permission

The default permission, core:resources:default, includes the following:

  • allow-close

Permission Table

Identifier Description
core:resources:allow-close Enables the close command without any pre-configured scope.
core:resources:deny-close Denies the close command without any pre-configured scope.

Tray

Default Permission

The default permission, core:tray:default, includes the following:

  • allow-new
  • allow-get-by-id
  • allow-remove-by-id
  • allow-set-icon
  • allow-set-menu
  • allow-set-tooltip
  • allow-set-title
  • allow-set-visible
  • allow-set-temp-dir-path
  • allow-set-icon-as-template
  • allow-set-icon-with-as-template
  • allow-set-show-menu-on-left-click

Permission Table

Identifier Description
core:tray:allow-get-by-id Enables the get_by_id command without any pre-configured scope.
core:tray:deny-get-by-id Denies the get_by_id command without any pre-configured scope.
core:tray:allow-new Enables the new command without any pre-configured scope.
core:tray:deny-new Denies the new command without any pre-configured scope.
core:tray:allow-remove-by-id Enables the remove_by_id command without any pre-configured scope.
core:tray:deny-remove-by-id Denies the remove_by_id command without any pre-configured scope.
core:tray:allow-set-icon Enables the set_icon command without any pre-configured scope.
core:tray:deny-set-icon Denies the set_icon command without any pre-configured scope.
core:tray:allow-set-icon-as-template Enables the set_icon_as_template command without any pre-configured scope.
core:tray:deny-set-icon-as-template Denies the set_icon_as_template command without any pre-configured scope.
core:tray:allow-set-icon-with-as-template Enables the set_icon_with_as_template command without any pre-configured scope.
core:tray:deny-set-icon-with-as-template Denies the set_icon_with_as_template command without any pre-configured scope.
core:tray:allow-set-menu Enables the set_menu command without any pre-configured scope.
core:tray:deny-set-menu Denies the set_menu command without any pre-configured scope.
core:tray:allow-set-show-menu-on-left-click Enables the set_show_menu_on_left_click command without any pre-configured scope.
core:tray:deny-set-show-menu-on-left-click Denies the set_show_menu_on_left_click command without any pre-configured scope.
core:tray:allow-set-temp-dir-path Enables the set_temp_dir_path command without any pre-configured scope.
core:tray:deny-set-temp-dir-path Denies the set_temp_dir_path command without any pre-configured scope.
core:tray:allow-set-title Enables the set_title command without any pre-configured scope.
core:tray:deny-set-title Denies the set_title command without any pre-configured scope.
core:tray:allow-set-tooltip Enables the set_tooltip command without any pre-configured scope.
core:tray:deny-set-tooltip Denies the set_tooltip command without any pre-configured scope.
core:tray:allow-set-visible Enables the set_visible command without any pre-configured scope.
core:tray:deny-set-visible Denies the set_visible command without any pre-configured scope.

Webview

Default Permission

The default permission, core:webview:default, includes the following:

  • allow-get-all-webviews
  • allow-webview-position
  • allow-webview-size
  • allow-internal-toggle-devtools

Permission Table

Identifier Description
core:webview:allow-clear-all-browsing-data Enables the clear_all_browsing_data command without any pre-configured scope.
core:webview:deny-clear-all-browsing-data Denies the clear_all_browsing_data command without any pre-configured scope.
core:webview:allow-create-webview Enables the create_webview command without any pre-configured scope.
core:webview:deny-create-webview Denies the create_webview command without any pre-configured scope.
core:webview:allow-create-webview-window Enables the create_webview_window command without any pre-configured scope.
core:webview:deny-create-webview-window Denies the create_webview_window command without any pre-configured scope.
core:webview:allow-get-all-webviews Enables the get_all_webviews command without any pre-configured scope.
core:webview:deny-get-all-webviews Denies the get_all_webviews command without any pre-configured scope.
core:webview:allow-internal-toggle-devtools Enables the internal_toggle_devtools command without any pre-configured scope.
core:webview:deny-internal-toggle-devtools Denies the internal_toggle_devtools command without any pre-configured scope.
core:webview:allow-print Enables the print command without any pre-configured scope.
core:webview:deny-print Denies the print command without any pre-configured scope.
core:webview:allow-reparent Enables the reparent command without any pre-configured scope.
core:webview:deny-reparent Denies the reparent command without any pre-configured scope.
core:webview:allow-set-webview-auto-resize Enables the set_webview_auto_resize command without any pre-configured scope.
core:webview:deny-set-webview-auto-resize Denies the set_webview_auto_resize command without any pre-configured scope.
core:webview:allow-set-webview-background-color Enables the set_webview_background_color command without any pre-configured scope.
core:webview:deny-set-webview-background-color Denies the set_webview_background_color command without any pre-configured scope.
core:webview:allow-set-webview-focus Enables the set_webview_focus command without any pre-configured scope.
core:webview:deny-set-webview-focus Denies the set_webview_focus command without any pre-configured scope.
core:webview:allow-set-webview-position Enables the set_webview_position command without any pre-configured scope.
core:webview:deny-set-webview-position Denies the set_webview_position command without any pre-configured scope.
core:webview:allow-set-webview-size Enables the set_webview_size command without any pre-configured scope.
core:webview:deny-set-webview-size Denies the set_webview_size command without any pre-configured scope.
core:webview:allow-set-webview-zoom Enables the set_webview_zoom command without any pre-configured scope.
core:webview:deny-set-webview-zoom Denies the set_webview_zoom command without any pre-configured scope.
core:webview:allow-webview-close Enables the webview_close command without any pre-configured scope.
core:webview:deny-webview-close Denies the webview_close command without any pre-configured scope.
core:webview:allow-webview-hide Enables the webview_hide command without any pre-configured scope.
core:webview:deny-webview-hide Denies the webview_hide command without any pre-configured scope.
core:webview:allow-webview-position Enables the webview_position command without any pre-configured scope.
core:webview:deny-webview-position Denies the webview_position command without any pre-configured scope.
core:webview:allow-webview-show Enables the webview_show command without any pre-configured scope.
core:webview:deny-webview-show Denies the webview_show command without any pre-configured scope.
core:webview:allow-webview-size Enables the webview_size command without any pre-configured scope.
core:webview:deny-webview-size Denies the webview_size command without any pre-configured scope.

Window

Default Permission

The default permission, core:window:default, includes the following:

  • allow-get-all-windows
  • allow-scale-factor
  • allow-inner-position
  • allow-outer-position
  • allow-inner-size
  • allow-outer-size
  • allow-is-fullscreen
  • allow-is-minimized
  • allow-is-maximized
  • allow-is-focused
  • allow-is-decorated
  • allow-is-resizable
  • allow-is-maximizable
  • allow-is-minimizable
  • allow-is-closable
  • allow-is-visible
  • allow-is-enabled
  • allow-title
  • allow-current-monitor
  • allow-primary-monitor
  • allow-monitor-from-point
  • allow-available-monitors
  • allow-cursor-position
  • allow-theme
  • allow-is-always-on-top
  • allow-activity-name
  • allow-scene-identifier
  • allow-internal-toggle-maximize

Permission Table

Identifier Description
core:window:allow-activity-name Enables the activity_name command without any pre-configured scope.
core:window:deny-activity-name Denies the activity_name command without any pre-configured scope.
core:window:allow-available-monitors Enables the available_monitors command without any pre-configured scope.
core:window:deny-available-monitors Denies the available_monitors command without any pre-configured scope.
core:window:allow-center Enables the center command without any pre-configured scope.
core:window:deny-center Denies the center command without any pre-configured scope.
core:window:allow-close Enables the close command without any pre-configured scope.
core:window:deny-close Denies the close command without any pre-configured scope.
core:window:allow-create Enables the create command without any pre-configured scope.
core:window:deny-create Denies the create command without any pre-configured scope.
core:window:allow-current-monitor Enables the current_monitor command without any pre-configured scope.
core:window:deny-current-monitor Denies the current_monitor command without any pre-configured scope.
core:window:allow-cursor-position Enables the cursor_position command without any pre-configured scope.
core:window:deny-cursor-position Denies the cursor_position command without any pre-configured scope.
core:window:allow-destroy Enables the destroy command without any pre-configured scope.
core:window:deny-destroy Denies the destroy command without any pre-configured scope.
core:window:allow-get-all-windows Enables the get_all_windows command without any pre-configured scope.
core:window:deny-get-all-windows Denies the get_all_windows command without any pre-configured scope.
core:window:allow-hide Enables the hide command without any pre-configured scope.
core:window:deny-hide Denies the hide command without any pre-configured scope.
core:window:allow-inner-position Enables the inner_position command without any pre-configured scope.
core:window:deny-inner-position Denies the inner_position command without any pre-configured scope.
core:window:allow-inner-size Enables the inner_size command without any pre-configured scope.
core:window:deny-inner-size Denies the inner_size command without any pre-configured scope.
core:window:allow-internal-toggle-maximize Enables the internal_toggle_maximize command without any pre-configured scope.
core:window:deny-internal-toggle-maximize Denies the internal_toggle_maximize command without any pre-configured scope.
core:window:allow-is-always-on-top Enables the is_always_on_top command without any pre-configured scope.
core:window:deny-is-always-on-top Denies the is_always_on_top command without any pre-configured scope.
core:window:allow-is-closable Enables the is_closable command without any pre-configured scope.
core:window:deny-is-closable Denies the is_closable command without any pre-configured scope.
core:window:allow-is-decorated Enables the is_decorated command without any pre-configured scope.
core:window:deny-is-decorated Denies the is_decorated command without any pre-configured scope.
core:window:allow-is-enabled Enables the is_enabled command without any pre-configured scope.
core:window:deny-is-enabled Denies the is_enabled command without any pre-configured scope.
core:window:allow-is-focused Enables the is_focused command without any pre-configured scope.
core:window:deny-is-focused Denies the is_focused command without any pre-configured scope.
core:window:allow-is-fullscreen Enables the is_fullscreen command without any pre-configured scope.
core:window:deny-is-fullscreen Denies the is_fullscreen command without any pre-configured scope.
core:window:allow-is-maximizable Enables the is_maximizable command without any pre-configured scope.
core:window:deny-is-maximizable Denies the is_maximizable command without any pre-configured scope.
core:window:allow-is-maximized Enables the is_maximized command without any pre-configured scope.
core:window:deny-is-maximized Denies the is_maximized command without any pre-configured scope.
core:window:allow-is-minimizable Enables the is_minimizable command without any pre-configured scope.
core:window:deny-is-minimizable Denies the is_minimizable command without any pre-configured scope.
core:window:allow-is-minimized Enables the is_minimized command without any pre-configured scope.
core:window:deny-is-minimized Denies the is_minimized command without any pre-configured scope.
core:window:allow-is-resizable Enables the is_resizable command without any pre-configured scope.
core:window:deny-is-resizable Denies the is_resizable command without any pre-configured scope.
core:window:allow-is-visible Enables the is_visible command without any pre-configured scope.
core:window:deny-is-visible Denies the is_visible command without any pre-configured scope.
core:window:allow-maximize Enables the maximize command without any pre-configured scope.
core:window:deny-maximize Denies the maximize command without any pre-configured scope.
core:window:allow-minimize Enables the minimize command without any pre-configured scope.
core:window:deny-minimize Denies the minimize command without any pre-configured scope.
core:window:allow-monitor-from-point Enables the monitor_from_point command without any pre-configured scope.
core:window:deny-monitor-from-point Denies the monitor_from_point command without any pre-configured scope.
core:window:allow-outer-position Enables the outer_position command without any pre-configured scope.
core:window:deny-outer-position Denies the outer_position command without any pre-configured scope.
core:window:allow-outer-size Enables the outer_size command without any pre-configured scope.
core:window:deny-outer-size Denies the outer_size command without any pre-configured scope.
core:window:allow-primary-monitor Enables the primary_monitor command without any pre-configured scope.
core:window:deny-primary-monitor Denies the primary_monitor command without any pre-configured scope.
core:window:allow-request-user-attention Enables the request_user_attention command without any pre-configured scope.
core:window:deny-request-user-attention Denies the request_user_attention command without any pre-configured scope.
core:window:allow-scale-factor Enables the scale_factor command without any pre-configured scope.
core:window:deny-scale-factor Denies the scale_factor command without any pre-configured scope.
core:window:allow-scene-identifier Enables the scene_identifier command without any pre-configured scope.
core:window:deny-scene-identifier Denies the scene_identifier command without any pre-configured scope.
core:window:allow-set-always-on-bottom Enables the set_always_on_bottom command without any pre-configured scope.
core:window:deny-set-always-on-bottom Denies the set_always_on_bottom command without any pre-configured scope.
core:window:allow-set-always-on-top Enables the set_always_on_top command without any pre-configured scope.
core:window:deny-set-always-on-top Denies the set_always_on_top command without any pre-configured scope.
core:window:allow-set-background-color Enables the set_background_color command without any pre-configured scope.
core:window:deny-set-background-color Denies the set_background_color command without any pre-configured scope.
core:window:allow-set-badge-count Enables the set_badge_count command without any pre-configured scope.
core:window:deny-set-badge-count Denies the set_badge_count command without any pre-configured scope.
core:window:allow-set-badge-label Enables the set_badge_label command without any pre-configured scope.
core:window:deny-set-badge-label Denies the set_badge_label command without any pre-configured scope.
core:window:allow-set-closable Enables the set_closable command without any pre-configured scope.
core:window:deny-set-closable Denies the set_closable command without any pre-configured scope.
core:window:allow-set-content-protected Enables the set_content_protected command without any pre-configured scope.
core:window:deny-set-content-protected Denies the set_content_protected command without any pre-configured scope.
core:window:allow-set-cursor-grab Enables the set_cursor_grab command without any pre-configured scope.
core:window:deny-set-cursor-grab Denies the set_cursor_grab command without any pre-configured scope.
core:window:allow-set-cursor-icon Enables the set_cursor_icon command without any pre-configured scope.
core:window:deny-set-cursor-icon Denies the set_cursor_icon command without any pre-configured scope.
core:window:allow-set-cursor-position Enables the set_cursor_position command without any pre-configured scope.
core:window:deny-set-cursor-position Denies the set_cursor_position command without any pre-configured scope.
core:window:allow-set-cursor-visible Enables the set_cursor_visible command without any pre-configured scope.
core:window:deny-set-cursor-visible Denies the set_cursor_visible command without any pre-configured scope.
core:window:allow-set-decorations Enables the set_decorations command without any pre-configured scope.
core:window:deny-set-decorations Denies the set_decorations command without any pre-configured scope.
core:window:allow-set-effects Enables the set_effects command without any pre-configured scope.
core:window:deny-set-effects Denies the set_effects command without any pre-configured scope.
core:window:allow-set-enabled Enables the set_enabled command without any pre-configured scope.
core:window:deny-set-enabled Denies the set_enabled command without any pre-configured scope.
core:window:allow-set-focus Enables the set_focus command without any pre-configured scope.
core:window:deny-set-focus Denies the set_focus command without any pre-configured scope.
core:window:allow-set-focusable Enables the set_focusable command without any pre-configured scope.
core:window:deny-set-focusable Denies the set_focusable command without any pre-configured scope.
core:window:allow-set-fullscreen Enables the set_fullscreen command without any pre-configured scope.
core:window:deny-set-fullscreen Denies the set_fullscreen command without any pre-configured scope.
core:window:allow-set-icon Enables the set_icon command without any pre-configured scope.
core:window:deny-set-icon Denies the set_icon command without any pre-configured scope.
core:window:allow-set-ignore-cursor-events Enables the set_ignore_cursor_events command without any pre-configured scope.
core:window:deny-set-ignore-cursor-events Denies the set_ignore_cursor_events command without any pre-configured scope.
core:window:allow-set-max-size Enables the set_max_size command without any pre-configured scope.
core:window:deny-set-max-size Denies the set_max_size command without any pre-configured scope.
core:window:allow-set-maximizable Enables the set_maximizable command without any pre-configured scope.
core:window:deny-set-maximizable Denies the set_maximizable command without any pre-configured scope.
core:window:allow-set-min-size Enables the set_min_size command without any pre-configured scope.
core:window:deny-set-min-size Denies the set_min_size command without any pre-configured scope.
core:window:allow-set-minimizable Enables the set_minimizable command without any pre-configured scope.
core:window:deny-set-minimizable Denies the set_minimizable command without any pre-configured scope.
core:window:allow-set-overlay-icon Enables the set_overlay_icon command without any pre-configured scope.
core:window:deny-set-overlay-icon Denies the set_overlay_icon command without any pre-configured scope.
core:window:allow-set-position Enables the set_position command without any pre-configured scope.
core:window:deny-set-position Denies the set_position command without any pre-configured scope.
core:window:allow-set-progress-bar Enables the set_progress_bar command without any pre-configured scope.
core:window:deny-set-progress-bar Denies the set_progress_bar command without any pre-configured scope.
core:window:allow-set-resizable Enables the set_resizable command without any pre-configured scope.
core:window:deny-set-resizable Denies the set_resizable command without any pre-configured scope.
core:window:allow-set-shadow Enables the set_shadow command without any pre-configured scope.
core:window:deny-set-shadow Denies the set_shadow command without any pre-configured scope.
core:window:allow-set-simple-fullscreen Enables the set_simple_fullscreen command without any pre-configured scope.
core:window:deny-set-simple-fullscreen Denies the set_simple_fullscreen command without any pre-configured scope.
core:window:allow-set-size Enables the set_size command without any pre-configured scope.
core:window:deny-set-size Denies the set_size command without any pre-configured scope.
core:window:allow-set-size-constraints Enables the set_size_constraints command without any pre-configured scope.
core:window:deny-set-size-constraints Denies the set_size_constraints command without any pre-configured scope.
core:window:allow-set-skip-taskbar Enables the set_skip_taskbar command without any pre-configured scope.
core:window:deny-set-skip-taskbar Denies the set_skip_taskbar command without any pre-configured scope.
core:window:allow-set-theme Enables the set_theme command without any pre-configured scope.
core:window:deny-set-theme Denies the set_theme command without any pre-configured scope.
core:window:allow-set-title Enables the set_title command without any pre-configured scope.
core:window:deny-set-title Denies the set_title command without any pre-configured scope.
core:window:allow-set-title-bar-style Enables the set_title_bar_style command without any pre-configured scope.
core:window:deny-set-title-bar-style Denies the set_title_bar_style command without any pre-configured scope.
core:window:allow-set-visible-on-all-workspaces Enables the set_visible_on_all_workspaces command without any pre-configured scope.
core:window:deny-set-visible-on-all-workspaces Denies the set_visible_on_all_workspaces command without any pre-configured scope.
core:window:allow-show Enables the show command without any pre-configured scope.
core:window:deny-show Denies the show command without any pre-configured scope.
core:window:allow-start-dragging Enables the start_dragging command without any pre-configured scope.
core:window:deny-start-dragging Denies the start_dragging command without any pre-configured scope.
core:window:allow-start-resize-dragging Enables the start_resize_dragging command without any pre-configured scope.
core:window:deny-start-resize-dragging Denies the start_resize_dragging command without any pre-configured scope.
core:window:allow-theme Enables the theme command without any pre-configured scope.
core:window:deny-theme Denies the theme command without any pre-configured scope.
core:window:allow-title Enables the title command without any pre-configured scope.
core:window:deny-title Denies the title command without any pre-configured scope.
core:window:allow-toggle-maximize Enables the toggle_maximize command without any pre-configured scope.
core:window:deny-toggle-maximize Denies the toggle_maximize command without any pre-configured scope.
core:window:allow-unmaximize Enables the unmaximize command without any pre-configured scope.
core:window:deny-unmaximize Denies the unmaximize command without any pre-configured scope.
core:window:allow-unminimize Enables the unminimize command without any pre-configured scope.
core:window:deny-unminimize Denies the unminimize command without any pre-configured scope.

Permission

Descriptions of explicit privileges of commands.

It can enable commands to be accessible in the frontend of the application.

If the scope is defined it can be used to fine grain control the access of individual or multiple commands.

Object Properties:

  • commands
  • description
  • identifier (required)
  • platforms
  • scope
  • version

commands

Commands

Allowed or denied commands when using this permission.

Default

{
  "allow": [],
  "deny": []
}

description

string | null

Human-readable description of what the permission does. Tauri internal convention is to use &lt;h4&gt; headings in markdown content for Tauri documentation generation purposes.

identifier

string

A unique identifier for the permission.

platforms

Target[] | null

Target platforms this permission applies. By default all platforms are affected by this permission.

scope

Scopes

Allowed or denied scoped when using this permission.

version

integer | null minimum of 1, formatted as uint64

The version of the permission.

Definitions

Commands

Allowed and denied commands inside a permission.

If two commands clash inside of allow and deny, it should be denied by default.

Object Properties:

  • allow
  • deny
allow

string[]

Allowed command.

Default: []

deny

string[]

Denied command, which takes priority.

Default: []

Number

Any of the following:

  • integer formatted as int64 Represents an [i64].
  • number formatted as double Represents a [f64].

A valid ACL number.

Scopes

An argument for fine grained behavior control of Tauri commands.

It can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.

Example
{
  "allow": [{ "path": "$HOME/**" }],
  "deny": [{ "path": "$HOME/secret.txt" }]
}

Object Properties:

  • allow
  • deny
allow

Value[] | null

Data that defines what is allowed by the scope.

deny

Value[] | null

Data that defines what is denied by the scope. This should be prioritized by validation logic.

Target

One of the following:

  • "macOS" MacOS.
  • "windows" Windows.
  • "linux" Linux.
  • "android" Android.
  • "iOS" iOS.

Platform target.

Value

Any of the following:

  • null Represents a null JSON value.
  • boolean Represents a [bool].
  • Number Represents a valid ACL [Number].
  • string Represents a [String].
  • Value[] Represents a list of other [Value]s.
  • Represents a map of [String] keys to [Value]s. Allows additional properties: Value

All supported ACL values.

Scope

An argument for fine grained behavior control of Tauri commands.

It can be of any serde serializable type and is used to allow or prevent certain actions inside a Tauri command. The configured scope is passed to the command and will be enforced by the command implementation.

Example

{
  "allow": [{ "path": "$HOME/**" }],
  "deny": [{ "path": "$HOME/secret.txt" }]
}

Object Properties:

  • allow
  • deny

allow

Value[] | null

Data that defines what is allowed by the scope.

deny

Value[] | null

Data that defines what is denied by the scope. This should be prioritized by validation logic.

Definitions

Number

Any of the following:

  • integer formatted as int64 Represents an [i64].
  • number formatted as double Represents a [f64].

A valid ACL number.

Value

Any of the following:

  • null Represents a null JSON value.
  • boolean Represents a [bool].
  • Number Represents a valid ACL [Number].
  • string Represents a [String].
  • Value[] Represents a list of other [Value]s.
  • Represents a map of [String] keys to [Value]s. Allows additional properties: Value

All supported ACL values.

Command Line Interface

The Tauri command line interface (CLI) is the way to interact with Tauri throughout the development lifecycle.

You can add the Tauri CLI to your current project using your package manager of choice:

  • npm

    npm install --save-dev @tauri-apps/cli@latest
    
  • yarn

    yarn add -D @tauri-apps/cli@latest
    
  • pnpm

    pnpm add -D @tauri-apps/cli@latest
    
  • deno

    deno add -D npm:@tauri-apps/cli@latest
    
  • cargo

    cargo install tauri-cli --version "^2.0.0" --locked
    

Developing a Plugin

For CLI commands related to developing plugins visit the Develop a Tauri Plugin guide.

List of Commands

Command Description
init Initialize a Tauri project in an existing directory
dev Run your app in development mode
build Build your app in release mode and generate bundles and installers
bundle Generate bundles and installers for your app (already built by tauri build)
android Android commands
android init Initialize Android target in the project
android dev Run your app in development mode on Android
android build Build your app in release mode for Android and generate APKs and AABs
android run Run your app in production mode on Android
ios iOS commands
ios init Initialize iOS target in the project
ios dev Run your app in development mode on iOS
ios build Build your app in release mode for iOS and generate IPAs
ios run Run your app in production mode on iOS
migrate Migrate from v1 to v2
info Show a concise list of information about the environment, Rust, Node.js and their versions as well as a few relevant project configurations
add Add a tauri plugin to the project
remove Remove a tauri plugin from the project
plugin Manage or create Tauri plugins
plugin new Initializes a new Tauri plugin project
plugin init Initialize a Tauri plugin project on an existing directory
plugin android Manage the Android project for a Tauri plugin
plugin ios Manage the iOS project for a Tauri plugin
plugin android init Initializes the Android project for an existing Tauri plugin
plugin ios init Initializes the iOS project for an existing Tauri plugin
icon Generate various icons for all major platforms
signer Generate signing keys for Tauri updater or sign files
signer sign Sign a file
signer generate Generate a new signing key to sign files
completions Generate Tauri CLI shell completions for Bash, Zsh, PowerShell or Fish
permission Manage or create permissions for your app or plugin
permission new Create a new permission file
permission add Add a permission to capabilities
permission rm Remove a permission file, and its reference from any capability
permission ls List permissions available to your application
capability Manage or create capabilities for your app
capability new Create a new permission file
inspect Inspect values used by Tauri
inspect wix-upgrade-code Print the default Upgrade Code used by MSI installer derived from productName

init

  • npm

    npm run tauri init
    
  • yarn

    yarn tauri init
    
  • pnpm

    pnpm tauri init
    
  • deno

    deno task tauri init
    
  • bun

    bun tauri init
    
  • cargo

    cargo tauri init
    
Initialize a Tauri project in an existing directory


Usage: tauri init [OPTIONS]


Options:
      --ci
          Skip prompting for values [env: CI=true]
  -v, --verbose...
          Enables verbose logging
  -f, --force
          Force init to overwrite the src-tauri folder
  -l, --log
          Enables logging
  -d, --directory <DIRECTORY>
          Set target directory for init [default: /opt/build/repo/packages/cli-generator]
  -t, --tauri-path <TAURI_PATH>
          Path of the Tauri project to use (relative to the cwd)
  -A, --app-name <APP_NAME>
          Name of your Tauri application
  -W, --window-title <WINDOW_TITLE>
          Window title of your Tauri application
  -D, --frontend-dist <FRONTEND_DIST>
          Web assets location, relative to <project-dir>/src-tauri
  -P, --dev-url <DEV_URL>
          Url of your dev server
      --before-dev-command <BEFORE_DEV_COMMAND>
          A shell command to run before `tauri dev` kicks in
      --before-build-command <BEFORE_BUILD_COMMAND>
          A shell command to run before `tauri build` kicks in
  -h, --help
          Print help
  -V, --version
          Print version

dev

  • npm

    npm run tauri dev
    
  • yarn

    yarn tauri dev
    
  • pnpm

    pnpm tauri dev
    
  • deno

    deno task tauri dev
    
  • bun

    bun tauri dev
    
  • cargo

    cargo tauri dev
    
Run your app in development mode with hot-reloading for the Rust code. It makes use of the `build.devUrl` property from your `tauri.conf.json` file. It also runs your `build.beforeDevCommand` which usually starts your frontend devServer.


Usage: tauri dev [OPTIONS] [ARGS]...


Arguments:
  [ARGS]...
          Command line arguments passed to the runner. Use `--` to explicitly mark the start of the arguments. Arguments after a second `--` are passed to the application e.g. `tauri dev -- [runnerArgs] -- [appArgs]`


Options:
  -r, --runner <RUNNER>
          Binary to use to run the application


  -v, --verbose...
          Enables verbose logging


  -t, --target <TARGET>
          Target triple to build against


  -f, --features [<FEATURES>...]
          List of cargo features to activate


  -e, --exit-on-panic
          Exit on panic


  -c, --config <CONFIG>
          JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file


          Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.


          Note that a platform-specific file is looked up and merged with the default file by default (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) but you can use this for more specific use cases such as different build flavors.


      --release
          Run the code in release mode


      --no-dev-server-wait
          Skip waiting for the frontend dev server to start before building the tauri application


          [env: TAURI_CLI_NO_DEV_SERVER_WAIT=]


      --no-watch
          Disable the file watcher


      --additional-watch-folders <ADDITIONAL_WATCH_FOLDERS>
          Additional paths to watch for changes


      --no-dev-server
          Disable the built-in dev server for static files


      --port <PORT>
          Specify port for the built-in dev server for static files. Defaults to 1430


          [env: TAURI_CLI_PORT=]


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

build

  • npm

    npm run tauri build
    
  • yarn

    yarn tauri build
    
  • pnpm

    pnpm tauri build
    
  • deno

    deno task tauri build
    
  • bun

    bun tauri build
    
  • cargo

    cargo tauri build
    
Build your app in release mode and generate bundles and installers. It makes use of the `build.frontendDist` property from your `tauri.conf.json` file. It also runs your `build.beforeBuildCommand` which usually builds your frontend into `build.frontendDist`. This will also run `build.beforeBundleCommand` before generating the bundles and installers of your app.


Usage: tauri build [OPTIONS] [ARGS]...


Arguments:
  [ARGS]...
          Command line arguments passed to the runner. Use `--` to explicitly mark the start of the arguments


Options:
  -r, --runner <RUNNER>
          Binary to use to build the application, defaults to `cargo`


  -v, --verbose...
          Enables verbose logging


  -d, --debug
          Builds with the debug flag


  -t, --target <TARGET>
          Target triple to build against.


          It must be one of the values outputted by `$rustc --print target-list` or `universal-apple-darwin` for an universal macOS application.


          Note that compiling an universal macOS application requires both `aarch64-apple-darwin` and `x86_64-apple-darwin` targets to be installed.


  -f, --features [<FEATURES>...]
          Space or comma separated list of features to activate


  -b, --bundles [<BUNDLES>...]
          Space or comma separated list of bundles to package


          [possible values: deb, rpm, appimage]


      --no-bundle
          Skip the bundling step even if `bundle > active` is `true` in tauri config


  -c, --config <CONFIG>
          JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file


          Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.


          Note that a platform-specific file is looked up and merged with the default file by default (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) but you can use this for more specific use cases such as different build flavors.


      --ci
          Skip prompting for values


          [env: CI=true]


      --skip-stapling
          Whether to wait for notarization to finish and `staple` the ticket onto the app.


          Gatekeeper will look for stapled tickets to tell whether your app was notarized without reaching out to Apple's servers which is helpful in offline environments.


          Enabling this option will also result in `tauri build` not waiting for notarization to finish which is helpful for the very first time your app is notarized as this can take multiple hours. On subsequent runs, it's recommended to disable this setting again.


      --ignore-version-mismatches
          Do not error out if a version mismatch is detected on a Tauri package.


          Only use this when you are sure the mismatch is incorrectly detected as version mismatched Tauri packages can lead to unknown behavior.


      --no-sign
          Skip code signing when bundling the app


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

bundle

  • npm

    npm run tauri bundle
    
  • yarn

    yarn tauri bundle
    
  • pnpm

    pnpm tauri bundle
    
  • deno

    deno task tauri bundle
    
  • bun

    bun tauri bundle
    
  • cargo

    cargo tauri bundle
    
Generate bundles and installers for your app (already built by `tauri build`). This run `build.beforeBundleCommand` before generating the bundles and installers of your app.


Usage: tauri bundle [OPTIONS]


Options:
  -d, --debug
          Builds with the debug flag


  -v, --verbose...
          Enables verbose logging


  -b, --bundles [<BUNDLES>...]
          Space or comma separated list of bundles to package


          [possible values: deb, rpm, appimage]


  -c, --config <CONFIG>
          JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file


          Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.


          Note that a platform-specific file is looked up and merged with the default file by default (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) but you can use this for more specific use cases such as different build flavors.


  -f, --features [<FEATURES>...]
          Space or comma separated list of features, should be the same features passed to `tauri build` if any


  -t, --target <TARGET>
          Target triple to build against.


          It must be one of the values outputted by `$rustc --print target-list` or `universal-apple-darwin` for an universal macOS application.


          Note that compiling an universal macOS application requires both `aarch64-apple-darwin` and `x86_64-apple-darwin` targets to be installed.


      --ci
          Skip prompting for values


          [env: CI=true]


      --skip-stapling
          Whether to wait for notarization to finish and `staple` the ticket onto the app.


          Gatekeeper will look for stapled tickets to tell whether your app was notarized without reaching out to Apple's servers which is helpful in offline environments.


          Enabling this option will also result in `tauri build` not waiting for notarization to finish which is helpful for the very first time your app is notarized as this can take multiple hours. On subsequent runs, it's recommended to disable this setting again.


      --no-sign
          Skip code signing during the build or bundling process.


          Useful for local development and CI environments where signing certificates or environment variables are not available or not needed.


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

android

  • npm

    npm run tauri android
    
  • yarn

    yarn tauri android
    
  • pnpm

    pnpm tauri android
    
  • deno

    deno task tauri android
    
  • bun

    bun tauri android
    
  • cargo

    cargo tauri android
    
Android commands


Usage: tauri android [OPTIONS] <COMMAND>


Commands:
  init   Initialize Android target in the project
  dev    Run your app in development mode on Android
  build  Build your app in release mode for Android and generate APKs and AABs
  run    Run your app in production mode on Android
  help   Print this message or the help of the given subcommand(s)


Options:
  -v, --verbose...  Enables verbose logging
  -h, --help        Print help
  -V, --version     Print version

android init

  • npm

    npm run tauri android init
    
  • yarn

    yarn tauri android init
    
  • pnpm

    pnpm tauri android init
    
  • deno

    deno task tauri android init
    
  • bun

    bun tauri android init
    
  • cargo

    cargo tauri android init
    
Initialize Android target in the project


Usage: tauri android init [OPTIONS]


Options:
      --ci
          Skip prompting for values


          [env: CI=true]


  -v, --verbose...
          Enables verbose logging


      --skip-targets-install
          Skips installing rust toolchains via rustup


  -c, --config <CONFIG>
          JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file


          Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.


          Note that a platform-specific file is looked up and merged with the default file by default (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) but you can use this for more specific use cases such as different build flavors.


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

android dev

  • npm

    npm run tauri android dev
    
  • yarn

    yarn tauri android dev
    
  • pnpm

    pnpm tauri android dev
    
  • deno

    deno task tauri android dev
    
  • bun

    bun tauri android dev
    
  • cargo

    cargo tauri android dev
    
Run your app in development mode on Android with hot-reloading for the Rust code. It makes use of the `build.devUrl` property from your `tauri.conf.json` file. It also runs your `build.beforeDevCommand` which usually starts your frontend devServer.


Usage: tauri android dev [OPTIONS] [DEVICE] [-- <ARGS>...]


Arguments:
  [DEVICE]
          Runs on the given device name


  [ARGS]...
          Command line arguments passed to the runner. Use `--` to explicitly mark the start of the arguments. e.g. `tauri android dev -- [runnerArgs]`


Options:
  -f, --features [<FEATURES>...]
          List of cargo features to activate


  -v, --verbose...
          Enables verbose logging


  -e, --exit-on-panic
          Exit on panic


  -c, --config <CONFIG>
          JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file


          Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.


          Note that a platform-specific file is looked up and merged with the default file by default (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) but you can use this for more specific use cases such as different build flavors.


      --release
          Run the code in release mode


      --no-dev-server-wait
          Skip waiting for the frontend dev server to start before building the tauri application


          [env: TAURI_CLI_NO_DEV_SERVER_WAIT=]


      --no-watch
          Disable the file watcher


      --additional-watch-folders <ADDITIONAL_WATCH_FOLDERS>
          Additional paths to watch for changes


  -o, --open
          Open Android Studio instead of trying to run on a connected device


      --force-ip-prompt
          Force prompting for an IP to use to connect to the dev server on mobile


      --host [<HOST>]
          Use the public network address for the development server. If an actual address it provided, it is used instead of prompting to pick one.


          On Windows we use the public network address by default.


          This option is particularly useful along the `--open` flag when you intend on running on a physical device.


          This replaces the devUrl configuration value to match the public network address host, it is your responsibility to set up your development server to listen on this address by using 0.0.0.0 as host for instance.


          When this is set or when running on an iOS device the CLI sets the `TAURI_DEV_HOST` environment variable so you can check this on your framework's configuration to expose the development server on the public network address.


          [default: <none>]


      --no-dev-server
          Disable the built-in dev server for static files


      --port <PORT>
          Specify port for the built-in dev server for static files. Defaults to 1430


          [env: TAURI_CLI_PORT=]


      --root-certificate-path <ROOT_CERTIFICATE_PATH>
          Path to the certificate file used by your dev server. Required for mobile dev when using HTTPS


          [env: TAURI_DEV_ROOT_CERTIFICATE_PATH=]


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

android build

  • npm

    npm run tauri android build
    
  • yarn

    yarn tauri android build
    
  • pnpm

    pnpm tauri android build
    
  • deno

    deno task tauri android build
    
  • bun

    bun tauri android build
    
  • cargo

    cargo tauri android build
    
Build your app in release mode for Android and generate APKs and AABs. It makes use of the `build.frontendDist` property from your `tauri.conf.json` file. It also runs your `build.beforeBuildCommand` which usually builds your frontend into `build.frontendDist`.


Usage: tauri android build [OPTIONS] [-- <ARGS>...]


Arguments:
  [ARGS]...
          Command line arguments passed to the runner. Use `--` to explicitly mark the start of the arguments. e.g. `tauri android build -- [runnerArgs]`


Options:
  -d, --debug
          Builds with the debug flag


  -v, --verbose...
          Enables verbose logging


  -t, --target [<TARGETS>...]
          Which targets to build (all by default)


          [possible values: aarch64, armv7, i686, x86_64]


  -f, --features [<FEATURES>...]
          List of cargo features to activate


  -c, --config <CONFIG>
          JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file


          Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.


          Note that a platform-specific file is looked up and merged with the default file by default (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) but you can use this for more specific use cases such as different build flavors.


      --split-per-abi
          Whether to split the APKs and AABs per ABIs


      --apk
          Build APKs


      --aab
          Build AABs


  -o, --open
          Open Android Studio


      --ci
          Skip prompting for values


          [env: CI=true]


      --ignore-version-mismatches
          Do not error out if a version mismatch is detected on a Tauri package.


          Only use this when you are sure the mismatch is incorrectly detected as version mismatched Tauri packages can lead to unknown behavior.


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

android run

  • npm

    npm run tauri android run
    
  • yarn

    yarn tauri android run
    
  • pnpm

    pnpm tauri android run
    
  • deno

    deno task tauri android run
    
  • bun

    bun tauri android run
    
  • cargo

    cargo tauri android run
    
Run your app in production mode on Android. It makes use of the `build.frontendDist` property from your `tauri.conf.json` file. It also runs your `build.beforeBuildCommand` which usually builds your frontend into `build.frontendDist`.


Usage: tauri android run [OPTIONS] [DEVICE] [-- <ARGS>...]


Arguments:
  [DEVICE]
          Runs on the given device name


  [ARGS]...
          Command line arguments passed to the runner. Use `--` to explicitly mark the start of the arguments. e.g. `tauri android build -- [runnerArgs]`


Options:
  -r, --release
          Run the app in release mode


  -v, --verbose...
          Enables verbose logging


  -f, --features [<FEATURES>...]
          List of cargo features to activate


  -c, --config <CONFIG>
          JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file


          Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.


          Note that a platform-specific file is looked up and merged with the default file by default (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) but you can use this for more specific use cases such as different build flavors.


      --no-watch
          Disable the file watcher


      --additional-watch-folders <ADDITIONAL_WATCH_FOLDERS>
          Additional paths to watch for changes


  -o, --open
          Open Android Studio


      --ignore-version-mismatches
          Do not error out if a version mismatch is detected on a Tauri package.


          Only use this when you are sure the mismatch is incorrectly detected as version mismatched Tauri packages can lead to unknown behavior.


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

ios

All iOS commands are only available on macOS hosts.

  • npm

    npm run tauri ios
    
  • yarn

    yarn tauri ios
    
  • pnpm

    pnpm tauri ios
    
  • deno

    deno task tauri ios
    
  • bun

    bun tauri ios
    
  • cargo

    cargo tauri ios
    
iOS commands


Usage: tauri ios [OPTIONS] <COMMAND>


Commands:
  init   Initialize iOS target in the project
  dev    Run your app in development mode on iOS
  build  Build your app in release mode for iOS and generate IPAs
  run    Run your app in production mode on iOS
  help   Print this message or the help of the given subcommand(s)


Options:
  -v, --verbose...  Enables verbose logging
  -h, --help        Print help
  -V, --version     Print version

ios init

All iOS commands are only available on macOS hosts.

  • npm

    npm run tauri ios init
    
  • yarn

    yarn tauri ios init
    
  • pnpm

    pnpm tauri ios init
    
  • deno

    deno task tauri ios init
    
  • bun

    bun tauri ios init
    
  • cargo

    cargo tauri ios init
    
Initialize iOS target in the project


Usage: tauri ios init [OPTIONS]


Options:
      --ci
          Skip prompting for values


          [env: CI=]


  -v, --verbose...
          Enables verbose logging


  -r, --reinstall-deps
          Reinstall dependencies


      --skip-targets-install
          Skips installing rust toolchains via rustup


  -c, --config <CONFIG>
          JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file


          Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.


          Note that a platform-specific file is looked up and merged with the default file by default (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) but you can use this for more specific use cases such as different build flavors.


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

ios dev

All iOS commands are only available on macOS hosts.

  • npm

    npm run tauri ios dev
    
  • yarn

    yarn tauri ios dev
    
  • pnpm

    pnpm tauri ios dev
    
  • deno

    deno task tauri ios dev
    
  • bun

    bun tauri ios dev
    
  • cargo

    cargo tauri ios dev
    
Run your app in development mode on iOS with hot-reloading for the Rust code.
It makes use of the `build.devUrl` property from your `tauri.conf.json` file.
It also runs your `build.beforeDevCommand` which usually starts your frontend devServer.


When connected to a physical iOS device, the public network address must be used instead of `localhost`
for the devUrl property. Tauri makes that change automatically, but your dev server might need
a different configuration to listen on the public address. You can check the `TAURI_DEV_HOST`
environment variable to determine whether the public network should be used or not.


Usage: tauri ios dev [OPTIONS] [DEVICE] [-- <ARGS>...]


Arguments:
  [DEVICE]
          Runs on the given device name


  [ARGS]...
          Command line arguments passed to the runner. Use `--` to explicitly mark the start of the arguments. e.g. `tauri ios dev -- [runnerArgs]`


Options:
  -f, --features [<FEATURES>...]
          List of cargo features to activate


  -v, --verbose...
          Enables verbose logging


  -e, --exit-on-panic
          Exit on panic


  -c, --config <CONFIG>
          JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file


          Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.


          Note that a platform-specific file is looked up and merged with the default file by default (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) but you can use this for more specific use cases such as different build flavors.


      --release
          Run the code in release mode


      --no-dev-server-wait
          Skip waiting for the frontend dev server to start before building the tauri application


          [env: TAURI_CLI_NO_DEV_SERVER_WAIT=]


      --no-watch
          Disable the file watcher


      --additional-watch-folders <ADDITIONAL_WATCH_FOLDERS>
          Additional paths to watch for changes


  -o, --open
          Open Xcode instead of trying to run on a connected device


      --force-ip-prompt
          Force prompting for an IP to use to connect to the dev server on mobile


      --host [<HOST>]
          Use the public network address for the development server. If an actual address it provided, it is used instead of prompting to pick one.


          This option is particularly useful along the `--open` flag when you intend on running on a physical device.


          This replaces the devUrl configuration value to match the public network address host, it is your responsibility to set up your development server to listen on this address by using 0.0.0.0 as host for instance.


          When this is set or when running on an iOS device the CLI sets the `TAURI_DEV_HOST` environment variable so you can check this on your framework's configuration to expose the development server on the public network address.


          [default: <none>]


      --no-dev-server
          Disable the built-in dev server for static files


      --port <PORT>
          Specify port for the built-in dev server for static files. Defaults to 1430


          [env: TAURI_CLI_PORT=]


      --root-certificate-path <ROOT_CERTIFICATE_PATH>
          Path to the certificate file used by your dev server. Required for mobile dev when using HTTPS


          [env: TAURI_DEV_ROOT_CERTIFICATE_PATH=]


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

ios build

All iOS commands are only available on macOS hosts.

  • npm

    npm run tauri ios build
    
  • yarn

    yarn tauri ios build
    
  • pnpm

    pnpm tauri ios build
    
  • deno

    deno task tauri ios build
    
  • bun

    bun tauri ios build
    
  • cargo

    cargo tauri ios build
    
Build your app in release mode for iOS and generate IPAs. It makes use of the `build.frontendDist` property from your `tauri.conf.json` file. It also runs your `build.beforeBuildCommand` which usually builds your frontend into `build.frontendDist`.


Usage: tauri ios build [OPTIONS] [-- <ARGS>...]


Arguments:
  [ARGS]...
          Command line arguments passed to the runner. Use `--` to explicitly mark the start of the arguments. e.g. `tauri ios build -- [runnerArgs]`


Options:
  -d, --debug
          Builds with the debug flag


  -v, --verbose...
          Enables verbose logging


  -t, --target [<TARGETS>...]
          Which targets to build


          [default: aarch64]
          [possible values: aarch64, aarch64-sim, x86_64]


  -f, --features [<FEATURES>...]
          List of cargo features to activate


  -c, --config <CONFIG>
          JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file


          Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.


          Note that a platform-specific file is looked up and merged with the default file by default (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) but you can use this for more specific use cases such as different build flavors.


      --build-number <BUILD_NUMBER>
          Build number to append to the app version


  -o, --open
          Open Xcode


      --ci
          Skip prompting for values


          [env: CI=]


      --export-method <EXPORT_METHOD>
          Describes how Xcode should export the archive.


          Use this to create a package ready for the App Store (app-store-connect option) or TestFlight (release-testing option).


          [possible values: app-store-connect, release-testing, debugging]


      --ignore-version-mismatches
          Do not error out if a version mismatch is detected on a Tauri package.


          Only use this when you are sure the mismatch is incorrectly detected as version mismatched Tauri packages can lead to unknown behavior.


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

ios run

All iOS commands are only available on macOS hosts.

  • npm

    npm run tauri ios run
    
  • yarn

    yarn tauri ios run
    
  • pnpm

    pnpm tauri ios run
    
  • deno

    deno task tauri ios run
    
  • bun

    bun tauri ios run
    
  • cargo

    cargo tauri ios run
    
Run your app in production mode on iOS. It makes use of the `build.frontendDist` property from your `tauri.conf.json` file. It also runs your `build.beforeBuildCommand` which usually builds your frontend into `build.frontendDist`.


Usage: tauri ios run [OPTIONS] [DEVICE] [-- <ARGS>...]


Arguments:
  [DEVICE]
          Runs on the given device name


  [ARGS]...
          Command line arguments passed to the runner. Use `--` to explicitly mark the start of the arguments. e.g. `tauri android build -- [runnerArgs]`


Options:
  -r, --release
          Run the app in release mode


  -v, --verbose...
          Enables verbose logging


  -f, --features [<FEATURES>...]
          List of cargo features to activate


  -c, --config <CONFIG>
          JSON strings or paths to JSON, JSON5 or TOML files to merge with the default configuration file


          Configurations are merged in the order they are provided, which means a particular value overwrites previous values when a config key-value pair conflicts.


          Note that a platform-specific file is looked up and merged with the default file by default (tauri.macos.conf.json, tauri.linux.conf.json, tauri.windows.conf.json, tauri.android.conf.json and tauri.ios.conf.json) but you can use this for more specific use cases such as different build flavors.


      --no-watch
          Disable the file watcher


      --additional-watch-folders <ADDITIONAL_WATCH_FOLDERS>
          Additional paths to watch for changes


  -o, --open
          Open Xcode


      --ignore-version-mismatches
          Do not error out if a version mismatch is detected on a Tauri package.


          Only use this when you are sure the mismatch is incorrectly detected as version mismatched Tauri packages can lead to unknown behavior.


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

migrate

  • npm

    npm run tauri migrate
    
  • yarn

    yarn tauri migrate
    
  • pnpm

    pnpm tauri migrate
    
  • deno

    deno task tauri migrate
    
  • bun

    bun tauri migrate
    
  • cargo

    cargo tauri migrate
    
Migrate from v1 to v2


Usage: tauri migrate [OPTIONS]


Options:
  -v, --verbose...  Enables verbose logging
  -h, --help        Print help
  -V, --version     Print version

info

  • npm

    npm run tauri info
    
  • yarn

    yarn tauri info
    
  • pnpm

    pnpm tauri info
    
  • deno

    deno task tauri info
    
  • bun

    bun tauri info
    
  • cargo

    cargo tauri info
    
Show a concise list of information about the environment, Rust, Node.js and their versions as well as a few relevant project configurations


Usage: tauri info [OPTIONS]


Options:
      --interactive  Interactive mode to apply automatic fixes
  -v, --verbose...   Enables verbose logging
  -h, --help         Print help
  -V, --version      Print version

add

  • npm

    npm run tauri add
    
  • yarn

    yarn tauri add
    
  • pnpm

    pnpm tauri add
    
  • deno

    deno task tauri add
    
  • bun

    bun tauri add
    
  • cargo

    cargo tauri add
    
Add a tauri plugin to the project


Usage: tauri add [OPTIONS] <PLUGIN>


Arguments:
  <PLUGIN>  The plugin to add


Options:
  -t, --tag <TAG>        Git tag to use
  -v, --verbose...       Enables verbose logging
  -r, --rev <REV>        Git rev to use
  -b, --branch <BRANCH>  Git branch to use
      --no-fmt           Don't format code with rustfmt
  -h, --help             Print help
  -V, --version          Print version

remove

  • npm

    npm run tauri remove
    
  • yarn

    yarn tauri remove
    
  • pnpm

    pnpm tauri remove
    
  • deno

    deno task tauri remove
    
  • bun

    bun tauri remove
    
  • cargo

    cargo tauri remove
    
Remove a tauri plugin from the project


Usage: tauri remove [OPTIONS] <PLUGIN>


Arguments:
  <PLUGIN>  The plugin to remove


Options:
  -v, --verbose...  Enables verbose logging
  -h, --help        Print help
  -V, --version     Print version

plugin

  • npm

    npm run tauri plugin
    
  • yarn

    yarn tauri plugin
    
  • pnpm

    pnpm tauri plugin
    
  • deno

    deno task tauri plugin
    
  • bun

    bun tauri plugin
    
  • cargo

    cargo tauri plugin
    
Manage or create Tauri plugins


Usage: tauri plugin [OPTIONS] <COMMAND>


Commands:
  new      Initializes a new Tauri plugin project
  init     Initialize a Tauri plugin project on an existing directory
  android  Manage the Android project for a Tauri plugin
  ios      Manage the iOS project for a Tauri plugin
  help     Print this message or the help of the given subcommand(s)


Options:
  -v, --verbose...  Enables verbose logging
  -h, --help        Print help
  -V, --version     Print version

plugin new

  • npm

    npm run tauri plugin new
    
  • yarn

    yarn tauri plugin new
    
  • pnpm

    pnpm tauri plugin new
    
  • deno

    deno task tauri plugin new
    
  • bun

    bun tauri plugin new
    
  • cargo

    cargo tauri plugin new
    
Initializes a new Tauri plugin project


Usage: tauri plugin new [OPTIONS] <PLUGIN_NAME>


Arguments:
  <PLUGIN_NAME>
          Name of your Tauri plugin


Options:
      --no-api
          Initializes a Tauri plugin without the TypeScript API


  -v, --verbose...
          Enables verbose logging


      --no-example
          Initialize without an example project


  -d, --directory <DIRECTORY>
          Set target directory for init


  -a, --author <AUTHOR>
          Author name


      --android
          Whether to initialize an Android project for the plugin


      --ios
          Whether to initialize an iOS project for the plugin


      --mobile
          Whether to initialize Android and iOS projects for the plugin


      --ios-framework <IOS_FRAMEWORK>
          Type of framework to use for the iOS project


          [default: spm]


          Possible values:
          - spm:   Swift Package Manager project
          - xcode: Xcode project


      --github-workflows
          Generate github workflows


  -t, --tauri-path <TAURI_PATH>
          Path of the Tauri project to use (relative to the cwd)


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

plugin init

  • npm

    npm run tauri plugin init
    
  • yarn

    yarn tauri plugin init
    
  • pnpm

    pnpm tauri plugin init
    
  • deno

    deno task tauri plugin init
    
  • bun

    bun tauri plugin init
    
  • cargo

    cargo tauri plugin init
    
Initialize a Tauri plugin project on an existing directory


Usage: tauri plugin init [OPTIONS] [PLUGIN_NAME]


Arguments:
  [PLUGIN_NAME]
          Name of your Tauri plugin. If not specified, it will be inferred from the current directory


Options:
      --no-api
          Initializes a Tauri plugin without the TypeScript API


  -v, --verbose...
          Enables verbose logging


      --no-example
          Initialize without an example project


  -d, --directory <DIRECTORY>
          Set target directory for init


          [default: /opt/build/repo/packages/cli-generator]


  -a, --author <AUTHOR>
          Author name


      --android
          Whether to initialize an Android project for the plugin


      --ios
          Whether to initialize an iOS project for the plugin


      --mobile
          Whether to initialize Android and iOS projects for the plugin


      --ios-framework <IOS_FRAMEWORK>
          Type of framework to use for the iOS project


          [default: spm]


          Possible values:
          - spm:   Swift Package Manager project
          - xcode: Xcode project


      --github-workflows
          Generate github workflows


  -t, --tauri-path <TAURI_PATH>
          Path of the Tauri project to use (relative to the cwd)


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

plugin android

  • npm

    npm run tauri plugin android
    
  • yarn

    yarn tauri plugin android
    
  • pnpm

    pnpm tauri plugin android
    
  • deno

    deno task tauri plugin android
    
  • bun

    bun tauri plugin android
    
  • cargo

    cargo tauri plugin android
    
Manage the Android project for a Tauri plugin


Usage: tauri plugin android [OPTIONS] <COMMAND>


Commands:
  init  Initializes the Android project for an existing Tauri plugin
  help  Print this message or the help of the given subcommand(s)


Options:
  -v, --verbose...  Enables verbose logging
  -h, --help        Print help
  -V, --version     Print version
plugin android init
  • npm

    npm run tauri plugin android init
    
  • yarn

    yarn tauri plugin android init
    
  • pnpm

    pnpm tauri plugin android init
    
  • deno

    deno task tauri plugin android init
    
  • bun

    bun tauri plugin android init
    
  • cargo

    cargo tauri plugin android init
    
Initializes the Android project for an existing Tauri plugin


Usage: tauri plugin android init [OPTIONS] [PLUGIN_NAME]


Arguments:
  [PLUGIN_NAME]  Name of your Tauri plugin. Must match the current plugin's name. If not specified, it will be inferred from the current directory


Options:
  -o, --out-dir <OUT_DIR>  The output directory [default: /opt/build/repo/packages/cli-generator]
  -v, --verbose...         Enables verbose logging
  -h, --help               Print help
  -V, --version            Print version

plugin ios

  • npm

    npm run tauri plugin ios
    
  • yarn

    yarn tauri plugin ios
    
  • pnpm

    pnpm tauri plugin ios
    
  • deno

    deno task tauri plugin ios
    
  • bun

    bun tauri plugin ios
    
  • cargo

    cargo tauri plugin ios
    
Manage the iOS project for a Tauri plugin


Usage: tauri plugin ios [OPTIONS] <COMMAND>


Commands:
  init  Initializes the iOS project for an existing Tauri plugin
  help  Print this message or the help of the given subcommand(s)


Options:
  -v, --verbose...  Enables verbose logging
  -h, --help        Print help
  -V, --version     Print version
plugin ios init
  • npm

    npm run tauri plugin ios init
    
  • yarn

    yarn tauri plugin ios init
    
  • pnpm

    pnpm tauri plugin ios init
    
  • deno

    deno task tauri plugin ios init
    
  • bun

    bun tauri plugin ios init
    
  • cargo

    cargo tauri plugin ios init
    
Initializes the iOS project for an existing Tauri plugin


Usage: tauri plugin ios init [OPTIONS] [PLUGIN_NAME]


Arguments:
  [PLUGIN_NAME]
          Name of your Tauri plugin. Must match the current plugin's name. If not specified, it will be inferred from the current directory


Options:
  -o, --out-dir <OUT_DIR>
          The output directory


          [default: /opt/build/repo/packages/cli-generator]


  -v, --verbose...
          Enables verbose logging


      --ios-framework <IOS_FRAMEWORK>
          Type of framework to use for the iOS project


          [default: spm]


          Possible values:
          - spm:   Swift Package Manager project
          - xcode: Xcode project


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

icon

  • npm

    npm run tauri icon
    
  • yarn

    yarn tauri icon
    
  • pnpm

    pnpm tauri icon
    
  • deno

    deno task tauri icon
    
  • bun

    bun tauri icon
    
  • cargo

    cargo tauri icon
    
Generate various icons for all major platforms


Usage: tauri icon [OPTIONS] [INPUT]


Arguments:
  [INPUT]
          Path to the source icon (squared PNG or SVG file with transparency) or a manifest file.


          The manifest file is a JSON file with the following structure: { "default": "app-icon.png", "bg_color": "#fff", "android_bg": "app-icon-bg.png", "android_fg": "app-icon-fg.png", "android_fg_scale": 85, "android_monochrome": "app-icon-monochrome.png" }


          All file paths defined in the manifest JSON are relative to the manifest file path.


          Only the `default` manifest property is required.


          The `bg_color` manifest value overwrites the `--ios-color` option if set.


          [default: ./app-icon.png]


Options:
  -o, --output <OUTPUT>
          Output directory. Default: 'icons' directory next to the tauri.conf.json file


  -v, --verbose...
          Enables verbose logging


  -p, --png <PNG>
          Custom PNG icon sizes to generate. When set, the default icons are not generated


      --ios-color <IOS_COLOR>
          The background color of the iOS icon - string as defined in the W3C's CSS Color Module Level 4 <https://www.w3.org/TR/css-color-4/>


          [default: #fff]


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

signer

  • npm

    npm run tauri signer
    
  • yarn

    yarn tauri signer
    
  • pnpm

    pnpm tauri signer
    
  • deno

    deno task tauri signer
    
  • bun

    bun tauri signer
    
  • cargo

    cargo tauri signer
    
Generate signing keys for Tauri updater or sign files


Usage: tauri signer [OPTIONS] <COMMAND>


Commands:
  sign      Sign a file
  generate  Generate a new signing key to sign files
  help      Print this message or the help of the given subcommand(s)


Options:
  -v, --verbose...  Enables verbose logging
  -h, --help        Print help
  -V, --version     Print version

signer sign

  • npm

    npm run tauri signer sign
    
  • yarn

    yarn tauri signer sign
    
  • pnpm

    pnpm tauri signer sign
    
  • deno

    deno task tauri signer sign
    
  • bun

    bun tauri signer sign
    
  • cargo

    cargo tauri signer sign
    
Sign a file


Usage: tauri signer sign [OPTIONS] <FILE>


Arguments:
  <FILE>  Sign the specified file


Options:
  -k, --private-key <PRIVATE_KEY>
          Load the private key from a string [env: TAURI_SIGNING_PRIVATE_KEY=]
  -v, --verbose...
          Enables verbose logging
  -f, --private-key-path <PRIVATE_KEY_PATH>
          Load the private key from a file [env: TAURI_SIGNING_PRIVATE_KEY_PATH=]
  -p, --password <PASSWORD>
          Set private key password when signing [env: TAURI_SIGNING_PRIVATE_KEY_PASSWORD=]
  -h, --help
          Print help
  -V, --version
          Print version

signer generate

  • npm

    npm run tauri signer generate
    
  • yarn

    yarn tauri signer generate
    
  • pnpm

    pnpm tauri signer generate
    
  • deno

    deno task tauri signer generate
    
  • bun

    bun tauri signer generate
    
  • cargo

    cargo tauri signer generate
    
Generate a new signing key to sign files


Usage: tauri signer generate [OPTIONS]


Options:
  -p, --password <PASSWORD>      Set private key password when signing
  -v, --verbose...               Enables verbose logging
  -w, --write-keys <WRITE_KEYS>  Write private key to a file
  -f, --force                    Overwrite private key even if it exists on the specified path
      --ci                       Skip prompting for values [env: CI=true]
  -h, --help                     Print help
  -V, --version                  Print version

completions

  • npm

    npm run tauri completions
    
  • yarn

    yarn tauri completions
    
  • pnpm

    pnpm tauri completions
    
  • deno

    deno task tauri completions
    
  • bun

    bun tauri completions
    
  • cargo

    cargo tauri completions
    
Generate Tauri CLI shell completions for Bash, Zsh, PowerShell or Fish


Usage: tauri completions [OPTIONS] --shell <SHELL>


Options:
  -s, --shell <SHELL>    Shell to generate a completion script for. [possible values: bash, elvish, fish, powershell, zsh]
  -v, --verbose...       Enables verbose logging
  -o, --output <OUTPUT>  Output file for the shell completions. By default the completions are printed to stdout
  -h, --help             Print help
  -V, --version          Print version

permission

  • npm

    npm run tauri permission
    
  • yarn

    yarn tauri permission
    
  • pnpm

    pnpm tauri permission
    
  • deno

    deno task tauri permission
    
  • bun

    bun tauri permission
    
  • cargo

    cargo tauri permission
    
Manage or create permissions for your app or plugin


Usage: tauri permission [OPTIONS] <COMMAND>


Commands:
  new   Create a new permission file
  add   Add a permission to capabilities
  rm    Remove a permission file, and its reference from any capability
  ls    List permissions available to your application
  help  Print this message or the help of the given subcommand(s)


Options:
  -v, --verbose...  Enables verbose logging
  -h, --help        Print help
  -V, --version     Print version

permission new

  • npm

    npm run tauri permission new
    
  • yarn

    yarn tauri permission new
    
  • pnpm

    pnpm tauri permission new
    
  • deno

    deno task tauri permission new
    
  • bun

    bun tauri permission new
    
  • cargo

    cargo tauri permission new
    
Create a new permission file


Usage: tauri permission new [OPTIONS] [IDENTIFIER]


Arguments:
  [IDENTIFIER]  Permission identifier


Options:
      --description <DESCRIPTION>  Permission description
  -v, --verbose...                 Enables verbose logging
  -a, --allow <ALLOW>              List of commands to allow
  -d, --deny <DENY>                List of commands to deny
      --format <FORMAT>            Output file format [default: json] [possible values: json, toml]
  -o, --out <OUT>                  The output file
  -h, --help                       Print help
  -V, --version                    Print version

permission add

  • npm

    npm run tauri permission add
    
  • yarn

    yarn tauri permission add
    
  • pnpm

    pnpm tauri permission add
    
  • deno

    deno task tauri permission add
    
  • bun

    bun tauri permission add
    
  • cargo

    cargo tauri permission add
    
Add a permission to capabilities


Usage: tauri permission add [OPTIONS] <IDENTIFIER> [CAPABILITY]


Arguments:
  <IDENTIFIER>  Permission to add
  [CAPABILITY]  Capability to add the permission to


Options:
  -v, --verbose...  Enables verbose logging
  -h, --help        Print help
  -V, --version     Print version

permission rm

  • npm

    npm run tauri permission rm
    
  • yarn

    yarn tauri permission rm
    
  • pnpm

    pnpm tauri permission rm
    
  • deno

    deno task tauri permission rm
    
  • bun

    bun tauri permission rm
    
  • cargo

    cargo tauri permission rm
    
Remove a permission file, and its reference from any capability


Usage: tauri permission rm [OPTIONS] <IDENTIFIER>


Arguments:
  <IDENTIFIER>
          Permission to remove.


          To remove all permissions for a given plugin, provide `<plugin-name>:*`


Options:
  -v, --verbose...
          Enables verbose logging


  -h, --help
          Print help (see a summary with '-h')


  -V, --version
          Print version

permission ls

  • npm

    npm run tauri permission ls
    
  • yarn

    yarn tauri permission ls
    
  • pnpm

    pnpm tauri permission ls
    
  • deno

    deno task tauri permission ls
    
  • bun

    bun tauri permission ls
    
  • cargo

    cargo tauri permission ls
    
List permissions available to your application


Usage: tauri permission ls [OPTIONS] [PLUGIN]


Arguments:
  [PLUGIN]  Name of the plugin to list permissions


Options:
  -f, --filter <FILTER>  Permission identifier filter
  -v, --verbose...       Enables verbose logging
  -h, --help             Print help
  -V, --version          Print version

capability

  • npm

    npm run tauri capability
    
  • yarn

    yarn tauri capability
    
  • pnpm

    pnpm tauri capability
    
  • deno

    deno task tauri capability
    
  • bun

    bun tauri capability
    
  • cargo

    cargo tauri capability
    
Manage or create capabilities for your app


Usage: tauri capability [OPTIONS] <COMMAND>


Commands:
  new   Create a new permission file
  help  Print this message or the help of the given subcommand(s)


Options:
  -v, --verbose...  Enables verbose logging
  -h, --help        Print help
  -V, --version     Print version

capability new

  • npm

    npm run tauri capability new
    
  • yarn

    yarn tauri capability new
    
  • pnpm

    pnpm tauri capability new
    
  • deno

    deno task tauri capability new
    
  • bun

    bun tauri capability new
    
  • cargo

    cargo tauri capability new
    
Create a new permission file


Usage: tauri capability new [OPTIONS] [IDENTIFIER]


Arguments:
  [IDENTIFIER]  Capability identifier


Options:
      --description <DESCRIPTION>  Capability description
  -v, --verbose...                 Enables verbose logging
      --windows <WINDOWS>          Capability windows
      --permission <PERMISSION>    Capability permissions
      --format <FORMAT>            Output file format [default: json] [possible values: json, toml]
  -o, --out <OUT>                  The output file
  -h, --help                       Print help
  -V, --version                    Print version

inspect

  • npm

    npm run tauri inspect
    
  • yarn

    yarn tauri inspect
    
  • pnpm

    pnpm tauri inspect
    
  • deno

    deno task tauri inspect
    
  • bun

    bun tauri inspect
    
  • cargo

    cargo tauri inspect
    
Inspect values used by Tauri


Usage: tauri inspect [OPTIONS] <COMMAND>


Commands:
  wix-upgrade-code  Print the default Upgrade Code used by MSI installer derived from productName
  help              Print this message or the help of the given subcommand(s)


Options:
  -v, --verbose...  Enables verbose logging
  -h, --help        Print help
  -V, --version     Print version

inspect wix-upgrade-code

  • npm

    npm run tauri inspect wix-upgrade-code
    
  • yarn

    yarn tauri inspect wix-upgrade-code
    
  • pnpm

    pnpm tauri inspect wix-upgrade-code
    
  • deno

    deno task tauri inspect wix-upgrade-code
    
  • bun

    bun tauri inspect wix-upgrade-code
    
  • cargo

    cargo tauri inspect wix-upgrade-code
    
Print the default Upgrade Code used by MSI installer derived from productName


Usage: tauri inspect wix-upgrade-code [OPTIONS]


Options:
  -v, --verbose...  Enables verbose logging
  -h, --help        Print help
  -V, --version     Print version

Configuration

The Tauri configuration object. It is read from a file where you can define your frontend assets, configure the bundler and define a tray icon.

The configuration file is generated by the tauri init command that lives in your Tauri application source directory (src-tauri).

Once generated, you may modify it at will to customize your Tauri application.

File Formats

By default, the configuration is defined as a JSON file named tauri.conf.json.

Tauri also supports JSON5 and TOML files via the config-json5 and config-toml Cargo features, respectively. The JSON5 file name must be either tauri.conf.json or tauri.conf.json5. The TOML file name is Tauri.toml.

Platform-Specific Configuration

In addition to the default configuration file, Tauri can read a platform-specific configuration from tauri.linux.conf.json, tauri.windows.conf.json, tauri.macos.conf.json, tauri.android.conf.json and tauri.ios.conf.json (or Tauri.linux.toml, Tauri.windows.toml, Tauri.macos.toml, Tauri.android.toml and Tauri.ios.toml if the Tauri.toml format is used), which gets merged with the main configuration object.

Configuration Structure

The configuration is composed of the following objects:

  • app: The Tauri configuration
  • build: The build configuration
  • bundle: The bundle configurations
  • plugins: The plugins configuration

Example tauri.config.json file:

{
  "productName": "tauri-app",
  "version": "0.1.0",
  "build": {
    "beforeBuildCommand": "",
    "beforeDevCommand": "",
    "devUrl": "http://localhost:3000",
    "frontendDist": "../dist"
  },
  "app": {
    "security": {
      "csp": null
    },
    "windows": [
      {
        "fullscreen": false,
        "height": 600,
        "resizable": true,
        "title": "Tauri App",
        "width": 800
      }
    ]
  },
  "bundle": {},
  "plugins": {}
}

Object Properties:

  • app
  • build
  • bundle
  • identifier (required)
  • mainBinaryName
  • plugins
  • productName
  • version

app

AppConfig

The App configuration.

Default

{
  "enableGTKAppId": false,
  "macOSPrivateApi": false,
  "security": {
    "assetProtocol": {
      "enable": false,
      "scope": []
    },
    "capabilities": [],
    "dangerousDisableAssetCspModification": false,
    "freezePrototype": false,
    "pattern": {
      "use": "brownfield"
    }
  },
  "windows": [],
  "withGlobalTauri": false
}

build

BuildConfig

The build configuration.

Default

{
  "additionalWatchFolders": [],
  "removeUnusedCommands": false,
  "windows": {
    "staticVCRuntime": true
  }
}

bundle

BundleConfig

The bundler configuration.

Default

{
  "active": false,
  "android": {
    "autoIncrementVersionCode": false,
    "minSdkVersion": 24
  },
  "createUpdaterArtifacts": false,
  "iOS": {
    "minimumSystemVersion": "14.0"
  },
  "icon": [],
  "linux": {
    "appimage": {
      "bundleMediaFramework": false,
      "files": {}
    },
    "deb": {
      "files": {}
    },
    "rpm": {
      "epoch": 0,
      "files": {},
      "release": "1"
    }
  },
  "macOS": {
    "dmg": {
      "appPosition": {
        "x": 180,
        "y": 170
      },
      "applicationFolderPosition": {
        "x": 480,
        "y": 170
      },
      "windowSize": {
        "height": 400,
        "width": 660
      }
    },
    "files": {},
    "hardenedRuntime": true,
    "minimumSystemVersion": "10.13"
  },
  "targets": "all",
  "useLocalToolsDir": false,
  "windows": {
    "allowDowngrades": true,
    "bundleVCRuntime": false,
    "certificateThumbprint": null,
    "digestAlgorithm": null,
    "minimumWebview2Version": null,
    "nsis": null,
    "signCommand": null,
    "timestampUrl": null,
    "tsp": false,
    "webviewInstallMode": {
      "silent": true,
      "type": "downloadBootstrapper"
    },
    "wix": null
  }
}

identifier

string

The application identifier in reverse domain name notation (e.g. com.tauri.example). This string must be unique across applications since it is used in system configurations like the bundle ID and path to the webview data directory. This string must contain only alphanumeric characters (A-Z, a-z, and 0-9), hyphens (-), and periods (.).

mainBinaryName

string | null

Overrides apps main binary filename.

By default, Tauri uses the output binary from cargo, by setting this, we will rename that binary in tauri-clis tauri build command, and target tauri bundle to it

If possible, change the package name or set the name field instead, and if thats not enough and youre using nightly, consider using the different-binary-name feature instead

Note: this config should not include the binary extension (e.g. .exe), well add that for you

plugins

PluginConfig

The plugins config.

Default: {}

productName

string | null pattern of ^[^/\:*?"<>|]+$

App name.

version

string | null

App version. It is a semver version number or a path to a package.json file containing the version field.

If removed the version number from Cargo.toml is used. Its recommended to manage the app versioning in the Tauri config.

Platform-specific

  • macOS: Translates to the bundles CFBundleShortVersionString property and is used as the default CFBundleVersion. You can set an specific bundle version using bundle &gt; macOS &gt; bundleVersion.
  • iOS: Translates to the bundles CFBundleShortVersionString property and is used as the default CFBundleVersion. You can set an specific bundle version using bundle &gt; iOS &gt; bundleVersion. The tauri ios build CLI command has a --build-number &lt;number&gt; option that lets you append a build number to the app version.
  • Android: By default version 1.0 is used. You can set a version code using bundle &gt; android &gt; versionCode.

By default version 1.0 is used on Android.

Definitions

AndroidConfig

General configuration for the Android target.

Object Properties:

  • autoIncrementVersionCode
  • debugApplicationIdSuffix
  • minSdkVersion
  • versionCode
autoIncrementVersionCode

boolean

Whether to automatically increment the versionCode on each build.

  • If true, the generator will try to read the last versionCode from tauri.properties and increment it by 1 for every build.
  • If false or not set, it falls back to version_code or semver-derived logic.

Note that to use this feature, you should remove /tauri.properties from src-tauri/gen/android/app/.gitignore so the current versionCode is committed to the repository.

debugApplicationIdSuffix

string | null

Application ID suffix to append for debug builds. This allows installing debug and release versions side-by-side on the same device. Example: “.debug” will make debug builds use “com.example.app.debug” as the application ID.

minSdkVersion

integer formatted as uint32

The minimum API level required for the application to run. The Android system will prevent the user from installing the application if the systems API level is lower than the value specified.

Default: 24

versionCode

integer | null maximum of 2100000000, minimum of 1, formatted as uint32

The version code of the application. It is limited to 2,100,000,000 as per Google Play Store requirements.

By default we use your configured version and perform the following math: versionCode = version.major * 1000000 + version.minor * 1000 + version.patch

AndroidIntentAction

One of the following:

Android intent action.

AppConfig

The App configuration object.

See more: <https://v2.tauri.app/reference/config/#appconfig>

Object Properties:

  • enableGTKAppId
  • macOSPrivateApi
  • security
  • trayIcon
  • windows
  • withGlobalTauri
enableGTKAppId

boolean

If set to true “identifier” will be set as GTK app ID (on systems that use GTK).

macOSPrivateApi

boolean

MacOS private API configuration. Enables the transparent background API and sets the fullScreenEnabled preference to true.

security

SecurityConfig

Security configuration.

Default

{
  "assetProtocol": {
    "enable": false,
    "scope": []
  },
  "capabilities": [],
  "dangerousDisableAssetCspModification": false,
  "freezePrototype": false,
  "pattern": {
    "use": "brownfield"
  }
}
trayIcon

TrayIconConfig | null

Configuration for app tray icon.

windows

WindowConfig[]

The app windows configuration.

Example:

To create a window at app startup

{
  "app": {
    "windows": [
      { "width": 800, "height": 600 }
    ]
  }
}

If not specified, the windows label (its identifier) defaults to “main”, you can use this label to get the window through app.get_webview_window in Rust or WebviewWindow.getByLabel in JavaScript

When working with multiple windows, each window will need an unique label

{
  "app": {
    "windows": [
      { "label": "main", "width": 800, "height": 600 },
      { "label": "secondary", "width": 800, "height": 600 }
    ]
  }
}

You can also set create to false and use this config through the Rust APIs

{
  "app": {
    "windows": [
      { "create": false, "width": 800, "height": 600 }
    ]
  }
}

and use it like this

tauri::Builder::default()
  .setup(|app| {
    tauri::WebviewWindowBuilder::from_config(app.handle(), &app.config().app.windows[0])?.build()?;
    Ok(())
  });

Default: []

withGlobalTauri

boolean

Whether we should inject the Tauri API on window.__TAURI__ or not.

AppImageConfig

Configuration for AppImage bundles.

See more: <https://v2.tauri.app/reference/config/#appimageconfig>

Object Properties:

  • bundleMediaFramework
  • files
bundleMediaFramework

boolean

Include additional gstreamer dependencies needed for audio and video playback. This increases the bundle size by ~15-35MB depending on your build system.

files

The files to include in the Appimage Binary.

Allows additional properties: string

Default: {}

AssetProtocolConfig

Config for the asset custom protocol.

See more: <https://v2.tauri.app/reference/config/#assetprotocolconfig>

Object Properties:

  • enable
  • scope
enable

boolean

Enables the asset protocol.

scope

FsScope

The access scope for the asset protocol.

Default: []

AssociationExt

string

An extension for a [FileAssociation].

A leading . is automatically stripped.

BackgroundThrottlingPolicy

One of the following:

  • "disabled" A policy where background throttling is disabled
  • "suspend" A policy where a web view thats not in a window fully suspends tasks. This is usually the default behavior in case no policy is set.
  • "throttle" A policy where a web view thats not in a window limits processing, but does not fully suspend tasks.

Background throttling policy.

BeforeDevCommand

Any of the following:

  • string Run the given script with the default options.
  • Run the given script with custom options. Object Properties: - cwd - script (required) - wait ##### cwd string | null The current working directory. ##### script string The script to execute. ##### wait boolean Whether tauri dev should wait for the command to finish or not. Defaults to false.

Describes the shell command to run before tauri dev.

BuildConfig

The Build configuration object.

See more: <https://v2.tauri.app/reference/config/#buildconfig>

Object Properties:

  • additionalWatchFolders
  • beforeBuildCommand
  • beforeBundleCommand
  • beforeDevCommand
  • devUrl
  • features
  • frontendDist
  • removeUnusedCommands
  • runner
  • windows
additionalWatchFolders

string[]

Additional paths to watch for changes when running tauri dev.

Default: []

beforeBuildCommand

HookCommand | null

A shell command to run before tauri build kicks in.

The TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG environment variables are set if you perform conditional compilation.

beforeBundleCommand

HookCommand | null

A shell command to run before the bundling phase in tauri build kicks in.

The TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG environment variables are set if you perform conditional compilation.

beforeDevCommand

BeforeDevCommand | null

A shell command to run before tauri dev kicks in.

The TAURI_ENV_PLATFORM, TAURI_ENV_ARCH, TAURI_ENV_FAMILY, TAURI_ENV_PLATFORM_VERSION, TAURI_ENV_PLATFORM_TYPE and TAURI_ENV_DEBUG environment variables are set if you perform conditional compilation.

devUrl

string | null formatted as uri

The URL to load in development.

This is usually an URL to a dev server, which serves your application assets with hot-reload and HMR. Most modern JavaScript bundlers like Vite provides a way to start a dev server by default.

If you dont have a dev server or dont want to use one, ignore this option and use frontendDist and point to a web assets directory, and Tauri CLI will run its built-in dev server and provide a simple hot-reload experience.

features

string[] | null

Features passed to cargo commands.

frontendDist

FrontendDist | null

The path to the application assets (usually the dist folder of your javascript bundler) or a URL that could be either a custom protocol registered in the tauri app (for example: myprotocol://) or a remote URL (for example: https://site.com/app).

When a path relative to the configuration file is provided, it is read recursively and all files are embedded in the application binary. Tauri then looks for an index.html and serves it as the default entry point for your application.

You can also provide a list of paths to be embedded, which allows granular control over what files are added to the binary. In this case, all files are added to the root and you must reference it that way in your HTML files.

When a URL is provided, the application wont have bundled assets and the application will load that URL by default.

removeUnusedCommands

boolean

Try to remove unused commands registered from plugins base on the ACL list during tauri build, the way it works is that tauri-cli will read this and set the environment variables for the build script and macros, and theyll try to get all the allowed commands and remove the rest

Note:

  • This wont be accounting for dynamically added ACLs when you use features from the dynamic-acl (currently enabled by default) feature flag, so make sure to check it when using this
  • This feature requires tauri-plugin 2.1 and tauri 2.4
runner

RunnerConfig | null

The binary used to build and run the application.

windows

WindowsBuildConfig

Windows-specific build configuration.

Default

{
  "staticVCRuntime": true
}

BundleConfig

Configuration for tauri-bundler.

See more: <https://v2.tauri.app/reference/config/#bundleconfig>

Object Properties:

  • active
  • android
  • category
  • copyright
  • createUpdaterArtifacts
  • externalBin
  • fileAssociations
  • homepage
  • icon
  • iOS
  • license
  • licenseFile
  • linux
  • longDescription
  • macOS
  • publisher
  • resources
  • shortDescription
  • targets
  • useLocalToolsDir
  • windows
active

boolean

Whether Tauri should bundle your application or just output the executable.

android

AndroidConfig

Android configuration.

Default

{
  "autoIncrementVersionCode": false,
  "minSdkVersion": 24
}
category

string | null

The application kind.

Should be one of the following: Business, DeveloperTool, Education, Entertainment, Finance, Game, ActionGame, AdventureGame, ArcadeGame, BoardGame, CardGame, CasinoGame, DiceGame, EducationalGame, FamilyGame, KidsGame, MusicGame, PuzzleGame, RacingGame, RolePlayingGame, SimulationGame, SportsGame, StrategyGame, TriviaGame, WordGame, GraphicsAndDesign, HealthcareAndFitness, Lifestyle, Medical, Music, News, Photography, Productivity, Reference, SocialNetworking, Sports, Travel, Utility, Video, Weather.

string | null

A copyright string associated with your application.

createUpdaterArtifacts

Updater

Produce updaters and their signatures or not

externalBin

string[] | null

A list of—either absolute or relative—paths to binaries to embed with your application.

Note that Tauri will look for system-specific binaries following the pattern “binary-name{-target-triple}{.system-extension}”.

E.g. for the external binary “my-binary”, Tauri looks for:

  • “my-binary-x86_64-pc-windows-msvc.exe” for Windows
  • “my-binary-x86_64-apple-darwin” for macOS
  • “my-binary-x86_64-unknown-linux-gnu” for Linux

so dont forget to provide binaries for all targeted platforms.

fileAssociations

FileAssociation[] | null

File types to associate with the application.

homepage

string | null

A url to the home page of your application. If unset, will fallback to homepage defined in Cargo.toml.

Supported bundle targets: deb, rpm, nsis and msi.

icon

string[]

The apps icons

Default: []

iOS

IosConfig

iOS configuration.

Default

{
  "minimumSystemVersion": "14.0"
}
license

string | null

The packages license identifier to be included in the appropriate bundles. If not set, defaults to the license from the Cargo.toml file.

licenseFile

string | null

The path to the license file to be included in the appropriate bundles.

linux

LinuxConfig

Configuration for the Linux bundles.

Default

{
  "appimage": {
    "bundleMediaFramework": false,
    "files": {}
  },
  "deb": {
    "files": {}
  },
  "rpm": {
    "epoch": 0,
    "files": {},
    "release": "1"
  }
}
longDescription

string | null

A longer, multi-line description of the application.

macOS

MacConfig

Configuration for the macOS bundles.

Default

{
  "dmg": {
    "appPosition": {
      "x": 180,
      "y": 170
    },
    "applicationFolderPosition": {
      "x": 480,
      "y": 170
    },
    "windowSize": {
      "height": 400,
      "width": 660
    }
  },
  "files": {},
  "hardenedRuntime": true,
  "minimumSystemVersion": "10.13"
}
publisher

string | null

The applications publisher. Defaults to the second element in the identifier string.

Currently maps to the Manufacturer property of the Windows Installer and the Maintainer field of debian packages if the Cargo.toml does not have the authors field.

resources

BundleResources | null

App resources to bundle. Each resource is a path to a file or directory. Glob patterns are supported.

Examples

To include a list of files:

{
  "bundle": {
    "resources": [
      "./path/to/some-file.txt",
      "/absolute/path/to/textfile.txt",
      "../relative/path/to/jsonfile.json",
      "some-folder/",
      "resources/**/*.md"
    ]
  }
}

The bundled files will be in $RESOURCES/ with the original directory structure preserved, for example: ./path/to/some-file.txt -> $RESOURCE/path/to/some-file.txt

To fine control where the files will get copied to, use a map instead

{
  "bundle": {
    "resources": {
      "/absolute/path/to/textfile.txt": "resources/textfile.txt",
      "relative/path/to/jsonfile.json": "resources/jsonfile.json",
      "resources/": "",
      "docs/**/*md": "website-docs/"
    }
  }
}

Note that when using glob pattern in this case, the original directory structure is not preserved, everything gets copied to the target directory directly

See more: <https://v2.tauri.app/develop/resources/>

shortDescription

string | null

A short description of your application.

targets

BundleTarget

The bundle targets, currently supports [“deb”, “rpm”, “appimage”, “nsis”, “msi”, “app”, “dmg”] or “all”.

Default: "all"

useLocalToolsDir

boolean

Whether to use the projects target directory, for caching build tools (e.g., Wix and NSIS) when building this application. Defaults to false.

If true, tools will be cached in target/.tauri/. If false, tools will be cached in the current users platform-specific cache directory.

An example where it can be appropriate to set this to true is when building this application as a Windows System user (e.g., AWS EC2 workloads), because the Window systems app data directory is restricted.

windows

WindowsConfig

Configuration for the Windows bundles.

Default

{
  "allowDowngrades": true,
  "bundleVCRuntime": false,
  "certificateThumbprint": null,
  "digestAlgorithm": null,
  "minimumWebview2Version": null,
  "nsis": null,
  "signCommand": null,
  "timestampUrl": null,
  "tsp": false,
  "webviewInstallMode": {
    "silent": true,
    "type": "downloadBootstrapper"
  },
  "wix": null
}

BundleResources

Any of the following:

  • string[] A list of paths to include.
  • A map of source to target paths. Allows additional properties: string

Definition for bundle resources. Can be either a list of paths to include or a map of source to target paths.

BundleTarget

Any of the following:

  • "all" Bundle all targets.
  • BundleType[] A list of bundle targets.
  • BundleType A single bundle target.

Targets to bundle. Each value is case insensitive.

BundleType

One of the following:

  • "deb" The debian bundle (.deb).
  • "rpm" The RPM bundle (.rpm).
  • "appimage" The AppImage bundle (.appimage).
  • "msi" The Microsoft Installer bundle (.msi).
  • "nsis" The NSIS bundle (.exe).
  • "app" The macOS application bundle (.app).
  • "dmg" The Apple Disk Image bundle (.dmg).

A bundle referenced by tauri-bundler.

BundleTypeRole

One of the following:

  • "Editor" CFBundleTypeRole.Editor. Files can be read and edited.
  • "Viewer" CFBundleTypeRole.Viewer. Files can be read.
  • "Shell" CFBundleTypeRole.Shell
  • "QLGenerator" CFBundleTypeRole.QLGenerator
  • "None" CFBundleTypeRole.None

macOS-only. Corresponds to CFBundleTypeRole

Capability

A grouping and boundary mechanism developers can use to isolate access to the IPC layer.

It controls application windows and webviews fine grained access to the Tauri core, application, or plugin commands. If a webview or its window is not matching any capability then it has no access to the IPC layer at all.

This can be done to create groups of windows, based on their required system access, which can reduce impact of frontend vulnerabilities in less privileged windows. Windows can be added to a capability by exact name (e.g. main-window) or glob patterns like * or admin-*. A Window can have none, one, or multiple associated capabilities.

Example
{
  "identifier": "main-user-files-write",
  "description": "This capability allows the `main` window on macOS and Windows access to `filesystem` write related commands and `dialog` commands to enable programmatic access to files selected by the user.",
  "windows": [
    "main"
  ],
  "permissions": [
    "core:default",
    "dialog:open",
    {
      "identifier": "fs:allow-write-text-file",
      "allow": [{ "path": "$HOME/test.txt" }]
    },
  ],
  "platforms": ["macOS","windows"]
}

Object Properties:

  • description
  • identifier (required)
  • local
  • permissions (required)
  • platforms
  • remote
  • webviews
  • windows
description

string

Description of what the capability is intended to allow on associated windows.

It should contain a description of what the grouped permissions should allow.

Example

This capability allows the main window access to filesystem write related commands and dialog commands to enable programmatic access to files selected by the user.

identifier

string

Identifier of the capability.

Example

main-user-files-write

local

boolean

Whether this capability is enabled for local app URLs or not. Defaults to true.

Default: true

permissions

PermissionEntry[] each item must be unique

List of permissions attached to this capability.

Must include the plugin name as prefix in the form of ${plugin-name}:${permission-name}. For commands directly implemented in the application itself only ${permission-name} is required.

Example
[
  "core:default",
  "shell:allow-open",
  "dialog:open",
  {
    "identifier": "fs:allow-write-text-file",
    "allow": [{ "path": "$HOME/test.txt" }]
  }
]
platforms

Target[] | null

Limit which target platforms this capability applies to.

By default all platforms are targeted.

Example

["macOS","windows"]

remote

CapabilityRemote | null

Configure remote URLs that can use the capability permissions.

This setting is optional and defaults to not being set, as our default use case is that the content is served from our local application.

Caution

Make sure you understand the security implications of providing remote sources with local system access.

Example
{
  "urls": ["https://*.mydomain.dev"]
}
webviews

string[]

List of webviews that are affected by this capability. Can be a glob pattern.

The capability will be enabled on all the webviews whose label matches any of the patterns in this list, regardless of whether the webviews window label matches a pattern in [Self::windows].

Example

["sub-webview-one", "sub-webview-two"]

windows

string[]

List of windows that are affected by this capability. Can be a glob pattern.

If a window label matches any of the patterns in this list, the capability will be enabled on all the webviews of that window, regardless of the value of [Self::webviews].

On multiwebview windows, prefer specifying [Self::webviews] and omitting [Self::windows] for a fine grained access control.

Example

["main"]

CapabilityEntry

Any of the following:

  • Capability An inlined capability.
  • string Reference to a capability identifier.

A capability entry which can be either an inlined capability or a reference to a capability defined on its own file.

CapabilityRemote

Configuration for remote URLs that are associated with the capability.

Object Properties:

  • urls (required)
urls

string[]

Remote domains this capability refers to using the URLPattern standard.

Examples

Color

Any of the following:

  • string pattern of ^#?([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$ Color hex string, for example: #fff, #ffffff, or #ffffffff.
  • integer formatted as uint8 | integer formatted as uint8 | integer formatted as uint8[] maximum of 3 items, minimum of 3 items Array of RGB colors. Each value has minimum of 0 and maximum of 255.
  • integer formatted as uint8 | integer formatted as uint8 | integer formatted as uint8 | integer formatted as uint8[] maximum of 4 items, minimum of 4 items Array of RGBA colors. Each value has minimum of 0 and maximum of 255.
  • Object of red, green, blue, alpha color values. Each value has minimum of 0 and maximum of 255. Object Properties: - alpha - blue (required) - green (required) - red (required) ##### alpha integer formatted as uint8 Default: 255 ##### blue integer formatted as uint8 ##### green integer formatted as uint8 ##### red integer formatted as uint8

Csp

Any of the following:

  • string The entire CSP policy in a single text string.
  • An object mapping a directive with its sources values as a list of strings. Allows additional properties: CspDirectiveSources

A Content-Security-Policy definition. See <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>.

CspDirectiveSources

Any of the following:

  • string An inline list of CSP sources. Same as [Self::List], but concatenated with a space separator.
  • string[] A list of CSP sources. The collection will be concatenated with a space separator for the CSP string.

A Content-Security-Policy directive source list. See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/Sources#sources>.

CustomSignCommandConfig

Any of the following:

  • string A string notation of the script to execute. “%1” will be replaced with the path to the binary to be signed. This is a simpler notation for the command. Tauri will split the string with ' ' and use the first element as the command name and the rest as arguments. If you need to use whitespace in the command or arguments, use the object notation [Self::CommandWithOptions].
  • An object notation of the command. This is more complex notation for the command but this allows you to use whitespace in the command and arguments. Object Properties: - args (required) - cmd (required) ##### args string[] The arguments to pass to the command. “%1” will be replaced with the path to the binary to be signed. ##### cmd string The command to run to sign the binary.

Custom Signing Command configuration.

DebConfig

Configuration for Debian (.deb) bundles.

See more: <https://v2.tauri.app/reference/config/#debconfig>

Object Properties:

  • changelog
  • conflicts
  • depends
  • desktopTemplate
  • files
  • postInstallScript
  • postRemoveScript
  • preInstallScript
  • preRemoveScript
  • priority
  • provides
  • recommends
  • replaces
  • section
changelog

string | null

Path of the uncompressed Changelog file, to be stored at /usr/share/doc/package-name/changelog.gz. See <https://www.debian.org/doc/debian-policy/ch-docs.html#changelog-files-and-release-notes>

conflicts

string[] | null

The list of package conflicts.

depends

string[] | null

The list of deb dependencies your application relies on.

desktopTemplate

string | null

Path to a custom desktop file Handlebars template.

Available variables: categories, comment (optional), exec, icon and name.

files

The files to include on the package.

Allows additional properties: string

Default: {}

postInstallScript

string | null

Path to script that will be executed after the package is unpacked. See <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>

postRemoveScript

string | null

Path to script that will be executed after the package is removed. See <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>

preInstallScript

string | null

Path to script that will be executed before the package is unpacked. See <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>

preRemoveScript

string | null

Path to script that will be executed before the package is removed. See <https://www.debian.org/doc/debian-policy/ch-maintainerscripts.html>

priority

string | null

Change the priority of the Debian Package. By default, it is set to optional. Recognized Priorities as of now are : required, important, standard, optional, extra

provides

string[] | null

The list of dependencies the package provides.

recommends

string[] | null

The list of deb dependencies your application recommends.

replaces

string[] | null

The list of package replaces.

section

string | null

Define the section in Debian Control file. See : https://www.debian.org/doc/debian-policy/ch-archive.html#s-subsections

DisabledCspModificationKind

Any of the following:

  • boolean If true, disables all CSP modification. false is the default value and it configures Tauri to control the CSP.
  • string[] Disables the given list of CSP directives modifications.

The possible values for the dangerous_disable_asset_csp_modification config option.

DmgConfig

Configuration for Apple Disk Image (.dmg) bundles.

See more: <https://v2.tauri.app/reference/config/#dmgconfig>

Object Properties:

  • applicationFolderPosition
  • appPosition
  • background
  • windowPosition
  • windowSize
applicationFolderPosition

Position

Position of application folder on window.

Default

{
  "x": 480,
  "y": 170
}
appPosition

Position

Position of app file on window.

Default

{
  "x": 180,
  "y": 170
}
background

string | null

Image to use as the background in dmg file. Accepted formats: png/jpg/gif.

windowPosition

Position | null

Position of volume window on screen.

windowSize

Size

Size of volume window.

Default

{
  "height": 400,
  "width": 660
}

ExportedFileAssociation

The exported type definition. Maps to a UTExportedTypeDeclarations entry on macOS.

Object Properties:

  • conformsTo
  • identifier (required)
conformsTo

string[] | null

The types that this type conforms to. Maps to UTTypeConformsTo.

Examples are public.data, public.image, public.json and public.database.

identifier

string

The unique identifier for the exported type. Maps to UTTypeIdentifier.

FileAssociation

File association

Object Properties:

  • androidIntentActionFilters
  • contentTypes
  • description
  • exportedType
  • ext (required)
  • mimeType
  • name
  • rank
  • role
androidIntentActionFilters

AndroidIntentAction[] | null

Intent action filters for this file association.

By default all filters are used.

contentTypes

string[] | null

Declare support to a file with the given content type. Maps to LSItemContentTypes on macOS.

This allows supporting any file format declared by another application that conforms to this type. Declaration of new types can be done with [Self::exported_type] and linking to certain content types are done via [ExportedFileAssociation::conforms_to].

description

string | null

The association description. Windows-only. It is displayed on the Type column on Windows Explorer.

exportedType

ExportedFileAssociation | null

The exported type definition. Maps to a UTExportedTypeDeclarations entry on macOS.

You should define this if the associated file is a custom file type defined by your application.

ext

AssociationExt[]

File extensions to associate with this app. e.g. png

mimeType

string | null

The mime-type of the association, e.g. 'image/png' or 'text/plain'.

  • Linux: written as MimeType= in the .desktop file.
  • macOS / iOS: added as public.mime-type in the UTTypeTagSpecification dictionary of the UTExportedTypeDeclarations entry in Info.plist.
  • Android: used as android:mimeType in the &lt;data&gt; element of an &lt;intent-filter&gt; in AndroidManifest.xml.
name

string | null

The name. Maps to CFBundleTypeName on macOS. Default to ext[0]

rank

HandlerRank

The ranking of this app among apps that declare themselves as editors or viewers of the given file type. Maps to LSHandlerRank on macOS.

Default: "Default"

role

BundleTypeRole

The apps role with respect to the type. Maps to CFBundleTypeRole on macOS.

Default: "Editor"

FrontendDist

Any of the following:

  • string formatted as uri An external URL that should be used as the default application URL. No assets are embedded in the app in this case.
  • string Path to a directory containing the frontend dist assets.
  • string[] An array of files to embed in the app.

Defines the URL or assets to embed in the application.

FsScope

Any of the following:

  • string[] A list of paths that are allowed by this scope.
  • A complete scope configuration. Object Properties: - allow - deny - requireLiteralLeadingDot ##### allow string[] A list of paths that are allowed by this scope. Default: [] ##### deny string[] A list of paths that are not allowed by this scope. This gets precedence over the [Self::Scope::allow] list. Default: [] ##### requireLiteralLeadingDot boolean | null Whether or not paths that contain components that start with a . will require that . appears literally in the pattern; *, ?, **, or [...] will not match. This is useful because such files are conventionally considered hidden on Unix systems and it might be desirable to skip them when listing files. Defaults to true on Unix systems and false on Windows

Protocol scope definition. It is a list of glob patterns that restrict the API access from the webview.

Each pattern can start with a variable that resolves to a system base directory. The variables are: $AUDIO, $CACHE, $CONFIG, $DATA, $LOCALDATA, $DESKTOP, $DOCUMENT, $DOWNLOAD, $EXE, $FONT, $HOME, $PICTURE, $PUBLIC, $RUNTIME, $TEMPLATE, $VIDEO, $RESOURCE, $TEMP, $APPCONFIG, $APPDATA, $APPLOCALDATA, $APPCACHE, $APPLOG.

HandlerRank

One of the following:

  • "Default" LSHandlerRank.Default. This app is an opener of files of this type; this value is also used if no rank is specified.
  • "Owner" LSHandlerRank.Owner. This app is the primary creator of files of this type.
  • "Alternate" LSHandlerRank.Alternate. This app is a secondary viewer of files of this type.
  • "None" LSHandlerRank.None. This app is never selected to open files of this type, but it accepts drops of files of this type.

Corresponds to LSHandlerRank

HeaderConfig

A struct, where the keys are some specific http header names.

If the values to those keys are defined, then they will be send as part of a response message. This does not include error messages and ipc messages

Example configuration
{
 //..
  app:{
    //..
    security: {
      headers: {
        "Cross-Origin-Opener-Policy": "same-origin",
        "Cross-Origin-Embedder-Policy": "require-corp",
        "Timing-Allow-Origin": [
          "https://developer.mozilla.org",
          "https://example.com",
        ],
        "Access-Control-Expose-Headers": "Tauri-Custom-Header",
        "Tauri-Custom-Header": {
          "key1": "'value1' 'value2'",
          "key2": "'value3'"
        }
      },
      csp: "default-src 'self'; connect-src ipc: http://ipc.localhost",
    }
    //..
  }
 //..
}

In this example Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy are set to allow for the use of SharedArrayBuffer. The result is, that those headers are then set on every response sent via the get_response function in crates/tauri/src/protocol/tauri.rs. The Content-Security-Policy header is defined separately, because it is also handled separately.

For the helloworld example, this config translates into those response headers:

access-control-allow-origin:  http://tauri.localhost
access-control-expose-headers: Tauri-Custom-Header
content-security-policy: default-src 'self'; connect-src ipc: http://ipc.localhost; script-src 'self' 'sha256-Wjjrs6qinmnr+tOry8x8PPwI77eGpUFR3EEGZktjJNs='
content-type: text/html
cross-origin-embedder-policy: require-corp
cross-origin-opener-policy: same-origin
tauri-custom-header: key1 'value1' 'value2'; key2 'value3'
timing-allow-origin: https://developer.mozilla.org, https://example.com

Since the resulting header values are always string-like. So depending on the what data type the HeaderSource is, they need to be converted.

  • String(JS/Rust): stay the same for the resulting header value
  • Array(JS)/Vec\&lt;String\&gt;(Rust): Item are joined by “, “ for the resulting header value
  • Object(JS)/ Hashmap\&lt;String,String\&gt;(Rust): Items are composed from: key + space + value. Item are then joined by “; “ for the resulting header value

Object Properties:

  • Access-Control-Allow-Credentials
  • Access-Control-Allow-Headers
  • Access-Control-Allow-Methods
  • Access-Control-Expose-Headers
  • Access-Control-Max-Age
  • Cross-Origin-Embedder-Policy
  • Cross-Origin-Opener-Policy
  • Cross-Origin-Resource-Policy
  • Permissions-Policy
  • Service-Worker-Allowed
  • Tauri-Custom-Header
  • Timing-Allow-Origin
  • X-Content-Type-Options
Access-Control-Allow-Credentials

HeaderSource | null

The Access-Control-Allow-Credentials response header tells browsers whether the server allows cross-origin HTTP requests to include credentials.

See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials>

Access-Control-Allow-Headers

HeaderSource | null

The Access-Control-Allow-Headers response header is used in response to a preflight request which includes the Access-Control-Request-Headers to indicate which HTTP headers can be used during the actual request.

This header is required if the request has an Access-Control-Request-Headers header.

See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Headers>

Access-Control-Allow-Methods

HeaderSource | null

The Access-Control-Allow-Methods response header specifies one or more methods allowed when accessing a resource in response to a preflight request.

See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods>

Access-Control-Expose-Headers

HeaderSource | null

The Access-Control-Expose-Headers response header allows a server to indicate which response headers should be made available to scripts running in the browser, in response to a cross-origin request.

See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers>

Access-Control-Max-Age

HeaderSource | null

The Access-Control-Max-Age response header indicates how long the results of a preflight request (that is the information contained in the Access-Control-Allow-Methods and Access-Control-Allow-Headers headers) can be cached.

See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age>

Cross-Origin-Embedder-Policy

HeaderSource | null

The HTTP Cross-Origin-Embedder-Policy (COEP) response header configures embedding cross-origin resources into the document.

See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy>

Cross-Origin-Opener-Policy

HeaderSource | null

The HTTP Cross-Origin-Opener-Policy (COOP) response header allows you to ensure a top-level document does not share a browsing context group with cross-origin documents. COOP will process-isolate your document and potential attackers cant access your global object if they were to open it in a popup, preventing a set of cross-origin attacks dubbed XS-Leaks.

See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy>

Cross-Origin-Resource-Policy

HeaderSource | null

The HTTP Cross-Origin-Resource-Policy response header conveys a desire that the browser blocks no-cors cross-origin/cross-site requests to the given resource.

See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Resource-Policy>

Permissions-Policy

HeaderSource | null

The HTTP Permissions-Policy header provides a mechanism to allow and deny the use of browser features in a document or within any &lt;iframe&gt; elements in the document.

See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy>

Service-Worker-Allowed

HeaderSource | null

The HTTP Service-Worker-Allowed response header is used to broaden the path restriction for a service workers default scope.

By default, the scope for a service worker registration is the directory where the service worker script is located. For example, if the script sw.js is located in /js/sw.js, it can only control URLs under /js/ by default. Servers can use the Service-Worker-Allowed header to allow a service worker to control URLs outside of its own directory.

See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Service-Worker-Allowed>

Tauri-Custom-Header

HeaderSource | null

A custom header field Tauri-Custom-Header, dont use it. Remember to set Access-Control-Expose-Headers accordingly

NOT INTENDED FOR PRODUCTION USE

Timing-Allow-Origin

HeaderSource | null

The Timing-Allow-Origin response header specifies origins that are allowed to see values of attributes retrieved via features of the Resource Timing API, which would otherwise be reported as zero due to cross-origin restrictions.

See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Timing-Allow-Origin>

X-Content-Type-Options

HeaderSource | null

The X-Content-Type-Options response HTTP header is a marker used by the server to indicate that the MIME types advertised in the Content-Type headers should be followed and not be changed. The header allows you to avoid MIME type sniffing by saying that the MIME types are deliberately configured.

See <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options>

HeaderSource

Any of the following:

  • string string version of the header Value
  • string[] list version of the header value. Item are joined by “,” for the real header value
  • (Rust struct | Json | JavaScript Object) equivalent of the header value. Items are composed from: key + space + value. Item are then joined by “;” for the real header value Allows additional properties: string

definition of a header source

The header value to a header name

HookCommand

Any of the following:

  • string Run the given script with the default options.
  • Run the given script with custom options. Object Properties: - cwd - script (required) ##### cwd string | null The current working directory. ##### script string The script to execute.

Describes a shell command to be executed when a CLI hook is triggered.

Identifier

string

IosConfig

General configuration for the iOS target.

Object Properties:

  • bundleVersion
  • developmentTeam
  • frameworks
  • infoPlist
  • minimumSystemVersion
  • template
bundleVersion

string | null

The version of the build that identifies an iteration of the bundle.

Translates to the bundles CFBundleVersion property.

developmentTeam

string | null

The development team. This value is required for iOS development because code signing is enforced. The APPLE_DEVELOPMENT_TEAM environment variable can be set to overwrite it.

frameworks

string[] | null

A list of strings indicating any iOS frameworks that need to be bundled with the application.

Note that you need to recreate the iOS project for the changes to be applied.

infoPlist

string | null

Path to a Info.plist file to merge with the default Info.plist.

Note that Tauri also looks for a Info.plist and Info.ios.plist file in the same directory as the Tauri configuration file.

minimumSystemVersion

string

A version string indicating the minimum iOS version that the bundled application supports. Defaults to 13.0.

Maps to the IPHONEOS_DEPLOYMENT_TARGET value.

Default: "14.0"

template

string | null

A custom XcodeGen project.yml template to use.

LinuxConfig

Configuration for Linux bundles.

See more: <https://v2.tauri.app/reference/config/#linuxconfig>

Object Properties:

  • appimage
  • deb
  • rpm
appimage

AppImageConfig

Configuration for the AppImage bundle.

Default

{
  "bundleMediaFramework": false,
  "files": {}
}
deb

DebConfig

Configuration for the Debian bundle.

Default

{
  "files": {}
}
rpm

RpmConfig

Configuration for the RPM bundle.

Default

{
  "epoch": 0,
  "files": {},
  "release": "1"
}

LogicalPosition

Position coordinates struct.

Object Properties:

  • x (required)
  • y (required)
x

number formatted as double

X coordinate.

y

number formatted as double

Y coordinate.

MacConfig

Configuration for the macOS bundles.

See more: <https://v2.tauri.app/reference/config/#macconfig>

Object Properties:

  • bundleName
  • bundleVersion
  • dmg
  • entitlements
  • exceptionDomain
  • files
  • frameworks
  • hardenedRuntime
  • infoPlist
  • minimumSystemVersion
  • providerShortName
  • signingIdentity
bundleName

string | null

The name of the builder that built the bundle.

Translates to the bundles CFBundleName property.

If not set, defaults to the packages product name.

bundleVersion

string | null

The version of the build that identifies an iteration of the bundle.

Translates to the bundles CFBundleVersion property.

dmg

DmgConfig

DMG-specific settings.

Default

{
  "appPosition": {
    "x": 180,
    "y": 170
  },
  "applicationFolderPosition": {
    "x": 480,
    "y": 170
  },
  "windowSize": {
    "height": 400,
    "width": 660
  }
}
entitlements

string | null

Path to the entitlements file.

exceptionDomain

string | null

Allows your application to communicate with the outside world. It should be a lowercase, without port and protocol domain name.

files

The files to include in the application relative to the Contents directory.

Allows additional properties: string

Default: {}

frameworks

string[] | null

A list of strings indicating any macOS X frameworks that need to be bundled with the application.

If a name is used, “.framework” must be omitted and it will look for standard install locations. You may also use a path to a specific framework.

hardenedRuntime

boolean

Whether the codesign should enable hardened runtime (for executables) or not.

Default: true

infoPlist

string | null

Path to a Info.plist file to merge with the default Info.plist.

Note that Tauri also looks for a Info.plist file in the same directory as the Tauri configuration file.

minimumSystemVersion

string | null

A version string indicating the minimum macOS X version that the bundled application supports. Defaults to 10.13.

Setting it to null completely removes the LSMinimumSystemVersion field on the bundles Info.plist and the MACOSX_DEPLOYMENT_TARGET environment variable.

Ignored in tauri dev.

An empty string is considered an invalid value so the default value is used.

Default: "10.13"

providerShortName

string | null

Provider short name for notarization.

signingIdentity

string | null

Identity to use for code signing.

NsisCompression

One of the following:

  • "zlib" ZLIB uses the deflate algorithm, it is a quick and simple method. With the default compression level it uses about 300 KB of memory.
  • "bzip2" BZIP2 usually gives better compression ratios than ZLIB, but it is a bit slower and uses more memory. With the default compression level it uses about 4 MB of memory.
  • "lzma" LZMA (default) is a new compression method that gives very good compression ratios. The decompression speed is high (10-20 MB/s on a 2 GHz CPU), the compression speed is lower. The memory size that will be used for decompression is the dictionary size plus a few KBs, the default is 8 MB.
  • "none" Disable compression

Compression algorithms used in the NSIS installer.

See <https://nsis.sourceforge.io/Reference/SetCompressor>

NsisConfig

Configuration for the Installer bundle using NSIS.

Object Properties:

  • compression
  • customLanguageFiles
  • displayLanguageSelector
  • headerImage
  • installerHooks
  • installerIcon
  • installMode
  • languages
  • minimumWebview2Version
  • sidebarImage
  • startMenuFolder
  • template
  • uninstallerHeaderImage
  • uninstallerIcon
compression

NsisCompression

Set the compression algorithm used to compress files in the installer.

See <https://nsis.sourceforge.io/Reference/SetCompressor>

Default: "lzma"

customLanguageFiles

| null

A key-value pair where the key is the language and the value is the path to a custom .nsh file that holds the translated text for tauris custom messages.

See <https://github.com/tauri-apps/tauri/blob/dev/crates/tauri-bundler/src/bundle/windows/nsis/languages/English.nsh> for an example .nsh file.

Note: the key must be a valid NSIS language and it must be added to the [Self::languages] array,

Allows additional properties: string

displayLanguageSelector

boolean

Whether to display a language selector dialog before the installer and uninstaller windows are rendered or not. By default the OS language is selected, with a fallback to the first language in the languages array.

headerImage

string | null

The path to a bitmap file to display on the header of installers pages.

The recommended dimensions are 150px x 57px.

installerHooks

string | null

A path to a .nsh file that contains special NSIS macros to be hooked into the main installer.nsi script.

Supported hooks are:

  • NSIS_HOOK_PREINSTALL: This hook runs before copying files, setting registry key values and creating shortcuts.
  • NSIS_HOOK_POSTINSTALL: This hook runs after the installer has finished copying all files, setting the registry keys and created shortcuts.
  • NSIS_HOOK_PREUNINSTALL: This hook runs before removing any files, registry keys and shortcuts.
  • NSIS_HOOK_POSTUNINSTALL: This hook runs after files, registry keys and shortcuts have been removed.
Example
!macro NSIS_HOOK_PREINSTALL
  MessageBox MB_OK "PreInstall"
!macroend


!macro NSIS_HOOK_POSTINSTALL
  MessageBox MB_OK "PostInstall"
!macroend


!macro NSIS_HOOK_PREUNINSTALL
  MessageBox MB_OK "PreUnInstall"
!macroend


!macro NSIS_HOOK_POSTUNINSTALL
  MessageBox MB_OK "PostUninstall"
!macroend
installerIcon

string | null

The path to an icon file used as the installer icon.

installMode

NSISInstallerMode

Whether the installation will be for all users or just the current user.

Default: "currentUser"

languages

string[] | null

A list of installer languages. Default to ["English"] if not set.

By default the OS language is used. If the OS language is not in the list of languages, the first language will be used. To allow the user to select the language, set display_language_selector to true.

See <https://github.com/kichik/nsis/tree/9465c08046f00ccb6eda985abbdbf52c275c6c4d/Contrib/Language%20files> for the complete list of languages.

minimumWebview2Version

string | null

Deprecated: use [WindowsConfig::minimum_webview2_version] (bundle &gt; windows &gt; minimumWebview2Version) instead.

Try to ensure that the WebView2 version is equal to or newer than this version, if the users WebView2 is older than this version, the installer will try to trigger a WebView2 update.

sidebarImage

string | null

The path to a bitmap file for the Welcome page and the Finish page.

The recommended dimensions are 164px x 314px.

startMenuFolder

string | null

Set the folder name for the start menu shortcut.

Use this option if you have multiple apps and wish to group their shortcuts under one folder or if you generally prefer to set your shortcut inside a folder.

Examples:

  • AwesomePublisher, shortcut will be placed in %AppData%\Microsoft\Windows\Start Menu\Programs\AwesomePublisher\&lt;your-app&gt;.lnk
  • If unset, shortcut will be placed in %AppData%\Microsoft\Windows\Start Menu\Programs\&lt;your-app&gt;.lnk
template

string | null

A custom .nsi template to use.

uninstallerHeaderImage

string | null

The path to a bitmap file to display on the header of uninstallers pages. Defaults to [Self::header_image]. If this is set but [Self::header_image] is not, a default image from NSIS will be applied to header_image

The recommended dimensions are 150px x 57px.

uninstallerIcon

string | null

The path to an icon file used as the uninstaller icon.

NSISInstallerMode

One of the following:

  • "currentUser" Default mode for the installer. Install the app by default in a directory that doesnt require Administrator access. Installer metadata will be saved under the HKCU registry path.
  • "perMachine" Install the app by default in the Program Files folder directory requires Administrator access for the installation. Installer metadata will be saved under the HKLM registry path.
  • "both" Combines both modes and allows the user to choose at install time whether to install for the current user or per machine. Note that this mode will require Administrator access even if the user wants to install it for the current user only. Installer metadata will be saved under the HKLM or HKCU registry path based on the users choice.

Install Modes for the NSIS installer.

Number

Any of the following:

  • integer formatted as int64 Represents an [i64].
  • number formatted as double Represents a [f64].

A valid ACL number.

PatternKind

One of the following:

  • Brownfield pattern. Object Properties: - use (required) ##### use "brownfield"
  • Isolation pattern. Recommended for security purposes. Object Properties: - options (required) - use (required) ##### options Object Properties: - dir (required) ###### dir string The dir containing the index.html file that contains the secure isolation application. ##### use "isolation"

The application pattern.

PermissionEntry

Any of the following:

  • Identifier Reference a permission or permission set by identifier.
  • Reference a permission or permission set by identifier and extends its scope. Object Properties: - allow - deny - identifier (required) ##### allow Value[] | null Data that defines what is allowed by the scope. ##### deny Value[] | null Data that defines what is denied by the scope. This should be prioritized by validation logic. ##### identifier Identifier Identifier of the permission or permission set.

An entry for a permission value in a [Capability] can be either a raw permission [Identifier] or an object that references a permission and extends its scope.

PluginConfig

The plugin configs holds a HashMap mapping a plugin name to its configuration object.

See more: <https://v2.tauri.app/reference/config/#pluginconfig>

Allows additional properties: true

Position

Position coordinates struct.

Object Properties:

  • x (required)
  • y (required)
x

integer formatted as uint32

X coordinate.

y

integer formatted as uint32

Y coordinate.

PreventOverflowConfig

Any of the following:

  • boolean Enable prevent overflow or not
  • PreventOverflowMargin Enable prevent overflow with a margin so that the windows size + this margin wont overflow the workarea

Prevent overflow with a margin

PreventOverflowMargin

Enable prevent overflow with a margin so that the windows size + this margin wont overflow the workarea

Object Properties:

  • height (required)
  • width (required)
height

integer formatted as uint32

Vertical margin in physical pixels

width

integer formatted as uint32

Horizontal margin in physical pixels

RpmCompression

One of the following:

  • Gzip compression Object Properties: - level (required) - type (required) ##### level integer formatted as uint32 Gzip compression level ##### type "gzip"
  • Zstd compression Object Properties: - level (required) - type (required) ##### level integer formatted as int32 Zstd compression level ##### type "zstd"
  • Xz compression Object Properties: - level (required) - type (required) ##### level integer formatted as uint32 Xz compression level ##### type "xz"
  • Bzip2 compression Object Properties: - level (required) - type (required) ##### level integer formatted as uint32 Bzip2 compression level ##### type "bzip2"
  • Disable compression Object Properties: - type (required) ##### type "none"

Compression algorithms used when bundling RPM packages.

RpmConfig

Configuration for RPM bundles.

Object Properties:

  • compression
  • conflicts
  • depends
  • desktopTemplate
  • epoch
  • files
  • obsoletes
  • postInstallScript
  • postRemoveScript
  • preInstallScript
  • preRemoveScript
  • provides
  • recommends
  • release
compression

RpmCompression | null

Compression algorithm and level. Defaults to Gzip with level 6.

conflicts

string[] | null

The list of RPM dependencies your application conflicts with. They must not be present in order for the package to be installed.

depends

string[] | null

The list of RPM dependencies your application relies on.

desktopTemplate

string | null

Path to a custom desktop file Handlebars template.

Available variables: categories, comment (optional), exec, icon and name.

epoch

integer formatted as uint32

The RPM epoch.

files

The files to include on the package.

Allows additional properties: string

Default: {}

obsoletes

string[] | null

The list of RPM dependencies your application supersedes - if this package is installed, packages listed as “obsoletes” will be automatically removed (if they are present).

postInstallScript

string | null

Path to script that will be executed after the package is unpacked. See <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>

postRemoveScript

string | null

Path to script that will be executed after the package is removed. See <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>

preInstallScript

string | null

Path to script that will be executed before the package is unpacked. See <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>

preRemoveScript

string | null

Path to script that will be executed before the package is removed. See <http://ftp.rpm.org/max-rpm/s1-rpm-inside-scripts.html>

provides

string[] | null

The list of RPM dependencies your application provides.

recommends

string[] | null

The list of RPM dependencies your application recommends.

release

string

The RPM release tag.

Default: "1"

RunnerConfig

Any of the following:

  • string A string specifying the binary to run.
  • An object with advanced configuration options. Object Properties: - args - cmd (required) - cwd ##### args string[] | null Arguments to pass to the command. ##### cmd string The binary to run. ##### cwd string | null The current working directory to run the command from.

The runner configuration.

ScrollBarStyle

One of the following:

The scrollbar style to use in the webview.

Platform-specific
  • Windows: This option must be given the same value for all webviews that target the same data directory.

SecurityConfig

Security configuration.

See more: <https://v2.tauri.app/reference/config/#securityconfig>

Object Properties:

  • assetProtocol
  • capabilities
  • csp
  • dangerousDisableAssetCspModification
  • devCsp
  • freezePrototype
  • headers
  • pattern
assetProtocol

AssetProtocolConfig

Custom protocol config.

Default

{
  "enable": false,
  "scope": []
}
capabilities

CapabilityEntry[]

List of capabilities that are enabled on the application.

By default (not set or empty list), all capability files from ./capabilities/ are included, by setting values in this entry, you have fine grained control over which capabilities are included

You can either reference a capability file defined in ./capabilities/ with its identifier or inline a [Capability]

Example
{
  "app": {
    "capabilities": [
      "main-window",
      {
        "identifier": "drag-window",
        "permissions": ["core:window:allow-start-dragging"]
      }
    ]
  }
}

Default: []

csp

Csp | null

The Content Security Policy that will be injected on all HTML files on the built application. If dev_csp is not specified, this value is also injected on dev.

This is a really important part of the configuration since it helps you ensure your WebView is secured. See <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>.

dangerousDisableAssetCspModification

DisabledCspModificationKind

Disables the Tauri-injected CSP sources.

At compile time, Tauri parses all the frontend assets and changes the Content-Security-Policy to only allow loading of your own scripts and styles by injecting nonce and hash sources. This stricts your CSP, which may introduce issues when using along with other flexing sources.

This configuration option allows both a boolean and a list of strings as value. A boolean instructs Tauri to disable the injection for all CSP injections, and a list of strings indicates the CSP directives that Tauri cannot inject.

WARNING: Only disable this if you know what you are doing and have properly configured the CSP. Your application might be vulnerable to XSS attacks without this Tauri protection.

devCsp

Csp | null

The Content Security Policy that will be injected on all HTML files on development.

This is a really important part of the configuration since it helps you ensure your WebView is secured. See <https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP>.

freezePrototype

boolean

Freeze the Object.prototype when using the custom protocol.

headers

HeaderConfig | null

The headers, which are added to every http response from tauri to the web view This doesnt include IPC Messages and error responses

pattern

PatternKind

The pattern to use.

Default

{
  "use": "brownfield"
}

Size

Size of the window.

Object Properties:

  • height (required)
  • width (required)
height

integer formatted as uint32

Height of the window.

width

integer formatted as uint32

Width of the window.

Target

One of the following:

  • "macOS" MacOS.
  • "windows" Windows.
  • "linux" Linux.
  • "android" Android.
  • "iOS" iOS.

Platform target.

Theme

One of the following:

  • "Light" Light theme.
  • "Dark" Dark theme.

System theme.

TitleBarStyle

One of the following:

  • "Visible" A normal title bar.
  • "Transparent" Makes the title bar transparent, so the window background color is shown instead. Useful if you dont need to have actual HTML under the title bar. This lets you avoid the caveats of using TitleBarStyle::Overlay. Will be more useful when Tauri lets you set a custom window background color.
  • "Overlay" Shows the title bar as a transparent overlay over the windows content. Keep in mind: - The height of the title bar is different on different OS versions, which can lead to window the controls and title not being where you dont expect. - You need to define a custom drag region to make your window draggable, however due to a limitation you cant drag the window when its not in focus <https://github.com/tauri-apps/tauri/issues/4316>. - The color of the window title depends on the system theme.

How the window title bar should be displayed on macOS.

TrayIconConfig

Configuration for application tray icon.

See more: <https://v2.tauri.app/reference/config/#trayiconconfig>

Object Properties:

  • iconAsTemplate
  • iconPath (required)
  • id
  • menuOnLeftClick
  • showMenuOnLeftClick
  • title
  • tooltip
iconAsTemplate

boolean

A Boolean value that determines whether the image represents a template image on macOS.

iconPath

string

Path to the default icon to use for the tray icon.

Note: this stores the image in raw pixels to the final binary, so keep the icon size (width and height) small or else its going to bloat your final executable

id

string | null

Set an id for this tray icon so you can reference it later, defaults to main.

menuOnLeftClick

boolean

No longer works since v2.2, use [Self::show_menu_on_left_click] instead

A Boolean value that determines whether the menu should appear when the tray icon receives a left click.

Platform-specific:
  • Linux: Unsupported.

Default: true

showMenuOnLeftClick

boolean

A Boolean value that determines whether the menu should appear when the tray icon receives a left click.

Platform-specific:
  • Linux: Unsupported.

Default: true

title

string | null

Title for MacOS tray

tooltip

string | null

Tray icon tooltip on Windows and macOS

Updater

Any of the following:

  • V1Compatible Generates legacy zipped v1 compatible updaters
  • boolean Produce updaters and their signatures or not

Updater type

V1Compatible

"v1Compatible",Generates legacy zipped v1 compatible updaters

Generates legacy zipped v1 compatible updaters

Value

Any of the following:

  • null Represents a null JSON value.
  • boolean Represents a [bool].
  • Number Represents a valid ACL [Number].
  • string Represents a [String].
  • Value[] Represents a list of other [Value]s.
  • Represents a map of [String] keys to [Value]s. Allows additional properties: Value

All supported ACL values.

WebviewInstallMode

One of the following:

  • Do not install the Webview2 as part of the Windows Installer. Object Properties: - type (required) ##### type "skip"
  • Download the bootstrapper and run it. Requires an internet connection. Results in a smaller installer size, but is not recommended on Windows 7. Object Properties: - silent - type (required) ##### silent boolean Instructs the installer to run the bootstrapper in silent mode. Defaults to true. Default: true ##### type "downloadBootstrapper"
  • Embed the bootstrapper and run it. Requires an internet connection. Increases the installer size by around 1.8MB, but offers better support on Windows 7. Object Properties: - silent - type (required) ##### silent boolean Instructs the installer to run the bootstrapper in silent mode. Defaults to true. Default: true ##### type "embedBootstrapper"
  • Embed the offline installer and run it. Does not require an internet connection. Increases the installer size by around 127MB. Object Properties: - silent - type (required) ##### silent boolean Instructs the installer to run the installer in silent mode. Defaults to true. Default: true ##### type "offlineInstaller"
  • Embed a fixed webview2 version and use it at runtime. Increases the installer size by around 180MB. Object Properties: - path (required) - type (required) ##### path string The path to the fixed runtime to use. The fixed version can be downloaded on the official website. The .cab file must be extracted to a folder and this folder path must be defined on this field. ##### type "fixedRuntime"

Install modes for the Webview2 runtime. Note that for the updater bundle [Self::DownloadBootstrapper] is used.

For more information see <https://v2.tauri.app/distribute/windows-installer/#webview2-installation-options>.

WebviewUrl

Any of the following:

  • string formatted as uri An external URL. Must use either the http or https schemes.
  • string The path portion of an app URL. For instance, to load tauri://localhost/users/john, you can simply provide users/john in this configuration.
  • string formatted as uri A custom protocol url, for example, doom://index.html

An URL to open on a Tauri webview window.

WindowConfig

The window configuration object.

See more: <https://v2.tauri.app/reference/config/#windowconfig>

Object Properties:

  • acceptFirstMouse
  • activityName
  • additionalBrowserArgs
  • allowLinkPreview
  • alwaysOnBottom
  • alwaysOnTop
  • backgroundColor
  • backgroundThrottling
  • browserExtensionsEnabled
  • center
  • closable
  • contentProtected
  • create
  • createdByActivityName
  • dataDirectory
  • dataStoreIdentifier
  • decorations
  • devtools
  • disableInputAccessoryView
  • dragDropEnabled
  • focus
  • focusable
  • fullscreen
  • generalAutofillEnabled
  • height
  • hiddenTitle
  • incognito
  • javascriptDisabled
  • label
  • limitNavigationsToAppBoundDomains
  • maxHeight
  • maximizable
  • maximized
  • maxWidth
  • minHeight
  • minimizable
  • minWidth
  • noRedirectionBitmap
  • parent
  • preventOverflow
  • proxyUrl
  • requestedBySceneIdentifier
  • resizable
  • scrollBarStyle
  • shadow
  • skipTaskbar
  • tabbingIdentifier
  • theme
  • title
  • titleBarStyle
  • trafficLightPosition
  • transparent
  • url
  • useHttpsScheme
  • userAgent
  • visible
  • visibleOnAllWorkspaces
  • width
  • windowClassname
  • windowEffects
  • x
  • y
  • zoomHotkeysEnabled
acceptFirstMouse

boolean

Whether clicking an inactive window also clicks through to the webview on macOS.

activityName

string | null

The name of the Android activity to create for this window.

additionalBrowserArgs

string | null

Defines additional browser arguments on Windows.

Warning

Webview instances with different browser arguments must also have different data directories.

By default wry passes --disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection so if you set this, you also need to disable these components by yourself if you want.

allowLinkPreview

boolean

on macOS and iOS there is a link preview on long pressing links, this is enabled by default. see https://docs.rs/objc2-web-kit/latest/objc2_web_kit/struct.WKWebView.html#method.allowsLinkPreview

Default: true

alwaysOnBottom

boolean

Whether the window should always be below other windows.

alwaysOnTop

boolean

Whether the window should always be on top of other windows.

backgroundColor

Color | null

Set the window and webview background color.

Platform-specific:
  • Windows: alpha channel is ignored for the window layer.
  • Windows: On Windows 7, alpha channel is ignored for the webview layer.
  • Windows: On Windows 8 and newer, if alpha channel is not 0, it will be ignored for the webview layer.
backgroundThrottling

BackgroundThrottlingPolicy | null

Change the default background throttling behaviour.

By default, browsers use a suspend policy that will throttle timers and even unload the whole tab (view) to free resources after roughly 5 minutes when a view became minimized or hidden. This will pause all tasks until the documents visibility state changes back from hidden to visible by bringing the view back to the foreground.

Platform-specific
  • Linux / Windows / Android: Unsupported. Workarounds like a pending WebLock transaction might suffice.
  • iOS: Supported since version 17.0+.
  • macOS: Supported since version 14.0+.

see <https://github.com/tauri-apps/tauri/issues/5250#issuecomment-2569380578>

browserExtensionsEnabled

boolean

Whether browser extensions can be installed for the webview process

Platform-specific:
center

boolean

Whether or not the window starts centered or not.

closable

boolean

Whether the windows native close button is enabled or not.

Platform-specific
  • Linux: “GTK+ will do its best to convince the window manager not to show a close button. Depending on the system, this function may not have any effect when called on a window that is already visible”
  • iOS / Android: Unsupported.

Default: true

contentProtected

boolean

Prevents the window contents from being captured by other apps.

create

boolean

Whether Tauri should create this window at app startup or not.

When this is set to false you must manually grab the config object via app.config().app.windows and create it with WebviewWindowBuilder::from_config.

Example:
tauri::Builder::default()
  .setup(|app| {
    tauri::WebviewWindowBuilder::from_config(app.handle(), &app.config().app.windows[0])?.build()?;
    Ok(())
  });

Default: true

createdByActivityName

string | null

The name of the Android activity that is creating this webview window.

This is important to determine which stack the activity will belong to.

dataDirectory

string | null

Set a custom path for the webviews data directory (localStorage, cache, etc.) relative to [appDataDir()]/${label}.

To set absolute paths, use WebviewWindowBuilder::data_directory

Platform-specific:
  • Windows: WebViews with different values for settings like additionalBrowserArgs, browserExtensionsEnabled or scrollBarStyle must have different data directories.
  • macOS / iOS: Unsupported, use dataStoreIdentifier instead.
  • Android: Unsupported.
dataStoreIdentifier

integer formatted as uint8[] | null maximum of 16 items, minimum of 16 items

Initialize the WebView with a custom data store identifier. This can be seen as a replacement for dataDirectory which is unavailable in WKWebView. See https://developer.apple.com/documentation/webkit/wkwebsitedatastore/init(foridentifier:)?language=objc

The array must contain 16 u8 numbers.

Platform-specific:
  • iOS: Supported since version 17.0+.
  • macOS: Supported since version 14.0+.
  • Windows / Linux / Android: Unsupported.
decorations

boolean

Whether the window should have borders and bars.

Default: true

devtools

boolean | null

Enable web inspector which is usually called browser devtools. Enabled by default.

This API works in debug builds, but requires devtools feature flag to enable it in release builds.

Platform-specific
  • macOS: This will call private functions on macOS.
  • Android: Open chrome://inspect/#devices in Chrome to get the devtools window. Wrys WebView devtools API isnt supported on Android.
  • iOS: Open Safari > Develop > [Your Device Name] > [Your WebView] to get the devtools window.
disableInputAccessoryView

boolean

Allows disabling the input accessory view on iOS.

The accessory view is the view that appears above the keyboard when a text input element is focused. It usually displays a view with “Done”, “Next” buttons.

dragDropEnabled

boolean

Whether the drag and drop handlers used internally to generate DragDropEvents are enabled on the webview. By default it is enabled.

Disabling it is required to use HTML5 drag and drop on the frontend on Windows since we replace the drag drop handler of WebView2.

Note: this setting maps to WebviewBuilder::disable_drag_drop_handler, not WindowBuilder::drag_and_drop.

Default: true

focus

boolean

Whether the window will be initially focused or not.

Default: true

focusable

boolean

Whether the window will be focusable or not.

Default: true

fullscreen

boolean

Whether the window starts as fullscreen or not.

generalAutofillEnabled

boolean

Controls the WebViews browser-level general autofill behavior.

This option does not disable password or credit card autofill.

When set to false, the WebView will not automatically populate general form fields using previously stored data such as addresses or contact information.

If not specified, this is true by default.

Platform-specific
  • Windows: Supported. WebView2s autofill feature (called “Suggestions”) may not honor autocomplete="off" on input elements in some cases.
  • Linux / Android / iOS / macOS: Unsupported and performs no operation.

Default: true

height

number formatted as double

The window height in logical pixels.

Default: 600

hiddenTitle

boolean

If true, sets the window title to be hidden on macOS.

incognito

boolean

Whether or not the webview should be launched in incognito mode.

Platform-specific:
  • Android: Unsupported.
javascriptDisabled

boolean

Whether we should disable JavaScript code execution on the webview or not.

label

string

The window identifier. It must be alphanumeric.

Default: "main"

limitNavigationsToAppBoundDomains

boolean

Whether to limit navigations to App-Bound Domains. This is necessary to enable Service Workers on iOS according to StackOverflow.

Default is false.

Note: If you set this to true make sure to add localhost and any registrable domains used in this webview to tauri-src/Info.ios.plist:

&lt;plist&gt;
&lt;dict&gt;
    &lt;key&gt;WKAppBoundDomains&lt;/key&gt;
    &lt;array&gt;
        &lt;string&gt;localhost&lt;/string&gt;
        &lt;string&gt;aregistrabledomain.example&lt;/string&gt;
    &lt;/array&gt;
&lt;/dict&gt;
&lt;/plist&gt;

You must add localhost if any webview with this set to true opens a local webpage, makes any localhost calls, or uses the isolation pattern because Tauri uses the localhost domain for hosting the application webpage, the IPC protocol, and the isolation patterns iframe.

Requests served through custom uri schemes are allowed so long as they use a registrable domain specified in the WKAppBoundDomains array for all the requests from the app, including requests for the localhost domain.

In theory, you can whitelist an entire uri scheme by including the protocol name followed by a colon. For example, to allow all requests using a custom “stream” uri scheme (see this tauri example), you could add stream: to the AppBoundDomains array. That said, Im not sure whether Apple would let your app through app review if you do whitelist an entire protocol because this feature is not mentioned in their blog post on App-Bound Domains.

See https://webkit.org/blog/10882/app-bound-domains/ and https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/limitsnavigationstoappbounddomains for the official documentation on App-Bound Domains.

Platform-specific
  • iOS: Supported since version 14.0+.
  • Linux / Windows / Android / MacOS: Unsupported.
maxHeight

number | null formatted as double

The max window height in logical pixels.

maximizable

boolean

Whether the windows native maximize button is enabled or not. If resizable is set to false, this setting is ignored.

Platform-specific
  • macOS: Disables the “zoom” button in the window titlebar, which is also used to enter fullscreen mode.
  • Linux / iOS / Android: Unsupported.

Default: true

maximized

boolean

Whether the window is maximized or not.

maxWidth

number | null formatted as double

The max window width in logical pixels.

minHeight

number | null formatted as double

The min window height in logical pixels.

minimizable

boolean

Whether the windows native minimize button is enabled or not.

Platform-specific
  • Linux / iOS / Android: Unsupported.

Default: true

minWidth

number | null formatted as double

The min window width in logical pixels.

noRedirectionBitmap

boolean

This sets WS_EX_NOREDIRECTIONBITMAP.

This can avoid the white flash that may appear before the webview content is rendered when using a transparent window. Windows only.

parent

string | null

Sets the window associated with this label to be the parent of the window to be created.

Platform-specific
preventOverflow

PreventOverflowConfig | null

Whether or not to prevent the window from overflowing the workarea

Platform-specific
  • iOS / Android: Unsupported.
proxyUrl

string | null formatted as uri

The proxy URL for the WebView for all network requests.

Must be either a http:// or a socks5:// URL.

Platform-specific
  • macOS: Requires the macos-proxy feature flag and only compiles for macOS 14+.
requestedBySceneIdentifier

string | null

Sets the identifier of the scene that is requesting the new scene, establishing a relationship between the two scenes.

By default the system uses the foreground scene.

resizable

boolean

Whether the window is resizable or not. When resizable is set to false, native windows maximize button is automatically disabled.

Default: true

scrollBarStyle

ScrollBarStyle

Specifies the native scrollbar style to use with the webview. CSS styles that modify the scrollbar are applied on top of the native appearance configured here.

Defaults to default, which is the browser default.

Platform-specific
  • Windows:

    • fluentOverlay requires WebView2 Runtime version 125.0.2535.41 or higher, and does nothing on older versions.
    • This option must be given the same value for all webviews that target the same data directory.
  • Linux / Android / iOS / macOS: Unsupported. Only supports Default and performs no operation.

Default: "default"

shadow

boolean

Whether or not the window has shadow.

Platform-specific
  • Windows:

    • false has no effect on decorated window, shadow are always ON.
    • true will make undecorated window have a 1px white border, and on Windows 11, it will have a rounded corners.
  • Linux: Unsupported.

Default: true

skipTaskbar

boolean

If true, hides the window icon from the taskbar on Windows and Linux.

tabbingIdentifier

string | null

Defines the window tabbing identifier for macOS.

Windows with matching tabbing identifiers will be grouped together. If the tabbing identifier is not set, automatic tabbing will be disabled.

theme

Theme | null

The initial window theme. Defaults to the system theme. Only implemented on Windows and macOS 10.14+.

title

string

The window title.

Default: "Tauri App"

titleBarStyle

TitleBarStyle

The style of the macOS title bar.

Default: "Visible"

trafficLightPosition

LogicalPosition | null

The position of the window controls on macOS.

Requires titleBarStyle: Overlay and decorations: true.

transparent

boolean

Whether the window is transparent or not.

Note that on macOS this requires the macos-private-api feature flag, enabled under tauri &gt; macOSPrivateApi. WARNING: Using private APIs on macOS prevents your application from being accepted to the App Store.

On Windows, using noRedirectionBitmap can help avoid a white flash when creating a transparent window.

url

WebviewUrl

The window webview URL.

Default: "index.html"

useHttpsScheme

boolean

Sets whether the custom protocols should use https://&lt;scheme&gt;.localhost instead of the default http://&lt;scheme&gt;.localhost on Windows and Android. Defaults to false.

Note

Using a https scheme will NOT allow mixed content when trying to fetch http endpoints and therefore will not match the behavior of the &lt;scheme&gt;://localhost protocols used on macOS and Linux.

Warning

Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access the old data.

userAgent

string | null

The user agent for the webview

visible

boolean

Whether the window is visible or not.

Default: true

visibleOnAllWorkspaces

boolean

Whether the window should be visible on all workspaces or virtual desktops.

Platform-specific
  • Windows / iOS / Android: Unsupported.
width

number formatted as double

The window width in logical pixels.

Default: 800

windowClassname

string | null

The name of the window class created on Windows to create the window. Windows only.

windowEffects

WindowEffectsConfig | null

Window effects.

Requires the window to be transparent.

Platform-specific:
x

number | null formatted as double

The horizontal position of the windows top left corner in logical pixels

y

number | null formatted as double

The vertical position of the windows top left corner in logical pixels

zoomHotkeysEnabled

boolean

Whether page zooming by hotkeys is enabled

Platform-specific:
  • Windows: Controls WebView2s IsZoomControlEnabled setting.

  • MacOS / Linux: Injects a polyfill that zooms in and out with ctrl/command + -/=, 20% in each step, ranging from 20% to 1000%. Requires webview:allow-set-webview-zoom permission

  • Android / iOS: Unsupported.

WindowEffect

One of the following:

  • "appearanceBased" A default material appropriate for the views effectiveAppearance. macOS 10.14-
  • "light" macOS 10.14-
  • "dark" macOS 10.14-
  • "mediumLight" macOS 10.14-
  • "ultraDark" macOS 10.14-
  • "titlebar" macOS 10.10+
  • "selection" macOS 10.10+
  • "menu" macOS 10.11+
  • "popover" macOS 10.11+
  • "sidebar" macOS 10.11+
  • "headerView" macOS 10.14+
  • "sheet" macOS 10.14+
  • "windowBackground" macOS 10.14+
  • "hudWindow" macOS 10.14+
  • "fullScreenUI" macOS 10.14+
  • "tooltip" macOS 10.14+
  • "contentBackground" macOS 10.14+
  • "underWindowBackground" macOS 10.14+
  • "underPageBackground" macOS 10.14+
  • "mica" Mica effect that matches the system dark preference Windows 11 Only
  • "micaDark" Mica effect with dark mode but only if dark mode is enabled on the system Windows 11 Only
  • "micaLight" Mica effect with light mode Windows 11 Only
  • "tabbed" Tabbed effect that matches the system dark preference Windows 11 Only
  • "tabbedDark" Tabbed effect with dark mode but only if dark mode is enabled on the system Windows 11 Only
  • "tabbedLight" Tabbed effect with light mode Windows 11 Only
  • "blur" Windows 7/10/11(22H1) Only ##### Notes This effect has bad performance when resizing/dragging the window on Windows 11 build 22621.
  • "acrylic" Windows 10/11 Only ##### Notes This effect has bad performance when resizing/dragging the window on Windows 10 v1903+ and Windows 11 build 22000.

Platform-specific window effects

WindowEffectsConfig

The window effects configuration object

Object Properties:

  • color
  • effects (required)
  • radius
  • state
color

Color | null

Window effect color. Affects [WindowEffect::Blur] and [WindowEffect::Acrylic] only on Windows 10 v1903+. Doesnt have any effect on Windows 7 or Windows 11.

effects

WindowEffect[]

List of Window effects to apply to the Window. Conflicting effects will apply the first one and ignore the rest.

radius

number | null formatted as double

Window effect corner radius macOS Only

state

WindowEffectState | null

Window effect state macOS Only

WindowEffectState

One of the following:

  • "followsWindowActiveState" Make window effect state follow the windows active state
  • "active" Make window effect state always active
  • "inactive" Make window effect state always inactive

Window effect state macOS only

<https://developer.apple.com/documentation/appkit/nsvisualeffectview/state>

WindowsBuildConfig

Windows-specific build configuration.

Object Properties:

  • staticVCRuntime
staticVCRuntime

boolean

Whether to statically link the Visual C++ runtime into the application binary on Windows MSVC targets.

Default: true

WindowsConfig

Windows bundler configuration.

See more: <https://v2.tauri.app/reference/config/#windowsconfig>

Object Properties:

  • allowDowngrades
  • bundleVCRuntime
  • certificateThumbprint
  • digestAlgorithm
  • minimumWebview2Version
  • nsis
  • signCommand
  • timestampUrl
  • tsp
  • webviewInstallMode
  • wix
allowDowngrades

boolean

Validates a second app installation, blocking the user from installing an older version if set to false.

For instance, if 1.2.1 is installed, the user wont be able to install app version 1.2.0 or 1.1.5.

The default value of this flag is true.

Default: true

bundleVCRuntime

boolean

Whether to bundle the Visual C++ runtime DLLs alongside the application.

This can be particularly useful when your application includes sidecars or DLLs that do not statically link the Visual C++ runtime and require the runtime DLLs at runtime, and you do not want to require users to install the Visual C++ Redistributable. This can also be useful when build &gt; windows &gt; staticVCRuntime is set to false.

certificateThumbprint

string | null

Specifies the SHA1 hash of the signing certificate.

digestAlgorithm

string | null

Specifies the file digest algorithm to use for creating file signatures. Required for code signing. SHA-256 is recommended.

minimumWebview2Version

string | null

Try to ensure that the WebView2 version is equal to or newer than this version, if the users WebView2 is older than this version, the installer will try to trigger a WebView2 update.

nsis

NsisConfig | null

Configuration for the installer generated with NSIS.

signCommand

CustomSignCommandConfig | null

Specify a custom command to sign the binaries. This command needs to have a %1 in args which is just a placeholder for the binary path, which we will detect and replace before calling the command.

By Default we use signtool.exe which can be found only on Windows so if you are on another platform and want to cross-compile and sign you will need to use another tool like osslsigncode.

timestampUrl

string | null

Server to use during timestamping.

tsp

boolean

Whether to use Time-Stamp Protocol (TSP, a.k.a. RFC 3161) for the timestamp server. Your code signing provider may use a TSP timestamp server, like e.g. SSL.com does. If so, enable TSP by setting to true.

webviewInstallMode

WebviewInstallMode

The installation mode for the Webview2 runtime.

Default

{
  "silent": true,
  "type": "downloadBootstrapper"
}
wix

WixConfig | null

Configuration for the MSI generated with WiX.

WixConfig

Configuration for the MSI bundle using WiX.

See more: <https://v2.tauri.app/reference/config/#wixconfig>

Object Properties:

  • bannerPath
  • componentGroupRefs
  • componentRefs
  • dialogImagePath
  • enableElevatedUpdateTask
  • featureGroupRefs
  • featureRefs
  • fipsCompliant
  • fragmentPaths
  • language
  • mergeRefs
  • template
  • upgradeCode
  • version
bannerPath

string | null

Path to a bitmap file to use as the installation user interface banner. This bitmap will appear at the top of all but the first page of the installer.

The required dimensions are 493px × 58px.

componentGroupRefs

string[]

The ComponentGroup element ids you want to reference from the fragments.

Default: []

componentRefs

string[]

The Component element ids you want to reference from the fragments.

Default: []

dialogImagePath

string | null

Path to a bitmap file to use on the installation user interface dialogs. It is used on the welcome and completion dialogs.

The required dimensions are 493px × 312px.

enableElevatedUpdateTask

boolean

Create an elevated update task within Windows Task Scheduler.

featureGroupRefs

string[]

The FeatureGroup element ids you want to reference from the fragments.

Default: []

featureRefs

string[]

The Feature element ids you want to reference from the fragments.

Default: []

fipsCompliant

boolean

Enables FIPS compliant algorithms. Can also be enabled via the TAURI_BUNDLER_WIX_FIPS_COMPLIANT env var.

fragmentPaths

string[]

A list of paths to .wxs files with WiX fragments to use.

Default: []

language

WixLanguage

The installer languages to build. See <https://docs.microsoft.com/en-us/windows/win32/msi/localizing-the-error-and-actiontext-tables>.

Default: "en-US"

mergeRefs

string[]

The Merge element ids you want to reference from the fragments.

Default: []

template

string | null

A custom .wxs template to use.

upgradeCode

string | null formatted as uuid

A GUID upgrade code for MSI installer. This code must stay the same across all of your updates, otherwise, Windows will treat your update as a different app and your users will have duplicate versions of your app.

By default, tauri generates this code by generating a Uuid v5 using the string &lt;productName&gt;.exe.app.x64 in the DNS namespace. You can use Tauris CLI to generate and print this code for you, run tauri inspect wix-upgrade-code.

It is recommended that you set this value in your tauri config file to avoid accidental changes in your upgrade code whenever you want to change your product name.

version

string | null

MSI installer version in the format major.minor.patch.build (build is optional).

Because a valid version is required for MSI installer, it will be derived from [Config::version] if this field is not set.

The first field is the major version and has a maximum value of 255. The second field is the minor version and has a maximum value of 255. The third and fourth fields have a maximum value of 65,535.

See <https://learn.microsoft.com/en-us/windows/win32/msi/productversion> for more info.

WixLanguage

Any of the following:

  • string A single language to build, without configuration.
  • string[] A list of languages to build, without configuration.
  • A map of languages and its configuration. Allows additional properties: WixLanguageConfig

The languages to build using WiX.

WixLanguageConfig

Configuration for a target language for the WiX build.

See more: <https://v2.tauri.app/reference/config/#wixlanguageconfig>

Object Properties:

  • localePath
localePath

string | null

The path to a locale (.wxl) file. See <https://wixtoolset.org/documentation/manual/v3/howtos/ui_and_localization/build_a_localized_version.html>.

Environment Variables

This is a documentation of all environment variables used by tauri core crates and tauri CLI.

Tauri CLI

These environment variables are inputs to the CLI which may have an equivalent CLI flag.

Environment Variable Priority

If both environment variable and CLI flag are used, the CLI flag will have priority.

  • CI — If set, the CLI will run in CI mode and wont require any user interaction.
  • TAURI_CLI_CONFIG_DEPTH — Number of levels to traverse and find tauri configuration file.
  • TAURI_CLI_PORT — Port to use for the CLI built-in dev server.
  • TAURI_CLI_WATCHER_IGNORE_FILENAME — Name of a .gitignore-style file to control which files should be watched by the CLI in dev command. The CLI will look for this file name in each directory.
  • TAURI_CLI_NO_DEV_SERVER_WAIT — Skip waiting for the frontend dev server to start before building the tauri application.
  • TAURI_LINUX_AYATANA_APPINDICATOR — Set this var to true or 1 to force usage of libayatana-appindicator for system tray on Linux.
  • TAURI_BUNDLER_WIX_FIPS_COMPLIANT — Specify the bundlers WiX FipsCompliant option.
  • TAURI_BUNDLER_TOOLS_GITHUB_MIRROR - Specify a GitHub mirror to download files and tools used by tauri bundler.
  • TAURI_BUNDLER_TOOLS_GITHUB_MIRROR_TEMPLATE - Specify a GitHub mirror template to download files and tools used by tauri bundler, for example: https://mirror.example.com/<owner>/<repo>/releases/download/<version>/<asset>.
  • TAURI_SKIP_SIDECAR_SIGNATURE_CHECK - Skip signing sidecars.
  • TAURI_SIGNING_PRIVATE_KEY — Private key used to sign your app bundles, can be either a string or a path to the file.
  • TAURI_SIGNING_PRIVATE_KEY_PASSWORD — The signing private key password, see TAURI_SIGNING_PRIVATE_KEY.
  • TAURI_SIGNING_RPM_KEY — The private GPG key used to sign the RPM bundle, exported to its ASCII-armored format.
  • TAURI_SIGNING_RPM_KEY_PASSPHRASE — The GPG key passphrase for TAURI_SIGNING_RPM_KEY, if needed.
  • TAURI_WINDOWS_SIGNTOOL_PATH — Specify a path to signtool.exe used for code signing the application on Windows.
  • APPLE_CERTIFICATE — Base64 encoded of the .p12 certificate for code signing. To get this value, run openssl base64 -A -in MyCertificate.p12 -out MyCertificate-base64.txt.
  • APPLE_CERTIFICATE_PASSWORD — The password you used to export the certificate.
  • APPLE_ID — The Apple ID used to notarize the application. If this environment variable is provided, APPLE_PASSWORD and APPLE_TEAM_ID must also be set. Alternatively, APPLE_API_KEY and APPLE_API_ISSUER can be used to authenticate.
  • APPLE_PASSWORD — The Apple password used to authenticate for application notarization. Required if APPLE_ID is specified. An app-specific password can be used. Alternatively to entering the password in plaintext, it may also be specified using a @keychain: or @env: prefix followed by a keychain password item name or environment variable name.
  • APPLE_TEAM_ID: Developer team ID. To find your Team ID, go to the Account page on the Apple Developer website, and check your membership details.
  • APPLE_API_KEY — Alternative to APPLE_ID and APPLE_PASSWORD for notarization authentication using JWT. Also an option to allow automated iOS certificate and provisioning profile management.
  • API_PRIVATE_KEYS_DIR — Specify the directory where your AuthKey file is located. See APPLE_API_KEY.
  • APPLE_API_ISSUER — Issuer ID. Required if APPLE_API_KEY is specified.
  • APPLE_API_KEY_PATH - path to the API key .p8 file. If not specified, for macOS apps the bundler searches the following directories in sequence for a private key file with the name of AuthKey_<api_key>.p8: ./private_keys, /private_keys, /.private_keys, and ~/.appstoreconnect/private_keys. For iOS this variable is required.
  • APPLE_SIGNING_IDENTITY — The identity used to code sign. Overwrites tauri.conf.json > bundle > macOS > signingIdentity. If neither are set, it is inferred from APPLE_CERTIFICATE when provided.
  • APPLE_PROVIDER_SHORT_NAME — If your Apple ID is connected to multiple teams, you have to specify the provider short name of the team you want to use to notarize your app. Overwrites tauri.conf.json > bundle > macOS > providerShortName.
  • APPLE_DEVELOPMENT_TEAM — The team ID used to code sign on iOS. Overwrites tauri.conf.json > bundle > iOS > developmentTeam. Can be found in https://developer.apple.com/account#MembershipDetailsCard.
  • TAURI_WEBVIEW_AUTOMATION — Enables webview automation (Linux Only).
  • TAURI_ANDROID_PROJECT_PATH — Path of the tauri android project, usually will be <project>/src-tauri/gen/android.
  • TAURI_IOS_PROJECT_PATH — Path of the tauri iOS project, usually will be <project>/src-tauri/gen/ios.

Tauri CLI Hook Commands

These environment variables are set for each hook command (beforeDevCommand, beforeBuildCommand, …etc) which could be useful to conditionally build your frontend or execute a specific action.

  • TAURI_ENV_DEBUGtrue for dev command or build --debug, false otherwise.
  • TAURI_ENV_TARGET_TRIPLE — Target triple the CLI is building.
  • TAURI_ENV_ARCH — Target arch, x86_64, aarch64…etc.
  • TAURI_ENV_PLATFORM — Target platform, windows, darwin, linux…etc.
  • TAURI_ENV_PLATFORM_VERSION — Build platform version
  • TAURI_ENV_FAMILY — Target platform family unix or windows.

@tauri-apps/api

The Tauri API allows you to interface with the backend layer.

This module exposes all other modules as an object where the key is the module name, and the value is the module exports.

Examples

import { event, window, path } from '@tauri-apps/api'

Vanilla JS API

The above import syntax is for JavaScript/TypeScript with a bundler. If youre using vanilla JavaScript, you can use the global window.__TAURI__ object instead. It requires app.withGlobalTauri configuration option enabled.

const { event, window: tauriWindow, path } = window.__TAURI__;

Namespaces

app

Enumerations

BundleType

Bundle type of the current application.

Enumeration Members

App
App: "app";

macOS app bundle

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L48

AppImage
AppImage: "appimage";

Linux AppImage

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L46

Deb
Deb: "deb";

Linux Debian package

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L42

Msi
Msi: "msi";

Windows MSI

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L40

Nsis
Nsis: "nsis";

Windows NSIS

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L38

Rpm
Rpm: "rpm";

Linux RPM

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L44

Type Aliases

DataStoreIdentifier

type DataStoreIdentifier: [number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number];

Identifier type used for data stores on macOS and iOS.

Represents a 128-bit identifier, commonly expressed as a 16-byte UUID.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L14


OnBackButtonPressPayload

type OnBackButtonPressPayload: object;

Payload for the onBackButtonPress event.

Type declaration

Name Type Description Defined in
canGoBack boolean Whether the webview canGoBack property is true. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L260

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L258

Functions

defaultWindowIcon()

function defaultWindowIcon(): Promise<Image | null>

Gets the default window icon.

Returns

Promise<Image | null>

Example

import { defaultWindowIcon } from '@tauri-apps/api/app';
const icon = await defaultWindowIcon();

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L197


fetchDataStoreIdentifiers()

function fetchDataStoreIdentifiers(): Promise<DataStoreIdentifier[]>

Fetches the data store identifiers on macOS and iOS.

See https://developer.apple.com/documentation/webkit/wkwebsitedatastore for more information.

Returns

Promise<DataStoreIdentifier[]>

Example

import { fetchDataStoreIdentifiers } from '@tauri-apps/api/app';
const ids = await fetchDataStoreIdentifiers();

Since

2.4.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L160


getBundleType()

function getBundleType(): Promise<BundleType>

Gets the application bundle type.

Returns

Promise<BundleType>

Example

import { getBundleType } from '@tauri-apps/api/app';
const type = await getBundleType();

Since

2.5.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L251


getIdentifier()

function getIdentifier(): Promise<string>

Gets the application identifier.

Returns

Promise<string>

The application identifier as configured in tauri.conf.json.

Example

import { getIdentifier } from '@tauri-apps/api/app';
const identifier = await getIdentifier();

Since

2.4.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L112


getName()

function getName(): Promise<string>

Gets the application name.

Returns

Promise<string>

Example

import { getName } from '@tauri-apps/api/app';
const appName = await getName();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L81


getTauriVersion()

function getTauriVersion(): Promise<string>

Gets the Tauri framework version used by this application.

Returns

Promise<string>

Example

import { getTauriVersion } from '@tauri-apps/api/app';
const tauriVersion = await getTauriVersion();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L96


getVersion()

function getVersion(): Promise<string>

Gets the application version.

Returns

Promise<string>

Example

import { getVersion } from '@tauri-apps/api/app';
const appVersion = await getVersion();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L67


hide()

function hide(): Promise<void>

Hides the application on macOS.

Returns

Promise<void>

Example

import { hide } from '@tauri-apps/api/app';
await hide();

Since

1.2.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L143


onBackButtonPress()

function onBackButtonPress(handler): Promise<PluginListener>

Listens to the backButton event on Android.

Parameters

Parameter Type Description
handler (payload) => void

Returns

Promise<PluginListener>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L267


removeDataStore()

function removeDataStore(uuid): Promise<void>

Removes the data store with the given identifier.

Note that any webview using this data store should be closed before running this API.

See https://developer.apple.com/documentation/webkit/wkwebsitedatastore for more information.

Parameters

Parameter Type
uuid DataStoreIdentifier

Returns

Promise<void>

Example

import { fetchDataStoreIdentifiers, removeDataStore } from '@tauri-apps/api/app';
for (const id of (await fetchDataStoreIdentifiers())) {
  await removeDataStore(id);
}

Since

2.4.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L181


setDockVisibility()

function setDockVisibility(visible): Promise<void>

Sets the dock visibility for the application on macOS.

Parameters

Parameter Type Description
visible boolean Whether the dock should be visible or not.

Returns

Promise<void>

Example

import { setDockVisibility } from '@tauri-apps/api/app';
await setDockVisibility(false);

Since

2.5.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L236


setTheme()

function setTheme(theme?): Promise<void>

Sets the applications theme. Pass in null or undefined to follow the system theme.

Parameters

Parameter Type
theme? null | Theme

Returns

Promise<void>

Example

import { setTheme } from '@tauri-apps/api/app';
await setTheme('dark');

Platform-specific

  • iOS / Android: Unsupported.

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L219


show()

function show(): Promise<void>

Shows the application on macOS. This function does not automatically focus any specific app window.

Returns

Promise<void>

Example

import { show } from '@tauri-apps/api/app';
await show();

Since

1.2.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L128


supportsMultipleWindows()

function supportsMultipleWindows(): Promise<boolean>

Returns

Promise<boolean>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/app.ts#L277

core

Invoke your custom commands.

This package is also accessible with window.__TAURI__.core when app.withGlobalTauri in tauri.conf.json is set to true.

Classes

Channel<T>

Type Parameters

Type Parameter Default type
T unknown

Constructors

new Channel()
new Channel<T>(onmessage?): Channel<T>
Parameters
Parameter Type
onmessage? (response) => void
Returns

Channel<T>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L87

Properties

Property Type Description Defined in
id number The callback id returned from transformCallback Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L79

Accessors

onmessage
get onmessage(): (response) => void
set onmessage(handler): void
Parameters
Parameter Type
handler (response) => void
Returns

Function

Parameters
Parameter Type
response T
Returns

void

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L142

Methods

__TAURI_TO_IPC_KEY__()
__TAURI_TO_IPC_KEY__(): string
Returns

string

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L146

toJSON()
toJSON(): string
Returns

string

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L150


PluginListener

Constructors

new PluginListener()
new PluginListener(
   plugin,
   event,
   channelId): PluginListener
Parameters
Parameter Type
plugin string
event string
channelId number
Returns

PluginListener

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L161

Properties

Property Type Defined in
channelId number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L159
event string Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L158
plugin string Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L157

Methods

unregister()
unregister(): Promise<void>
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L167


Resource

A rust-backed resource stored through tauri::Manager::resources_table API.

The resource lives in the main process and does not exist in the Javascript world, and thus will not be cleaned up automatically except on application exit. If you want to clean it up early, call Resource.close

Example

import { Resource, invoke } from '@tauri-apps/api/core';
export class DatabaseHandle extends Resource {
  static async open(path: string): Promise<DatabaseHandle> {
    const rid: number = await invoke('open_db', { path });
    return new DatabaseHandle(rid);
  }


  async execute(sql: string): Promise<void> {
    await invoke('execute_sql', { rid: this.rid, sql });
  }
}

Extended by

Constructors

new Resource()
new Resource(rid): Resource
Parameters
Parameter Type
rid number
Returns

Resource

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L322

Accessors

rid
get rid(): number
Returns

number

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L318

Methods

close()
close(): Promise<void>

Destroys and cleans up this resource from memory. You should not call any method on this object anymore and should drop any reference to it.

Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L330

Interfaces

InvokeOptions

Since

2.0.0

Properties

Property Type Defined in
headers HeadersInit Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L233

Type Aliases

InvokeArgs

type InvokeArgs: Record<string, unknown> | number[] | ArrayBuffer | Uint8Array;

Command arguments.

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L227


PermissionState

type PermissionState: "granted" | "denied" | "prompt" | "prompt-with-rationale";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L202

Variables

SERIALIZE_TO_IPC_FN

const SERIALIZE_TO_IPC_FN: "__TAURI_TO_IPC_KEY__" = '__TAURI_TO_IPC_KEY__';

A key to be used to implement a special function on your types that define how your type should be serialized when passing across the IPC.

Example

Given a type in Rust that looks like this

#[derive(serde::Serialize, serde::Deserialize)
enum UserId {
  String(String),
  Number(u32),
}

UserId::String("id") would be serialized into { String: "id" } and so we need to pass the same structure back to Rust

import { SERIALIZE_TO_IPC_FN } from "@tauri-apps/api/core"


class UserIdString {
  id
  constructor(id) {
    this.id = id
  }


  [SERIALIZE_TO_IPC_FN]() {
    return { String: this.id }
  }
}


class UserIdNumber {
  id
  constructor(id) {
    this.id = id
  }


  [SERIALIZE_TO_IPC_FN]() {
    return { Number: this.id }
  }
}


type UserId = UserIdString | UserIdNumber

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L59

Functions

addPluginListener()

function addPluginListener<T>(
   plugin,
   event,
cb): Promise<PluginListener>

Adds a listener to a plugin event.

Type Parameters

Type Parameter
T

Parameters

Parameter Type
plugin string
event string
cb (payload) => void

Returns

Promise<PluginListener>

The listener object to stop listening to the events.

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L182


checkPermissions()

function checkPermissions<T>(plugin): Promise<T>

Get permission state for a plugin.

This should be used by plugin authors to wrap their actual implementation.

Type Parameters

Type Parameter
T

Parameters

Parameter Type
plugin string

Returns

Promise<T>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L209


convertFileSrc()

function convertFileSrc(filePath, protocol): string

Convert a device file path to an URL that can be loaded by the webview. Note that asset: and http://asset.localhost must be added to app.security.csp in tauri.conf.json. Example CSP value: "csp": "default-src 'self' ipc: http://ipc.localhost; img-src 'self' asset: http://asset.localhost" to use the asset protocol on image sources.

Additionally, "enable" : "true" must be added to app.security.assetProtocol in tauri.conf.json and its access scope must be defined on the scope array on the same assetProtocol object.

Parameters

Parameter Type Default value Description
filePath string undefined The file path.
protocol string 'asset' The protocol to use. Defaults to asset. You only need to set this when using a custom protocol.

Returns

string

the URL that can be used as source on the webview.

Example

import { appDataDir, join } from '@tauri-apps/api/path';
import { convertFileSrc } from '@tauri-apps/api/core';
const appDataDirPath = await appDataDir();
const filePath = await join(appDataDirPath, 'assets/video.mp4');
const assetUrl = convertFileSrc(filePath);


const video = document.getElementById('my-video');
const source = document.createElement('source');
source.type = 'video/mp4';
source.src = assetUrl;
video.appendChild(source);
video.load();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L289


invoke()

function invoke<T>(
   cmd,
   args,
options?): Promise<T>

Sends a message to the backend.

Type Parameters

Type Parameter
T

Parameters

Parameter Type Description
cmd string The command name.
args InvokeArgs The optional arguments to pass to the command.
options? InvokeOptions The request options.

Returns

Promise<T>

A promise resolving or rejecting to the backend response.

Example

import { invoke } from '@tauri-apps/api/core';
await invoke('login', { user: 'tauri', password: 'poiwe3h4r5ip3yrhtew9ty' });

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L251


isTauri()

function isTauri(): boolean

Returns

boolean

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L337


requestPermissions()

function requestPermissions<T>(plugin): Promise<T>

Request permissions.

This should be used by plugin authors to wrap their actual implementation.

Type Parameters

Type Parameter
T

Parameters

Parameter Type
plugin string

Returns

Promise<T>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L218


transformCallback()

function transformCallback<T>(callback?, once?): number

Stores the callback in a known location, and returns an identifier that can be passed to the backend. The backend uses the identifier to eval() the callback.

Type Parameters

Type Parameter Default type
T unknown

Parameters

Parameter Type Default value
callback? (response) => void undefined
once? boolean false

Returns

number

An unique identifier associated with the callback function.

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L69

dpi

Classes

LogicalPosition

A position represented in logical pixels. For an explanation of what logical pixels are, see description of LogicalSize.

Since

2.0.0

Constructors

new LogicalPosition()
new LogicalPosition(x, y): LogicalPosition
Parameters
Parameter Type
x number
y number
Returns

LogicalPosition

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L219

new LogicalPosition()
new LogicalPosition(object): LogicalPosition
Parameters
Parameter Type
object object
object.Logical object
object.Logical.x number
object.Logical.y number
Returns

LogicalPosition

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L220

new LogicalPosition()
new LogicalPosition(object): LogicalPosition
Parameters
Parameter Type
object object
object.x number
object.y number
Returns

LogicalPosition

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L221

Properties

Property Modifier Type Default value Defined in
type readonly "Logical" 'Logical' Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L215
x public number undefined Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L216
y public number undefined Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L217

Methods

__TAURI_TO_IPC_KEY__()
__TAURI_TO_IPC_KEY__(): object
Returns

object

Name Type Defined in
x number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L263
y number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L264

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L261

toJSON()
toJSON(): object
Returns

object

Name Type Defined in
x number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L263
y number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L264

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L268

toPhysical()
toPhysical(scaleFactor): PhysicalPosition

Converts the logical position to a physical one.

Parameters
Parameter Type
scaleFactor number
Returns

PhysicalPosition

Example
import { LogicalPosition } from '@tauri-apps/api/dpi';
import { getCurrentWindow } from '@tauri-apps/api/window';


const appWindow = getCurrentWindow();
const factor = await appWindow.scaleFactor();
const position = new LogicalPosition(400, 500);
const physical = position.toPhysical(factor);
Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L257


LogicalSize

A size represented in logical pixels. Logical pixels are scaled according to the windows DPI scale. Most browser APIs (i.e. MouseEvents clientX) will return logical pixels.

For logical-pixel-based position, see LogicalPosition.

Since

2.0.0

Constructors

new LogicalSize()
new LogicalSize(width, height): LogicalSize
Parameters
Parameter Type
width number
height number
Returns

LogicalSize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L21

new LogicalSize()
new LogicalSize(object): LogicalSize
Parameters
Parameter Type
object object
object.Logical object
object.Logical.height number
object.Logical.width number
Returns

LogicalSize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L22

new LogicalSize()
new LogicalSize(object): LogicalSize
Parameters
Parameter Type
object object
object.height number
object.width number
Returns

LogicalSize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L23

Properties

Property Modifier Type Default value Defined in
height public number undefined Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L19
type readonly "Logical" 'Logical' Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L17
width public number undefined Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L18

Methods

__TAURI_TO_IPC_KEY__()
__TAURI_TO_IPC_KEY__(): object
Returns

object

Name Type Defined in
height number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L66
width number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L65

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L63

toJSON()
toJSON(): object
Returns

object

Name Type Defined in
height number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L66
width number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L65

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L70

toPhysical()
toPhysical(scaleFactor): PhysicalSize

Converts the logical size to a physical one.

Parameters
Parameter Type
scaleFactor number
Returns

PhysicalSize

Example
import { LogicalSize } from '@tauri-apps/api/dpi';
import { getCurrentWindow } from '@tauri-apps/api/window';


const appWindow = getCurrentWindow();
const factor = await appWindow.scaleFactor();
const size = new LogicalSize(400, 500);
const physical = size.toPhysical(factor);
Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L59


PhysicalPosition

A position represented in physical pixels.

For an explanation of what physical pixels are, see description of PhysicalSize.

Since

2.0.0

Constructors

new PhysicalPosition()
new PhysicalPosition(x, y): PhysicalPosition
Parameters
Parameter Type
x number
y number
Returns

PhysicalPosition

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L286

new PhysicalPosition()
new PhysicalPosition(object): PhysicalPosition
Parameters
Parameter Type
object object
object.Physical object
object.Physical.x number
object.Physical.y number
Returns

PhysicalPosition

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L287

new PhysicalPosition()
new PhysicalPosition(object): PhysicalPosition
Parameters
Parameter Type
object object
object.x number
object.y number
Returns

PhysicalPosition

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L288

Properties

Property Modifier Type Default value Defined in
type readonly "Physical" 'Physical' Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L282
x public number undefined Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L283
y public number undefined Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L284

Methods

__TAURI_TO_IPC_KEY__()
__TAURI_TO_IPC_KEY__(): object
Returns

object

Name Type Defined in
x number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L330
y number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L331

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L328

toJSON()
toJSON(): object
Returns

object

Name Type Defined in
x number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L330
y number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L331

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L335

toLogical()
toLogical(scaleFactor): LogicalPosition

Converts the physical position to a logical one.

Parameters
Parameter Type
scaleFactor number
Returns

LogicalPosition

Example
import { PhysicalPosition } from '@tauri-apps/api/dpi';
import { getCurrentWindow } from '@tauri-apps/api/window';


const appWindow = getCurrentWindow();
const factor = await appWindow.scaleFactor();
const position = new PhysicalPosition(400, 500);
const physical = position.toLogical(factor);
Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L324


PhysicalSize

A size represented in physical pixels.

Physical pixels represent actual screen pixels, and are DPI-independent. For high-DPI windows, this means that any point in the window on the screen will have a different position in logical pixels LogicalSize.

For physical-pixel-based position, see PhysicalPosition.

Since

2.0.0

Constructors

new PhysicalSize()
new PhysicalSize(width, height): PhysicalSize
Parameters
Parameter Type
width number
height number
Returns

PhysicalSize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L92

new PhysicalSize()
new PhysicalSize(object): PhysicalSize
Parameters
Parameter Type
object object
object.Physical object
object.Physical.height number
object.Physical.width number
Returns

PhysicalSize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L93

new PhysicalSize()
new PhysicalSize(object): PhysicalSize
Parameters
Parameter Type
object object
object.height number
object.width number
Returns

PhysicalSize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L94

Properties

Property Modifier Type Default value Defined in
height public number undefined Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L90
type readonly "Physical" 'Physical' Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L88
width public number undefined Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L89

Methods

__TAURI_TO_IPC_KEY__()
__TAURI_TO_IPC_KEY__(): object
Returns

object

Name Type Defined in
height number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L133
width number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L132

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L130

toJSON()
toJSON(): object
Returns

object

Name Type Defined in
height number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L133
width number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L132

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L137

toLogical()
toLogical(scaleFactor): LogicalSize

Converts the physical size to a logical one.

Parameters
Parameter Type
scaleFactor number
Returns

LogicalSize

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const appWindow = getCurrentWindow();
const factor = await appWindow.scaleFactor();
const size = await appWindow.innerSize(); // PhysicalSize
const logical = size.toLogical(factor);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L126


Position

A position represented either in physical or in logical pixels.

This type is basically a union type of LogicalSize and PhysicalSize but comes in handy when using tauri::Position in Rust as an argument to a command, as this class automatically serializes into a valid format so it can be deserialized correctly into tauri::Position

So instead of

import { invoke } from '@tauri-apps/api/core';
import { LogicalPosition, PhysicalPosition } from '@tauri-apps/api/dpi';


const position: LogicalPosition | PhysicalPosition = someFunction(); // where someFunction returns either LogicalPosition or PhysicalPosition
const validPosition = position instanceof LogicalPosition
  ? { Logical: { x: position.x, y: position.y } }
  : { Physical: { x: position.x, y: position.y } }
await invoke("do_something_with_position", { position: validPosition });

You can just use Position

import { invoke } from '@tauri-apps/api/core';
import { LogicalPosition, PhysicalPosition, Position } from '@tauri-apps/api/dpi';


const position: LogicalPosition | PhysicalPosition = someFunction(); // where someFunction returns either LogicalPosition or PhysicalPosition
const validPosition = new Position(position);
await invoke("do_something_with_position", { position: validPosition });

Since

2.1.0

Constructors

new Position()
new Position(position): Position
Parameters
Parameter Type
position LogicalPosition | PhysicalPosition
Returns

Position

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L375

Properties

Property Type Defined in
position LogicalPosition | PhysicalPosition Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L373

Methods

__TAURI_TO_IPC_KEY__()
__TAURI_TO_IPC_KEY__(): object
Returns

object

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L391

toJSON()
toJSON(): object
Returns

object

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L400

toLogical()
toLogical(scaleFactor): LogicalPosition
Parameters
Parameter Type
scaleFactor number
Returns

LogicalPosition

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L379

toPhysical()
toPhysical(scaleFactor): PhysicalPosition
Parameters
Parameter Type
scaleFactor number
Returns

PhysicalPosition

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L385


Size

A size represented either in physical or in logical pixels.

This type is basically a union type of LogicalSize and PhysicalSize but comes in handy when using tauri::Size in Rust as an argument to a command, as this class automatically serializes into a valid format so it can be deserialized correctly into tauri::Size

So instead of

import { invoke } from '@tauri-apps/api/core';
import { LogicalSize, PhysicalSize } from '@tauri-apps/api/dpi';


const size: LogicalSize | PhysicalSize = someFunction(); // where someFunction returns either LogicalSize or PhysicalSize
const validSize = size instanceof LogicalSize
  ? { Logical: { width: size.width, height: size.height } }
  : { Physical: { width: size.width, height: size.height } }
await invoke("do_something_with_size", { size: validSize });

You can just use Size

import { invoke } from '@tauri-apps/api/core';
import { LogicalSize, PhysicalSize, Size } from '@tauri-apps/api/dpi';


const size: LogicalSize | PhysicalSize = someFunction(); // where someFunction returns either LogicalSize or PhysicalSize
const validSize = new Size(size);
await invoke("do_something_with_size", { size: validSize });

Since

2.1.0

Constructors

new Size()
new Size(size): Size
Parameters
Parameter Type
size LogicalSize | PhysicalSize
Returns

Size

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L177

Properties

Property Type Defined in
size LogicalSize | PhysicalSize Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L175

Methods

__TAURI_TO_IPC_KEY__()
__TAURI_TO_IPC_KEY__(): object
Returns

object

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L193

toJSON()
toJSON(): object
Returns

object

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L202

toLogical()
toLogical(scaleFactor): LogicalSize
Parameters
Parameter Type
scaleFactor number
Returns

LogicalSize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L181

toPhysical()
toPhysical(scaleFactor): PhysicalSize
Parameters
Parameter Type
scaleFactor number
Returns

PhysicalSize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/dpi.ts#L187

event

The event system allows you to emit events to the backend and listen to events from it.

This package is also accessible with window.__TAURI__.event when app.withGlobalTauri in tauri.conf.json is set to true.

Enumerations

TauriEvent

Since

1.1.0

Enumeration Members

DRAG_DROP
DRAG_DROP: "tauri://drag-drop";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L73

DRAG_ENTER
DRAG_ENTER: "tauri://drag-enter";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L71

DRAG_LEAVE
DRAG_LEAVE: "tauri://drag-leave";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L74

DRAG_OVER
DRAG_OVER: "tauri://drag-over";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L72

WEBVIEW_CREATED
WEBVIEW_CREATED: "tauri://webview-created";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L70

WINDOW_BLUR
WINDOW_BLUR: "tauri://blur";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L64

WINDOW_CLOSE_REQUESTED
WINDOW_CLOSE_REQUESTED: "tauri://close-requested";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L61

WINDOW_CREATED
WINDOW_CREATED: "tauri://window-created";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L67

WINDOW_DESTROYED
WINDOW_DESTROYED: "tauri://destroyed";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L62

WINDOW_FOCUS
WINDOW_FOCUS: "tauri://focus";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L63

WINDOW_MOVED
WINDOW_MOVED: "tauri://move";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L60

WINDOW_RESIZED
WINDOW_RESIZED: "tauri://resize";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L59

WINDOW_RESUMED
WINDOW_RESUMED: "tauri://resumed";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L69

WINDOW_SCALE_FACTOR_CHANGED
WINDOW_SCALE_FACTOR_CHANGED: "tauri://scale-change";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L65

WINDOW_SUSPENDED
WINDOW_SUSPENDED: "tauri://suspended";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L68

WINDOW_THEME_CHANGED
WINDOW_THEME_CHANGED: "tauri://theme-changed";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L66

Interfaces

Event<T>

Type Parameters

Type Parameter
T

Properties

Property Type Description Defined in
event EventName Event name Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L32
id number Event identifier used to unlisten Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L34
payload T Event payload Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L36

Options

Properties

Property Type Description Defined in
target? string | EventTarget The event target to listen to, defaults to { kind: 'Any' }, see EventTarget. If a string is provided, EventTarget.AnyLabel is used. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L52

Type Aliases

EventCallback()<T>

type EventCallback<T>: (event) => void;

Type Parameters

Type Parameter
T

Parameters

Parameter Type
event Event<T>

Returns

void

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L39


EventName

type EventName: `${TauriEvent}` | string & Record<never, never>;

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L44


EventTarget

type EventTarget:
  | object
  | object
  | object
  | object
  | object
  | object;

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L22


UnlistenFn()

type UnlistenFn: () => void;

Returns

void

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L42

Functions

emit()

function emit<T>(event, payload?): Promise<void>

Emits an event to all targets.

Type Parameters

Type Parameter
T

Parameters

Parameter Type Description
event string Event name. Must include only alphanumeric characters, -, /, : and _.
payload? T Event payload.

Returns

Promise<void>

Example

import { emit } from '@tauri-apps/api/event';
await emit('frontend-loaded', { loggedIn: true, token: 'authToken' });

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L188


emitTo()

function emitTo<T>(
   target,
   event,
payload?): Promise<void>

Emits an event to all targets matching the given target.

Type Parameters

Type Parameter
T

Parameters

Parameter Type Description
target string | EventTarget Label of the target Window/Webview/WebviewWindow or raw EventTarget object.
event string Event name. Must include only alphanumeric characters, -, /, : and _.
payload? T Event payload.

Returns

Promise<void>

Example

import { emitTo } from '@tauri-apps/api/event';
await emitTo('main', 'frontend-loaded', { loggedIn: true, token: 'authToken' });

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L210


listen()

function listen<T>(
   event,
   handler,
options?): Promise<UnlistenFn>

Listen to an emitted event to any target.

Type Parameters

Type Parameter
T

Parameters

Parameter Type Description
event EventName Event name. Must include only alphanumeric characters, -, /, : and _.
handler EventCallback<T> Event handler callback.
options? Options Event listening options.

Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example

import { listen } from '@tauri-apps/api/event';
const unlisten = await listen<string>('error', (event) => {
  console.log(`Got error, payload: ${event.payload}`);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L115


once()

function once<T>(
   event,
   handler,
options?): Promise<UnlistenFn>

Listens once to an emitted event to any target.

Type Parameters

Type Parameter
T

Parameters

Parameter Type Description
event EventName Event name. Must include only alphanumeric characters, -, /, : and _.
handler EventCallback<T> Event handler callback.
options? Options Event listening options.

Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example

import { once } from '@tauri-apps/api/event';
interface LoadedPayload {
  loggedIn: boolean,
  token: string
}
const unlisten = await once<LoadedPayload>('loaded', (event) => {
  console.log(`App is loaded, loggedIn: ${event.payload.loggedIn}, token: ${event.payload.token}`);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/event.ts#L159

image

Classes

Image

An RGBA Image in row-major order from top to bottom.

Extends

Accessors

rid
get rid(): number
Returns

number

Inherited from

Resource.rid

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L318

Methods

close()
close(): Promise<void>

Destroys and cleans up this resource from memory. You should not call any method on this object anymore and should drop any reference to it.

Returns

Promise<void>

Inherited from

Resource.close

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L330

rgba()
rgba(): Promise<Uint8Array>

Returns the RGBA data for this image, in row-major order from top to bottom.

Returns

Promise<Uint8Array>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/image.ts#L89

size()
size(): Promise<ImageSize>

Returns the size of this image.

Returns

Promise<ImageSize>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/image.ts#L96

fromBytes()
static fromBytes(bytes): Promise<Image>

Creates a new image using the provided bytes by inferring the file format. If the format is known, prefer [@link Image.fromPngBytes] or [@link Image.fromIcoBytes].

Only ico and png are supported (based on activated feature flag).

Note that you need the image-ico or image-png Cargo features to use this API. To enable it, change your Cargo.toml file:

[dependencies]
tauri = { version = "...", features = ["...", "image-png"] }
Parameters
Parameter Type
bytes Uint8Array | number[] | ArrayBuffer
Returns

Promise<Image>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/image.ts#L62

fromPath()
static fromPath(path): Promise<Image>

Creates a new image using the provided path.

Only ico and png are supported (based on activated feature flag).

Note that you need the image-ico or image-png Cargo features to use this API. To enable it, change your Cargo.toml file:

[dependencies]
tauri = { version = "...", features = ["...", "image-png"] }
Parameters
Parameter Type
path string
Returns

Promise<Image>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/image.ts#L82

new()
static new(
   rgba,
   width,
height): Promise<Image>

Creates a new Image using RGBA data, in row-major order from top to bottom, and with specified width and height.

Parameters
Parameter Type
rgba Uint8Array | number[] | ArrayBuffer
width number
height number
Returns

Promise<Image>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/image.ts#L37

Interfaces

ImageSize

Properties

Property Type Defined in
height number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/image.ts#L13
width number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/image.ts#L11

Type Aliases

MenuIcon

type MenuIcon:
  | NativeIcon
  | string
  | Image
  | Uint8Array
  | ArrayBuffer
  | number[];

A type that represents an icon that can be used in menu items.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/image.ts#L17

Functions

transformImage()

function transformImage<T>(image): T

Transforms image from various types into a type acceptable by Rust.

See tauri::image::JsImage for more information. Note the API signature is not stable and might change.

Type Parameters

Type Parameter
T

Parameters

Parameter Type
image | null | string | Uint8Array | number[] | ArrayBuffer | Image

Returns

T

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/image.ts#L107

menu

Enumerations

NativeIcon

A native Icon to be used for the menu item

Platform-specific:

  • Windows / Linux: Unsupported.

Enumeration Members

Add
Add: "Add";

An add item template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L19

Advanced
Advanced: "Advanced";

Advanced preferences toolbar icon for the preferences window.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L21

Bluetooth
Bluetooth: "Bluetooth";

A Bluetooth template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L23

Bookmarks
Bookmarks: "Bookmarks";

Bookmarks image suitable for a template.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L25

Caution
Caution: "Caution";

A caution image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L27

ColorPanel
ColorPanel: "ColorPanel";

A color panel toolbar icon.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L29

ColumnView
ColumnView: "ColumnView";

A column view mode template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L31

Computer
Computer: "Computer";

A computer icon.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L33

EnterFullScreen
EnterFullScreen: "EnterFullScreen";

An enter full-screen mode template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L35

Everyone
Everyone: "Everyone";

Permissions for all users.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L37

ExitFullScreen
ExitFullScreen: "ExitFullScreen";

An exit full-screen mode template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L39

FlowView
FlowView: "FlowView";

A cover flow view mode template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L41

Folder
Folder: "Folder";

A folder image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L43

FolderBurnable
FolderBurnable: "FolderBurnable";

A burnable folder icon.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L45

FolderSmart
FolderSmart: "FolderSmart";

A smart folder icon.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L47

FollowLinkFreestanding
FollowLinkFreestanding: "FollowLinkFreestanding";

A link template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L49

FontPanel
FontPanel: "FontPanel";

A font panel toolbar icon.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L51

GoLeft
GoLeft: "GoLeft";

A go back template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L53

GoRight
GoRight: "GoRight";

A go forward template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L55

Home
Home: "Home";

Home image suitable for a template.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L57

IChatTheater
IChatTheater: "IChatTheater";

An iChat Theater template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L59

IconView
IconView: "IconView";

An icon view mode template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L61

Info
Info: "Info";

An information toolbar icon.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L63

InvalidDataFreestanding
InvalidDataFreestanding: "InvalidDataFreestanding";

A template image used to denote invalid data.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L65

LeftFacingTriangle
LeftFacingTriangle: "LeftFacingTriangle";

A generic left-facing triangle template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L67

ListView
ListView: "ListView";

A list view mode template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L69

LockLocked
LockLocked: "LockLocked";

A locked padlock template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L71

LockUnlocked
LockUnlocked: "LockUnlocked";

An unlocked padlock template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L73

MenuMixedState
MenuMixedState: "MenuMixedState";

A horizontal dash, for use in menus.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L75

MenuOnState
MenuOnState: "MenuOnState";

A check mark template image, for use in menus.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L77

MobileMe
MobileMe: "MobileMe";

A MobileMe icon.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L79

MultipleDocuments
MultipleDocuments: "MultipleDocuments";

A drag image for multiple items.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L81

Network
Network: "Network";

A network icon.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L83

Path
Path: "Path";

A path button template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L85

PreferencesGeneral
PreferencesGeneral: "PreferencesGeneral";

General preferences toolbar icon for the preferences window.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L87

QuickLook
QuickLook: "QuickLook";

A Quick Look template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L89

Refresh
Refresh: "Refresh";

A refresh template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L93

RefreshFreestanding
RefreshFreestanding: "RefreshFreestanding";

A refresh template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L91

Remove
Remove: "Remove";

A remove item template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L95

RevealFreestanding
RevealFreestanding: "RevealFreestanding";

A reveal contents template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L97

RightFacingTriangle
RightFacingTriangle: "RightFacingTriangle";

A generic right-facing triangle template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L99

Share
Share: "Share";

A share view template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L101

Slideshow
Slideshow: "Slideshow";

A slideshow template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L103

SmartBadge
SmartBadge: "SmartBadge";

A badge for a smart item.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L105

StatusAvailable
StatusAvailable: "StatusAvailable";

Small green indicator, similar to iChats available image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L107

StatusNone
StatusNone: "StatusNone";

Small clear indicator.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L109

StatusPartiallyAvailable
StatusPartiallyAvailable: "StatusPartiallyAvailable";

Small yellow indicator, similar to iChats idle image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L111

StatusUnavailable
StatusUnavailable: "StatusUnavailable";

Small red indicator, similar to iChats unavailable image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L113

StopProgress
StopProgress: "StopProgress";

A stop progress button template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L117

StopProgressFreestanding
StopProgressFreestanding: "StopProgressFreestanding";

A stop progress template image.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L115

TrashEmpty
TrashEmpty: "TrashEmpty";

An image of the empty trash can.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L119

TrashFull
TrashFull: "TrashFull";

An image of the full trash can.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L121

User
User: "User";

Permissions for a single user.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L123

UserAccounts
UserAccounts: "UserAccounts";

User account toolbar icon for the preferences window.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L125

UserGroup
UserGroup: "UserGroup";

Permissions for a group of users.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L127

UserGuest
UserGuest: "UserGuest";

Permissions for guests.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L129

Classes

CheckMenuItem

A check menu item inside a Menu or Submenu and usually contains a text and a check mark or a similar toggle that corresponds to a checked and unchecked states.

Extends

  • MenuItemBase

Accessors

id
get id(): string

The id of this item.

Returns

string

Inherited from

MenuItemBase.id

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/base.ts#L128

rid
get rid(): number
Returns

number

Inherited from

MenuItemBase.rid

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L318

Methods

close()
close(): Promise<void>

Destroys and cleans up this resource from memory. You should not call any method on this object anymore and should drop any reference to it.

Returns

Promise<void>

Inherited from

MenuItemBase.close

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L330

isChecked()
isChecked(): Promise<boolean>

Returns whether this check menu item is checked or not.

Returns

Promise<boolean>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/checkMenuItem.ts#L71

isEnabled()
isEnabled(): Promise<boolean>

Returns whether this check menu item is enabled or not.

Returns

Promise<boolean>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/checkMenuItem.ts#L48

setAccelerator()
setAccelerator(accelerator): Promise<void>

Sets the accelerator for this check menu item.

Parameters
Parameter Type
accelerator null | string
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/checkMenuItem.ts#L62

setChecked()
setChecked(checked): Promise<void>

Sets whether this check menu item is checked or not.

Parameters
Parameter Type
checked boolean
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/checkMenuItem.ts#L76

setEnabled()
setEnabled(enabled): Promise<void>

Sets whether this check menu item is enabled or not.

Parameters
Parameter Type
enabled boolean
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/checkMenuItem.ts#L53

setText()
setText(text): Promise<void>

Sets the text for this check menu item.

Parameters
Parameter Type
text string
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/checkMenuItem.ts#L39

text()
text(): Promise<string>

Returns the text of this check menu item.

Returns

Promise<string>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/checkMenuItem.ts#L34

new()
static new(opts): Promise<CheckMenuItem>

Create a new check menu item.

Parameters
Parameter Type
opts CheckMenuItemOptions
Returns

Promise<CheckMenuItem>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/checkMenuItem.ts#L27


IconMenuItem

An icon menu item inside a Menu or Submenu and usually contains an icon and a text.

Extends

  • MenuItemBase

Accessors

id
get id(): string

The id of this item.

Returns

string

Inherited from

MenuItemBase.id

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/base.ts#L128

rid
get rid(): number
Returns

number

Inherited from

MenuItemBase.rid

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L318

Methods

close()
close(): Promise<void>

Destroys and cleans up this resource from memory. You should not call any method on this object anymore and should drop any reference to it.

Returns

Promise<void>

Inherited from

MenuItemBase.close

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L330

isEnabled()
isEnabled(): Promise<boolean>

Returns whether this icon menu item is enabled or not.

Returns

Promise<boolean>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L177

setAccelerator()
setAccelerator(accelerator): Promise<void>

Sets the accelerator for this icon menu item.

Parameters
Parameter Type
accelerator null | string
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L191

setEnabled()
setEnabled(enabled): Promise<void>

Sets whether this icon menu item is enabled or not.

Parameters
Parameter Type
enabled boolean
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L182

setIcon()
setIcon(icon): Promise<void>

Sets an icon for this icon menu item

Parameters
Parameter Type
icon null | MenuIcon
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L200

setText()
setText(text): Promise<void>

Sets the text for this icon menu item.

Parameters
Parameter Type
text string
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L168

text()
text(): Promise<string>

Returns the text of this icon menu item.

Returns

Promise<string>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L163

new()
static new(opts): Promise<IconMenuItem>

Create a new icon menu item.

Parameters
Parameter Type
opts IconMenuItemOptions
Returns

Promise<IconMenuItem>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L158


Menu

A type that is either a menu bar on the window on Windows and Linux or as a global menu in the menubar on macOS.

Platform-specific:

  • macOS: if using Menu for the global menubar, it can only contain Submenus.

Extends

  • MenuItemBase

Accessors

id
get id(): string

The id of this item.

Returns

string

Inherited from

MenuItemBase.id

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/base.ts#L128

rid
get rid(): number
Returns

number

Inherited from

MenuItemBase.rid

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L318

Methods

append()
append<T>(items): Promise<void>

Add a menu item to the end of this menu.

Platform-specific:

Type Parameters
Type Parameter
T extends | MenuItemOptions | MenuItem | SubmenuOptions | PredefinedMenuItemOptions | CheckMenuItemOptions | IconMenuItemOptions | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem
Parameters
Parameter Type
items T | T[]
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menu.ts#L73

close()
close(): Promise<void>

Destroys and cleans up this resource from memory. You should not call any method on this object anymore and should drop any reference to it.

Returns

Promise<void>

Inherited from

MenuItemBase.close

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L330

get()
get(id): Promise<
  | null
  | MenuItem
  | PredefinedMenuItem
  | Submenu
  | CheckMenuItem
| IconMenuItem>

Retrieves the menu item matching the given identifier.

Parameters
Parameter Type
id string
Returns

Promise< | null | MenuItem | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menu.ts#L196

insert()
insert<T>(items, position): Promise<void>

Add a menu item to the specified position in this menu.

Platform-specific:

Type Parameters
Type Parameter
T extends | MenuItemOptions | MenuItem | SubmenuOptions | PredefinedMenuItemOptions | CheckMenuItemOptions | IconMenuItemOptions | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem
Parameters
Parameter Type
items T | T[]
position number
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menu.ts#L131

items()
items(): Promise<(
  | MenuItem
  | PredefinedMenuItem
  | Submenu
  | CheckMenuItem
| IconMenuItem)[]>

Returns a list of menu items that has been added to this menu.

Returns

Promise<( | MenuItem | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem)[]>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menu.ts#L184

popup()
popup(at?, window?): Promise<void>

Popup this menu as a context menu on the specified window.

Parameters
Parameter Type Description
at? LogicalPosition | PhysicalPosition | Position If a position is provided, it is relative to the windows top-left corner. If there isnt one provided, the menu will pop up at the current location of the mouse.
window? Window -
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menu.ts#L219

prepend()
prepend<T>(items): Promise<void>

Add a menu item to the beginning of this menu.

Platform-specific:

Type Parameters
Type Parameter
T extends | MenuItemOptions | MenuItem | SubmenuOptions | PredefinedMenuItemOptions | CheckMenuItemOptions | IconMenuItemOptions | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem
Parameters
Parameter Type
items T | T[]
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menu.ts#L102

remove()
remove(item): Promise<void>

Remove a menu item from this menu.

Parameters
Parameter Type
item | MenuItem | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menu.ts#L155

removeAt()
removeAt(position): Promise<
  | null
  | MenuItem
  | PredefinedMenuItem
  | Submenu
  | CheckMenuItem
| IconMenuItem>

Remove a menu item from this menu at the specified position.

Parameters
Parameter Type
position number
Returns

Promise< | null | MenuItem | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menu.ts#L166

setAsAppMenu()
setAsAppMenu(): Promise<null | Menu>

Sets the app-wide menu and returns the previous one.

If a window was not created with an explicit menu or had one set explicitly, this menu will be assigned to it.

Returns

Promise<null | Menu>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menu.ts#L237

setAsWindowMenu()
setAsWindowMenu(window?): Promise<null | Menu>

Sets the window menu and returns the previous one.

Platform-specific:

  • macOS: Unsupported. The menu on macOS is app-wide and not specific to one window, if you need to set it, use Menu.setAsAppMenu instead.
Parameters
Parameter Type
window? Window
Returns

Promise<null | Menu>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menu.ts#L251

default()
static default(): Promise<Menu>

Create a default menu.

Returns

Promise<Menu>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menu.ts#L60

new()
static new(opts?): Promise<Menu>

Create a new menu.

Parameters
Parameter Type
opts? MenuOptions
Returns

Promise<Menu>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menu.ts#L55


MenuItem

A menu item inside a Menu or Submenu and contains only text.

Extends

  • MenuItemBase

Accessors

id
get id(): string

The id of this item.

Returns

string

Inherited from

MenuItemBase.id

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/base.ts#L128

rid
get rid(): number
Returns

number

Inherited from

MenuItemBase.rid

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L318

Methods

close()
close(): Promise<void>

Destroys and cleans up this resource from memory. You should not call any method on this object anymore and should drop any reference to it.

Returns

Promise<void>

Inherited from

MenuItemBase.close

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L330

isEnabled()
isEnabled(): Promise<boolean>

Returns whether this menu item is enabled or not.

Returns

Promise<boolean>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L49

setAccelerator()
setAccelerator(accelerator): Promise<void>

Sets the accelerator for this menu item.

Parameters
Parameter Type
accelerator null | string
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L63

setEnabled()
setEnabled(enabled): Promise<void>

Sets whether this menu item is enabled or not.

Parameters
Parameter Type
enabled boolean
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L54

setText()
setText(text): Promise<void>

Sets the text for this menu item.

Parameters
Parameter Type
text string
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L40

text()
text(): Promise<string>

Returns the text of this menu item.

Returns

Promise<string>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L35

new()
static new(opts): Promise<MenuItem>

Create a new menu item.

Parameters
Parameter Type
opts MenuItemOptions
Returns

Promise<MenuItem>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L30


PredefinedMenuItem

A predefined (native) menu item which has a predefined behavior by the OS or by tauri.

Extends

  • MenuItemBase

Accessors

id
get id(): string

The id of this item.

Returns

string

Inherited from

MenuItemBase.id

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/base.ts#L128

rid
get rid(): number
Returns

number

Inherited from

MenuItemBase.rid

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L318

Methods

close()
close(): Promise<void>

Destroys and cleans up this resource from memory. You should not call any method on this object anymore and should drop any reference to it.

Returns

Promise<void>

Inherited from

MenuItemBase.close

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L330

setText()
setText(text): Promise<void>

Sets the text for this predefined menu item.

Parameters
Parameter Type
text string
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L133

text()
text(): Promise<string>

Returns the text of this predefined menu item.

Returns

Promise<string>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L128

new()
static new(opts?): Promise<PredefinedMenuItem>

Create a new predefined menu item.

Parameters
Parameter Type
opts? PredefinedMenuItemOptions
Returns

Promise<PredefinedMenuItem>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L119


Submenu

A type that is a submenu inside a Menu or Submenu.

Extends

  • MenuItemBase

Accessors

id
get id(): string

The id of this item.

Returns

string

Inherited from

MenuItemBase.id

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/base.ts#L128

rid
get rid(): number
Returns

number

Inherited from

MenuItemBase.rid

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L318

Methods

append()
append<T>(items): Promise<void>

Add a menu item to the end of this submenu.

Platform-specific:

Type Parameters
Type Parameter
T extends | MenuItemOptions | MenuItem | SubmenuOptions | PredefinedMenuItemOptions | CheckMenuItemOptions | IconMenuItemOptions | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem
Parameters
Parameter Type
items T | T[]
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L106

close()
close(): Promise<void>

Destroys and cleans up this resource from memory. You should not call any method on this object anymore and should drop any reference to it.

Returns

Promise<void>

Inherited from

MenuItemBase.close

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L330

get()
get(id): Promise<
  | null
  | MenuItem
  | PredefinedMenuItem
  | Submenu
  | CheckMenuItem
| IconMenuItem>

Retrieves the menu item matching the given identifier.

Parameters
Parameter Type
id string
Returns

Promise< | null | MenuItem | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L229

insert()
insert<T>(items, position): Promise<void>

Add a menu item to the specified position in this submenu.

Platform-specific:

Type Parameters
Type Parameter
T extends | MenuItemOptions | MenuItem | SubmenuOptions | PredefinedMenuItemOptions | CheckMenuItemOptions | IconMenuItemOptions | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem
Parameters
Parameter Type
items T | T[]
position number
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L164

isEnabled()
isEnabled(): Promise<boolean>

Returns whether this submenu is enabled or not.

Returns

Promise<boolean>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L86

items()
items(): Promise<(
  | MenuItem
  | PredefinedMenuItem
  | Submenu
  | CheckMenuItem
| IconMenuItem)[]>

Returns a list of menu items that has been added to this submenu.

Returns

Promise<( | MenuItem | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem)[]>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L217

popup()
popup(at?, window?): Promise<void>

Popup this submenu as a context menu on the specified window.

If the position, is provided, it is relative to the windows top-left corner.

Parameters
Parameter Type
at? LogicalPosition | PhysicalPosition
window? Window
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L251

prepend()
prepend<T>(items): Promise<void>

Add a menu item to the beginning of this submenu.

Platform-specific:

Type Parameters
Type Parameter
T extends | MenuItemOptions | MenuItem | SubmenuOptions | PredefinedMenuItemOptions | CheckMenuItemOptions | IconMenuItemOptions | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem
Parameters
Parameter Type
items T | T[]
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L135

remove()
remove(item): Promise<void>

Remove a menu item from this submenu.

Parameters
Parameter Type
item | MenuItem | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L188

removeAt()
removeAt(position): Promise<
  | null
  | MenuItem
  | PredefinedMenuItem
  | Submenu
  | CheckMenuItem
| IconMenuItem>

Remove a menu item from this submenu at the specified position.

Parameters
Parameter Type
position number
Returns

Promise< | null | MenuItem | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L199

setAsHelpMenuForNSApp()
setAsHelpMenuForNSApp(): Promise<void>

Set this submenu as the Help menu for the application on macOS.

This will cause macOS to automatically add a search box to the menu.

If no menu is set as the Help menu, macOS will automatically use any menu which has a title matching the localized word “Help”.

Platform-specific:

  • Windows / Linux: Unsupported.
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L291

setAsWindowsMenuForNSApp()
setAsWindowsMenuForNSApp(): Promise<void>

Set this submenu as the Window menu for the application on macOS.

This will cause macOS to automatically add window-switching items and certain other items to the menu.

Platform-specific:

  • Windows / Linux: Unsupported.
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L273

setEnabled()
setEnabled(enabled): Promise<void>

Sets whether this submenu is enabled or not.

Parameters
Parameter Type
enabled boolean
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L91

setIcon()
setIcon(icon): Promise<void>

Sets an icon for this submenu

Parameters
Parameter Type
icon null | MenuIcon
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L298

setText()
setText(text): Promise<void>

Sets the text for this submenu.

Parameters
Parameter Type
text string
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L77

text()
text(): Promise<string>

Returns the text of this submenu.

Returns

Promise<string>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L72

new()
static new(opts): Promise<Submenu>

Create a new submenu.

Parameters
Parameter Type
opts SubmenuOptions
Returns

Promise<Submenu>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L67

Interfaces

AboutMetadata

A metadata for the about predefined menu item.

Properties

Property Type Description Defined in
authors? string[] The authors of the application. Platform-specific - macOS: Unsupported. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L30
comments? string Application comments. Platform-specific - macOS: Unsupported. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L38
copyright? string The copyright of the application. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L40
credits? string The credits. Platform-specific - Windows / Linux: Unsupported. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L72
icon? | string | Uint8Array | number[] | ArrayBuffer | Image The application icon. Platform-specific - Windows: Unsupported. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L80
license? string The license of the application. Platform-specific - macOS: Unsupported. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L48
name? string Sets the application name. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L12
shortVersion? string The short version, e.g. “1.0”. Platform-specific - Windows / Linux: Appended to the end of version in parentheses. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L22
version? string The application version. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L14
website? string The application website. Platform-specific - macOS: Unsupported. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L56
websiteLabel? string The website label. Platform-specific - macOS: Unsupported. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L64

CheckMenuItemOptions

Options for creating a new check menu item.

Extends

Properties

Property Type Description Inherited from Defined in
accelerator? string Specify an accelerator for the new menu item. MenuItemOptions.accelerator Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L17
action? (id: string) => void Specify a handler to be called when this menu item is activated. MenuItemOptions.action Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L19
checked? boolean Whether the new check menu item is enabled or not. - Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/checkMenuItem.ts#L12
enabled? boolean Whether the new menu item is enabled or not. MenuItemOptions.enabled Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L15
id? string Specify an id to use for the new menu item. MenuItemOptions.id Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L11
text string The text of the new menu item. MenuItemOptions.text Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L13

IconMenuItemOptions

Options for creating a new icon menu item.

Extends

Properties

Property Type Description Inherited from Defined in
accelerator? string Specify an accelerator for the new menu item. MenuItemOptions.accelerator Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L17
action? (id: string) => void Specify a handler to be called when this menu item is activated. MenuItemOptions.action Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L19
enabled? boolean Whether the new menu item is enabled or not. MenuItemOptions.enabled Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L15
icon? MenuIcon Icon to be used for the new icon menu item. Note that you may need the image-ico or image-png Cargo features to use this API. To enable it, change your Cargo.toml file: [dependencies] tauri = { version = "...", features = ["...", "image-png"] } - Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/iconMenuItem.ts#L144
id? string Specify an id to use for the new menu item. MenuItemOptions.id Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L11
text string The text of the new menu item. MenuItemOptions.text Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L13

MenuItemOptions

Options for creating a new menu item.

Extended by

Properties

Property Type Description Defined in
accelerator? string Specify an accelerator for the new menu item. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L17
action? (id: string) => void Specify a handler to be called when this menu item is activated. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L19
enabled? boolean Whether the new menu item is enabled or not. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L15
id? string Specify an id to use for the new menu item. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L11
text string The text of the new menu item. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menuItem.ts#L13

MenuOptions

Options for creating a new menu.

Properties

Property Type Description Defined in
id? string Specify an id to use for the new menu. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menu.ts#L25
items? ( | MenuItemOptions | MenuItem | SubmenuOptions | PredefinedMenuItemOptions | CheckMenuItemOptions | IconMenuItemOptions | PredefinedMenuItem | Submenu | CheckMenuItem | IconMenuItem)[] List of items to add to the new menu. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/menu.ts#L27

PredefinedMenuItemOptions

Options for creating a new predefined menu item.

Properties

Property Type Description Defined in
item | object | "Separator" | "Copy" | "Cut" | "Paste" | "SelectAll" | "Undo" | "Redo" | "Minimize" | "Maximize" | "Fullscreen" | "Hide" | "HideOthers" | "ShowAll" | "CloseWindow" | "Quit" | "Services" | "BringAllToFront" The predefined item type Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L88
text? string The text of the new predefined menu item. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/predefinedMenuItem.ts#L86

Type Aliases

SubmenuOptions

type SubmenuOptions: Omit<MenuItemOptions, "accelerator" | "action"> & MenuOptions & object;

Type declaration

Name Type Description Defined in
icon MenuIcon Icon to be used for the submenu. Note: you may need the image-ico or image-png Cargo features to use this API. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L56

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/menu/submenu.ts#L50

mocks

Interfaces

MockIPCOptions

Options for mockIPC.

Options

shouldMockEvents: If true, the listen and emit functions will be mocked, allowing you to test event handling without a real backend. This will consume any events emitted with the plugin:event prefix.

Since

2.7.0

Properties

Property Type Defined in
shouldMockEvents? boolean Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/mocks.ts#L24

Functions

clearMocks()

function clearMocks(): void

Clears mocked functions/data injected by the other functions in this module. When using a test runner that doesnt provide a fresh window object for each test, calling this function will reset tauri specific properties.

Example

import { mockWindows, clearMocks } from "@tauri-apps/api/mocks"


afterEach(() => {
   clearMocks()
})


test("mocked windows", () => {
   mockWindows("main", "second", "third");


   expect(window.__TAURI_INTERNALS__).toHaveProperty("metadata")
})


test("no mocked windows", () => {
   expect(window.__TAURI_INTERNALS__).not.toHaveProperty("metadata")
})

Returns

void

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/mocks.ts#L316


mockConvertFileSrc()

function mockConvertFileSrc(osName): void

Mock convertFileSrc function

Parameters

Parameter Type Description
osName string The operating system to mock, can be one of linux, macos, or windows

Returns

void

Example

import { mockConvertFileSrc } from "@tauri-apps/api/mocks";
import { convertFileSrc } from "@tauri-apps/api/core";


mockConvertFileSrc("windows")


const url = convertFileSrc("C:\\Users\\user\\file.txt")

Since

1.6.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/mocks.ts#L277


mockIPC()

function mockIPC(cb, options?): void

Intercepts all IPC requests with the given mock handler.

This function can be used when testing tauri frontend applications or when running the frontend in a Node.js context during static site generation.

Examples

Testing setup using Vitest:

import { mockIPC, clearMocks } from "@tauri-apps/api/mocks"
import { invoke } from "@tauri-apps/api/core"


afterEach(() => {
   clearMocks()
})


test("mocked command", () => {
 mockIPC((cmd, payload) => {
  switch (cmd) {
    case "add":
      return (payload.a as number) + (payload.b as number);
    default:
      break;
    }
 });


 expect(invoke('add', { a: 12, b: 15 })).resolves.toBe(27);
})

The callback function can also return a Promise:

import { mockIPC, clearMocks } from "@tauri-apps/api/mocks"
import { invoke } from "@tauri-apps/api/core"


afterEach(() => {
   clearMocks()
})


test("mocked command", () => {
 mockIPC((cmd, payload) => {
  if(cmd === "get_data") {
   return fetch("https://example.com/data.json")
     .then((response) => response.json())
  }
 });


 expect(invoke('get_data')).resolves.toBe({ foo: 'bar' });
})

listen can also be mocked with direct calls to the emit function. This functionality is opt-in via the shouldMockEvents option:

import { mockIPC, clearMocks } from "@tauri-apps/api/mocks"
import { emit, listen } from "@tauri-apps/api/event"


afterEach(() => {
   clearMocks()
})


test("mocked event", () => {
 mockIPC(() => {}, { shouldMockEvents: true }); // enable event mocking


 const eventHandler = vi.fn();
 listen('test-event', eventHandler); // typically in component setup or similar


 emit('test-event', { foo: 'bar' });
 expect(eventHandler).toHaveBeenCalledWith({
   event: 'test-event',
   payload: { foo: 'bar' }
 });
})

emitTo is currently not supported by this mock implementation.

Parameters

Parameter Type
cb (cmd, payload?) => unknown
options? MockIPCOptions

Returns

void

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/mocks.ts#L104


mockWindows()

function mockWindows(current, ..._additionalWindows): void

Mocks one or many window labels. In non-tauri context it is required to call this function before using the @tauri-apps/api/window module.

This function only mocks the presence of windows, window properties (e.g. width and height) can be mocked like regular IPC calls using the mockIPC function.

Examples

import { mockWindows } from "@tauri-apps/api/mocks";
import { getCurrentWindow } from "@tauri-apps/api/window";


mockWindows("main", "second", "third");


const win = getCurrentWindow();


win.label // "main"
import { mockWindows } from "@tauri-apps/api/mocks";


mockWindows("main", "second", "third");


mockIPC((cmd, args) => {
 if (cmd === "plugin:event|emit") {
   console.log('emit event', args?.event, args?.payload);
 }
});


const { emit } = await import("@tauri-apps/api/event");
await emit('loaded'); // this will cause the mocked IPC handler to log to the console.

Parameters

Parameter Type Description
current string Label of window this JavaScript context is running in.
_additionalWindows string[] -

Returns

void

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/mocks.ts#L248

path

The path module provides utilities for working with file and directory paths.

This package is also accessible with window.__TAURI__.path when app.withGlobalTauri in tauri.conf.json is set to true.

It is recommended to allowlist only the APIs you use for optimal bundle size and security.

Enumerations

BaseDirectory

Since

2.0.0

Enumeration Members

AppCache
AppCache: 16;
See

appCacheDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L83

AppConfig
AppConfig: 13;
See

appConfigDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L71

AppData
AppData: 14;
See

appDataDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L75

AppLocalData
AppLocalData: 15;
See

appLocalDataDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L79

AppLog
AppLog: 17;
See

appLogDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L87

Audio
Audio: 1;
See

audioDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L23

Cache
Cache: 2;
See

cacheDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L27

Config
Config: 3;
See

configDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L31

Data
Data: 4;
See

dataDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L35

Desktop
Desktop: 18;
See

desktopDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L91

Document
Document: 6;
See

documentDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L43

Download
Download: 7;
See

downloadDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L47

Executable
Executable: 19;
See

executableDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L95

Font
Font: 20;
See

fontDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L99

Home
Home: 21;
See

homeDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L103

LocalData
LocalData: 5;
See

localDataDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L39

Picture
Picture: 8;
See

pictureDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L51

Public
Public: 9;
See

publicDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L55

Resource
Resource: 11;
See

resourceDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L63

Runtime
Runtime: 22;
See

runtimeDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L107

Temp
Temp: 12;
See

tempDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L67

Template
Template: 23;
See

templateDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L111

Video
Video: 10;
See

videoDir for more information.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L59

Functions

appCacheDir()

function appCacheDir(): Promise<string>

Returns the path to the suggested directory for your apps cache files. Resolves to ${cacheDir}/${bundleIdentifier}, where bundleIdentifier is the identifier value configured in tauri.conf.json.

Returns

Promise<string>

Example

import { appCacheDir } from '@tauri-apps/api/path';
const appCacheDirPath = await appCacheDir();

Since

1.2.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L176


appConfigDir()

function appConfigDir(): Promise<string>

Returns the path to the suggested directory for your apps config files. Resolves to ${configDir}/${bundleIdentifier}, where bundleIdentifier is the identifier value configured in tauri.conf.json.

Returns

Promise<string>

Example

import { appConfigDir } from '@tauri-apps/api/path';
const appConfigDirPath = await appConfigDir();

Since

1.2.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L125


appDataDir()

function appDataDir(): Promise<string>

Returns the path to the suggested directory for your apps data files. Resolves to ${dataDir}/${bundleIdentifier}, where bundleIdentifier is the identifier value configured in tauri.conf.json.

Returns

Promise<string>

Example

import { appDataDir } from '@tauri-apps/api/path';
const appDataDirPath = await appDataDir();

Since

1.2.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L142


appLocalDataDir()

function appLocalDataDir(): Promise<string>

Returns the path to the suggested directory for your apps local data files. Resolves to ${localDataDir}/${bundleIdentifier}, where bundleIdentifier is the identifier value configured in tauri.conf.json.

Returns

Promise<string>

Example

import { appLocalDataDir } from '@tauri-apps/api/path';
const appLocalDataDirPath = await appLocalDataDir();

Since

1.2.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L159


appLogDir()

function appLogDir(): Promise<string>

Returns the path to the suggested directory for your apps log files.

Platform-specific

  • Linux: Resolves to ${configDir}/${bundleIdentifier}/logs.
  • macOS: Resolves to ${homeDir}/Library/Logs/{bundleIdentifier}
  • Windows: Resolves to ${configDir}/${bundleIdentifier}/logs.

Returns

Promise<string>

Example

import { appLogDir } from '@tauri-apps/api/path';
const appLogDirPath = await appLogDir();

Since

1.2.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L604


audioDir()

function audioDir(): Promise<string>

Returns the path to the users audio directory.

Platform-specific

  • Linux: Resolves to xdg-user-dirs XDG_MUSIC_DIR.
  • macOS: Resolves to $HOME/Music.
  • Windows: Resolves to {FOLDERID_Music}.

Returns

Promise<string>

Example

import { audioDir } from '@tauri-apps/api/path';
const audioDirPath = await audioDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L198


basename()

function basename(path, ext?): Promise<string>

Returns the last portion of a path. Trailing directory separators are ignored.

Parameters

Parameter Type Description
path string -
ext? string An optional file extension to be removed from the returned path.

Returns

Promise<string>

Example

import { basename } from '@tauri-apps/api/path';
const base = await basename('path/to/app.conf');
assert(base === 'app.conf');

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L734


cacheDir()

function cacheDir(): Promise<string>

Returns the path to the users cache directory.

Platform-specific

  • Linux: Resolves to $XDG_CACHE_HOME or $HOME/.cache.
  • macOS: Resolves to $HOME/Library/Caches.
  • Windows: Resolves to {FOLDERID_LocalAppData}.

Returns

Promise<string>

Example

import { cacheDir } from '@tauri-apps/api/path';
const cacheDirPath = await cacheDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L220


configDir()

function configDir(): Promise<string>

Returns the path to the users config directory.

Platform-specific

  • Linux: Resolves to $XDG_CONFIG_HOME or $HOME/.config.
  • macOS: Resolves to $HOME/Library/Application Support.
  • Windows: Resolves to {FOLDERID_RoamingAppData}.

Returns

Promise<string>

Example

import { configDir } from '@tauri-apps/api/path';
const configDirPath = await configDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L242


dataDir()

function dataDir(): Promise<string>

Returns the path to the users data directory.

Platform-specific

  • Linux: Resolves to $XDG_DATA_HOME or $HOME/.local/share.
  • macOS: Resolves to $HOME/Library/Application Support.
  • Windows: Resolves to {FOLDERID_RoamingAppData}.

Returns

Promise<string>

Example

import { dataDir } from '@tauri-apps/api/path';
const dataDirPath = await dataDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L264


delimiter()

function delimiter(): string

Returns the platform-specific path segment delimiter:

  • ; on Windows
  • : on POSIX

Returns

string

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L644


desktopDir()

function desktopDir(): Promise<string>

Returns the path to the users desktop directory.

Platform-specific

  • Linux: Resolves to xdg-user-dirs XDG_DESKTOP_DIR.
  • macOS: Resolves to $HOME/Desktop.
  • Windows: Resolves to {FOLDERID_Desktop}.

Returns

Promise<string>

Example

import { desktopDir } from '@tauri-apps/api/path';
const desktopPath = await desktopDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L286


dirname()

function dirname(path): Promise<string>

Returns the parent directory of a given path. Trailing directory separators are ignored.

Parameters

Parameter Type
path string

Returns

Promise<string>

Example

import { dirname } from '@tauri-apps/api/path';
const dir = await dirname('/path/to/somedir/');
assert(dir === '/path/to');

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L703


documentDir()

function documentDir(): Promise<string>

Returns the path to the users document directory.

Returns

Promise<string>

Example

import { documentDir } from '@tauri-apps/api/path';
const documentDirPath = await documentDir();

Platform-specific

  • Linux: Resolves to xdg-user-dirs XDG_DOCUMENTS_DIR.
  • macOS: Resolves to $HOME/Documents.
  • Windows: Resolves to {FOLDERID_Documents}.

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L308


downloadDir()

function downloadDir(): Promise<string>

Returns the path to the users download directory.

Platform-specific

  • Linux: Resolves to xdg-user-dirs XDG_DOWNLOAD_DIR.
  • macOS: Resolves to $HOME/Downloads.
  • Windows: Resolves to {FOLDERID_Downloads}.

Returns

Promise<string>

Example

import { downloadDir } from '@tauri-apps/api/path';
const downloadDirPath = await downloadDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L330


executableDir()

function executableDir(): Promise<string>

Returns the path to the users executable directory.

Platform-specific

  • Linux: Resolves to $XDG_BIN_HOME/../bin or $XDG_DATA_HOME/../bin or $HOME/.local/bin.
  • macOS: Not supported.
  • Windows: Not supported.

Returns

Promise<string>

Example

import { executableDir } from '@tauri-apps/api/path';
const executableDirPath = await executableDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L352


extname()

function extname(path): Promise<string>

Returns the extension of the path.

Parameters

Parameter Type
path string

Returns

Promise<string>

Example

import { extname } from '@tauri-apps/api/path';
const ext = await extname('/path/to/file.html');
assert(ext === 'html');

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L718


fontDir()

function fontDir(): Promise<string>

Returns the path to the users font directory.

Platform-specific

  • Linux: Resolves to $XDG_DATA_HOME/fonts or $HOME/.local/share/fonts.
  • macOS: Resolves to $HOME/Library/Fonts.
  • Windows: Not supported.

Returns

Promise<string>

Example

import { fontDir } from '@tauri-apps/api/path';
const fontDirPath = await fontDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L374


homeDir()

function homeDir(): Promise<string>

Returns the path to the users home directory.

Platform-specific

  • Linux: Resolves to $HOME.
  • macOS: Resolves to $HOME.
  • Windows: Resolves to {FOLDERID_Profile}.

Returns

Promise<string>

Example

import { homeDir } from '@tauri-apps/api/path';
const homeDirPath = await homeDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L396


isAbsolute()

function isAbsolute(path): Promise<boolean>

Returns whether the path is absolute or not.

Parameters

Parameter Type
path string

Returns

Promise<boolean>

Example

import { isAbsolute } from '@tauri-apps/api/path';
assert(await isAbsolute('/home/tauri'));

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L748


join()

function join(...paths): Promise<string>

Joins all given path segments together using the platform-specific separator as a delimiter, then normalizes the resulting path.

Parameters

Parameter Type
paths string[]

Returns

Promise<string>

Example

import { join, appDataDir } from '@tauri-apps/api/path';
const appDataDirPath = await appDataDir();
const path = await join(appDataDirPath, 'users', 'tauri', 'avatar.png');

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L688


localDataDir()

function localDataDir(): Promise<string>

Returns the path to the users local data directory.

Platform-specific

  • Linux: Resolves to $XDG_DATA_HOME or $HOME/.local/share.
  • macOS: Resolves to $HOME/Library/Application Support.
  • Windows: Resolves to {FOLDERID_LocalAppData}.

Returns

Promise<string>

Example

import { localDataDir } from '@tauri-apps/api/path';
const localDataDirPath = await localDataDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L418


normalize()

function normalize(path): Promise<string>

Normalizes the given path, resolving '..' and '.' segments and resolve symbolic links.

Parameters

Parameter Type
path string

Returns

Promise<string>

Example

import { normalize, appDataDir } from '@tauri-apps/api/path';
const appDataDirPath = await appDataDir();
const path = await normalize(`${appDataDirPath}/../users/tauri/avatar.png`);

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L673


pictureDir()

function pictureDir(): Promise<string>

Returns the path to the users picture directory.

Platform-specific

  • Linux: Resolves to xdg-user-dirs XDG_PICTURES_DIR.
  • macOS: Resolves to $HOME/Pictures.
  • Windows: Resolves to {FOLDERID_Pictures}.

Returns

Promise<string>

Example

import { pictureDir } from '@tauri-apps/api/path';
const pictureDirPath = await pictureDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L440


publicDir()

function publicDir(): Promise<string>

Returns the path to the users public directory.

Platform-specific

  • Linux: Resolves to xdg-user-dirs XDG_PUBLICSHARE_DIR.
  • macOS: Resolves to $HOME/Public.
  • Windows: Resolves to {FOLDERID_Public}.

Returns

Promise<string>

Example

import { publicDir } from '@tauri-apps/api/path';
const publicDirPath = await publicDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L462


resolve()

function resolve(...paths): Promise<string>

Resolves a sequence of paths or path segments into an absolute path.

Parameters

Parameter Type
paths string[]

Returns

Promise<string>

Example

import { resolve, appDataDir } from '@tauri-apps/api/path';
const appDataDirPath = await appDataDir();
const path = await resolve(appDataDirPath, '..', 'users', 'tauri', 'avatar.png');

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L658


resolveResource()

function resolveResource(resourcePath): Promise<string>

Resolve the path to a resource file.

Parameters

Parameter Type Description
resourcePath string The path to the resource. Must follow the same syntax as defined in tauri.conf.json > bundle > resources, i.e. keeping subfolders and parent dir components (../).

Returns

Promise<string>

The full path to the resource.

Example

import { resolveResource } from '@tauri-apps/api/path';
const resourcePath = await resolveResource('script.sh');

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L515


resourceDir()

function resourceDir(): Promise<string>

Returns the path to the applications resource directory. To resolve a resource path, see resolveResource.

Platform-specific

Although we provide the exact path where this function resolves to, this is not a contract and things might change in the future

  • Windows: Resolves to the directory that contains the main executable.
  • Linux: When running in an AppImage, the APPDIR variable will be set to the mounted location of the app, and the resource dir will be ${APPDIR}/usr/lib/${exe_name}. If not running in an AppImage, the path is /usr/lib/${exe_name}. When running the app from src-tauri/target/(debug|release)/, the path is ${exe_dir}/../lib/${exe_name}.
  • macOS: Resolves to ${exe_dir}/../Resources (inside .app).
  • iOS: Resolves to ${exe_dir}/assets.
  • Android: Currently the resources are stored in the APK as assets so its not a normal file system path, we return a special URI prefix asset://localhost/ here that can be used with the file system plugin,

Returns

Promise<string>

Example

import { resourceDir } from '@tauri-apps/api/path';
const resourceDirPath = await resourceDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L495


runtimeDir()

function runtimeDir(): Promise<string>

Returns the path to the users runtime directory.

Platform-specific

  • Linux: Resolves to $XDG_RUNTIME_DIR.
  • macOS: Not supported.
  • Windows: Not supported.

Returns

Promise<string>

Example

import { runtimeDir } from '@tauri-apps/api/path';
const runtimeDirPath = await runtimeDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L538


sep()

function sep(): string

Returns the platform-specific path segment separator:

  • \ on Windows
  • / on POSIX

Returns

string

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L633


tempDir()

function tempDir(): Promise<string>

Returns a temporary directory.

Returns

Promise<string>

Example

import { tempDir } from '@tauri-apps/api/path';
const temp = await tempDir();

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L620


templateDir()

function templateDir(): Promise<string>

Returns the path to the users template directory.

Platform-specific

  • Linux: Resolves to xdg-user-dirs XDG_TEMPLATES_DIR.
  • macOS: Not supported.
  • Windows: Resolves to {FOLDERID_Templates}.

Returns

Promise<string>

Example

import { templateDir } from '@tauri-apps/api/path';
const templateDirPath = await templateDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L560


videoDir()

function videoDir(): Promise<string>

Returns the path to the users video directory.

Platform-specific

  • Linux: Resolves to xdg-user-dirs XDG_VIDEOS_DIR.
  • macOS: Resolves to $HOME/Movies.
  • Windows: Resolves to {FOLDERID_Videos}.

Returns

Promise<string>

Example

import { videoDir } from '@tauri-apps/api/path';
const videoDirPath = await videoDir();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/path.ts#L582

tray

Classes

TrayIcon

Tray icon class and associated methods. This type constructor is private, instead, you should use the static method TrayIcon.new.

Warning

Unlike Rust, javascript does not have any way to run cleanup code when an object is being removed by garbage collection, but this tray icon will be cleaned up when the tauri app exists, however if you want to cleanup this object early, you need to call TrayIcon.close.

Example

import { TrayIcon } from '@tauri-apps/api/tray';
const tray = await TrayIcon.new({ tooltip: 'awesome tray tooltip' });
tray.set_tooltip('new tooltip');

Extends

Properties

Property Modifier Type Description Defined in
id public string The id associated with this tray icon. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L160

Accessors

rid
get rid(): number
Returns

number

Inherited from

Resource.rid

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L318

Methods

close()
close(): Promise<void>

Destroys and cleans up this resource from memory. You should not call any method on this object anymore and should drop any reference to it.

Returns

Promise<void>

Inherited from

Resource.close

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/core.ts#L330

setIcon()
setIcon(icon): Promise<void>

Sets a new tray icon. If null is provided, it will remove the icon.

Note that you may need the image-ico or image-png Cargo features to use this API. To enable it, change your Cargo.toml file:

[dependencies]
tauri = { version = "...", features = ["...", "image-png"] }
Parameters
Parameter Type
icon | null | string | Uint8Array | number[] | ArrayBuffer | Image
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L224

setIconAsTemplate()
setIconAsTemplate(asTemplate): Promise<void>

Sets the current icon as a template. macOS only

Parameters
Parameter Type
asTemplate boolean
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L292

setIconWithAsTemplate()
setIconWithAsTemplate(icon, asTemplate): Promise<void>

Sets a new tray icon and template status atomically. macOS only.

Note that you may need the image-ico or image-png Cargo features to use this API. To enable it, change your Cargo.toml file:

[dependencies]
tauri = { version = "...", features = ["...", "image-png"] }
Parameters
Parameter Type
icon | null | string | Uint8Array | number[] | ArrayBuffer | Image
asTemplate boolean
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L309

setMenu()
setMenu(menu): Promise<void>

Sets a new tray menu.

Platform-specific:

  • Linux: once a menu is set it cannot be removed so null has no effect
Parameters
Parameter Type
menu null | Submenu | Menu
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L241

setMenuOnLeftClick()
setMenuOnLeftClick(onLeft): Promise<void>

Disable or enable showing the tray menu on left click.

Platform-specific:

  • Linux: Unsupported.
Parameters
Parameter Type
onLeft boolean
Returns

Promise<void>

Deprecated

use TrayIcon.setShowMenuOnLeftClick instead.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L333

setShowMenuOnLeftClick()
setShowMenuOnLeftClick(onLeft): Promise<void>

Disable or enable showing the tray menu on left click.

Platform-specific:

  • Linux: Unsupported.
Parameters
Parameter Type
onLeft boolean
Returns

Promise<void>

Since

2.2.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L349

setTempDirPath()
setTempDirPath(path): Promise<void>

Sets the tray icon temp dir path. Linux only.

On Linux, we need to write the icon to the disk and usually it will be $XDG_RUNTIME_DIR/tray-icon or $TEMP/tray-icon.

Parameters
Parameter Type
path null | string
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L287

setTitle()
setTitle(title): Promise<void>

Sets the tooltip for this tray icon.

Platform-specific:

  • Linux: The title will not be shown unless there is an icon as well. The title is useful for numerical and other frequently updated information. In general, it shouldnt be shown unless a user requests it as it can take up a significant amount of space on the users panel. This may not be shown in all visualizations.
  • Windows: Unsupported
Parameters
Parameter Type
title null | string
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L272

setTooltip()
setTooltip(tooltip): Promise<void>

Sets the tooltip for this tray icon.

Platform-specific:

  • Linux: Unsupported
Parameters
Parameter Type
tooltip null | string
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L256

setVisible()
setVisible(visible): Promise<void>

Show or hide this tray icon.

Parameters
Parameter Type
visible boolean
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L277

getById()
static getById(id): Promise<null | TrayIcon>

Gets a tray icon using the provided id.

Parameters
Parameter Type
id string
Returns

Promise<null | TrayIcon>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L168

new()
static new(options?): Promise<TrayIcon>

Creates a new TrayIcon

Platform-specific:

  • Linux: Sometimes the icon wont be visible unless a menu is set. Setting an empty Menu is enough.
Parameters
Parameter Type
options? TrayIconOptions
Returns

Promise<TrayIcon>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L192

removeById()
static removeById(id): Promise<void>

Removes a tray icon using the provided id from tauris internal state.

Note that this may cause the tray icon to disappear if it wasnt cloned somewhere else or referenced by JS.

Parameters
Parameter Type
id string
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L180

Interfaces

TrayIconOptions

TrayIcon creation options

Properties

Property Type Description Defined in
action? (event: TrayIconEvent) => void A handler for an event on the tray icon. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L137
icon? | string | Uint8Array | number[] | ArrayBuffer | Image The tray icon which could be icon bytes or path to the icon file. Note that you may need the image-ico or image-png Cargo features to use this API. To enable it, change your Cargo.toml file: [dependencies] tauri = { version = "...", features = ["...", "image-png"] } Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L89
iconAsTemplate? boolean Use the icon as a template. macOS only. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L115
id? string The tray icon id. If undefined, a random one will be assigned Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L76
menu? Submenu | Menu The tray icon menu Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L78
menuOnLeftClick? boolean Whether to show the tray menu on left click or not, default is true. Platform-specific: - Linux: Unsupported. Deprecated use TrayIconOptions.showMenuOnLeftClick instead. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L125
showMenuOnLeftClick? boolean Whether to show the tray menu on left click or not, default is true. Platform-specific: - Linux: Unsupported. Since 2.2.0 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L135
tempDirPath? string The tray icon temp dir path. Linux only. On Linux, we need to write the icon to the disk and usually it will be $XDG_RUNTIME_DIR/tray-icon or $TEMP/tray-icon. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L111
title? string The tray title Platform-specific - Linux: The title will not be shown unless there is an icon as well. The title is useful for numerical and other frequently updated information. In general, it shouldnt be shown unless a user requests it as it can take up a significant amount of space on the users panel. This may not be shown in all visualizations. - Windows: Unsupported. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L104
tooltip? string The tray icon tooltip Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L91

Type Aliases

MouseButton

type MouseButton: "Left" | "Right" | "Middle";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L11


MouseButtonState

type MouseButtonState: "Up" | "Down";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L10


TrayIconClickEvent

type TrayIconClickEvent: object;

Type declaration

Name Type Description Defined in
button MouseButton Mouse button that triggered this event. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L35
buttonState MouseButtonState Mouse button state when this event was triggered. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L37

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L33


TrayIconEvent

type TrayIconEvent:
  | TrayIconEventBase<"Click"> & TrayIconClickEvent
  | TrayIconEventBase<"DoubleClick"> & Omit<TrayIconClickEvent, "buttonState">
  | TrayIconEventBase<"Enter">
  | TrayIconEventBase<"Move">
| TrayIconEventBase<"Leave">;

Describes a tray icon event.

Platform-specific:

  • Linux: Unsupported. The event is not emitted even though the icon is shown, the icon will still show a context menu on right click.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L48


TrayIconEventBase<T>

type TrayIconEventBase<T>: object;

Type Parameters

Type Parameter
T extends TrayIconEventType

Type declaration

Name Type Description Defined in
id string Id of the tray icon which triggered this event. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L23
position PhysicalPosition Physical position of the click the triggered this event. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L25
rect object Position and size of the tray icon. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L27
rect.position PhysicalPosition - Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L28
rect.size PhysicalSize - Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L29
type T The tray icon event type Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L21

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L19


TrayIconEventType

type TrayIconEventType:
  | "Click"
  | "DoubleClick"
  | "Enter"
  | "Move"
  | "Leave";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/tray.ts#L12

webview

Provides APIs to create webviews, communicate with other webviews and manipulate the current webview.

Webview events

Events can be listened to using Webview.listen:

import { getCurrentWebview } from "@tauri-apps/api/webview";
getCurrentWebview().listen("my-webview-event", ({ event, payload }) => { });

Classes

Webview

Create new webview or get a handle to an existing one.

Webviews are identified by a label a unique identifier that can be used to reference it later. It may only contain alphanumeric characters a-zA-Z plus the following special characters -, /, : and _.

Example

import { Window } from "@tauri-apps/api/window"
import { Webview } from "@tauri-apps/api/webview"


const appWindow = new Window('uniqueLabel');


appWindow.once('tauri://created', async function () {
  // `new Webview` Should be called after the window is successfully created,
  // or webview may not be attached to the window since window is not created yet.


  // loading embedded asset:
  const webview = new Webview(appWindow, 'theUniqueLabel', {
    url: 'path/to/page.html',


    // create a webview with specific logical position and size
    x: 0,
    y: 0,
    width: 800,
    height: 600,
  });
  // alternatively, load a remote URL:
  const webview = new Webview(appWindow, 'theUniqueLabel', {
    url: 'https://github.com/tauri-apps/tauri',


    // create a webview with specific logical position and size
    x: 0,
    y: 0,
    width: 800,
    height: 600,
  });


  webview.once('tauri://created', function () {
    // webview successfully created
  });
  webview.once('tauri://error', function (e) {
    // an error happened creating the webview
  });


  // emit an event to the backend
  await webview.emit("some-event", "data");
  // listen to an event from the backend
  const unlisten = await webview.listen("event-name", e => { });
  unlisten();
});

Since

2.0.0

Extended by

Constructors

new Webview()
new Webview(
   window,
   label,
   options): Webview

Creates a new Webview.

Parameters
Parameter Type Description
window Window the window to add this webview to.
label string The unique webview label. Must be alphanumeric: a-zA-Z-/:_.
options WebviewOptions -
Returns

Webview

The Webview instance to communicate with the webview.

Example
import { Window } from '@tauri-apps/api/window'
import { Webview } from '@tauri-apps/api/webview'
const appWindow = new Window('my-label')


appWindow.once('tauri://created', async function() {
  const webview = new Webview(appWindow, 'my-label', {
    url: 'https://github.com/tauri-apps/tauri',


    // create a webview with specific logical position and size
    x: 0,
    y: 0,
    width: 800,
    height: 600,
  });


  webview.once('tauri://created', function () {
    // webview successfully created
  });
  webview.once('tauri://error', function (e) {
    // an error happened creating the webview
  });
});

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L194

Properties

Property Type Description Defined in
label string The webview label. It is a unique identifier for the webview, can be used to reference it later. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L155
listeners Record<string, EventCallback<any>[]> Local event listeners. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L160
window Window The window hosting this webview. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L157

Methods

clearAllBrowsingData()
clearAllBrowsingData(): Promise<void>

Clears all browsing data for this webview.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().clearAllBrowsingData();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L589

close()
close(): Promise<void>

Closes the webview.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().close();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L436

emit()
emit<T>(event, payload?): Promise<void>

Emits an event to all targets.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
event string Event name. Must include only alphanumeric characters, -, /, : and _.
payload? T Event payload.
Returns

Promise<void>

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().emit('webview-loaded', { loggedIn: true, token: 'authToken' });

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L325

emitTo()
emitTo<T>(
   target,
   event,
payload?): Promise<void>

Emits an event to all targets matching the given target.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
target string | EventTarget Label of the target Window/Webview/WebviewWindow or raw EventTarget object.
event string Event name. Must include only alphanumeric characters, -, /, : and _.
payload? T Event payload.
Returns

Promise<void>

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().emitTo('main', 'webview-loaded', { loggedIn: true, token: 'authToken' });

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L353

hide()
hide(): Promise<void>

Hide the webview.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().hide();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L523

listen()
listen<T>(event, handler): Promise<UnlistenFn>

Listen to an emitted event on this webview.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
event EventName Event name. Must include only alphanumeric characters, -, /, : and _.
handler EventCallback<T> Event handler.
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
const unlisten = await getCurrentWebview().listen<string>('state-changed', (event) => {
  console.log(`Got error: ${payload}`);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L262

onDragDropEvent()
onDragDropEvent(handler): Promise<UnlistenFn>

Listen to a file drop event. The listener is triggered when the user hovers the selected files on the webview, drops the files or cancels the operation.

Parameters
Parameter Type
handler EventCallback<DragDropEvent>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWebview } from "@tauri-apps/api/webview";
const unlisten = await getCurrentWebview().onDragDropEvent((event) => {
 if (event.payload.type === 'over') {
   console.log('User hovering', event.payload.position);
 } else if (event.payload.type === 'drop') {
   console.log('User dropped', event.payload.paths);
 } else {
   console.log('File drop cancelled');
 }
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

When the debugger panel is open, the drop position of this event may be inaccurate due to a known limitation. To retrieve the correct drop position, please detach the debugger.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L641

once()
once<T>(event, handler): Promise<UnlistenFn>

Listen to an emitted event on this webview only once.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
event EventName Event name. Must include only alphanumeric characters, -, /, : and _.
handler EventCallback<T> Event handler.
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
const unlisten = await getCurrent().once<null>('initialized', (event) => {
  console.log(`Webview initialized!`);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L297

position()
position(): Promise<PhysicalPosition>

The position of the top-left hand corner of the webviews client area relative to the top-left hand corner of the desktop.

Returns

Promise<PhysicalPosition>

The webviews position.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
const position = await getCurrentWebview().position();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L398

reparent()
reparent(window): Promise<void>

Moves this webview to the given label.

Parameters
Parameter Type
window string | Window | WebviewWindow
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().reparent('other-window');

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L572

setAutoResize()
setAutoResize(autoResize): Promise<void>

Sets whether the webview should automatically grow and shrink its size and position when the parent window resizes.

Parameters
Parameter Type
autoResize boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().setAutoResize(true);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L506

setBackgroundColor()
setBackgroundColor(color): Promise<void>

Specify the webview background color.

Platform-specific:

  • macOS / iOS: Not implemented.

  • Windows:

    • On Windows 7, transparency is not supported and the alpha value will be ignored.
    • On Windows higher than 7: translucent colors are not supported so any alpha value other than 0 will be replaced by 255
Parameters
Parameter Type
color null | Color
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Since

2.1.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L607

setFocus()
setFocus(): Promise<void>

Bring the webview to front and focus.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().setFocus();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L490

setPosition()
setPosition(position): Promise<void>

Sets the webview position.

Parameters
Parameter Type Description
position LogicalPosition | PhysicalPosition | Position The new position, in logical or physical pixels.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrent, LogicalPosition } from '@tauri-apps/api/webview';
await getCurrentWebview().setPosition(new LogicalPosition(600, 500));

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L471

setSize()
setSize(size): Promise<void>

Resizes the webview.

Parameters
Parameter Type Description
size LogicalSize | PhysicalSize | Size The logical or physical size.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrent, LogicalSize } from '@tauri-apps/api/webview';
await getCurrentWebview().setSize(new LogicalSize(600, 500));

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L453

setZoom()
setZoom(scaleFactor): Promise<void>

Set webview zoom level.

Parameters
Parameter Type
scaleFactor number
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().setZoom(1.5);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L555

show()
show(): Promise<void>

Show the webview.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().show();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L539

size()
size(): Promise<PhysicalSize>

The physical size of the webviews client area. The client area is the content of the webview, excluding the title bar and borders.

Returns

Promise<PhysicalSize>

The webviews size.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
const size = await getCurrentWebview().size();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L415

getAll()
static getAll(): Promise<Webview[]>

Gets a list of instances of Webview for all available webviews.

Returns

Promise<Webview[]>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L239

getByLabel()
static getByLabel(label): Promise<null | Webview>

Gets the Webview for the webview associated with the given label.

Parameters
Parameter Type Description
label string The webview label.
Returns

Promise<null | Webview>

The Webview instance to communicate with the webview or null if the webview doesnt exist.

Example
import { Webview } from '@tauri-apps/api/webview';
const mainWebview = Webview.getByLabel('main');

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L225

getCurrent()
static getCurrent(): Webview

Get an instance of Webview for the current webview.

Returns

Webview

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L232

Interfaces

WebviewOptions

Configuration for the webview to create.

Since

2.0.0

Properties

Property Type Description Defined in
acceptFirstMouse? boolean Whether clicking an inactive webview also clicks through to the webview on macOS. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L746
allowLinkPreview? boolean on macOS and iOS there is a link preview on long pressing links, this is enabled by default. see https://docs.rs/objc2-web-kit/latest/objc2_web_kit/struct.WKWebView.html#method.allowsLinkPreview Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L850
backgroundColor? Color Set the window and webview background color. Platform-specific: - macOS / iOS: Not implemented. - Windows: - On Windows 7, alpha channel is ignored. - On Windows 8 and newer, if alpha channel is not 0, it will be ignored. Since 2.1.0 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L822
backgroundThrottling? BackgroundThrottlingPolicy Change the default background throttling behaviour. By default, browsers use a suspend policy that will throttle timers and even unload the whole tab (view) to free resources after roughly 5 minutes when a view became minimized or hidden. This will pause all tasks until the documents visibility state changes back from hidden to visible by bringing the view back to the foreground. ## Platform-specific - Linux / Windows / Android: Unsupported. Workarounds like a pending WebLock transaction might suffice. - iOS: Supported since version 17.0+. - macOS: Supported since version 14.0+. see https://github.com/tauri-apps/tauri/issues/5250#issuecomment-2569380578 Since 2.3.0 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L841
dataDirectory? string Set a custom path for the webviews data directory (localStorage, cache, etc.) relative to [appDataDir()]/${label}. For security reasons, paths outside of that location can only be configured on the Rust side. Platform-specific: - Windows: WebViews with different values for settings like additionalBrowserArgs, browserExtensionsEnabled or scrollBarStyle must have different data directories. - macOS / iOS: Unsupported, use dataStoreIdentifier instead. - Android: Unsupported. Since 2.9.0 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L870
dataStoreIdentifier? number[] Initialize the WebView with a custom data store identifier. This can be seen as a replacement for dataDirectory which is unavailable in WKWebView. See https://developer.apple.com/documentation/webkit/wkwebsitedatastore/init(foridentifier:)?language=objc The array must contain 16 u8 numbers. Platform-specific: - macOS / iOS: Available on macOS >= 14 and iOS >= 17 - Windows / Linux / Android: Unsupported. Since 2.9.0 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L884
devtools? boolean Whether web inspector, which is usually called browser devtools, is enabled or not. Enabled by default. This API works in debug builds, but requires devtools feature flag to enable it in release builds. Platform-specific - macOS: This will call private functions on macOS. - Android: Open chrome://inspect/#devices in Chrome to get the devtools window. Wrys WebView devtools API isnt supported on Android. - iOS: Open Safari > Develop > [Your Device Name] > [Your WebView] to get the devtools window. Since 2.1.0 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L809
disableInputAccessoryView? boolean Allows disabling the input accessory view on iOS. The accessory view is the view that appears above the keyboard when a text input element is focused. It usually displays a view with “Done”, “Next” buttons. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L857
dragDropEnabled? boolean Whether the drag and drop is enabled or not on the webview. By default it is enabled. Disabling it is required to use HTML5 drag and drop on the frontend on Windows. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L742
focus? boolean Whether the webview should have focus or not Since 2.1.0 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L736
generalAutofillEnabled? boolean Controls the WebViews browser-level general autofill behavior. This option does not disable password or credit card autofill. When set to false, the WebView will not automatically populate general form fields using previously stored data such as addresses or contact information. If not specified, this is true by default. ## Platform-specific - Windows: Supported. WebView2s autofill feature (called “Suggestions”) may not honor autocomplete="off" on input elements in some cases. - Linux / Android / iOS / macOS: Unsupported and performs no operation. Since 2.11.0 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L918
height number The initial height in logical pixels. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L724
incognito? boolean Whether or not the webview should be launched in incognito mode. Platform-specific - Android: Unsupported. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L758
javascriptDisabled? boolean Whether we should disable JavaScript code execution on the webview or not. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L845
proxyUrl? string The proxy URL for the WebView for all network requests. Must be either a http:// or a socks5:// URL. Platform-specific - macOS: Requires the macos-proxy feature flag and only compiles for macOS 14+. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L768
scrollBarStyle? ScrollBarStyle Specifies the native scrollbar style to use with the webview. CSS styles that modify the scrollbar are applied on top of the native appearance configured here. Defaults to default, which is the browser default. ## Platform-specific - Windows: - fluentOverlay requires WebView2 Runtime version 125.0.2535.41 or higher, and does nothing on older versions. - This option must be given the same value for all webviews. - Linux / Android / iOS / macOS: Unsupported. Only supports Default and performs no operation. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L899
transparent? boolean Whether the webview is transparent or not. Note that on macOS this requires the macos-private-api feature flag, enabled under tauri.conf.json > app > macOSPrivateApi. WARNING: Using private APIs on macOS prevents your application from being accepted to the App Store. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L730
url? string Remote URL or local file path to open. - URL such as https://github.com/tauri-apps is opened directly on a Tauri webview. - data: URL such as data:text/html,<html>... is only supported with the webview-data-url Cargo feature for the tauri dependency. - local file path or route such as /path/to/page.html or /users is appended to the application URL (the devServer URL on development, or tauri://localhost/ and https://tauri.localhost/ on production). Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L716
useHttpsScheme? boolean Sets whether the custom protocols should use https://<scheme>.localhost instead of the default http://<scheme>.localhost on Windows and Android. Defaults to false. #### Note Using a https scheme will NOT allow mixed content when trying to fetch http endpoints and therefore will not match the behavior of the <scheme>://localhost protocols used on macOS and Linux. #### Warning Changing this value between releases will change the IndexedDB, cookies and localstorage location and your app will not be able to access them. Since 2.1.0 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L795
userAgent? string The user agent for the webview. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L750
width number The initial width in logical pixels. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L722
x number The initial vertical position in logical pixels. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L718
y number The initial horizontal position in logical pixels. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L720
zoomHotkeysEnabled? boolean Whether page zooming by hotkeys is enabled Platform-specific: - Windows: Controls WebView2s IsZoomControlEnabled setting. - MacOS / Linux: Injects a polyfill that zooms in and out with ctrl/command + -/=, 20% in each step, ranging from 20% to 1000%. Requires webview:allow-set-webview-zoom permission - Android / iOS: Unsupported. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L780

Type Aliases

Color

type Color: [number, number, number] | [number, number, number, number] | object | string;

An RGBA color. Each value has minimum of 0 and maximum of 255.

It can be either a string #ffffff, an array of 3 or 4 elements or an object.

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2121


DragDropEvent

type DragDropEvent: object | object | object | object;

The drag and drop event types.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L43

Functions

getAllWebviews()

function getAllWebviews(): Promise<Webview[]>

Gets a list of instances of Webview for all available webviews.

Returns

Promise<Webview[]>

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L70


getCurrentWebview()

function getCurrentWebview(): Webview

Get an instance of Webview for the current webview.

Returns

Webview

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L54

webviewWindow

References

Color

Re-exports Color

DragDropEvent

Re-exports DragDropEvent

Classes

WebviewWindow

Create new webview or get a handle to an existing one.

Webviews are identified by a label a unique identifier that can be used to reference it later. It may only contain alphanumeric characters a-zA-Z plus the following special characters -, /, : and _.

Example

import { Window } from "@tauri-apps/api/window"
import { Webview } from "@tauri-apps/api/webview"


const appWindow = new Window('uniqueLabel');


appWindow.once('tauri://created', async function () {
  // `new Webview` Should be called after the window is successfully created,
  // or webview may not be attached to the window since window is not created yet.


  // loading embedded asset:
  const webview = new Webview(appWindow, 'theUniqueLabel', {
    url: 'path/to/page.html',


    // create a webview with specific logical position and size
    x: 0,
    y: 0,
    width: 800,
    height: 600,
  });
  // alternatively, load a remote URL:
  const webview = new Webview(appWindow, 'theUniqueLabel', {
    url: 'https://github.com/tauri-apps/tauri',


    // create a webview with specific logical position and size
    x: 0,
    y: 0,
    width: 800,
    height: 600,
  });


  webview.once('tauri://created', function () {
    // webview successfully created
  });
  webview.once('tauri://error', function (e) {
    // an error happened creating the webview
  });


  // emit an event to the backend
  await webview.emit("some-event", "data");
  // listen to an event from the backend
  const unlisten = await webview.listen("event-name", e => { });
  unlisten();
});

Since

2.0.0

Extends

Constructors

new WebviewWindow()
new WebviewWindow(label, options): WebviewWindow

Creates a new Window hosting a Webview.

Parameters
Parameter Type Description
label string The unique webview label. Must be alphanumeric: a-zA-Z-/:_.
options Omit<WebviewOptions, "x" | "y" | "width" | "height"> & WindowOptions -
Returns

WebviewWindow

The WebviewWindow instance to communicate with the window and webview.

Example
import { WebviewWindow } from '@tauri-apps/api/webviewWindow'
const webview = new WebviewWindow('my-label', {
  url: 'https://github.com/tauri-apps/tauri'
});
webview.once('tauri://created', function () {
 // webview successfully created
});
webview.once('tauri://error', function (e) {
 // an error happened creating the webview
});
Inherited from

Window.constructor

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webviewWindow.ts#L75

Properties

Property Type Description Inherited from Defined in
label string The webview label. It is a unique identifier for the webview, can be used to reference it later. Window.label Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webviewWindow.ts#L51
listeners Record<string, EventCallback<any>[]> Local event listeners. Window.listeners Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webviewWindow.ts#L54
window Window The window hosting this webview. Webview.window Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L157

Methods

activityName()
activityName(): Promise<string>
Returns

Promise<string>

Inherited from

Window.activityName

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L853

center()
center(): Promise<void>

Centers the window.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().center();
Inherited from

Window.center

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L877

clearAllBrowsingData()
clearAllBrowsingData(): Promise<void>

Clears all browsing data for this webview.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().clearAllBrowsingData();
Inherited from

Webview.clearAllBrowsingData

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L589

clearEffects()
clearEffects(): Promise<void>

Clear any applied effects if possible.

Returns

Promise<void>

Inherited from

Window.clearEffects

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1265

close()
close(): Promise<void>

Closes the webview.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().close();
Inherited from

Window.close

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L436

destroy()
destroy(): Promise<void>

Destroys the window. Behaves like Window.close but forces the window close instead of emitting a closeRequested event.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().destroy();
Inherited from

Window.destroy

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1202

emit()
emit<T>(event, payload?): Promise<void>

Emits an event to all targets.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
event string Event name. Must include only alphanumeric characters, -, /, : and _.
payload? T Event payload.
Returns

Promise<void>

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().emit('webview-loaded', { loggedIn: true, token: 'authToken' });
Inherited from

Window.emit

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L325

emitTo()
emitTo<T>(
   target,
   event,
payload?): Promise<void>

Emits an event to all targets matching the given target.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
target string | EventTarget Label of the target Window/Webview/WebviewWindow or raw EventTarget object.
event string Event name. Must include only alphanumeric characters, -, /, : and _.
payload? T Event payload.
Returns

Promise<void>

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().emitTo('main', 'webview-loaded', { loggedIn: true, token: 'authToken' });
Inherited from

Window.emitTo

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L353

hide()
hide(): Promise<void>

Hide the webview.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().hide();
Inherited from

Window.hide

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L523

innerPosition()
innerPosition(): Promise<PhysicalPosition>

The position of the top-left hand corner of the windows client area relative to the top-left hand corner of the desktop.

Returns

Promise<PhysicalPosition>

The windows inner position.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const position = await getCurrentWindow().innerPosition();
Inherited from

Window.innerPosition

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L567

innerSize()
innerSize(): Promise<PhysicalSize>

The physical size of the windows client area. The client area is the content of the window, excluding the title bar and borders.

Returns

Promise<PhysicalSize>

The windows inner size.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const size = await getCurrentWindow().innerSize();
Inherited from

Window.innerSize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L600

isAlwaysOnTop()
isAlwaysOnTop(): Promise<boolean>

Whether the window is configured to be always on top of other windows or not.

Returns

Promise<boolean>

Whether the window is visible or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const alwaysOnTop = await getCurrentWindow().isAlwaysOnTop();
Inherited from

Window.isAlwaysOnTop

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L847

isClosable()
isClosable(): Promise<boolean>

Gets the windows native close button state.

Platform-specific

  • iOS / Android: Unsupported.
Returns

Promise<boolean>

Whether the windows native close button is enabled or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const closable = await getCurrentWindow().isClosable();
Inherited from

Window.isClosable

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L780

isDecorated()
isDecorated(): Promise<boolean>

Gets the windows current decorated state.

Returns

Promise<boolean>

Whether the window is decorated or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const decorated = await getCurrentWindow().isDecorated();
Inherited from

Window.isDecorated

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L701

isEnabled()
isEnabled(): Promise<boolean>

Whether the window is enabled or disabled.

Returns

Promise<boolean>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setEnabled(false);
Since

2.0.0

Inherited from

Window.isEnabled

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L969

isFocused()
isFocused(): Promise<boolean>

Gets the windows current focus state.

Returns

Promise<boolean>

Whether the window is focused or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const focused = await getCurrentWindow().isFocused();
Inherited from

Window.isFocused

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L685

isFullscreen()
isFullscreen(): Promise<boolean>

Gets the windows current fullscreen state.

Returns

Promise<boolean>

Whether the window is in fullscreen mode or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const fullscreen = await getCurrentWindow().isFullscreen();
Inherited from

Window.isFullscreen

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L639

isMaximizable()
isMaximizable(): Promise<boolean>

Gets the windows native maximize button state.

Platform-specific

  • Linux / iOS / Android: Unsupported.
Returns

Promise<boolean>

Whether the windows native maximize button is enabled or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const maximizable = await getCurrentWindow().isMaximizable();
Inherited from

Window.isMaximizable

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L738

isMaximized()
isMaximized(): Promise<boolean>

Gets the windows current maximized state.

Returns

Promise<boolean>

Whether the window is maximized or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const maximized = await getCurrentWindow().isMaximized();
Inherited from

Window.isMaximized

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L669

isMinimizable()
isMinimizable(): Promise<boolean>

Gets the windows native minimize button state.

Platform-specific

  • Linux / iOS / Android: Unsupported.
Returns

Promise<boolean>

Whether the windows native minimize button is enabled or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const minimizable = await getCurrentWindow().isMinimizable();
Inherited from

Window.isMinimizable

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L759

isMinimized()
isMinimized(): Promise<boolean>

Gets the windows current minimized state.

Returns

Promise<boolean>

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const minimized = await getCurrentWindow().isMinimized();
Inherited from

Window.isMinimized

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L653

isResizable()
isResizable(): Promise<boolean>

Gets the windows current resizable state.

Returns

Promise<boolean>

Whether the window is resizable or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const resizable = await getCurrentWindow().isResizable();
Inherited from

Window.isResizable

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L717

isVisible()
isVisible(): Promise<boolean>

Gets the windows current visible state.

Returns

Promise<boolean>

Whether the window is visible or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const visible = await getCurrentWindow().isVisible();
Inherited from

Window.isVisible

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L796

listen()
listen<T>(event, handler): Promise<UnlistenFn>

Listen to an emitted event on this webview window.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
event EventName Event name. Must include only alphanumeric characters, -, /, : and _.
handler EventCallback<T> Event handler.
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { WebviewWindow } from '@tauri-apps/api/webviewWindow';
const unlisten = await WebviewWindow.getCurrent().listen<string>('state-changed', (event) => {
  console.log(`Got error: ${payload}`);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();
Inherited from

Window.listen

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webviewWindow.ts#L155

maximize()
maximize(): Promise<void>

Maximizes the window.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().maximize();
Inherited from

Window.maximize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1072

minimize()
minimize(): Promise<void>

Minimizes the window.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().minimize();
Inherited from

Window.minimize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1120

onCloseRequested()
onCloseRequested(handler): Promise<UnlistenFn>

Listen to window close requested. Emitted when the user requests to closes the window.

Parameters
Parameter Type
handler (event) => void | Promise<void>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from "@tauri-apps/api/window";
import { confirm } from '@tauri-apps/api/dialog';
const unlisten = await getCurrentWindow().onCloseRequested(async (event) => {
  const confirmed = await confirm('Are you sure?');
  if (!confirmed) {
    // user did not confirm closing the window; let's prevent it
    event.preventDefault();
  }
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();
Inherited from

Window.onCloseRequested

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1927

onDragDropEvent()
onDragDropEvent(handler): Promise<UnlistenFn>

Listen to a file drop event. The listener is triggered when the user hovers the selected files on the webview, drops the files or cancels the operation.

Parameters
Parameter Type
handler EventCallback<DragDropEvent>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWebview } from "@tauri-apps/api/webview";
const unlisten = await getCurrentWebview().onDragDropEvent((event) => {
 if (event.payload.type === 'over') {
   console.log('User hovering', event.payload.position);
 } else if (event.payload.type === 'drop') {
   console.log('User dropped', event.payload.paths);
 } else {
   console.log('File drop cancelled');
 }
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

When the debugger panel is open, the drop position of this event may be inaccurate due to a known limitation. To retrieve the correct drop position, please detach the debugger.

Inherited from

Window.onDragDropEvent

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L641

onFocusChanged()
onFocusChanged(handler): Promise<UnlistenFn>

Listen to window focus change.

Parameters
Parameter Type
handler EventCallback<boolean>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from "@tauri-apps/api/window";
const unlisten = await getCurrentWindow().onFocusChanged(({ payload: focused }) => {
 console.log('Focus changed, window is focused? ' + focused);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();
Inherited from

Window.onFocusChanged

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2043

onMoved()
onMoved(handler): Promise<UnlistenFn>

Listen to window move.

Parameters
Parameter Type
handler EventCallback<PhysicalPosition>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from "@tauri-apps/api/window";
const unlisten = await getCurrentWindow().onMoved(({ payload: position }) => {
 console.log('Window moved', position);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();
Inherited from

Window.onMoved

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1898

onResized()
onResized(handler): Promise<UnlistenFn>

Listen to window resize.

Parameters
Parameter Type
handler EventCallback<PhysicalSize>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from "@tauri-apps/api/window";
const unlisten = await getCurrentWindow().onResized(({ payload: size }) => {
 console.log('Window resized', size);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();
Inherited from

Window.onResized

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1874

onScaleChanged()
onScaleChanged(handler): Promise<UnlistenFn>

Listen to window scale change. Emitted when the windows scale factor has changed. The following user actions can cause DPI changes:

  • Changing the displays resolution.
  • Changing the displays scale factor (e.g. in Control Panel on Windows).
  • Moving the window to a display with a different scale factor.
Parameters
Parameter Type
handler EventCallback<ScaleFactorChanged>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from "@tauri-apps/api/window";
const unlisten = await getCurrentWindow().onScaleChanged(({ payload }) => {
 console.log('Scale changed', payload.scaleFactor, payload.size);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();
Inherited from

Window.onScaleChanged

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2083

onThemeChanged()
onThemeChanged(handler): Promise<UnlistenFn>

Listen to the system theme change.

Parameters
Parameter Type
handler EventCallback<Theme>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from "@tauri-apps/api/window";
const unlisten = await getCurrentWindow().onThemeChanged(({ payload: theme }) => {
 console.log('New theme: ' + theme);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();
Inherited from

Window.onThemeChanged

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2109

once()
once<T>(event, handler): Promise<UnlistenFn>

Listen to an emitted event on this webview window only once.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
event EventName Event name. Must include only alphanumeric characters, -, /, : and _.
handler EventCallback<T> Event handler.
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { WebviewWindow } from '@tauri-apps/api/webviewWindow';
const unlisten = await WebviewWindow.getCurrent().once<null>('initialized', (event) => {
  console.log(`Webview initialized!`);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();
Inherited from

Window.once

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webviewWindow.ts#L190

outerPosition()
outerPosition(): Promise<PhysicalPosition>

The position of the top-left hand corner of the window relative to the top-left hand corner of the desktop.

Returns

Promise<PhysicalPosition>

The windows outer position.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const position = await getCurrentWindow().outerPosition();
Inherited from

Window.outerPosition

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L583

outerSize()
outerSize(): Promise<PhysicalSize>

The physical size of the entire window. These dimensions include the title bar and borders. If you dont want that (and you usually dont), use inner_size instead.

Returns

Promise<PhysicalSize>

The windows outer size.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const size = await getCurrentWindow().outerSize();
Inherited from

Window.outerSize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L620

position()
position(): Promise<PhysicalPosition>

The position of the top-left hand corner of the webviews client area relative to the top-left hand corner of the desktop.

Returns

Promise<PhysicalPosition>

The webviews position.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
const position = await getCurrentWebview().position();
Inherited from

Webview.position

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L398

reparent()
reparent(window): Promise<void>

Moves this webview to the given label.

Parameters
Parameter Type
window string | Window | WebviewWindow
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().reparent('other-window');
Inherited from

Webview.reparent

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L572

requestUserAttention()
requestUserAttention(requestType): Promise<void>

Requests user attention to the window, this has no effect if the application is already focused. How requesting for user attention manifests is platform dependent, see UserAttentionType for details.

Providing null will unset the request for user attention. Unsetting the request for user attention might not be done automatically by the WM when the window receives input.

Platform-specific

  • macOS: null has no effect.
  • Linux: Urgency levels have the same effect.
Parameters
Parameter Type
requestType null | UserAttentionType
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().requestUserAttention();
Inherited from

Window.requestUserAttention

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L903

scaleFactor()
scaleFactor(): Promise<number>

The scale factor that can be used to map physical pixels to logical pixels.

Returns

Promise<number>

The windows monitor scale factor.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const factor = await getCurrentWindow().scaleFactor();
Inherited from

Window.scaleFactor

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L551

sceneIdentifier()
sceneIdentifier(): Promise<string>
Returns

Promise<string>

Inherited from

Window.sceneIdentifier

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L859

setAlwaysOnBottom()
setAlwaysOnBottom(alwaysOnBottom): Promise<void>

Whether the window should always be below other windows.

Parameters
Parameter Type Description
alwaysOnBottom boolean Whether the window should always be below other windows or not.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setAlwaysOnBottom(true);
Inherited from

Window.setAlwaysOnBottom

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1301

setAlwaysOnTop()
setAlwaysOnTop(alwaysOnTop): Promise<void>

Whether the window should always be on top of other windows.

Parameters
Parameter Type Description
alwaysOnTop boolean Whether the window should always be on top of other windows or not.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setAlwaysOnTop(true);
Inherited from

Window.setAlwaysOnTop

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1283

setAutoResize()
setAutoResize(autoResize): Promise<void>

Sets whether the webview should automatically grow and shrink its size and position when the parent window resizes.

Parameters
Parameter Type
autoResize boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().setAutoResize(true);
Inherited from

Webview.setAutoResize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L506

setBackgroundColor()
setBackgroundColor(color): Promise<void>

Set the window and webview background color.

Platform-specific:

  • Android / iOS: Unsupported for the window layer.

  • macOS / iOS: Not implemented for the webview layer.

  • Windows:

    • alpha channel is ignored for the window layer.
    • On Windows 7, alpha channel is ignored for the webview layer.
    • On Windows 8 and newer, if alpha channel is not 0, it will be ignored.
Parameters
Parameter Type
color Color
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Since

2.1.0

Inherited from

Window.setBackgroundColor

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webviewWindow.ts#L222

setBadgeCount()
setBadgeCount(count?): Promise<void>

Sets the badge count. It is app wide and not specific to this window.

Platform-specific

  • Windows: Unsupported. Use @{linkcode Window.setOverlayIcon} instead.
Parameters
Parameter Type Description
count? number The badge count. Use undefined to remove the badge.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setBadgeCount(5);
Inherited from

Window.setBadgeCount

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1727

setBadgeLabel()
setBadgeLabel(label?): Promise<void>

Sets the badge cont macOS only.

Parameters
Parameter Type Description
label? string The badge label. Use undefined to remove the badge.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setBadgeLabel("Hello");
Inherited from

Window.setBadgeLabel

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1746

setClosable()
setClosable(closable): Promise<void>

Sets whether the windows native close button is enabled or not.

Platform-specific

  • Linux: GTK+ will do its best to convince the window manager not to show a close button. Depending on the system, this function may not have any effect when called on a window that is already visible
  • iOS / Android: Unsupported.
Parameters
Parameter Type
closable boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setClosable(false);
Inherited from

Window.setClosable

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1037

setContentProtected()
setContentProtected(protected_): Promise<void>

Prevents the window contents from being captured by other apps.

Parameters
Parameter Type
protected_ boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setContentProtected(true);
Inherited from

Window.setContentProtected

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1318

setCursorGrab()
setCursorGrab(grab): Promise<void>

Grabs the cursor, preventing it from leaving the window.

Theres no guarantee that the cursor will be hidden. You should hide it by yourself if you want so.

Platform-specific

  • Linux: Unsupported.
  • macOS: This locks the cursor in a fixed location, which looks visually awkward.
Parameters
Parameter Type Description
grab boolean true to grab the cursor icon, false to release it.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setCursorGrab(true);
Inherited from

Window.setCursorGrab

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1574

setCursorIcon()
setCursorIcon(icon): Promise<void>

Modifies the cursor icon of the window.

Parameters
Parameter Type Description
icon CursorIcon The new cursor icon.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setCursorIcon('help');
Inherited from

Window.setCursorIcon

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1616

setCursorPosition()
setCursorPosition(position): Promise<void>

Changes the position of the cursor in window coordinates.

Parameters
Parameter Type Description
position LogicalPosition | PhysicalPosition | Position The new cursor position.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow, LogicalPosition } from '@tauri-apps/api/window';
await getCurrentWindow().setCursorPosition(new LogicalPosition(600, 300));
Inherited from

Window.setCursorPosition

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1650

setCursorVisible()
setCursorVisible(visible): Promise<void>

Modifies the cursors visibility.

Platform-specific

  • Windows: The cursor is only hidden within the confines of the window.
  • macOS: The cursor is hidden as long as the window has input focus, even if the cursor is outside of the window.
Parameters
Parameter Type Description
visible boolean If false, this will hide the cursor. If true, this will show the cursor.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setCursorVisible(false);
Inherited from

Window.setCursorVisible

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1598

setDecorations()
setDecorations(decorations): Promise<void>

Whether the window should have borders and bars.

Parameters
Parameter Type Description
decorations boolean Whether the window should have borders and bars.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setDecorations(false);
Inherited from

Window.setDecorations

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1219

setEffects()
setEffects(effects): Promise<void>

Set window effects.

Parameters
Parameter Type
effects Effects
Returns

Promise<void>

Inherited from

Window.setEffects

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1255

setEnabled()
setEnabled(enabled): Promise<void>

Enable or disable the window.

Parameters
Parameter Type
enabled boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setEnabled(false);
Since

2.0.0

Inherited from

Window.setEnabled

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L950

setFocus()
setFocus(): Promise<void>

Bring the webview to front and focus.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().setFocus();
Inherited from

Window.setFocus

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L490

setFocusable()
setFocusable(focusable): Promise<void>

Sets whether the window can be focused.

Platform-specific

  • macOS: If the window is already focused, it is not possible to unfocus it after calling set_focusable(false). In this case, you might consider calling Window.setFocus but it will move the window to the back i.e. at the bottom in terms of z-order.
Parameters
Parameter Type Description
focusable boolean Whether the window can be focused.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setFocusable(true);
Inherited from

Window.setFocusable

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1499

setFullscreen()
setFullscreen(fullscreen): Promise<void>

Sets the window fullscreen state.

Parameters
Parameter Type Description
fullscreen boolean Whether the window should go to fullscreen or not.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setFullscreen(true);
Inherited from

Window.setFullscreen

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1443

setIcon()
setIcon(icon): Promise<void>

Sets the window icon.

Parameters
Parameter Type Description
icon | string | Uint8Array | number[] | ArrayBuffer | Image Icon bytes or path to the icon file.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setIcon('/tauri/awesome.png');

Note that you may need the image-ico or image-png Cargo features to use this API. To enable it, change your Cargo.toml file:

[dependencies]
tauri = { version = "...", features = ["...", "image-png"] }
Inherited from

Window.setIcon

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1524

setIgnoreCursorEvents()
setIgnoreCursorEvents(ignore): Promise<void>

Changes the cursor events behavior.

Parameters
Parameter Type Description
ignore boolean true to ignore the cursor events; false to process them as usual.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setIgnoreCursorEvents(true);
Inherited from

Window.setIgnoreCursorEvents

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1671

setMaxSize()
setMaxSize(size): Promise<void>

Sets the window maximum inner size. If the size argument is undefined, the constraint is unset.

Parameters
Parameter Type Description
size | undefined | null | LogicalSize | PhysicalSize | Size The logical or physical inner size, or null to unset the constraint.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow, LogicalSize } from '@tauri-apps/api/window';
await getCurrentWindow().setMaxSize(new LogicalSize(600, 500));
Inherited from

Window.setMaxSize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1374

setMaximizable()
setMaximizable(maximizable): Promise<void>

Sets whether the windows native maximize button is enabled or not. If resizable is set to false, this setting is ignored.

Platform-specific

  • macOS: Disables the “zoom” button in the window titlebar, which is also used to enter fullscreen mode.
  • Linux / iOS / Android: Unsupported.
Parameters
Parameter Type
maximizable boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setMaximizable(false);
Inherited from

Window.setMaximizable

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L992

setMinSize()
setMinSize(size): Promise<void>

Sets the window minimum inner size. If the size argument is not provided, the constraint is unset.

Parameters
Parameter Type Description
size | undefined | null | LogicalSize | PhysicalSize | Size The logical or physical inner size, or null to unset the constraint.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow, PhysicalSize } from '@tauri-apps/api/window';
await getCurrentWindow().setMinSize(new PhysicalSize(600, 500));
Inherited from

Window.setMinSize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1354

setMinimizable()
setMinimizable(minimizable): Promise<void>

Sets whether the windows native minimize button is enabled or not.

Platform-specific

  • Linux / iOS / Android: Unsupported.
Parameters
Parameter Type
minimizable boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setMinimizable(false);
Inherited from

Window.setMinimizable

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1014

setOverlayIcon()
setOverlayIcon(icon?): Promise<void>

Sets the overlay icon. Windows only The overlay icon can be set for every window.

Note that you may need the image-ico or image-png Cargo features to use this API. To enable it, change your Cargo.toml file:

[dependencies]
tauri = { version = "...", features = ["...", "image-png"] }
Parameters
Parameter Type Description
icon? | string | Uint8Array | number[] | ArrayBuffer | Image Icon bytes or path to the icon file. Use undefined to remove the overlay icon.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setOverlayIcon("/tauri/awesome.png");
Inherited from

Window.setOverlayIcon

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1775

setPosition()
setPosition(position): Promise<void>

Sets the webview position.

Parameters
Parameter Type Description
position LogicalPosition | PhysicalPosition | Position The new position, in logical or physical pixels.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrent, LogicalPosition } from '@tauri-apps/api/webview';
await getCurrentWebview().setPosition(new LogicalPosition(600, 500));
Inherited from

Window.setPosition

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L471

setProgressBar()
setProgressBar(state): Promise<void>

Sets the taskbar progress state.

Platform-specific

  • Linux / macOS: Progress bar is app-wide and not specific to this window.
  • Linux: Only supported desktop environments with libunity (e.g. GNOME).
Parameters
Parameter Type
state ProgressBarState
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow, ProgressBarStatus } from '@tauri-apps/api/window';
await getCurrentWindow().setProgressBar({
  status: ProgressBarStatus.Normal,
  progress: 50,
});
Inherited from

Window.setProgressBar

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1803

setResizable()
setResizable(resizable): Promise<void>

Updates the window resizable flag.

Parameters
Parameter Type
resizable boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setResizable(false);
Inherited from

Window.setResizable

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L931

setShadow()
setShadow(enable): Promise<void>

Whether or not the window should have shadow.

Platform-specific

  • Windows:

    • false has no effect on decorated window, shadows are always ON.
    • true will make undecorated window have a 1px white border, and on Windows 11, it will have a rounded corners.
  • Linux: Unsupported.

Parameters
Parameter Type
enable boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setShadow(false);
Inherited from

Window.setShadow

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1245

setSimpleFullscreen()
setSimpleFullscreen(fullscreen): Promise<void>

On macOS, Toggles a fullscreen mode that doesnt require a new macOS space. Returns a boolean indicating whether the transition was successful (this wont work if the window was already in the native fullscreen). This is how fullscreen used to work on macOS in versions before Lion. And allows the user to have a fullscreen window without using another space or taking control over the entire monitor.

On other platforms, this is the same as Window.setFullscreen.

Parameters
Parameter Type Description
fullscreen boolean Whether the window should go to simple fullscreen or not.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Inherited from

Window.setSimpleFullscreen

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1459

setSize()
setSize(size): Promise<void>

Resizes the webview.

Parameters
Parameter Type Description
size LogicalSize | PhysicalSize | Size The logical or physical size.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrent, LogicalSize } from '@tauri-apps/api/webview';
await getCurrentWebview().setSize(new LogicalSize(600, 500));
Inherited from

Window.setSize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L453

setSizeConstraints()
setSizeConstraints(constraints): Promise<void>

Sets the window inner size constraints.

Parameters
Parameter Type Description
constraints undefined | null | WindowSizeConstraints The logical or physical inner size, or null to unset the constraint.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setSizeConstraints({ minWidth: 300 });
Inherited from

Window.setSizeConstraints

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1394

setSkipTaskbar()
setSkipTaskbar(skip): Promise<void>

Whether the window icon should be hidden from the taskbar or not.

Platform-specific

  • macOS: Unsupported.
Parameters
Parameter Type Description
skip boolean true to hide window icon, false to show it.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setSkipTaskbar(true);
Inherited from

Window.setSkipTaskbar

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1548

setTheme()
setTheme(theme?): Promise<void>

Set window theme, pass in null or undefined to follow system theme

Platform-specific

  • Linux / macOS: Theme is app-wide and not specific to this window.
  • iOS / Android: Unsupported.
Parameters
Parameter Type
theme? null | Theme
Returns

Promise<void>

Since

2.0.0

Inherited from

Window.setTheme

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1848

setTitle()
setTitle(title): Promise<void>

Sets the window title.

Parameters
Parameter Type Description
title string The new title
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setTitle('Tauri');
Inherited from

Window.setTitle

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1055

setTitleBarStyle()
setTitleBarStyle(style): Promise<void>

Sets the title bar style. macOS only.

Parameters
Parameter Type
style TitleBarStyle
Returns

Promise<void>

Since

2.0.0

Inherited from

Window.setTitleBarStyle

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1831

setVisibleOnAllWorkspaces()
setVisibleOnAllWorkspaces(visible): Promise<void>

Sets whether the window should be visible on all workspaces or virtual desktops.

Platform-specific

  • Windows / iOS / Android: Unsupported.
Parameters
Parameter Type
visible boolean
Returns

Promise<void>

Since

2.0.0

Inherited from

Window.setVisibleOnAllWorkspaces

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1819

setZoom()
setZoom(scaleFactor): Promise<void>

Set webview zoom level.

Parameters
Parameter Type
scaleFactor number
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().setZoom(1.5);
Inherited from

Webview.setZoom

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L555

show()
show(): Promise<void>

Show the webview.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
await getCurrentWebview().show();
Inherited from

Window.show

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L539

size()
size(): Promise<PhysicalSize>

The physical size of the webviews client area. The client area is the content of the webview, excluding the title bar and borders.

Returns

Promise<PhysicalSize>

The webviews size.

Example
import { getCurrentWebview } from '@tauri-apps/api/webview';
const size = await getCurrentWebview().size();
Inherited from

Webview.size

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webview.ts#L415

startDragging()
startDragging(): Promise<void>

Starts dragging the window.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().startDragging();
Inherited from

Window.startDragging

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1688

startResizeDragging()
startResizeDragging(direction): Promise<void>

Starts resize-dragging the window.

Parameters
Parameter Type
direction ResizeDirection
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().startResizeDragging();
Inherited from

Window.startResizeDragging

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1704

theme()
theme(): Promise<null | Theme>

Gets the windows current theme.

Platform-specific

  • macOS: Theme was introduced on macOS 10.14. Returns light on macOS 10.13 and below.
Returns

Promise<null | Theme>

The window theme.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const theme = await getCurrentWindow().theme();
Inherited from

Window.theme

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L831

title()
title(): Promise<string>

Gets the windows current title.

Returns

Promise<string>

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const title = await getCurrentWindow().title();
Inherited from

Window.title

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L810

toggleMaximize()
toggleMaximize(): Promise<void>

Toggles the window maximized state.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().toggleMaximize();
Inherited from

Window.toggleMaximize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1104

unmaximize()
unmaximize(): Promise<void>

Unmaximizes the window.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().unmaximize();
Inherited from

Window.unmaximize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1088

unminimize()
unminimize(): Promise<void>

Unminimizes the window.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().unminimize();
Inherited from

Window.unminimize

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1136

getAll()
static getAll(): Promise<WebviewWindow[]>

Gets a list of instances of Webview for all available webviews.

Returns

Promise<WebviewWindow[]>

Inherited from

Window.getAll

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webviewWindow.ts#L132

getByLabel()
static getByLabel(label): Promise<null | WebviewWindow>

Gets the Webview for the webview associated with the given label.

Parameters
Parameter Type Description
label string The webview label.
Returns

Promise<null | WebviewWindow>

The Webview instance to communicate with the webview or null if the webview doesnt exist.

Example
import { WebviewWindow } from '@tauri-apps/api/webviewWindow';
const mainWebview = WebviewWindow.getByLabel('main');
Inherited from

Window.getByLabel

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webviewWindow.ts#L112

getCurrent()
static getCurrent(): WebviewWindow

Get an instance of Webview for the current webview.

Returns

WebviewWindow

Inherited from

Window.getCurrent

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webviewWindow.ts#L125

Functions

getAllWebviewWindows()

function getAllWebviewWindows(): Promise<WebviewWindow[]>

Gets a list of instances of Webview for all available webview windows.

Returns

Promise<WebviewWindow[]>

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webviewWindow.ts#L34


getCurrentWebviewWindow()

function getCurrentWebviewWindow(): WebviewWindow

Get an instance of Webview for the current webview window.

Returns

WebviewWindow

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/webviewWindow.ts#L23

window

Provides APIs to create windows, communicate with other windows and manipulate the current window.

Window events

Events can be listened to using Window.listen:

import { getCurrentWindow } from "@tauri-apps/api/window";
getCurrentWindow().listen("my-window-event", ({ event, payload }) => { });

References

Color

Re-exports Color

DragDropEvent

Re-exports DragDropEvent

LogicalPosition

Re-exports LogicalPosition

LogicalSize

Re-exports LogicalSize

PhysicalPosition

Re-exports PhysicalPosition

PhysicalSize

Re-exports PhysicalSize

Enumerations

BackgroundThrottlingPolicy

Background throttling policy

Since

2.0.0

Enumeration Members

Disabled
Disabled: "disabled";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2133

Suspend
Suspend: "suspend";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2135

Throttle
Throttle: "throttle";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2134


Effect

Platform-specific window effects

Since

2.0.0

Enumeration Members

Acrylic
Acrylic: "acrylic";

Windows 10/11

Notes

This effect has bad performance when resizing/dragging the window on Windows 10 v1903+ and Windows 11 build 22000.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2272

AppearanceBased
AppearanceBased: "appearanceBased";

A default material appropriate for the views effectiveAppearance. macOS 10.14-

Deprecated

since macOS 10.14. You should instead choose an appropriate semantic material.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2172

Blur
Blur: "blur";

Windows 7/10/11(22H1) Only

Notes

This effect has bad performance when resizing/dragging the window on Windows 11 build 22621.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2264

ContentBackground
ContentBackground: "contentBackground";

macOS 10.14+

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2244

Dark
Dark: "dark";

macOS 10.14-

Deprecated

since macOS 10.14. Use a semantic material instead.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2184

FullScreenUI
FullScreenUI: "fullScreenUI";

macOS 10.14+

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2236

HeaderView
HeaderView: "headerView";

macOS 10.14+

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2220

HudWindow
HudWindow: "hudWindow";

macOS 10.14+

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2232

Light
Light: "light";

macOS 10.14-

Deprecated

since macOS 10.14. Use a semantic material instead.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2178

MediumLight
MediumLight: "mediumLight";

macOS 10.14-

Deprecated

since macOS 10.14. Use a semantic material instead.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2190

Menu
Menu: "menu";

macOS 10.11+

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2208

Mica
Mica: "mica";

Windows 11 Only

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2256

Popover
Popover: "popover";

macOS 10.11+

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2212

Selection
Selection: "selection";

macOS 10.10+

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2204

Sheet
Sheet: "sheet";

macOS 10.14+

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2224

Sidebar
Sidebar: "sidebar";

macOS 10.11+

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2216

Tabbed
Tabbed: "tabbed";

Tabbed effect that matches the system dark preference Windows 11 Only

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2276

TabbedDark
TabbedDark: "tabbedDark";

Tabbed effect with dark mode but only if dark mode is enabled on the system Windows 11 Only

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2280

TabbedLight
TabbedLight: "tabbedLight";

Tabbed effect with light mode Windows 11 Only

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2284

Titlebar
Titlebar: "titlebar";

macOS 10.10+

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2200

Tooltip
Tooltip: "tooltip";

macOS 10.14+

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2240

UltraDark
UltraDark: "ultraDark";

macOS 10.14-

Deprecated

since macOS 10.14. Use a semantic material instead.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2196

UnderPageBackground
UnderPageBackground: "underPageBackground";

macOS 10.14+

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2252

UnderWindowBackground
UnderWindowBackground: "underWindowBackground";

macOS 10.14+

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2248

WindowBackground
WindowBackground: "windowBackground";

macOS 10.14+

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2228


EffectState

Window effect state macOS only

See

https://developer.apple.com/documentation/appkit/nsvisualeffectview/state

Since

2.0.0

Enumeration Members

Active
Active: "active";

Make window effect state always active macOS only

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2302

FollowsWindowActiveState
FollowsWindowActiveState: "followsWindowActiveState";

Make window effect state follow the windows active state macOS only

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2298

Inactive
Inactive: "inactive";

Make window effect state always inactive macOS only

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2306


ProgressBarStatus

Enumeration Members

Error
Error: "error";

Error state. Treated as Normal on linux

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L220

Indeterminate
Indeterminate: "indeterminate";

Indeterminate state. Treated as Normal on Linux and macOS

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L212

None
None: "none";

Hide progress bar.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L204

Normal
Normal: "normal";

Normal state.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L208

Paused
Paused: "paused";

Paused state. Treated as Normal on Linux

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L216


ScrollBarStyle

The scrollbar style to use in the webview.

Platform-specific

Windows: This option must be given the same value for all webviews.

Since

2.8.0

Enumeration Members

Default
Default: "default";

The default scrollbar style for the webview.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2151

FluentOverlay
FluentOverlay: "fluentOverlay";

Fluent UI style overlay scrollbars. Windows Only

Requires WebView2 Runtime version 125.0.2535.41 or higher, does nothing on older versions, see https://learn.microsoft.com/en-us/microsoft-edge/webview2/release-notes/?tabs=dotnetcsharp#10253541

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2158


UserAttentionType

Attention type to request on a window.

Since

1.0.0

Enumeration Members

Critical
Critical: 1;

Platform-specific

  • macOS: Bounces the dock icon until the application is in focus.
  • Windows: Flashes both the window and the taskbar button until the application is in focus.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L129

Informational
Informational: 2;

Platform-specific

  • macOS: Bounces the dock icon once.
  • Windows: Flashes the taskbar button until the application is in focus.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L135

Classes

CloseRequestedEvent

Constructors

new CloseRequestedEvent()
new CloseRequestedEvent(event): CloseRequestedEvent
Parameters
Parameter Type
event Event<unknown>
Returns

CloseRequestedEvent

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L145

Properties

Property Type Description Defined in
event EventName Event name Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L140
id number Event identifier used to unlisten Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L142

Methods

isPreventDefault()
isPreventDefault(): boolean
Returns

boolean

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L154

preventDefault()
preventDefault(): void
Returns

void

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L150


Window

Create new window or get a handle to an existing one.

Windows are identified by a label a unique identifier that can be used to reference it later. It may only contain alphanumeric characters a-zA-Z plus the following special characters -, /, : and _.

Example

import { Window } from "@tauri-apps/api/window"


const appWindow = new Window('theUniqueLabel');


appWindow.once('tauri://created', function () {
 // window successfully created
});
appWindow.once('tauri://error', function (e) {
 // an error happened creating the window
});


// emit an event to the backend
await appWindow.emit("some-event", "data");
// listen to an event from the backend
const unlisten = await appWindow.listen("event-name", e => {});
unlisten();

Since

2.0.0

Extended by

Constructors

new Window()
new Window(label, options): Window

Creates a new Window.

Parameters
Parameter Type Description
label string The unique window label. Must be alphanumeric: a-zA-Z-/:_.
options WindowOptions -
Returns

Window

The Window instance to communicate with the window.

Example
import { Window } from '@tauri-apps/api/window';
const appWindow = new Window('my-label');
appWindow.once('tauri://created', function () {
 // window successfully created
});
appWindow.once('tauri://error', function (e) {
 // an error happened creating the window
});

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L328

Properties

Property Type Description Defined in
label string The window label. It is a unique identifier for the window, can be used to reference it later. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L306
listeners Record<string, EventCallback<any>[]> Local event listeners. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L309

Methods

activityName()
activityName(): Promise<string>
Returns

Promise<string>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L853

center()
center(): Promise<void>

Centers the window.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().center();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L877

clearEffects()
clearEffects(): Promise<void>

Clear any applied effects if possible.

Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1265

close()
close(): Promise<void>

Closes the window.

Note this emits a closeRequested event so you can intercept it. To force window close, use Window.destroy.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().close();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1186

destroy()
destroy(): Promise<void>

Destroys the window. Behaves like Window.close but forces the window close instead of emitting a closeRequested event.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().destroy();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1202

emit()
emit<T>(event, payload?): Promise<void>

Emits an event to all targets.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
event string Event name. Must include only alphanumeric characters, -, /, : and _.
payload? T Event payload.
Returns

Promise<void>

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().emit('window-loaded', { loggedIn: true, token: 'authToken' });

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L479

emitTo()
emitTo<T>(
   target,
   event,
payload?): Promise<void>

Emits an event to all targets matching the given target.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
target string | EventTarget Label of the target Window/Webview/WebviewWindow or raw EventTarget object.
event string Event name. Must include only alphanumeric characters, -, /, : and _.
payload? T Event payload.
Returns

Promise<void>

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().emit('main', 'window-loaded', { loggedIn: true, token: 'authToken' });

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L506

hide()
hide(): Promise<void>

Sets the window visibility to false.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().hide();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1168

innerPosition()
innerPosition(): Promise<PhysicalPosition>

The position of the top-left hand corner of the windows client area relative to the top-left hand corner of the desktop.

Returns

Promise<PhysicalPosition>

The windows inner position.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const position = await getCurrentWindow().innerPosition();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L567

innerSize()
innerSize(): Promise<PhysicalSize>

The physical size of the windows client area. The client area is the content of the window, excluding the title bar and borders.

Returns

Promise<PhysicalSize>

The windows inner size.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const size = await getCurrentWindow().innerSize();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L600

isAlwaysOnTop()
isAlwaysOnTop(): Promise<boolean>

Whether the window is configured to be always on top of other windows or not.

Returns

Promise<boolean>

Whether the window is visible or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const alwaysOnTop = await getCurrentWindow().isAlwaysOnTop();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L847

isClosable()
isClosable(): Promise<boolean>

Gets the windows native close button state.

Platform-specific

  • iOS / Android: Unsupported.
Returns

Promise<boolean>

Whether the windows native close button is enabled or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const closable = await getCurrentWindow().isClosable();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L780

isDecorated()
isDecorated(): Promise<boolean>

Gets the windows current decorated state.

Returns

Promise<boolean>

Whether the window is decorated or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const decorated = await getCurrentWindow().isDecorated();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L701

isEnabled()
isEnabled(): Promise<boolean>

Whether the window is enabled or disabled.

Returns

Promise<boolean>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setEnabled(false);
Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L969

isFocused()
isFocused(): Promise<boolean>

Gets the windows current focus state.

Returns

Promise<boolean>

Whether the window is focused or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const focused = await getCurrentWindow().isFocused();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L685

isFullscreen()
isFullscreen(): Promise<boolean>

Gets the windows current fullscreen state.

Returns

Promise<boolean>

Whether the window is in fullscreen mode or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const fullscreen = await getCurrentWindow().isFullscreen();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L639

isMaximizable()
isMaximizable(): Promise<boolean>

Gets the windows native maximize button state.

Platform-specific

  • Linux / iOS / Android: Unsupported.
Returns

Promise<boolean>

Whether the windows native maximize button is enabled or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const maximizable = await getCurrentWindow().isMaximizable();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L738

isMaximized()
isMaximized(): Promise<boolean>

Gets the windows current maximized state.

Returns

Promise<boolean>

Whether the window is maximized or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const maximized = await getCurrentWindow().isMaximized();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L669

isMinimizable()
isMinimizable(): Promise<boolean>

Gets the windows native minimize button state.

Platform-specific

  • Linux / iOS / Android: Unsupported.
Returns

Promise<boolean>

Whether the windows native minimize button is enabled or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const minimizable = await getCurrentWindow().isMinimizable();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L759

isMinimized()
isMinimized(): Promise<boolean>

Gets the windows current minimized state.

Returns

Promise<boolean>

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const minimized = await getCurrentWindow().isMinimized();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L653

isResizable()
isResizable(): Promise<boolean>

Gets the windows current resizable state.

Returns

Promise<boolean>

Whether the window is resizable or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const resizable = await getCurrentWindow().isResizable();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L717

isVisible()
isVisible(): Promise<boolean>

Gets the windows current visible state.

Returns

Promise<boolean>

Whether the window is visible or not.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const visible = await getCurrentWindow().isVisible();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L796

listen()
listen<T>(event, handler): Promise<UnlistenFn>

Listen to an emitted event on this window.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
event EventName Event name. Must include only alphanumeric characters, -, /, : and _.
handler EventCallback<T> Event handler.
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const unlisten = await getCurrentWindow().listen<string>('state-changed', (event) => {
  console.log(`Got error: ${payload}`);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L417

maximize()
maximize(): Promise<void>

Maximizes the window.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().maximize();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1072

minimize()
minimize(): Promise<void>

Minimizes the window.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().minimize();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1120

onCloseRequested()
onCloseRequested(handler): Promise<UnlistenFn>

Listen to window close requested. Emitted when the user requests to closes the window.

Parameters
Parameter Type
handler (event) => void | Promise<void>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from "@tauri-apps/api/window";
import { confirm } from '@tauri-apps/api/dialog';
const unlisten = await getCurrentWindow().onCloseRequested(async (event) => {
  const confirmed = await confirm('Are you sure?');
  if (!confirmed) {
    // user did not confirm closing the window; let's prevent it
    event.preventDefault();
  }
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1927

onDragDropEvent()
onDragDropEvent(handler): Promise<UnlistenFn>

Listen to a file drop event. The listener is triggered when the user hovers the selected files on the webview, drops the files or cancels the operation.

Parameters
Parameter Type
handler EventCallback<DragDropEvent>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from "@tauri-apps/api/webview";
const unlisten = await getCurrentWindow().onDragDropEvent((event) => {
 if (event.payload.type === 'over') {
   console.log('User hovering', event.payload.position);
 } else if (event.payload.type === 'drop') {
   console.log('User dropped', event.payload.paths);
 } else {
   console.log('File drop cancelled');
 }
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1965

onFocusChanged()
onFocusChanged(handler): Promise<UnlistenFn>

Listen to window focus change.

Parameters
Parameter Type
handler EventCallback<boolean>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from "@tauri-apps/api/window";
const unlisten = await getCurrentWindow().onFocusChanged(({ payload: focused }) => {
 console.log('Focus changed, window is focused? ' + focused);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2043

onMoved()
onMoved(handler): Promise<UnlistenFn>

Listen to window move.

Parameters
Parameter Type
handler EventCallback<PhysicalPosition>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from "@tauri-apps/api/window";
const unlisten = await getCurrentWindow().onMoved(({ payload: position }) => {
 console.log('Window moved', position);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1898

onResized()
onResized(handler): Promise<UnlistenFn>

Listen to window resize.

Parameters
Parameter Type
handler EventCallback<PhysicalSize>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from "@tauri-apps/api/window";
const unlisten = await getCurrentWindow().onResized(({ payload: size }) => {
 console.log('Window resized', size);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1874

onScaleChanged()
onScaleChanged(handler): Promise<UnlistenFn>

Listen to window scale change. Emitted when the windows scale factor has changed. The following user actions can cause DPI changes:

  • Changing the displays resolution.
  • Changing the displays scale factor (e.g. in Control Panel on Windows).
  • Moving the window to a display with a different scale factor.
Parameters
Parameter Type
handler EventCallback<ScaleFactorChanged>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from "@tauri-apps/api/window";
const unlisten = await getCurrentWindow().onScaleChanged(({ payload }) => {
 console.log('Scale changed', payload.scaleFactor, payload.size);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2083

onThemeChanged()
onThemeChanged(handler): Promise<UnlistenFn>

Listen to the system theme change.

Parameters
Parameter Type
handler EventCallback<Theme>
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from "@tauri-apps/api/window";
const unlisten = await getCurrentWindow().onThemeChanged(({ payload: theme }) => {
 console.log('New theme: ' + theme);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2109

once()
once<T>(event, handler): Promise<UnlistenFn>

Listen to an emitted event on this window only once.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
event EventName Event name. Must include only alphanumeric characters, -, /, : and _.
handler EventCallback<T> Event handler.
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event. Note that removing the listener is required if your listener goes out of scope e.g. the component is unmounted.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const unlisten = await getCurrentWindow().once<null>('initialized', (event) => {
  console.log(`Window initialized!`);
});


// you need to call unlisten if your handler goes out of scope e.g. the component is unmounted
unlisten();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L452

outerPosition()
outerPosition(): Promise<PhysicalPosition>

The position of the top-left hand corner of the window relative to the top-left hand corner of the desktop.

Returns

Promise<PhysicalPosition>

The windows outer position.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const position = await getCurrentWindow().outerPosition();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L583

outerSize()
outerSize(): Promise<PhysicalSize>

The physical size of the entire window. These dimensions include the title bar and borders. If you dont want that (and you usually dont), use inner_size instead.

Returns

Promise<PhysicalSize>

The windows outer size.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const size = await getCurrentWindow().outerSize();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L620

requestUserAttention()
requestUserAttention(requestType): Promise<void>

Requests user attention to the window, this has no effect if the application is already focused. How requesting for user attention manifests is platform dependent, see UserAttentionType for details.

Providing null will unset the request for user attention. Unsetting the request for user attention might not be done automatically by the WM when the window receives input.

Platform-specific

  • macOS: null has no effect.
  • Linux: Urgency levels have the same effect.
Parameters
Parameter Type
requestType null | UserAttentionType
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().requestUserAttention();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L903

scaleFactor()
scaleFactor(): Promise<number>

The scale factor that can be used to map physical pixels to logical pixels.

Returns

Promise<number>

The windows monitor scale factor.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const factor = await getCurrentWindow().scaleFactor();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L551

sceneIdentifier()
sceneIdentifier(): Promise<string>
Returns

Promise<string>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L859

setAlwaysOnBottom()
setAlwaysOnBottom(alwaysOnBottom): Promise<void>

Whether the window should always be below other windows.

Parameters
Parameter Type Description
alwaysOnBottom boolean Whether the window should always be below other windows or not.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setAlwaysOnBottom(true);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1301

setAlwaysOnTop()
setAlwaysOnTop(alwaysOnTop): Promise<void>

Whether the window should always be on top of other windows.

Parameters
Parameter Type Description
alwaysOnTop boolean Whether the window should always be on top of other windows or not.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setAlwaysOnTop(true);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1283

setBackgroundColor()
setBackgroundColor(color): Promise<void>

Sets the window background color.

Platform-specific:

  • Windows: alpha channel is ignored.
  • iOS / Android: Unsupported.
Parameters
Parameter Type
color Color
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Since

2.1.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1635

setBadgeCount()
setBadgeCount(count?): Promise<void>

Sets the badge count. It is app wide and not specific to this window.

Platform-specific

  • Windows: Unsupported. Use @{linkcode Window.setOverlayIcon} instead.
Parameters
Parameter Type Description
count? number The badge count. Use undefined to remove the badge.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setBadgeCount(5);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1727

setBadgeLabel()
setBadgeLabel(label?): Promise<void>

Sets the badge cont macOS only.

Parameters
Parameter Type Description
label? string The badge label. Use undefined to remove the badge.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setBadgeLabel("Hello");

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1746

setClosable()
setClosable(closable): Promise<void>

Sets whether the windows native close button is enabled or not.

Platform-specific

  • Linux: GTK+ will do its best to convince the window manager not to show a close button. Depending on the system, this function may not have any effect when called on a window that is already visible
  • iOS / Android: Unsupported.
Parameters
Parameter Type
closable boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setClosable(false);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1037

setContentProtected()
setContentProtected(protected_): Promise<void>

Prevents the window contents from being captured by other apps.

Parameters
Parameter Type
protected_ boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setContentProtected(true);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1318

setCursorGrab()
setCursorGrab(grab): Promise<void>

Grabs the cursor, preventing it from leaving the window.

Theres no guarantee that the cursor will be hidden. You should hide it by yourself if you want so.

Platform-specific

  • Linux: Unsupported.
  • macOS: This locks the cursor in a fixed location, which looks visually awkward.
Parameters
Parameter Type Description
grab boolean true to grab the cursor icon, false to release it.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setCursorGrab(true);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1574

setCursorIcon()
setCursorIcon(icon): Promise<void>

Modifies the cursor icon of the window.

Parameters
Parameter Type Description
icon CursorIcon The new cursor icon.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setCursorIcon('help');

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1616

setCursorPosition()
setCursorPosition(position): Promise<void>

Changes the position of the cursor in window coordinates.

Parameters
Parameter Type Description
position LogicalPosition | PhysicalPosition | Position The new cursor position.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow, LogicalPosition } from '@tauri-apps/api/window';
await getCurrentWindow().setCursorPosition(new LogicalPosition(600, 300));

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1650

setCursorVisible()
setCursorVisible(visible): Promise<void>

Modifies the cursors visibility.

Platform-specific

  • Windows: The cursor is only hidden within the confines of the window.
  • macOS: The cursor is hidden as long as the window has input focus, even if the cursor is outside of the window.
Parameters
Parameter Type Description
visible boolean If false, this will hide the cursor. If true, this will show the cursor.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setCursorVisible(false);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1598

setDecorations()
setDecorations(decorations): Promise<void>

Whether the window should have borders and bars.

Parameters
Parameter Type Description
decorations boolean Whether the window should have borders and bars.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setDecorations(false);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1219

setEffects()
setEffects(effects): Promise<void>

Set window effects.

Parameters
Parameter Type
effects Effects
Returns

Promise<void>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1255

setEnabled()
setEnabled(enabled): Promise<void>

Enable or disable the window.

Parameters
Parameter Type
enabled boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setEnabled(false);
Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L950

setFocus()
setFocus(): Promise<void>

Bring the window to front and focus.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setFocus();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1476

setFocusable()
setFocusable(focusable): Promise<void>

Sets whether the window can be focused.

Platform-specific

  • macOS: If the window is already focused, it is not possible to unfocus it after calling set_focusable(false). In this case, you might consider calling Window.setFocus but it will move the window to the back i.e. at the bottom in terms of z-order.
Parameters
Parameter Type Description
focusable boolean Whether the window can be focused.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setFocusable(true);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1499

setFullscreen()
setFullscreen(fullscreen): Promise<void>

Sets the window fullscreen state.

Parameters
Parameter Type Description
fullscreen boolean Whether the window should go to fullscreen or not.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setFullscreen(true);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1443

setIcon()
setIcon(icon): Promise<void>

Sets the window icon.

Parameters
Parameter Type Description
icon | string | Uint8Array | number[] | ArrayBuffer | Image Icon bytes or path to the icon file.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setIcon('/tauri/awesome.png');

Note that you may need the image-ico or image-png Cargo features to use this API. To enable it, change your Cargo.toml file:

[dependencies]
tauri = { version = "...", features = ["...", "image-png"] }

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1524

setIgnoreCursorEvents()
setIgnoreCursorEvents(ignore): Promise<void>

Changes the cursor events behavior.

Parameters
Parameter Type Description
ignore boolean true to ignore the cursor events; false to process them as usual.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setIgnoreCursorEvents(true);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1671

setMaxSize()
setMaxSize(size): Promise<void>

Sets the window maximum inner size. If the size argument is undefined, the constraint is unset.

Parameters
Parameter Type Description
size | undefined | null | LogicalSize | PhysicalSize | Size The logical or physical inner size, or null to unset the constraint.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow, LogicalSize } from '@tauri-apps/api/window';
await getCurrentWindow().setMaxSize(new LogicalSize(600, 500));

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1374

setMaximizable()
setMaximizable(maximizable): Promise<void>

Sets whether the windows native maximize button is enabled or not. If resizable is set to false, this setting is ignored.

Platform-specific

  • macOS: Disables the “zoom” button in the window titlebar, which is also used to enter fullscreen mode.
  • Linux / iOS / Android: Unsupported.
Parameters
Parameter Type
maximizable boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setMaximizable(false);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L992

setMinSize()
setMinSize(size): Promise<void>

Sets the window minimum inner size. If the size argument is not provided, the constraint is unset.

Parameters
Parameter Type Description
size | undefined | null | LogicalSize | PhysicalSize | Size The logical or physical inner size, or null to unset the constraint.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow, PhysicalSize } from '@tauri-apps/api/window';
await getCurrentWindow().setMinSize(new PhysicalSize(600, 500));

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1354

setMinimizable()
setMinimizable(minimizable): Promise<void>

Sets whether the windows native minimize button is enabled or not.

Platform-specific

  • Linux / iOS / Android: Unsupported.
Parameters
Parameter Type
minimizable boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setMinimizable(false);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1014

setOverlayIcon()
setOverlayIcon(icon?): Promise<void>

Sets the overlay icon. Windows only The overlay icon can be set for every window.

Note that you may need the image-ico or image-png Cargo features to use this API. To enable it, change your Cargo.toml file:

[dependencies]
tauri = { version = "...", features = ["...", "image-png"] }
Parameters
Parameter Type Description
icon? | string | Uint8Array | number[] | ArrayBuffer | Image Icon bytes or path to the icon file. Use undefined to remove the overlay icon.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setOverlayIcon("/tauri/awesome.png");

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1775

setPosition()
setPosition(position): Promise<void>

Sets the window outer position.

Parameters
Parameter Type Description
position LogicalPosition | PhysicalPosition | Position The new position, in logical or physical pixels.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow, LogicalPosition } from '@tauri-apps/api/window';
await getCurrentWindow().setPosition(new LogicalPosition(600, 500));

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1423

setProgressBar()
setProgressBar(state): Promise<void>

Sets the taskbar progress state.

Platform-specific

  • Linux / macOS: Progress bar is app-wide and not specific to this window.
  • Linux: Only supported desktop environments with libunity (e.g. GNOME).
Parameters
Parameter Type
state ProgressBarState
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow, ProgressBarStatus } from '@tauri-apps/api/window';
await getCurrentWindow().setProgressBar({
  status: ProgressBarStatus.Normal,
  progress: 50,
});

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1803

setResizable()
setResizable(resizable): Promise<void>

Updates the window resizable flag.

Parameters
Parameter Type
resizable boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setResizable(false);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L931

setShadow()
setShadow(enable): Promise<void>

Whether or not the window should have shadow.

Platform-specific

  • Windows:

    • false has no effect on decorated window, shadows are always ON.
    • true will make undecorated window have a 1px white border, and on Windows 11, it will have a rounded corners.
  • Linux: Unsupported.

Parameters
Parameter Type
enable boolean
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setShadow(false);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1245

setSimpleFullscreen()
setSimpleFullscreen(fullscreen): Promise<void>

On macOS, Toggles a fullscreen mode that doesnt require a new macOS space. Returns a boolean indicating whether the transition was successful (this wont work if the window was already in the native fullscreen). This is how fullscreen used to work on macOS in versions before Lion. And allows the user to have a fullscreen window without using another space or taking control over the entire monitor.

On other platforms, this is the same as Window.setFullscreen.

Parameters
Parameter Type Description
fullscreen boolean Whether the window should go to simple fullscreen or not.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1459

setSize()
setSize(size): Promise<void>

Resizes the window with a new inner size.

Parameters
Parameter Type Description
size LogicalSize | PhysicalSize | Size The logical or physical inner size.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow, LogicalSize } from '@tauri-apps/api/window';
await getCurrentWindow().setSize(new LogicalSize(600, 500));

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1336

setSizeConstraints()
setSizeConstraints(constraints): Promise<void>

Sets the window inner size constraints.

Parameters
Parameter Type Description
constraints undefined | null | WindowSizeConstraints The logical or physical inner size, or null to unset the constraint.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setSizeConstraints({ minWidth: 300 });

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1394

setSkipTaskbar()
setSkipTaskbar(skip): Promise<void>

Whether the window icon should be hidden from the taskbar or not.

Platform-specific

  • macOS: Unsupported.
Parameters
Parameter Type Description
skip boolean true to hide window icon, false to show it.
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setSkipTaskbar(true);

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1548

setTheme()
setTheme(theme?): Promise<void>

Set window theme, pass in null or undefined to follow system theme

Platform-specific

  • Linux / macOS: Theme is app-wide and not specific to this window.
  • iOS / Android: Unsupported.
Parameters
Parameter Type
theme? null | Theme
Returns

Promise<void>

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1848

setTitle()
setTitle(title): Promise<void>

Sets the window title.

Parameters
Parameter Type Description
title string The new title
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().setTitle('Tauri');

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1055

setTitleBarStyle()
setTitleBarStyle(style): Promise<void>

Sets the title bar style. macOS only.

Parameters
Parameter Type
style TitleBarStyle
Returns

Promise<void>

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1831

setVisibleOnAllWorkspaces()
setVisibleOnAllWorkspaces(visible): Promise<void>

Sets whether the window should be visible on all workspaces or virtual desktops.

Platform-specific

  • Windows / iOS / Android: Unsupported.
Parameters
Parameter Type
visible boolean
Returns

Promise<void>

Since

2.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1819

show()
show(): Promise<void>

Sets the window visibility to true.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().show();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1152

startDragging()
startDragging(): Promise<void>

Starts dragging the window.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().startDragging();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1688

startResizeDragging()
startResizeDragging(direction): Promise<void>

Starts resize-dragging the window.

Parameters
Parameter Type
direction ResizeDirection
Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().startResizeDragging();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1704

theme()
theme(): Promise<null | Theme>

Gets the windows current theme.

Platform-specific

  • macOS: Theme was introduced on macOS 10.14. Returns light on macOS 10.13 and below.
Returns

Promise<null | Theme>

The window theme.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const theme = await getCurrentWindow().theme();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L831

title()
title(): Promise<string>

Gets the windows current title.

Returns

Promise<string>

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
const title = await getCurrentWindow().title();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L810

toggleMaximize()
toggleMaximize(): Promise<void>

Toggles the window maximized state.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().toggleMaximize();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1104

unmaximize()
unmaximize(): Promise<void>

Unmaximizes the window.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().unmaximize();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1088

unminimize()
unminimize(): Promise<void>

Unminimizes the window.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example
import { getCurrentWindow } from '@tauri-apps/api/window';
await getCurrentWindow().unminimize();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L1136

getAll()
static getAll(): Promise<Window[]>

Gets a list of instances of Window for all available windows.

Returns

Promise<Window[]>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L375

getByLabel()
static getByLabel(label): Promise<null | Window>

Gets the Window associated with the given label.

Parameters
Parameter Type Description
label string The window label.
Returns

Promise<null | Window>

The Window instance to communicate with the window or null if the window doesnt exist.

Example
import { Window } from '@tauri-apps/api/window';
const mainWindow = Window.getByLabel('main');

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L361

getCurrent()
static getCurrent(): Window

Get an instance of Window for the current window.

Returns

Window

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L368

getFocusedWindow()
static getFocusedWindow(): Promise<null | Window>

Gets the focused window.

Returns

Promise<null | Window>

The Window instance or undefined if there is not any focused window.

Example
import { Window } from '@tauri-apps/api/window';
const focusedWindow = Window.getFocusedWindow();

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L389

Interfaces

Effects

The window effects configuration object

Since

2.0.0

Properties

Property Type Description Defined in
color? Color Window effect color. Affects Effect.Blur and Effect.Acrylic only on Windows 10 v1903+. Doesnt have any effect on Windows 7 or Windows 11. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2331
effects Effect[] List of Window effects to apply to the Window. Conflicting effects will apply the first one and ignore the rest. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2318
radius? number Window effect corner radius macOS Only Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2326
state? EffectState Window effect state macOS Only Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2322

Monitor

Allows you to retrieve information about a given monitor.

Since

1.0.0

Properties

Property Type Description Defined in
name null | string Human-readable name of the monitor Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L49
position PhysicalPosition the Top-left corner position of the monitor relative to the larger full screen area, in physical pixels. Note that window creation options such as x, y, width and height expect logical pixels, so convert with Monitor.scaleFactor first: import { currentMonitor } from '@tauri-apps/api/window'; import { WebviewWindow } from '@tauri-apps/api/webviewWindow'; const monitor = await currentMonitor(); if (monitor) { const position = monitor.position.toLogical(monitor.scaleFactor); const webview = new WebviewWindow('my-label', { x: position.x, y: position.y }); } Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L75
scaleFactor number The scale factor that can be used to map physical pixels to logical pixels, e.g. monitor.position.toLogical(monitor.scaleFactor). Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L90
size PhysicalSize The monitors resolution in physical pixels. Use Monitor.scaleFactor to convert to logical pixels: const logicalSize = monitor.size.toLogical(monitor.scaleFactor); Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L58
workArea object The monitors work area (the monitor area excluding taskbars and docks) in physical pixels. Use Monitor.scaleFactor to convert to logical pixels as shown in Monitor.position. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L82
workArea.position PhysicalPosition - Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L83
workArea.size PhysicalSize - Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L84

ProgressBarState

Properties

Property Type Description Defined in
progress? number The progress bar progress. This can be a value ranging from 0 to 100 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L238
status? ProgressBarStatus The progress bar status. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L234

ScaleFactorChanged

The payload for the scaleChange event.

Since

1.0.2

Properties

Property Type Description Defined in
scaleFactor number The new window scale factor. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L113
size PhysicalSize The new window size Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L115

WindowOptions

Configuration for the window to create.

Since

1.0.0

Properties

Property Type Description Defined in
activityName? string The name of the Android activity to create for this window. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2568
allowLinkPreview? boolean on macOS and iOS there is a link preview on long pressing links, this is enabled by default. see https://docs.rs/objc2-web-kit/latest/objc2_web_kit/struct.WKWebView.html#method.allowsLinkPreview Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2542
alwaysOnBottom? boolean Whether the window should always be below other windows. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2408
alwaysOnTop? boolean Whether the window should always be on top of other windows or not. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2406
backgroundColor? Color Set the window background color. Platform-specific: - Android / iOS: Unsupported. - Windows: alpha channel is ignored. Since 2.1.0 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2519
backgroundThrottling? BackgroundThrottlingPolicy Change the default background throttling behaviour. ## Platform-specific - Linux / Windows / Android: Unsupported. Workarounds like a pending WebLock transaction might suffice. - iOS: Supported since version 17.0+. - macOS: Supported since version 14.0+. see https://github.com/tauri-apps/tauri/issues/5250#issuecomment-2569380578 Since 2.3.0 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2533
center? boolean Show window in the center of the screen.. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2349
closable? boolean Whether the windows native close button is enabled or not. Defaults to true. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2474
contentProtected? boolean Prevents the window contents from being captured by other apps. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2410
createdByActivityName? string The name of the Android activity that is creating this webview window. This is important to determine which stack the activity will belong to. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2574
decorations? boolean Whether the window should have borders and bars or not. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2404
disableInputAccessoryView? boolean Allows disabling the input accessory view on iOS. The accessory view is the view that appears above the keyboard when a text input element is focused. It usually displays a view with “Done”, “Next” buttons. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2549
focus? boolean Whether the window will be initially focused or not. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2388
focusable? boolean Whether the window can be focused or not. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2390
fullscreen? boolean Whether the window is in fullscreen mode or not. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2386
height? number The initial height in logical pixels. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2357
hiddenTitle? boolean If true, sets the window title to be hidden on macOS. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2455
javascriptDisabled? boolean Whether we should disable JavaScript code execution on the webview or not. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2537
maxHeight? number The maximum height in logical pixels. Only applies if maxWidth is also set. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2365
maxWidth? number The maximum width in logical pixels. Only applies if maxHeight is also set. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2363
maximizable? boolean Whether the windows native maximize button is enabled or not. Defaults to true. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2466
maximized? boolean Whether the window should be maximized upon creation or not. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2400
minHeight? number The minimum height in logical pixels. Only applies if minWidth is also set. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2361
minWidth? number The minimum width in logical pixels. Only applies if minHeight is also set. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2359
minimizable? boolean Whether the windows native minimize button is enabled or not. Defaults to true. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2470
noRedirectionBitmap? boolean This sets WS_EX_NOREDIRECTIONBITMAP. This can avoid the white flash that may appear before the webview content is rendered when using a transparent window. Windows only. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2419
parent? string | Window | WebviewWindow Sets a parent to the window to be created. Can be either a Window or a label of the window. Platform-specific - Windows: This sets the passed parent as an owner window to the window to be created. From MSDN owned windows docs: - An owned window is always above its owner in the z-order. - The system automatically destroys an owned window when its owner is destroyed. - An owned window is hidden when its owner is minimized. - Linux: This makes the new window transient for parent, see https://docs.gtk.org/gtk3/method.Window.set_transient_for.html - macOS: This adds the window as a child of parent, see https://developer.apple.com/documentation/appkit/nswindow/1419152-addchildwindow?language=objc Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2488
preventOverflow? boolean | PreventOverflowMargin Prevent the window from overflowing the working area (e.g. monitor size - taskbar size) on creation, which means the window size will be limited to monitor size - taskbar size Can either be set to true or to a PreventOverflowMargin object to set an additional margin that should be considered to determine the working area (in this case the window size will be limited to monitor size - taskbar size - margin) NOTE: The overflow check is only performed on window creation, resizes can still overflow Platform-specific - iOS / Android: Unsupported. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2380
requestedBySceneIdentifier? string Sets the identifier of the UIScene that is requesting the creation of this new scene, establishing a relationship between the two scenes. By default the system uses the foreground scene. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2581
resizable? boolean Whether the window is resizable or not. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2382
scrollBarStyle? ScrollBarStyle Specifies the native scrollbar style to use with the webview. CSS styles that modify the scrollbar are applied on top of the native appearance configured here. Defaults to default, which is the browser default. ## Platform-specific - Windows: - fluentOverlay requires WebView2 Runtime version 125.0.2535.41 or higher, and does nothing on older versions. - This option must be given the same value for all webviews. - Linux / Android / iOS / macOS: Unsupported. Only supports Default and performs no operation. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2564
shadow? boolean Whether or not the window has shadow. Platform-specific - Windows: - false has no effect on decorated window, shadows are always ON. - true will make undecorated window have a 1px white border, and on Windows 11, it will have a rounded corners. - Linux: Unsupported. Since 2.0.0 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2433
skipTaskbar? boolean Whether or not the window icon should be added to the taskbar. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2412
tabbingIdentifier? string Defines the window tabbing identifier on macOS. Windows with the same tabbing identifier will be grouped together. If the tabbing identifier is not set, automatic tabbing will be disabled. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2462
theme? Theme The initial window theme. Defaults to the system theme. Only implemented on Windows and macOS 10.14+. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2439
title? string Window title. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2384
titleBarStyle? TitleBarStyle The style of the macOS title bar. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2443
trafficLightPosition? LogicalPosition The position of the window controls on macOS. Requires titleBarStyle: 'overlay' and decorations: true. Since 2.4.0 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2451
transparent? boolean Whether the window is transparent or not. Note that on macOS this requires the macos-private-api feature flag, enabled under tauri.conf.json > app > macOSPrivateApi. WARNING: Using private APIs on macOS prevents your application from being accepted to the App Store. On Windows, using noRedirectionBitmap can help avoid a white flash when creating a transparent window. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2398
visible? boolean Whether the window should be immediately visible upon creation or not. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2402
visibleOnAllWorkspaces? boolean Whether the window should be visible on all workspaces or virtual desktops. Platform-specific - Windows / iOS / Android: Unsupported. Since 2.0.0 Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2497
width? number The initial width in logical pixels. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2355
windowEffects? Effects Window effects. Requires the window to be transparent. Platform-specific: - Windows: If using decorations or shadows, you may want to try this workaround https://github.com/tauri-apps/tao/issues/72#issuecomment-975607891 - Linux: Unsupported Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2508
x? number The initial vertical position in logical pixels. Only applies if y is also set. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2351
y? number The initial horizontal position in logical pixels. Only applies if x is also set. Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2353

WindowSizeConstraints

Properties

Property Type Defined in
maxHeight? number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L227
maxWidth? number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L226
minHeight? number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L225
minWidth? number Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L224

Type Aliases

CursorIcon

type CursorIcon:
  | "default"
  | "crosshair"
  | "hand"
  | "arrow"
  | "move"
  | "text"
  | "wait"
  | "help"
  | "progress"
  | "notAllowed"
  | "contextMenu"
  | "cell"
  | "verticalText"
  | "alias"
  | "copy"
  | "noDrop"
  | "grab"
  | "grabbing"
  | "allScroll"
  | "zoomIn"
  | "zoomOut"
  | "eResize"
  | "nResize"
  | "neResize"
  | "nwResize"
  | "sResize"
  | "seResize"
  | "swResize"
  | "wResize"
  | "ewResize"
  | "nsResize"
  | "neswResize"
  | "nwseResize"
  | "colResize"
  | "rowResize";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L159


Theme

type Theme: "light" | "dark";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L93


TitleBarStyle

type TitleBarStyle: "visible" | "transparent" | "overlay";

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L94

Functions

availableMonitors()

function availableMonitors(): Promise<Monitor[]>

Returns the list of all the monitors available on the system.

Returns

Promise<Monitor[]>

Example

import { availableMonitors } from '@tauri-apps/api/window';
const monitors = await availableMonitors();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2660


currentMonitor()

function currentMonitor(): Promise<Monitor | null>

Returns the monitor on which the window currently resides. Returns null if current monitor cant be detected.

Returns

Promise<Monitor | null>

Example

import { currentMonitor } from '@tauri-apps/api/window';
const monitor = await currentMonitor();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2610


cursorPosition()

function cursorPosition(): Promise<PhysicalPosition>

Get the cursor position relative to the top-left hand corner of the desktop.

Note that the top-left hand corner of the desktop is not necessarily the same as the screen. If the user uses a desktop with multiple monitors, the top-left hand corner of the desktop is the top-left hand corner of the main monitor on Windows and macOS or the top-left of the leftmost monitor on X11.

The coordinates can be negative if the top-left hand corner of the window is outside of the visible screen region.

Returns

Promise<PhysicalPosition>

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2676


getAllWindows()

function getAllWindows(): Promise<Window[]>

Gets a list of instances of Window for all available windows.

Returns

Promise<Window[]>

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L258


getCurrentWindow()

function getCurrentWindow(): Window

Get an instance of Window for the current window.

Returns

Window

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L246


monitorFromPoint()

function monitorFromPoint(x, y): Promise<Monitor | null>

Returns the monitor that contains the given point. Returns null if cant find any.

Parameters

Parameter Type
x number
y number

Returns

Promise<Monitor | null>

Example

import { monitorFromPoint } from '@tauri-apps/api/window';
const monitor = await monitorFromPoint(100.0, 200.0);

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2643


primaryMonitor()

function primaryMonitor(): Promise<Monitor | null>

Returns the primary monitor of the system. Returns null if it cant identify any monitor as a primary one.

Returns

Promise<Monitor | null>

Example

import { primaryMonitor } from '@tauri-apps/api/window';
const monitor = await primaryMonitor();

Since

1.0.0

Source: https://github.com/tauri-apps/tauri/blob/dev/packages/api/src/window.ts#L2627

@tauri-apps/plugin-autostart

Functions

disable()

function disable(): Promise<void>

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/autostart/guest-js/index.ts#L15


enable()

function enable(): Promise<void>

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/autostart/guest-js/index.ts#L11


isEnabled()

function isEnabled(): Promise<boolean>

Returns

Promise<boolean>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/autostart/guest-js/index.ts#L7

@tauri-apps/plugin-barcode-scanner

Enumerations

Format

Enumeration Members

Aztec
Aztec: "AZTEC";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L30

Codabar
Codabar: "CODABAR";

Not supported on iOS.

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L28

Code128
Code128: "CODE_128";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L24

Code39
Code39: "CODE_39";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L22

Code93
Code93: "CODE_93";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L23

DataMatrix
DataMatrix: "DATA_MATRIX";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L31

EAN13
EAN13: "EAN_13";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L21

EAN8
EAN8: "EAN_8";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L20

GS1DataBar
GS1DataBar: "GS1_DATA_BAR";

Not supported on Android. Requires iOS 15.4+

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L36

GS1DataBarExpanded
GS1DataBarExpanded: "GS1_DATA_BAR_EXPANDED";

Not supported on Android. Requires iOS 15.4+

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L44

GS1DataBarLimited
GS1DataBarLimited: "GS1_DATA_BAR_LIMITED";

Not supported on Android. Requires iOS 15.4+

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L40

ITF
ITF: "ITF";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L29

PDF417
PDF417: "PDF_417";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L32

QRCode
QRCode: "QR_CODE";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L14

UPC_A
UPC_A: "UPC_A";

Not supported on iOS.

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L18

UPC_E
UPC_E: "UPC_E";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L19

Interfaces

ScanOptions

Properties

Property Type Defined in
cameraDirection? "back" | "front" Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L48
formats? Format[] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L49
windowed? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L50

Scanned

Properties

Property Type Defined in
bounds unknown Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L56
content string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L54
format Format Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L55

Type Aliases

PermissionState

type PermissionState: "granted" | "denied" | "prompt" | "prompt-with-rationale";

Source: undefined

Functions

cancel()

function cancel(): Promise<void>

Cancel the current scan process.

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L70


checkPermissions()

function checkPermissions(): Promise<PermissionState>

Get permission state.

Returns

Promise<PermissionState>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L77


openAppSettings()

function openAppSettings(): Promise<void>

Open application settings. Useful if permission was denied and the user must manually enable it.

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L95


requestPermissions()

function requestPermissions(): Promise<PermissionState>

Request permissions to use the camera.

Returns

Promise<PermissionState>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L86


scan()

function scan(options?): Promise<Scanned>

Start scanning.

Parameters

Parameter Type Description
options? ScanOptions

Returns

Promise<Scanned>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/barcode-scanner/guest-js/index.ts#L63

@tauri-apps/plugin-biometric

Enumerations

BiometryType

Enumeration Members

FaceID
FaceID: 2;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L12

Iris
Iris: 3;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L14

None
None: 0;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L8

TouchID
TouchID: 1;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L10

Interfaces

AuthOptions

Properties

Property Type Defined in
allowDeviceCredential? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L36
cancelTitle? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L37
confirmationRequired? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L45
fallbackTitle? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L40
maxAttemps? number Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L46
subtitle? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L44
title? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L43

Status

Properties

Property Type Defined in
biometryType BiometryType Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L19
error? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L20
errorCode? | "appCancel" | "authenticationFailed" | "invalidContext" | "notInteractive" | "passcodeNotSet" | "systemCancel" | "userCancel" | "userFallback" | "biometryLockout" | "biometryNotAvailable" | "biometryNotEnrolled" Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L21
isAvailable boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L18

Functions

authenticate()

function authenticate(reason, options?): Promise<void>

Prompts the user for authentication using the system interface (touchID, faceID or Android Iris). Rejects if the authentication fails.

import { authenticate } from "@tauri-apps/plugin-biometric";
await authenticate('Open your wallet');

Parameters

Parameter Type Description
reason string
options? AuthOptions

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L69


checkStatus()

function checkStatus(): Promise<Status>

Checks if the biometric authentication is available.

Returns

Promise<Status>

a promise resolving to an object containing all the information about the status of the biometry.

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/biometric/guest-js/index.ts#L53

@tauri-apps/plugin-cli

Parse arguments from your Command Line Interface.

Interfaces

ArgMatch

Since

2.0.0

Properties

Property Type Description Defined in
occurrences number Number of occurrences Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/cli/guest-js/index.ts#L26
value null | string | boolean | string[] string if takes value boolean if flag string[] or null if takes multiple values Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/cli/guest-js/index.ts#L22

CliMatches

Since

2.0.0

Properties

Property Type Defined in
args Record<string, ArgMatch> Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/cli/guest-js/index.ts#L41
subcommand null | SubcommandMatch Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/cli/guest-js/index.ts#L42

SubcommandMatch

Since

2.0.0

Properties

Property Type Defined in
matches CliMatches Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/cli/guest-js/index.ts#L34
name string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/cli/guest-js/index.ts#L33

Functions

getMatches()

function getMatches(): Promise<CliMatches>

Parse the arguments provided to the current process and get the matches using the configuration defined tauri.cli in tauri.conf.json

Returns

Promise<CliMatches>

Example

import { getMatches } from '@tauri-apps/plugin-cli';
const matches = await getMatches();
if (matches.subcommand?.name === 'run') {
  // `./your-app run $ARGS` was executed
  const args = matches.subcommand?.matches.args
  if ('debug' in args) {
    // `./your-app run --debug` was executed
  }
} else {
  const args = matches.args
  // `./your-app $ARGS` was executed
}

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/cli/guest-js/index.ts#L66

@tauri-apps/plugin-clipboard-manager

Read and write to the system clipboard.

Functions

clear()

function clear(): Promise<void>

Clears the clipboard.

Platform-specific

  • Android: Only supported on SDK 28+. For older releases we write an empty string to the clipboard instead.

Returns

Promise<void>

Example

import { clear } from '@tauri-apps/plugin-clipboard-manager';
await clear();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/clipboard-manager/guest-js/index.ts#L147


readImage()

function readImage(): Promise<Image>

Gets the clipboard content as Uint8Array image.

Platform-specific

  • Android / iOS: Not supported.

Returns

Promise<Image>

Example

import { readImage } from '@tauri-apps/plugin-clipboard-manager';


const clipboardImage = await readImage();
const blob = new Blob([await clipboardImage.rgba()], { type: 'image' })
const url = URL.createObjectURL(blob)

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/clipboard-manager/guest-js/index.ts#L99


readText()

function readText(): Promise<string>

Gets the clipboard content as plain text.

Returns

Promise<string>

Example

import { readText } from '@tauri-apps/plugin-clipboard-manager';
const clipboardText = await readText();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/clipboard-manager/guest-js/index.ts#L46


writeHtml()

function writeHtml(html, altText?): Promise<void>
  • Writes HTML or fallbacks to write provided plain text to the clipboard.

Platform-specific

  • Android / iOS: Not supported.

Parameters

Parameter Type
html string
altText? string

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example

import { writeHtml } from '@tauri-apps/plugin-clipboard-manager';
await writeHtml('<h1>Tauri is awesome!</h1>', 'plaintext');
// The following will write "<h1>Tauri is awesome</h1>" as plain text
await writeHtml('<h1>Tauri is awesome!</h1>', '<h1>Tauri is awesome</h1>');
// we can read html data only as a string so there's just readText(), no readHtml()
assert(await readText(), '<h1>Tauri is awesome!</h1>');

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/clipboard-manager/guest-js/index.ts#L126


writeImage()

function writeImage(image): Promise<void>

Writes image buffer to the clipboard.

Platform-specific

  • Android / iOS: Not supported.

Parameters

Parameter Type
image | string | number[] | ArrayBuffer | Uint8Array | Image

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example

import { writeImage } from '@tauri-apps/plugin-clipboard-manager';
const buffer = [
  // A red pixel
  255, 0, 0, 255,


 // A green pixel
  0, 255, 0, 255,
];
await writeImage(buffer);

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/clipboard-manager/guest-js/index.ts#L74


writeText()

function writeText(text, opts?): Promise<void>

Writes plain text to the clipboard.

Parameters

Parameter Type
text string
opts? object
opts.label? string

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example

import { writeText, readText } from '@tauri-apps/plugin-clipboard-manager';
await writeText('Tauri is awesome!');
assert(await readText(), 'Tauri is awesome!');

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/clipboard-manager/guest-js/index.ts#L27

@tauri-apps/plugin-deep-link

Functions

getCurrent()

function getCurrent(): Promise<string[] | null>

Get the current URLs that triggered the deep link. Use this on app load to check whether your app was started via a deep link.

Returns

Promise<string[] | null>

Example

import { getCurrent } from '@tauri-apps/plugin-deep-link';
const urls = await getCurrent();

Platform-specific

  • Windows / Linux: This function reads the command line arguments and checks if theres only one value, which must be an URL with scheme matching one of the configured values. Note that you must manually check the arguments when registering deep link schemes dynamically with [Self::register]. Additionally, the deep link might have been provided as a CLI argument so you should check if its format matches what you expect.

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/deep-link/guest-js/index.ts#L25


isRegistered()

function isRegistered(protocol): Promise<boolean>

Check whether the app is the default handler for the specified protocol.

Parameters

Parameter Type Description
protocol string The name of the protocol without ://.

Returns

Promise<boolean>

Example

import { isRegistered } from '@tauri-apps/plugin-deep-link';
await isRegistered("my-scheme");

Platform-specific

  • macOS / Android / iOS: Unsupported.

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/deep-link/guest-js/index.ts#L88


onOpenUrl()

function onOpenUrl(handler): Promise<UnlistenFn>

Helper function for the deep-link://new-url event to run a function each time the protocol is triggered while the app is running. Use getCurrent on app load to check whether your app was started via a deep link.

Parameters

Parameter Type
handler (urls) => void

Returns

Promise<UnlistenFn>

Example

import { onOpenUrl } from '@tauri-apps/plugin-deep-link';
await onOpenUrl((urls) => { console.log(urls) });

Platform-specific

  • Windows / Linux: Unsupported without the single-instance plugin. The OS will spawn a new app instance passing the URL as a CLI argument.

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/deep-link/guest-js/index.ts#L109


register()

function register(protocol): Promise<null>

Register the app as the default handler for the specified protocol.

Parameters

Parameter Type Description
protocol string The name of the protocol without ://. For example, if you want your app to handle tauri:// links, call this method with tauri as the protocol.

Returns

Promise<null>

Example

import { register } from '@tauri-apps/plugin-deep-link';
await register("my-scheme");

Platform-specific

  • macOS / Android / iOS: Unsupported.

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/deep-link/guest-js/index.ts#L46


unregister()

function unregister(protocol): Promise<null>

Unregister the app as the default handler for the specified protocol.

Parameters

Parameter Type Description
protocol string The name of the protocol without ://.

Returns

Promise<null>

Example

import { unregister } from '@tauri-apps/plugin-deep-link';
await unregister("my-scheme");

Platform-specific

  • macOS / Linux / Android / iOS: Unsupported.

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/deep-link/guest-js/index.ts#L67

@tauri-apps/plugin-dialog

Interfaces

ConfirmDialogOptions

Properties

Property Type Description Defined in
cancelLabel? string The label of the cancel button. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L293
kind? "info" | "warning" | "error" The kind of the dialog. Defaults to info. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L289
okLabel? string The label of the confirm button. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L291
title? string The title of the dialog. Defaults to the app name. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L287

DialogFilter

Extension filters for the file dialog.

Since

2.0.0

Properties

Property Type Description Defined in
extensions string[] Extensions to filter, without a . prefix. Note: Mobile platforms have different APIs for filtering that may not support extensions. iOS: Extensions are supported in the document picker, but not in the media picker. Android: Extensions are not supported. For these platforms, MIME types are the primary way to filter files, as opposed to extensions. This means the string values here labeled as extensions may also be a MIME type. This property name of extensions is being kept for backwards compatibility, but this may be revisited to specify the difference between extension or MIME type filtering. Example extensions: ['svg', 'png'] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L32
name string Filter name. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L14

MessageDialogOptions

Since

2.0.0

Properties

Property Type Description Defined in
buttons? MessageDialogButtons The buttons of the dialog. Example // Use system default buttons texts await message('Hello World!', { buttons: 'Ok' }) await message('Hello World!', { buttons: 'OkCancel' }) // Or with custom button texts await message('Hello World!', { buttons: { ok: 'Yes!' } }) await message('Take on the task?', { buttons: { ok: 'Accept', cancel: 'Cancel' } }) await message('Show the file content?', { buttons: { yes: 'Show content', no: 'Show in folder', cancel: 'Cancel' } }) Since 2.4.0 Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L259
kind? "info" | "warning" | "error" The kind of the dialog. Defaults to info. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L230
okLabel? string The label of the Ok button. Deprecated Use MessageDialogOptions.buttons instead. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L236
title? string The title of the dialog. Defaults to the app name. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L228

OpenDialogOptions

Options for the open dialog.

Since

2.0.0

Properties

Property Type Description Defined in
canCreateDirectories? boolean Whether to allow creating directories in the dialog. Enabled by default. macOS Only Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L71
defaultPath? string Initial directory or file path. If its a directory path, the dialog interface will change to that folder. If its not an existing directory, the file name will be set to the dialogs file name input and the dialog will be set to the parent folder. On mobile the file name is always used on the dialogs file name input. If not provided, Android uses (invalid).txt as default file name. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L60
directory? boolean Whether the dialog is a directory selection or not. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L64
fileAccessMode? FileAccessMode The file access mode of the dialog. If not provided, copy is used, which matches the behavior of the open method before the introduction of this option. Usage If a file is opened with : 'copy', it will be copied to the apps sandbox. This means the file can be read, edited, deleted, copied, or any other operation without any issues, since the file now belongs to the app. This also means that the caller has responsibility of deleting the file if this file is not meant to be retained in the app sandbox. If a file is opened with : 'scoped', the file will remain in its original location and security-scoped access will be automatically managed by the system. Note This is specifically meant for document pickers on iOS or MacOS, in conjunction with security scoped resources. Why only document pickers, and not image or video pickers? The image and video pickers on iOS behave differently from the document pickers, and return NSItemProvider objects instead of file URLs. These are meant to be ephemeral (only available within the callback of the picker), and are not accessible outside of the callback. So for image and video pickers, the only way to access the file is to copy it to the apps sandbox, and this is the URL that is returned from this API. This means there is no provision for using scoped mode with image or video pickers. If an image or video picker is used, copy is always used. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L103
filters? DialogFilter[] The filters of the dialog. On mobile platforms, if either: A) the pickerMode is set to media, image, or video or B) the filters include only either image or video mime types, the media picker will be displayed. Otherwise, the document picker will be displayed. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L51
multiple? boolean Whether the dialog allows multiple selection or not. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L62
pickerMode? PickerMode The preferred mode of the dialog. This is meant for mobile platforms (iOS and Android) which have distinct file and media pickers. If not provided, the dialog will automatically choose the best mode based on the MIME types or extensions of the filters. On desktop, this option is ignored. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L78
recursive? boolean If directory is true, indicates that it will be read recursively later. Defines whether subdirectories will be allowed on the scope or not. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L69
title? string The title of the dialog window (desktop only). Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L42

SaveDialogOptions

Options for the save dialog.

Since

2.0.0

Properties

Property Type Description Defined in
canCreateDirectories? boolean Whether to allow creating directories in the dialog. Enabled by default. macOS Only Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L126
defaultPath? string Initial directory or file path. If its a directory path, the dialog interface will change to that folder. If its not an existing directory, the file name will be set to the dialogs file name input and the dialog will be set to the parent folder. On mobile the file name is always used on the dialogs file name input. If not provided, Android uses (invalid).txt as default file name. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L124
filters? DialogFilter[] The filters of the dialog. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L115
title? string The title of the dialog window (desktop only). Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L113

Type Aliases

FileAccessMode

type FileAccessMode: "copy" | "scoped";

The file access mode of the dialog.

  • copy: copy/move the picked file to the app sandbox; no scoped access required.
  • scoped: keep file in place; security-scoped access is automatically managed.

Note: This option is only supported on iOS 14 and above. This parameter is ignored on iOS 13 and below.

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L147


MessageDialogButtons

type MessageDialogButtons: MessageDialogDefaultButtons | MessageDialogCustomButtons;

The buttons of a message dialog.

Since

2.4.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L219


MessageDialogButtonsOk

type MessageDialogButtonsOk: object & BanExcept<"ok">;

The Ok button of a message dialog.

Type declaration

Name Type Description Defined in
ok string The Ok button. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L201

Since

2.4.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L199


MessageDialogButtonsOkCancel

type MessageDialogButtonsOkCancel: object & BanExcept<"ok" | "cancel">;

The Ok and Cancel buttons of a message dialog.

Type declaration

Name Type Description Defined in
cancel string The Cancel button. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L191
ok string The Ok button. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L189

Since

2.4.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L187


MessageDialogButtonsYesNoCancel

type MessageDialogButtonsYesNoCancel: object & BanExcept<"yes" | "no" | "cancel">;

The Yes, No and Cancel buttons of a message dialog.

Type declaration

Name Type Description Defined in
cancel string The Cancel button. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L179
no string The No button. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L177
yes string The Yes button. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L175

Since

2.4.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L173


MessageDialogCustomButtons

type MessageDialogCustomButtons: MessageDialogButtonsYesNoCancel | MessageDialogButtonsOkCancel | MessageDialogButtonsOk;

Custom buttons for a message dialog.

Since

2.4.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L209


MessageDialogDefaultButtons

type MessageDialogDefaultButtons: "Ok" | "OkCancel" | "YesNo" | "YesNoCancel";

Default buttons for a message dialog.

Since

2.4.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L154


MessageDialogResult

type MessageDialogResult:
  | "Yes"
  | "No"
  | "Ok"
  | "Cancel"
  | string & object;

The result of a message dialog.

The result is a string if the dialog has custom buttons, otherwise it is one of the default buttons.

Since

2.4.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L406


OpenDialogReturn<T>

type OpenDialogReturn<T>: T["directory"] extends true ? T["multiple"] extends true ? string[] | null : string | null : T["multiple"] extends true ? string[] | null : string | null;

Type Parameters

Type Parameter
T extends OpenDialogOptions

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L296


PickerMode

type PickerMode: "document" | "media" | "image" | "video";

The preferred mode of the dialog. This is meant for mobile platforms (iOS and Android) which have distinct file and media pickers. On desktop, this option is ignored. If not provided, the dialog will automatically choose the best mode based on the MIME types or extensions of the filters.

Note: This option is only supported on iOS 14 and above. This parameter is ignored on iOS 13 and below.

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L137

Functions

ask()

function ask(message, options?): Promise<boolean>

Shows a question dialog with Yes and No buttons.

Convenient wrapper for await message('msg', { buttons: 'YesNo' }) === 'Yes'

Parameters

Parameter Type Description
message string The message to show.
options? string | ConfirmDialogOptions The dialogs options. If a string, it represents the dialog title.

Returns

Promise<boolean>

A promise resolving to a boolean indicating whether Yes was clicked or not.

Example

import { ask } from '@tauri-apps/plugin-dialog';
const yes = await ask('Are you sure?', 'Tauri');
const yes2 = await ask('This action cannot be reverted. Are you sure?', { title: 'Tauri', kind: 'warning' });

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L467


confirm()

function confirm(message, options?): Promise<boolean>

Shows a question dialog with Ok and Cancel buttons.

Convenient wrapper for await message('msg', { buttons: 'OkCancel' }) === 'Ok'

Parameters

Parameter Type Description
message string The message to show.
options? string | ConfirmDialogOptions The dialogs options. If a string, it represents the dialog title.

Returns

Promise<boolean>

A promise resolving to a boolean indicating whether Ok was clicked or not.

Example

import { confirm } from '@tauri-apps/plugin-dialog';
const confirmed = await confirm('Are you sure?', 'Tauri');
const confirmed2 = await confirm('This action cannot be reverted. Are you sure?', { title: 'Tauri', kind: 'warning' });

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L504


message()

function message(message, options?): Promise<MessageDialogResult>

Shows a message dialog with an Ok button.

Parameters

Parameter Type Description
message string The message to show.
options? string | MessageDialogOptions The dialogs options. If a string, it represents the dialog title.

Returns

Promise<MessageDialogResult>

A promise indicating the success or failure of the operation.

Example

import { message } from '@tauri-apps/plugin-dialog';
await message('Tauri is awesome', 'Tauri');
await message('File not found', { title: 'Tauri', kind: 'error' });

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L437


open()

function open<T>(options): Promise<OpenDialogReturn<T>>

Open a file/directory selection dialog.

The selected paths are added to the filesystem and asset protocol scopes. When security is more important than the easy of use of this API, prefer writing a dedicated command instead.

Note that the scope change is not persisted, so the values are cleared when the application is restarted. You can save it to the filesystem using tauri-plugin-persisted-scope.

Type Parameters

Type Parameter
T extends OpenDialogOptions

Parameters

Parameter Type
options T

Returns

Promise<OpenDialogReturn<T>>

A promise resolving to the selected path(s)

Examples

import { open } from '@tauri-apps/plugin-dialog';
// Open a selection dialog for image files
const selected = await open({
  multiple: true,
  filters: [{
    name: 'Image',
    extensions: ['png', 'jpeg']
  }]
});
if (Array.isArray(selected)) {
  // user selected multiple files
} else if (selected === null) {
  // user cancelled the selection
} else {
  // user selected a single file
}
import { open } from '@tauri-apps/plugin-dialog';
import { appDir } from '@tauri-apps/api/path';
// Open a selection dialog for directories
const selected = await open({
  directory: true,
  multiple: true,
  defaultPath: await appDir(),
});
if (Array.isArray(selected)) {
  // user selected multiple directories
} else if (selected === null) {
  // user cancelled the selection
} else {
  // user selected a single directory
}

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L356


save()

function save(options): Promise<string | null>

Open a file/directory save dialog.

The selected path is added to the filesystem and asset protocol scopes. When security is more important than the easy of use of this API, prefer writing a dedicated command instead.

Note that the scope change is not persisted, so the values are cleared when the application is restarted. You can save it to the filesystem using tauri-plugin-persisted-scope.

Parameters

Parameter Type
options SaveDialogOptions

Returns

Promise<string | null>

A promise resolving to the selected path.

Example

import { save } from '@tauri-apps/plugin-dialog';
const filePath = await save({
  filters: [{
    name: 'Image',
    extensions: ['png', 'jpeg']
  }]
});

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/dialog/guest-js/index.ts#L390

@tauri-apps/plugin-fs

Access the file system.

iOS security-scoped resources

On iOS, the fs plugin automatically manages access to security-scoped resources when a file URL is accessed. This is required for files outside the apps sandbox (e.g., from file picker).

Example

import { open } from '@tauri-apps/plugin-fs';


const file = await open('file:///path/to/file.txt');
await file.close();

Security

This module prevents path traversal, not allowing parent directory accessors to be used (i.e. “/usr/path/to/../file” or “../path/to/file” paths are not allowed). Paths accessed with this API must be either relative to one of the base directories or created with the path API.

The API has a scope configuration that forces you to restrict the paths that can be accessed using glob patterns.

The scope configuration is an array of glob patterns describing file/directory paths that are allowed. For instance, this scope configuration allows all enabled fs APIs to (only) access files in the databases directory of the $APPDATA directory:

{
  "permissions": [
    {
      "identifier": "fs:scope",
      "allow": [{ "path": "$APPDATA/databases/*" }]
    }
  ]
}

Scopes can also be applied to specific fs APIs by using the APIs identifier instead of fs:scope:

{
  "permissions": [
    {
      "identifier": "fs:allow-exists",
      "allow": [{ "path": "$APPDATA/databases/*" }]
    }
  ]
}

Notice the use of the $APPDATA variable. The value is injected at runtime, resolving to the app data directory.

The available variables are: $APPCONFIG, $APPDATA, $APPLOCALDATA, $APPCACHE, $APPLOG, $AUDIO, $CACHE, $CONFIG, $DATA, $LOCALDATA, $DESKTOP, $DOCUMENT, $DOWNLOAD, $EXE, $FONT, $HOME, $PICTURE, $PUBLIC, $RUNTIME, $TEMPLATE, $VIDEO, $RESOURCE, $TEMP.

Trying to execute any API with a URL not configured on the scope results in a promise rejection due to denied access.

Enumerations

BaseDirectory

Since

2.0.0

Enumeration Members

AppCache
AppCache: 16;
See

appCacheDir for more information.

Source: undefined

AppConfig
AppConfig: 13;
See

appConfigDir for more information.

Source: undefined

AppData
AppData: 14;
See

appDataDir for more information.

Source: undefined

AppLocalData
AppLocalData: 15;
See

appLocalDataDir for more information.

Source: undefined

AppLog
AppLog: 17;
See

appLogDir for more information.

Source: undefined

Audio
Audio: 1;
See

audioDir for more information.

Source: undefined

Cache
Cache: 2;
See

cacheDir for more information.

Source: undefined

Config
Config: 3;
See

configDir for more information.

Source: undefined

Data
Data: 4;
See

dataDir for more information.

Source: undefined

Desktop
Desktop: 18;
See

desktopDir for more information.

Source: undefined

Document
Document: 6;
See

documentDir for more information.

Source: undefined

Download
Download: 7;
See

downloadDir for more information.

Source: undefined

Executable
Executable: 19;
See

executableDir for more information.

Source: undefined

Font
Font: 20;
See

fontDir for more information.

Source: undefined

Home
Home: 21;
See

homeDir for more information.

Source: undefined

LocalData
LocalData: 5;
See

localDataDir for more information.

Source: undefined

Picture
Picture: 8;
See

pictureDir for more information.

Source: undefined

Public
Public: 9;
See

publicDir for more information.

Source: undefined

Resource
Resource: 11;
See

resourceDir for more information.

Source: undefined

Runtime
Runtime: 22;
See

runtimeDir for more information.

Source: undefined

Temp
Temp: 12;
See

tempDir for more information.

Source: undefined

Template
Template: 23;
See

templateDir for more information.

Source: undefined

Video
Video: 10;
See

videoDir for more information.

Source: undefined


SeekMode

Enumeration Members

Current
Current: 1;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L93

End
End: 2;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L94

Start
Start: 0;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L92

Classes

FileHandle

The Tauri abstraction for reading and writing files.

Since

2.0.0

Extends

  • Resource

Constructors

new FileHandle()
new FileHandle(rid): FileHandle
Parameters
Parameter Type
rid number
Returns

FileHandle

Inherited from

Resource.constructor

Source: undefined

Accessors

rid
get rid(): number
Returns

number

Inherited from

Resource.rid

Source: undefined

Methods

close()
close(): Promise<void>

Destroys and cleans up this resource from memory. You should not call any method on this object anymore and should drop any reference to it.

Returns

Promise<void>

Inherited from

Resource.close

Source: undefined

read()
read(buffer): Promise<null | number>

Reads up to p.byteLength bytes into p. It resolves to the number of bytes read (0 < n <= p.byteLength) and rejects if any error encountered. Even if read() resolves to n < p.byteLength, it may use all of p as scratch space during the call. If some data is available but not p.byteLength bytes, read() conventionally resolves to what is available instead of waiting for more.

When read() encounters end-of-file condition, it resolves to EOF (null).

When read() encounters an error, it rejects with an error.

Callers should always process the n > 0 bytes returned before considering the EOF (null). Doing so correctly handles I/O errors that happen after reading some bytes and also both of the allowed EOF behaviors.

Parameters
Parameter Type
buffer Uint8Array
Returns

Promise<null | number>

Example
import { open, BaseDirectory } from "@tauri-apps/plugin-fs"
// if "$APPCONFIG/foo/bar.txt" contains the text "hello world":
const file = await open("foo/bar.txt", { baseDir: BaseDirectory.AppConfig });
const buf = new Uint8Array(100);
const numberOfBytesRead = await file.read(buf); // 11 bytes
const text = new TextDecoder().decode(buf);  // "hello world"
await file.close();
Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L327

seek()
seek(offset, whence): Promise<number>

Seek sets the offset for the next read() or write() to offset, interpreted according to whence: Start means relative to the start of the file, Current means relative to the current offset, and End means relative to the end. Seek resolves to the new offset relative to the start of the file.

Seeking to an offset before the start of the file is an error. Seeking to any positive offset is legal, but the behavior of subsequent I/O operations on the underlying object is implementation-dependent. It returns the number of cursor position.

Parameters
Parameter Type
offset number
whence SeekMode
Returns

Promise<number>

Example
import { open, SeekMode, BaseDirectory } from '@tauri-apps/plugin-fs';


// Given hello.txt pointing to file with "Hello world", which is 11 bytes long:
const file = await open('hello.txt', { read: true, write: true, truncate: true, create: true, baseDir: BaseDirectory.AppLocalData });
await file.write(new TextEncoder().encode("Hello world"));


// Seek 6 bytes from the start of the file
console.log(await file.seek(6, SeekMode.Start)); // "6"
// Seek 2 more bytes from the current position
console.log(await file.seek(2, SeekMode.Current)); // "8"
// Seek backwards 2 bytes from the end of the file
console.log(await file.seek(-2, SeekMode.End)); // "9" (e.g. 11-2)


await file.close();
Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L382

stat()
stat(): Promise<FileInfo>

Returns a FileInfo for this file.

Returns

Promise<FileInfo>

Example
import { open, BaseDirectory } from '@tauri-apps/plugin-fs';
const file = await open("file.txt", { read: true, baseDir: BaseDirectory.AppLocalData });
const fileInfo = await file.stat();
console.log(fileInfo.isFile); // true
await file.close();
Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L404

truncate()
truncate(len?): Promise<void>

Truncates or extends this file, to reach the specified len. If len is not specified then the entire file contents are truncated.

Parameters
Parameter Type
len? number
Returns

Promise<void>

Example
import { open, BaseDirectory } from '@tauri-apps/plugin-fs';


// truncate the entire file
const file = await open("my_file.txt", { read: true, write: true, create: true, baseDir: BaseDirectory.AppLocalData });
await file.truncate();


// truncate part of the file
const file = await open("my_file.txt", { read: true, write: true, create: true, baseDir: BaseDirectory.AppLocalData });
await file.write(new TextEncoder().encode("Hello World"));
await file.truncate(7);
const data = new Uint8Array(32);
await file.read(data);
console.log(new TextDecoder().decode(data)); // Hello W
await file.close();
Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L436

write()
write(data): Promise<number>

Writes data.byteLength bytes from data to the underlying data stream. It resolves to the number of bytes written from data (0 <= n <= data.byteLength) or reject with the error encountered that caused the write to stop early. write() must reject with a non-null error if would resolve to n < data.byteLength. write() must not modify the slice data, even temporarily.

Parameters
Parameter Type
data Uint8Array
Returns

Promise<number>

Example
import { open, write, BaseDirectory } from '@tauri-apps/plugin-fs';
const encoder = new TextEncoder();
const data = encoder.encode("Hello world");
const file = await open("bar.txt", { write: true, baseDir: BaseDirectory.AppLocalData });
const bytesWritten = await file.write(data); // 11
await file.close();
Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L463

Interfaces

CopyFileOptions

Since

2.0.0

Properties

Property Type Description Defined in
fromPathBaseDir? BaseDirectory Base directory for fromPath. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L599
toPathBaseDir? BaseDirectory Base directory for toPath. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L601

CreateOptions

Since

2.0.0

Properties

Property Type Description Defined in
baseDir? BaseDirectory Base directory for path Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L476

DebouncedWatchOptions

Since

2.0.0

Extends

Properties

Property Type Description Inherited from Defined in
baseDir? BaseDirectory Base directory for path WatchOptions.baseDir Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1195
delayMs? number Debounce delay - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1203
recursive? boolean Watch a directory recursively WatchOptions.recursive Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1193

DirEntry

A disk entry which is either a file, a directory or a symlink.

This is the result of the readDir.

Since

2.0.0

Properties

Property Type Description Defined in
isDirectory boolean Specifies whether this entry is a directory or not. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L690
isFile boolean Specifies whether this entry is a file or not. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L692
isSymlink boolean Specifies whether this entry is a symlink or not. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L694
name string The name of the entry (file name with extension or directory name). Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L688

ExistsOptions

Since

2.0.0

Properties

Property Type Description Defined in
baseDir? BaseDirectory Base directory for path. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1160

FileInfo

A FileInfo describes a file and is returned by stat, lstat or fstat.

Since

2.0.0

Properties

Property Type Description Defined in
atime null | Date The last access time of the file. This corresponds to the atime field from stat on Unix and ftLastAccessTime on Windows. This may not be available on all platforms. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L133
birthtime null | Date The creation time of the file. This corresponds to the birthtime field from stat on Mac/BSD and ftCreationTime on Windows. This may not be available on all platforms. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L139
blksize null | number Blocksize for filesystem I/O. Platform-specific - Windows: Unsupported. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L216
blocks null | number Number of blocks allocated to the file, in 512-byte units. Platform-specific - Windows: Unsupported. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L224
dev null | number ID of the device containing the file. Platform-specific - Windows: Unsupported. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L159
fileAttributes null | number This field contains the file system attribute information for a file or directory. For possible values and their descriptions, see File Attribute Constants in the Windows Dev Center Platform-specific - macOS / Linux / Android / iOS: Unsupported. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L151
gid null | number Group ID of the owner of this file. Platform-specific - Windows: Unsupported. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L200
ino null | number Inode number. Platform-specific - Windows: Unsupported. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L167
isDirectory boolean True if this is info for a regular directory. Mutually exclusive to FileInfo.isFile and FileInfo.isSymlink. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L112
isFile boolean True if this is info for a regular file. Mutually exclusive to FileInfo.isDirectory and FileInfo.isSymlink. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L107
isSymlink boolean True if this is info for a symlink. Mutually exclusive to FileInfo.isFile and FileInfo.isDirectory. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L117
mode null | number The underlying raw st_mode bits that contain the standard Unix permissions for this file/directory. Platform-specific - Windows: Unsupported. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L176
mtime null | Date The last modification time of the file. This corresponds to the mtime field from stat on Linux/Mac OS and ftLastWriteTime on Windows. This may not be available on all platforms. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L127
nlink null | number Number of hard links pointing to this file. Platform-specific - Windows: Unsupported. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L184
rdev null | number Device ID of this file. Platform-specific - Windows: Unsupported. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L208
readonly boolean Whether this is a readonly (unwritable) file. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L141
size number The size of the file, in bytes. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L121
uid null | number User ID of the owner of this file. Platform-specific - Windows: Unsupported. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L192

MkdirOptions

Since

2.0.0

Properties

Property Type Description Defined in
baseDir? BaseDirectory Base directory for path Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L644
mode? number Permissions to use when creating the directory (defaults to 0o777, before the processs umask). Ignored on Windows. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L638
recursive? boolean Defaults to false. If set to true, means that any intermediate directories will also be created (as with the shell command mkdir -p). Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L642

OpenOptions

Since

2.0.0

Properties

Property Type Description Defined in
append? boolean Sets the option for the append mode. This option, when true, means that writes will append to a file instead of overwriting previous contents. Note that setting { write: true, append: true } has the same effect as setting only { append: true }. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L531
baseDir? BaseDirectory Base directory for path Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L559
create? boolean Sets the option to allow creating a new file, if one doesnt already exist at the specified path. Requires write or append access to be used. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L544
createNew? boolean Defaults to false. If set to true, no file, directory, or symlink is allowed to exist at the target location. Requires write or append access to be used. When createNew is set to true, create and truncate are ignored. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L551
mode? number Permissions to use if creating the file (defaults to 0o666, before the processs umask). Ignored on Windows. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L557
read? boolean Sets the option for read access. This option, when true, means that the file should be read-able if opened. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L517
truncate? boolean Sets the option for truncating a previous file. If a file is successfully opened with this option set it will truncate the file to 0 size if it already exists. The file must be opened with write access for truncate to work. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L538
write? boolean Sets the option for write access. This option, when true, means that the file should be write-able if opened. If the file already exists, any write calls on it will overwrite its contents, by default without truncating it. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L524

ReadDirOptions

Since

2.0.0

Properties

Property Type Description Defined in
baseDir? BaseDirectory Base directory for path Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L676

ReadFileOptions

Since

2.0.0

Properties

Property Type Description Defined in
baseDir? BaseDirectory Base directory for path Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L738
encoding? string Text encoding to use when reading a text file. Defaults to utf-8. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L740

RemoveOptions

Since

2.0.0

Properties

Property Type Description Defined in
baseDir? BaseDirectory Base directory for path Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L882
recursive? boolean Defaults to false. If set to true, path will be removed even if its a non-empty directory. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L880

RenameOptions

Since

2.0.0

Properties

Property Type Description Defined in
newPathBaseDir? BaseDirectory Base directory for newPath. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L918
oldPathBaseDir? BaseDirectory Base directory for oldPath. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L916

StatOptions

Since

2.0.0

Properties

Property Type Description Defined in
baseDir? BaseDirectory Base directory for path. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L960

TruncateOptions

Since

2.0.0

Properties

Property Type Description Defined in
baseDir? BaseDirectory Base directory for path. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1019

WatchEvent

Since

2.0.0

Properties

Property Type Defined in
attrs unknown Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1212
paths string[] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1211
type WatchEventKind Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1210

WatchOptions

Since

2.0.0

Extended by

Properties

Property Type Description Defined in
baseDir? BaseDirectory Base directory for path Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1195
recursive? boolean Watch a directory recursively Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1193

WriteFileOptions

Since

2.0.0

Properties

Property Type Description Defined in
append? boolean Defaults to false. If set to true, will append to a file instead of overwriting previous contents. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1063
baseDir? BaseDirectory Base directory for path Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1071
create? boolean Sets the option to allow creating a new file, if one doesnt already exist at the specified path (defaults to true). Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1065
createNew? boolean Sets the option to create a new file, failing if it already exists. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1067
mode? number File permissions. Ignored on Windows. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1069

Type Aliases

UnwatchFn()

type UnwatchFn: () => void;

Returns

void

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1277


WatchEventKind

type WatchEventKind:
  | "any"
  | object
  | object
  | object
  | object
  | "other";

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1218


WatchEventKindAccess

type WatchEventKindAccess: object | object | object | object;

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1229


WatchEventKindCreate

type WatchEventKindCreate: object | object | object | object;

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1238


WatchEventKindModify

type WatchEventKindModify:
  | object
  | object
  | object
  | object
  | object;

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1247


WatchEventKindRemove

type WatchEventKindRemove: object | object | object | object;

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1267

Functions

copyFile()

function copyFile(
   fromPath,
   toPath,
options?): Promise<void>

Copies the contents and permissions of one file to another specified path, by default creating a new file if needed, else overwriting.

Parameters

Parameter Type
fromPath string | URL
toPath string | URL
options? CopyFileOptions

Returns

Promise<void>

Example

import { copyFile, BaseDirectory } from '@tauri-apps/plugin-fs';
await copyFile('app.conf', 'app.conf.bk', { fromPathBaseDir: BaseDirectory.AppConfig, toPathBaseDir: BaseDirectory.AppConfig });

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L614


create()

function create(path, options?): Promise<FileHandle>

Creates a file if none exists or truncates an existing file and resolves to an instance of FileHandle.

Parameters

Parameter Type
path string | URL
options? CreateOptions

Returns

Promise<FileHandle>

Example

import { create, BaseDirectory } from "@tauri-apps/plugin-fs"
const file = await create("foo/bar.txt", { baseDir: BaseDirectory.AppConfig });
await file.write(new TextEncoder().encode("Hello world"));
await file.close();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L493


exists()

function exists(path, options?): Promise<boolean>

Check if a path exists.

Parameters

Parameter Type
path string | URL
options? ExistsOptions

Returns

Promise<boolean>

Example

import { exists, BaseDirectory } from '@tauri-apps/plugin-fs';
// Check if the `$APPDATA/avatar.png` file exists
await exists('avatar.png', { baseDir: BaseDirectory.AppData });

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1174


lstat()

function lstat(path, options?): Promise<FileInfo>

Resolves to a FileInfo for the specified path. If path is a symlink, information for the symlink will be returned instead of what it points to.

Parameters

Parameter Type
path string | URL
options? StatOptions

Returns

Promise<FileInfo>

Example

import { lstat, BaseDirectory } from '@tauri-apps/plugin-fs';
const fileInfo = await lstat("hello.txt", { baseDir: BaseDirectory.AppLocalData });
console.log(fileInfo.isFile); // true

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1002


mkdir()

function mkdir(path, options?): Promise<void>

Creates a new directory with the specified path.

Parameters

Parameter Type
path string | URL
options? MkdirOptions

Returns

Promise<void>

Example

import { mkdir, BaseDirectory } from '@tauri-apps/plugin-fs';
await mkdir('users', { baseDir: BaseDirectory.AppLocalData });

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L657


open()

function open(path, options?): Promise<FileHandle>

Open a file and resolve to an instance of FileHandle. The file does not need to previously exist if using the create or createNew open options. It is the callers responsibility to close the file when finished with it.

Parameters

Parameter Type
path string | URL
options? OpenOptions

Returns

Promise<FileHandle>

Example

import { open, BaseDirectory } from "@tauri-apps/plugin-fs"
const file = await open("foo/bar.txt", { read: true, write: true, baseDir: BaseDirectory.AppLocalData });
// Do work with file
await file.close();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L578


readDir()

function readDir(path, options?): Promise<DirEntry[]>

Reads the directory given by path and returns an array of DirEntry.

Parameters

Parameter Type
path string | URL
options? ReadDirOptions

Returns

Promise<DirEntry[]>

Example

import { readDir, BaseDirectory } from '@tauri-apps/plugin-fs';
import { join } from '@tauri-apps/api/path';
const dir = "users"
const entries = await readDir('users', { baseDir: BaseDirectory.AppLocalData });
processEntriesRecursively(dir, entries);
async function processEntriesRecursively(parent, entries) {
  for (const entry of entries) {
    console.log(`Entry: ${entry.name}`);
    if (entry.isDirectory) {
       const dir = await join(parent, entry.name);
      processEntriesRecursively(dir, await readDir(dir, { baseDir: BaseDirectory.AppLocalData }))
    }
  }
}

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L719


readFile()

function readFile(path, options?): Promise<Uint8Array>

Reads and resolves to the entire contents of a file as an array of bytes. TextDecoder can be used to transform the bytes to string if required.

Parameters

Parameter Type
path string | URL
options? ReadFileOptions

Returns

Promise<Uint8Array>

Example

import { readFile, BaseDirectory } from '@tauri-apps/plugin-fs';
const contents = await readFile('avatar.png', { baseDir: BaseDirectory.Resource });

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L754


readTextFile()

function readTextFile(path, options?): Promise<string>

Reads and returns the entire contents of a file as a string using the specified encoding (default: UTF-8).

Parameters

Parameter Type
path string | URL
options? ReadFileOptions

Returns

Promise<string>

Example

import { readTextFile, BaseDirectory } from '@tauri-apps/plugin-fs';
const contents = await readTextFile('app.conf', { baseDir: BaseDirectory.AppConfig });

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L780


readTextFileLines()

function readTextFileLines(path, options?): Promise<AsyncIterableIterator<string>>

Returns an async AsyncIterableIterator over the lines of a file, decoded using the specified encoding (default: UTF-8).

Parameters

Parameter Type
path string | URL
options? ReadFileOptions

Returns

Promise<AsyncIterableIterator<string>>

Example

import { readTextFileLines, BaseDirectory } from '@tauri-apps/plugin-fs';
const lines = await readTextFileLines('app.conf', { baseDir: BaseDirectory.AppConfig });
for await (const line of lines) {
  console.log(line);
}

You could also call AsyncIterableIterator.next to advance the iterator so you can lazily read the next line whenever you want.

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L813


remove()

function remove(path, options?): Promise<void>

Removes the named file or directory. If the directory is not empty and the recursive option isnt set to true, the promise will be rejected.

Parameters

Parameter Type
path string | URL
options? RemoveOptions

Returns

Promise<void>

Example

import { remove, BaseDirectory } from '@tauri-apps/plugin-fs';
await remove('users/file.txt', { baseDir: BaseDirectory.AppLocalData });
await remove('users', { baseDir: BaseDirectory.AppLocalData });

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L897


rename()

function rename(
   oldPath,
   newPath,
options?): Promise<void>

Renames (moves) oldpath to newpath. Paths may be files or directories. If newpath already exists and is not a directory, rename() replaces it. OS-specific restrictions may apply when oldpath and newpath are in different directories.

On Unix, this operation does not follow symlinks at either path.

Parameters

Parameter Type
oldPath string | URL
newPath string | URL
options? RenameOptions

Returns

Promise<void>

Example

import { rename, BaseDirectory } from '@tauri-apps/plugin-fs';
await rename('avatar.png', 'deleted.png', { oldPathBaseDir: BaseDirectory.App, newPathBaseDir: BaseDirectory.AppLocalData });

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L936


size()

function size(path): Promise<number>

Get the size of a file or directory. For files, the stat functions can be used as well.

If path is a directory, this function will recursively iterate over every file and every directory inside of path and therefore will be very time consuming if used on larger directories.

Parameters

Parameter Type
path string | URL

Returns

Promise<number>

Example

import { size, BaseDirectory } from '@tauri-apps/plugin-fs';
// Get the size of the `$APPDATA/tauri` directory.
const dirSize = await size('tauri', { baseDir: BaseDirectory.AppData });
console.log(dirSize); // 1024

Since

2.1.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1359


startAccessingSecurityScopedResource()

function startAccessingSecurityScopedResource(path): Promise<void>

Starts accessing a security-scoped resource for the given file URL. This should be called when youre accessing a file that was opened using a security-scoped URL (e.g., from a file picker).

Note that accessing security-scoped resources is automatically managed by the plugin on iOS, so you dont need to call this function unless you want to manage the scope manually.

You must call stopAccessingSecurityScopedResource when youre done accessing the resource.

Platform-specific

  • iOS: Starts accessing the security-scoped resource.
  • Other platforms: does nothing.

Parameters

Parameter Type
path string | URL

Returns

Promise<void>

Example

import { startAccessingSecurityScopedResource } from '@tauri-apps/plugin-fs';


const filePath = 'file:///path/to/file.txt';
await startAccessingSecurityScopedResource(filePath);
// ... use the resource ...

Since

2.5.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1395


stat()

function stat(path, options?): Promise<FileInfo>

Resolves to a FileInfo for the specified path. Will always follow symlinks but will reject if the symlink points to a path outside of the scope.

Parameters

Parameter Type
path string | URL
options? StatOptions

Returns

Promise<FileInfo>

Example

import { stat, BaseDirectory } from '@tauri-apps/plugin-fs';
const fileInfo = await stat("hello.txt", { baseDir: BaseDirectory.AppLocalData });
console.log(fileInfo.isFile); // true

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L976


stopAccessingSecurityScopedResource()

function stopAccessingSecurityScopedResource(path): Promise<void>

Stops accessing a security-scoped resource for the given file URL. This should be called when youre done accessing a file that was opened using a security-scoped URL (e.g., from a file picker) when using manual tracking via startAccessingSecurityScopedResource.

Platform-specific

  • iOS: Stops accessing the security-scoped resource.
  • Other platforms: does nothing.

Parameters

Parameter Type
path string | URL

Returns

Promise<void>

Example

import { stopAccessingSecurityScopedResource } from '@tauri-apps/plugin-fs';


const filePath = 'file:///path/to/file.txt';
await startAccessingSecurityScopedResource(filePath);
// ... use the resource ...
// when you're done with the resource:
await stopAccessingSecurityScopedResource(filePath);

Since

2.5.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1430


truncate()

function truncate(
   path,
   len?,
options?): Promise<void>

Truncates or extends the specified file, to reach the specified len. If len is 0 or not specified, then the entire file contents are truncated.

Parameters

Parameter Type
path string | URL
len? number
options? TruncateOptions

Returns

Promise<void>

Example

import { truncate, readTextFile, writeTextFile, BaseDirectory } from '@tauri-apps/plugin-fs';
// truncate the entire file
await truncate("my_file.txt", 0, { baseDir: BaseDirectory.AppLocalData });


// truncate part of the file
const filePath = "file.txt";
await writeTextFile(filePath, "Hello World", { baseDir: BaseDirectory.AppLocalData });
await truncate(filePath, 7, { baseDir: BaseDirectory.AppLocalData });
const data = await readTextFile(filePath, { baseDir: BaseDirectory.AppLocalData });
console.log(data);  // "Hello W"

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1042


watch()

function watch(
   paths,
   cb,
options?): Promise<UnwatchFn>

Watch changes (after a delay) on files or directories.

Parameters

Parameter Type
paths string | URL | string[] | URL[]
cb (event) => void
options? DebouncedWatchOptions

Returns

Promise<UnwatchFn>

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1316


watchImmediate()

function watchImmediate(
   paths,
   cb,
options?): Promise<UnwatchFn>

Watch changes on files or directories.

Parameters

Parameter Type
paths string | URL | string[] | URL[]
cb (event) => void
options? WatchOptions

Returns

Promise<UnwatchFn>

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1333


writeFile()

function writeFile(
   path,
   data,
options?): Promise<void>

Write data to the given path, by default creating a new file if needed, else overwriting.

Parameters

Parameter Type
path string | URL
data Uint8Array | ReadableStream<Uint8Array>
options? WriteFileOptions

Returns

Promise<void>

Example

import { writeFile, BaseDirectory } from '@tauri-apps/plugin-fs';


let encoder = new TextEncoder();
let data = encoder.encode("Hello World");
await writeFile('file.txt', data, { baseDir: BaseDirectory.AppLocalData });

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1087


writeTextFile()

function writeTextFile(
   path,
   data,
options?): Promise<void>

Writes UTF-8 string data to the given path, by default creating a new file if needed, else overwriting.

Parameters

Parameter Type
path string | URL
data string
options? WriteFileOptions

Returns

Promise<void>

Example

import { writeTextFile, BaseDirectory } from '@tauri-apps/plugin-fs';


await writeTextFile('file.txt', "Hello world", { baseDir: BaseDirectory.AppLocalData });

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/fs/guest-js/index.ts#L1136

@tauri-apps/plugin-geolocation

Type Aliases

Coordinates

type Coordinates: object;

Type declaration

Name Type Description Defined in
accuracy number Accuracy level of the latitude and longitude coordinates in meters. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L24
altitude number | null The altitude the user is at, if available. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L33
altitudeAccuracy number | null Accuracy level of the altitude coordinate in meters, if available. Available on all iOS versions and on Android 8 and above. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L29
heading number | null The heading the user is facing, if available. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L38
latitude number Latitude in decimal degrees. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L16
longitude number Longitude in decimal degrees. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L20
speed number | null - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L34

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L12


PermissionStatus

type PermissionStatus: object;

Type declaration

Name Type Description Defined in
coarseLocation PermissionState Permissions state for the coarseLoaction alias. On Android it requests/checks ACCESS_COARSE_LOCATION. On Android 12+, users can choose between Approximate location (ACCESS_COARSE_LOCATION) and Precise location (ACCESS_FINE_LOCATION). On iOS it will have the same value as the location alias. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L59
location PermissionState Permission state for the location alias. On Android it requests/checks both ACCESS_COARSE_LOCATION and ACCESS_FINE_LOCATION permissions. On iOS it requests/checks location permissions. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L49

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L41


PermissionType

type PermissionType: "location" | "coarseLocation";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L62


Position

type Position: object;

Type declaration

Name Type Description Defined in
coords Coordinates The GPD coordinates along with the accuracy of the data. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L72
timestamp number Creation time for these coordinates. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L68

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L64


PositionOptions

type PositionOptions: object;

Type declaration

Name Type Description Defined in
enableHighAccuracy boolean High accuracy mode (such as GPS, if available) Will be ignored on Android 12+ if users didnt grant the ACCESS_FINE_LOCATION permission (coarseLocation permission). Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L80
maximumAge number The maximum age in milliseconds of a possible cached position that is acceptable to return. Default: 0 Ignored on iOS Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L92
timeout number The maximum wait time in milliseconds for location updates. On Android the timeout gets ignored for getCurrentPosition. Ignored on iOS Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L86

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L75

Functions

checkPermissions()

function checkPermissions(): Promise<PermissionStatus>

Returns

Promise<PermissionStatus>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L128


clearWatch()

function clearWatch(channelId): Promise<void>

Parameters

Parameter Type
channelId number

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L122


getCurrentPosition()

function getCurrentPosition(options?): Promise<Position>

Parameters

Parameter Type
options? PositionOptions

Returns

Promise<Position>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L114


requestPermissions()

function requestPermissions(permissions): Promise<PermissionStatus>

Parameters

Parameter Type
permissions null | PermissionType[]

Returns

Promise<PermissionStatus>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L132


watchPosition()

function watchPosition(options, cb): Promise<number>

Parameters

Parameter Type
options PositionOptions
cb (location, error?) => void

Returns

Promise<number>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/geolocation/guest-js/index.ts#L95

@tauri-apps/plugin-global-shortcut

Register global shortcuts.

Interfaces

ShortcutEvent

Properties

Property Type Defined in
id number Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/global-shortcut/guest-js/index.ts#L15
shortcut string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/global-shortcut/guest-js/index.ts#L14
state "Released" | "Pressed" Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/global-shortcut/guest-js/index.ts#L16

Type Aliases

ShortcutHandler()

type ShortcutHandler: (event) => void;

Parameters

Parameter Type
event ShortcutEvent

Returns

void

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/global-shortcut/guest-js/index.ts#L19

Functions

isRegistered()

function isRegistered(shortcut): Promise<boolean>

Determines whether the given shortcut is registered by this application or not.

If the shortcut is registered by another application, it will still return false.

Parameters

Parameter Type Description
shortcut string shortcut definition, modifiers and key separated by “+” e.g. CmdOrControl+Q

Returns

Promise<boolean>

Example

import { isRegistered } from '@tauri-apps/plugin-global-shortcut';
const isRegistered = await isRegistered('CommandOrControl+P');

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/global-shortcut/guest-js/index.ts#L117


register()

function register(shortcuts, handler): Promise<void>

Register a global shortcut or a list of shortcuts.

The handler is called when any of the registered shortcuts are pressed by the user.

If the shortcut is already taken by another application, the handler will not be triggered. Make sure the shortcut is as unique as possible while still taking user experience into consideration.

Parameters

Parameter Type Description
shortcuts string | string[] -
handler ShortcutHandler Shortcut handler callback - takes the triggered shortcut as argument

Returns

Promise<void>

Example

import { register } from '@tauri-apps/plugin-global-shortcut';


// register a single hotkey
await register('CommandOrControl+Shift+C', (event) => {
  if (event.state === "Pressed") {
      console.log('Shortcut triggered');
  }
});


// or register multiple hotkeys at once
await register(['CommandOrControl+Shift+C', 'Alt+A'], (event) => {
  console.log(`Shortcut ${event.shortcut} triggered`);
});

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/global-shortcut/guest-js/index.ts#L51


unregister()

function unregister(shortcuts): Promise<void>

Unregister a global shortcut or a list of shortcuts.

Parameters

Parameter Type
shortcuts string | string[]

Returns

Promise<void>

Example

import { unregister } from '@tauri-apps/plugin-global-shortcut';


// unregister a single hotkey
await unregister('CmdOrControl+Space');


// or unregister multiple hotkeys at the same time
await unregister(['CmdOrControl+Space', 'Alt+A']);

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/global-shortcut/guest-js/index.ts#L82


unregisterAll()

function unregisterAll(): Promise<void>

Unregister all global shortcuts.

Returns

Promise<void>

Example

import { unregisterAll } from '@tauri-apps/plugin-global-shortcut';
await unregisterAll();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/global-shortcut/guest-js/index.ts#L98

@tauri-apps/plugin-haptics

Type Aliases

ImpactFeedbackStyle

type ImpactFeedbackStyle:
  | "light"
  | "medium"
  | "heavy"
  | "soft"
  | "rigid";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/haptics/guest-js/bindings.ts#L76


NotificationFeedbackType

type NotificationFeedbackType: "success" | "warning" | "error";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/haptics/guest-js/bindings.ts#L82

Functions

impactFeedback()

function impactFeedback(style): Promise<Result<null, never>>

Parameters

Parameter Type
style ImpactFeedbackStyle

Returns

Promise<Result<null, never>>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/haptics/guest-js/index.ts#L11


notificationFeedback()

function notificationFeedback(type): Promise<Result<null, never>>

Parameters

Parameter Type
type NotificationFeedbackType

Returns

Promise<Result<null, never>>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/haptics/guest-js/index.ts#L12


selectionFeedback()

function selectionFeedback(): Promise<Result<null, never>>

Returns

Promise<Result<null, never>>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/haptics/guest-js/index.ts#L13


vibrate()

function vibrate(duration): Promise<Result<null, never>>

Parameters

Parameter Type
duration number

Returns

Promise<Result<null, never>>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/haptics/guest-js/index.ts#L10

@tauri-apps/plugin-http

Make HTTP requests with the Rust backend.

Security

This API has a scope configuration that forces you to restrict the URLs that can be accessed using glob patterns.

For instance, this scope configuration only allows making HTTP requests to all subdomains for tauri.app except for https://private.tauri.app:

{
  "permissions": [
    {
      "identifier": "http:default",
      "allow": [{ "url": "https://*.tauri.app" }],
      "deny": [{ "url": "https://private.tauri.app" }]
    }
  ]
}

Trying to execute any API with a URL not configured on the scope results in a promise rejection due to denied access.

Interfaces

ClientOptions

Options to configure the Rust client used to make fetch requests

Since

2.0.0

Properties

Property Type Description Defined in
connectTimeout? number Timeout in milliseconds Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L82
danger? DangerousSettings Configuration for dangerous settings on the client such as disabling SSL verification. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L90
maxRedirections? number Defines the maximum number of redirects the client should follow. If set to 0, no redirects will be followed. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L80
proxy? Proxy Configuration of a proxy that a Client should pass requests to. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L86

DangerousSettings

Configuration for dangerous settings on the client such as disabling SSL verification.

Since

2.3.0

Properties

Property Type Description Defined in
acceptInvalidCerts? boolean Disables SSL verification. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L102
acceptInvalidHostnames? boolean Disables hostname verification. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L106

Proxy

Configuration of a proxy that a Client should pass requests to.

Since

2.0.0

Properties

Property Type Description Defined in
all? string | ProxyConfig Proxy all traffic to the passed URL. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L40
http? string | ProxyConfig Proxy all HTTP traffic to the passed URL. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L44
https? string | ProxyConfig Proxy all HTTPS traffic to the passed URL. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L48

ProxyConfig

Properties

Property Type Description Defined in
basicAuth? object Set the Proxy-Authorization header using Basic auth. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L59
basicAuth.password string - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L61
basicAuth.username string - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L60
noProxy? string A configuration for filtering out requests that shouldnt be proxied. Entries are expected to be comma-separated (whitespace between entries is ignored) Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L67
url string The URL of the proxy server. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L55

Functions

fetch()

function fetch(input, init?): Promise<Response>

Fetch a resource from the network. It returns a Promise that resolves to the Response to that Request, whether it is successful or not.

Parameters

Parameter Type
input string | URL | Request
init? RequestInit & ClientOptions

Returns

Promise<Response>

Example

const response = await fetch("http://my.json.host/data.json");
console.log(response.status);  // e.g. 200
console.log(response.statusText); // e.g. "OK"
const jsonData = await response.json();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/http/guest-js/index.ts#L125

@tauri-apps/plugin-log

Enumerations

LogLevel

Enumeration Members

Debug
Debug: 2;

The “debug” level.

Designates lower priority information.

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L26

Error
Error: 5;

The “error” level.

Designates very serious errors.

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L44

Info
Info: 3;

The “info” level.

Designates useful information.

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L32

Trace
Trace: 1;

The “trace” level.

Designates very low priority, often extremely verbose, information.

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L20

Warn
Warn: 4;

The “warn” level.

Designates hazardous situations.

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L38

Interfaces

LogOptions

Properties

Property Type Defined in
file? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L9
keyValues? Record<string, undefined | string> Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L11
line? number Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L10

Functions

attachConsole()

function attachConsole(): Promise<UnlistenFn>

Attaches a listener that writes log entries to the console as they come in.

Returns

Promise<UnlistenFn>

a function to cancel the listener.

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L277


attachLogger()

function attachLogger(fn): Promise<UnlistenFn>

Attaches a listener for the log, and calls the passed function for each log entry.

Parameters

Parameter Type Description
fn LoggerFn

Returns

Promise<UnlistenFn>

a function to cancel the listener.

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L256


debug()

function debug(message, options?): Promise<void>

Logs a message at the debug level.

Parameters

Parameter Type Description
message string # Examples import { debug } from '@tauri-apps/plugin-log'; const pos = { x: 3.234, y: -1.223 }; debug(New position: x: {pos.x}, y: {pos.y});
options? LogOptions -

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L214


error()

function error(message, options?): Promise<void>

Logs a message at the error level.

Parameters

Parameter Type Description
message string # Examples import { error } from '@tauri-apps/plugin-log'; const err_info = "No connection"; const port = 22; error(Error: ${err_info} on port ${port});
options? LogOptions -

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L148


info()

function info(message, options?): Promise<void>

Logs a message at the info level.

Parameters

Parameter Type Description
message string # Examples import { info } from '@tauri-apps/plugin-log'; const conn_info = { port: 40, speed: 3.20 }; info(Connected to port {conn_info.port} at {conn_info.speed} Mb/s);
options? LogOptions -

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L192


trace()

function trace(message, options?): Promise<void>

Logs a message at the trace level.

Parameters

Parameter Type Description
message string # Examples import { trace } from '@tauri-apps/plugin-log'; let pos = { x: 3.234, y: -1.223 }; trace(Position is: x: {pos.x}, y: {pos.y});
options? LogOptions -

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L236


warn()

function warn(message, options?): Promise<void>

Logs a message at the warn level.

Parameters

Parameter Type Description
message string # Examples import { warn } from '@tauri-apps/plugin-log'; const warn_description = "Invalid Input"; warn(Warning! {warn_description}!);
options? LogOptions -

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/log/guest-js/index.ts#L170

@tauri-apps/plugin-nfc

Enumerations

NFCTypeNameFormat

Enumeration Members

AbsoluteURI
AbsoluteURI: 3;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L84

Empty
Empty: 0;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L81

Media
Media: 2;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L83

NfcExternal
NfcExternal: 4;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L85

NfcWellKnown
NfcWellKnown: 1;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L82

Unchanged
Unchanged: 6;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L87

Unknown
Unknown: 5;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L86


TechKind

Enumeration Members

IsoDep
IsoDep: 0;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L17

MifareClassic
MifareClassic: 1;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L18

MifareUltralight
MifareUltralight: 2;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L19

Ndef
Ndef: 3;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L20

NdefFormatable
NdefFormatable: 4;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L21

NfcA
NfcA: 5;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L22

NfcB
NfcB: 6;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L23

NfcBarcode
NfcBarcode: 7;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L24

NfcF
NfcF: 8;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L25

NfcV
NfcV: 9;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L26

Interfaces

NFCRecord

Properties

Property Type Defined in
format NFCTypeNameFormat Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L104
id number[] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L106
kind number[] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L105
payload number[] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L107

ScanOptions

Properties

Property Type Description Defined in
keepSessionAlive? boolean - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L63
message? string Message displayed in the UI. iOS only. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L65
successMessage? string Message displayed in the UI when the message has been read. iOS only. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L67

Tag

Properties

Property Type Defined in
id number[] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L98
kind string[] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L99
records TagRecord[] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L100

TagRecord

Properties

Property Type Defined in
id number[] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L93
kind number[] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L92
payload number[] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L94
tnf NFCTypeNameFormat Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L91

UriFilter

Properties

Property Type Defined in
host? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L12
pathPrefix? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L13
scheme? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L11

WriteOptions

Properties

Property Type Description Defined in
kind? ScanKind - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L71
message? string Message displayed in the UI when reading the tag. iOS only. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L73
successMessage? string Message displayed in the UI when the message has been written. iOS only. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L77
successfulReadMessage? string Message displayed in the UI when the tag has been read. iOS only. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L75

Type Aliases

ScanKind

type ScanKind: object | object;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L29

Variables

RTD_TEXT

const RTD_TEXT: number[];

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L7


RTD_URI

const RTD_URI: number[];

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L8

Functions

isAvailable()

function isAvailable(): Promise<boolean>

Returns

Promise<boolean>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L271


record()

function record(
   format,
   kind,
   id,
   payload): NFCRecord

Parameters

Parameter Type
format NFCTypeNameFormat
kind string | number[]
id string | number[]
payload string | number[]

Returns

NFCRecord

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L110


scan()

function scan(kind, options?): Promise<Tag>

Scans an NFC tag.

import { scan } from "@tauri-apps/plugin-nfc";
await scan({ type: "tag" });

See https://developer.android.com/develop/connectivity/nfc/nfc#ndef for more information.

Parameters

Parameter Type Description
kind ScanKind
options? ScanOptions

Returns

Promise<Tag>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L231


textRecord()

function textRecord(
   text,
   id?,
   language?): NFCRecord

Parameters

Parameter Type Default value
text string undefined
id? string | number[] undefined
language? string 'en'

Returns

NFCRecord

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L130


uriRecord()

function uriRecord(uri, id?): NFCRecord

Parameters

Parameter Type
uri string
id? string | number[]

Returns

NFCRecord

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L203


write()

function write(records, options?): Promise<void>

Write to an NFC tag.

import { uriRecord, write } from "@tauri-apps/plugin-nfc";
await write([uriRecord("https://tauri.app")], { kind: { type: "ndef" } });

If you did not previously call scan with ScanOptions.keepSessionAlive set to true, it will first scan the tag then write to it.

Parameters

Parameter Type Description
records NFCRecord[]
options? WriteOptions

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/nfc/guest-js/index.ts#L256

@tauri-apps/plugin-notification

Send toast notifications (brief auto-expiring OS window element) to your user. Can also be used with the Notification Web API.

Enumerations

Importance

Enumeration Members

Default
Default: 3;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L293

High
High: 4;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L294

Low
Low: 2;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L292

Min
Min: 1;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L291

None
None: 0;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L290


ScheduleEvery

Enumeration Members

Day
Day: "day";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L165

Hour
Hour: "hour";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L166

Minute
Minute: "minute";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L167

Month
Month: "month";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L162

Second
Second: "second";

Not supported on iOS.

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L171

TwoWeeks
TwoWeeks: "twoWeeks";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L163

Week
Week: "week";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L164

Year
Year: "year";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L161


Visibility

Enumeration Members

Private
Private: 0;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L299

Public
Public: 1;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L300

Secret
Secret: -1;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L298

Classes

Schedule

Constructors

new Schedule()
new Schedule(): Schedule
Returns

Schedule

Properties

Property Type Defined in
at undefined | object Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L175
every undefined | object Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L190
interval undefined | object Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L183

Methods

at()
static at(
   date,
   repeating,
   allowWhileIdle): Schedule
Parameters
Parameter Type Default value
date Date undefined
repeating boolean false
allowWhileIdle boolean false
Returns

Schedule

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L198

every()
static every(
   kind,
   count,
   allowWhileIdle): Schedule
Parameters
Parameter Type Default value
kind ScheduleEvery undefined
count number undefined
allowWhileIdle boolean false
Returns

Schedule

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L217

interval()
static interval(interval, allowWhileIdle): Schedule
Parameters
Parameter Type Default value
interval ScheduleInterval undefined
allowWhileIdle boolean false
Returns

Schedule

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L206

Interfaces

Action

Properties

Property Type Defined in
destructive? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L245
foreground? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L244
id string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L241
input? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L246
inputButtonTitle? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L247
inputPlaceholder? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L248
requiresAuthentication? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L243
title string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L242

ActionType

Properties

Property Type Description Defined in
actions Action[] The list of associated actions Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L259
allowInCarPlay? boolean - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L262
customDismissAction? boolean - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L261
hiddenPreviewsBodyPlaceholder? string - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L260
hiddenPreviewsShowSubtitle? boolean - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L264
hiddenPreviewsShowTitle? boolean - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L263
id string The identifier of this action type Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L255

ActiveNotification

Properties

Property Type Defined in
actionTypeId? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L284
attachments Attachment[] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L283
body? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L278
data Record<string, string> Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L281
extra Record<string, unknown> Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L282
group? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L279
groupSummary boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L280
id number Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L275
schedule? Schedule Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L285
sound? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L286
tag? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L276
title? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L277

Attachment

Attachment of a notification.

Properties

Property Type Description Defined in
id string Attachment identifier. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L235
url string Attachment URL. Accepts the asset and file protocols. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L237

Channel

Properties

Property Type Defined in
description? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L306
id string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L304
importance? Importance Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L311
lightColor? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L309
lights? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L308
name string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L305
sound? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L307
vibration? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L310
visibility? Visibility Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L312

Options

Options to send a notification.

Since

2.0.0

Properties

Property Type Description Defined in
actionTypeId? string Defines an action type for this notification. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L62
attachments? Attachment[] Notification attachments. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L110
autoCancel? boolean Automatically cancel the notification when the user clicks on it. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L126
body? string Optional notification body. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L44
channelId? string Identifier of the Channel that deliveres this notification. If the channel does not exist, the notification wont fire. Make sure the channel exists with listChannels and createChannel. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L36
extra? Record<string, unknown> Extra payload to store in the notification. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L114
group? string Identifier used to group multiple notifications. https://developer.apple.com/documentation/usernotifications/unmutablenotificationcontent/1649872-threadidentifier Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L68
groupSummary? boolean Instructs the system that this notification is the summary of a group on Android. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L72
icon? string Notification icon. On Android the icon must be placed in the apps res/drawable folder. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L96
iconColor? string Icon color on Android. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L106
id? number The notification identifier to reference this object later. Must be a 32-bit integer. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L29
inboxLines? string[] List of lines to add to the notification. Changes the notification style to inbox. Cannot be used with largeBody. Only supports up to 5 lines. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L90
largeBody? string Multiline text. Changes the notification style to big text. Cannot be used with inboxLines. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L54
largeIcon? string Notification large icon (Android). The icon must be placed in the apps res/drawable folder. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L102
number? number Sets the number of items this notification represents on Android. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L138
ongoing? boolean If true, the notification cannot be dismissed by the user on Android. An application service must manage the dismissal of the notification. It is typically used to indicate a background task that is pending (e.g. a file download) or the user is engaged with (e.g. playing music). Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L122
schedule? Schedule Schedule this notification to fire on a later time or a fixed interval. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L48
silent? boolean Changes the notification presentation to be silent on iOS (no badge, no sound, not listed). Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L130
sound? string The sound resource name or file path for the notification. Platform specific behavior: - On macOS: use system sounds (e.g., “Ping”, “Blow”) or sound files in the app bundle - On Linux: use XDG theme sounds (e.g., “message-new-instant”) or file paths - On Windows: use file paths to sound files (.wav format) - On Mobile: use resource names Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L82
summary? string Detail text for the notification with largeBody, inboxLines or groupSummary. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L58
title string Notification title. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L40
visibility? Visibility Notification visibility. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L134

PendingNotification

Properties

Property Type Defined in
body? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L270
id number Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L268
schedule Schedule Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L271
title? string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L269

ScheduleInterval

Properties

Property Type Description Defined in
day? number - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L144
hour? number - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L155
minute? number - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L156
month? number - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L143
second? number - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L157
weekday? number 1 - Sunday 2 - Monday 3 - Tuesday 4 - Wednesday 5 - Thursday 6 - Friday 7 - Saturday Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L154
year? number - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L142

Type Aliases

PermissionState

type PermissionState: "granted" | "denied" | "prompt" | "prompt-with-rationale";

Source: undefined

Functions

active()

function active(): Promise<ActiveNotification[]>

Retrieves the list of active notifications.

Returns

Promise<ActiveNotification[]>

A promise resolving to the list of active notifications.

Example

import { active } from '@tauri-apps/plugin-notification';
const activeNotifications = await active();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L465


cancel()

function cancel(notifications): Promise<void>

Cancels the pending notifications with the given list of identifiers.

Parameters

Parameter Type
notifications number[]

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example

import { cancel } from '@tauri-apps/plugin-notification';
await cancel([-34234, 23432, 4311]);

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L431


cancelAll()

function cancelAll(): Promise<void>

Cancels all pending notifications.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example

import { cancelAll } from '@tauri-apps/plugin-notification';
await cancelAll();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L448


channels()

function channels(): Promise<Channel[]>

Retrieves the list of notification channels.

Returns

Promise<Channel[]>

A promise resolving to the list of notification channels.

Example

import { channels } from '@tauri-apps/plugin-notification';
const notificationChannels = await channels();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L559


createChannel()

function createChannel(channel): Promise<void>

Creates a notification channel.

Parameters

Parameter Type
channel Channel

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example

import { createChannel, Importance, Visibility } from '@tauri-apps/plugin-notification';
await createChannel({
  id: 'new-messages',
  name: 'New Messages',
  lights: true,
  vibration: true,
  importance: Importance.Default,
  visibility: Visibility.Private
});

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L525


isPermissionGranted()

function isPermissionGranted(): Promise<boolean>

Checks if the permission to send notifications is granted.

Returns

Promise<boolean>

Example

import { isPermissionGranted } from '@tauri-apps/plugin-notification';
const permissionGranted = await isPermissionGranted();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L325


onAction()

function onAction(cb): Promise<PluginListener>

Parameters

Parameter Type
cb (notification) => void

Returns

Promise<PluginListener>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L569


onNotificationReceived()

function onNotificationReceived(cb): Promise<PluginListener>

Parameters

Parameter Type
cb (notification) => void

Returns

Promise<PluginListener>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L563


pending()

function pending(): Promise<PendingNotification[]>

Retrieves the list of pending notifications.

Returns

Promise<PendingNotification[]>

A promise resolving to the list of pending notifications.

Example

import { pending } from '@tauri-apps/plugin-notification';
const pendingNotifications = await pending();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L414


registerActionTypes()

function registerActionTypes(types): Promise<void>

Register actions that are performed when the user clicks on the notification.

Parameters

Parameter Type
types ActionType[]

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example

import { registerActionTypes } from '@tauri-apps/plugin-notification';
await registerActionTypes([{
  id: 'tauri',
  actions: [{
    id: 'my-action',
    title: 'Settings'
  }]
}])

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L397


removeActive()

function removeActive(notifications): Promise<void>

Removes the active notifications with the given list of identifiers.

Parameters

Parameter Type
notifications object[]

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example

import { cancel } from '@tauri-apps/plugin-notification';
await cancel([-34234, 23432, 4311])

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L482


removeAllActive()

function removeAllActive(): Promise<void>

Removes all active notifications.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example

import { removeAllActive } from '@tauri-apps/plugin-notification';
await removeAllActive()

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L501


removeChannel()

function removeChannel(id): Promise<void>

Removes the channel with the given identifier.

Parameters

Parameter Type
id string

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example

import { removeChannel } from '@tauri-apps/plugin-notification';
await removeChannel();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L542


requestPermission()

function requestPermission(): Promise<NotificationPermission>

Requests the permission to send notifications.

Returns

Promise<NotificationPermission>

A promise resolving to whether the user granted the permission or not.

Example

import { isPermissionGranted, requestPermission } from '@tauri-apps/plugin-notification';
let permissionGranted = await isPermissionGranted();
if (!permissionGranted) {
  const permission = await requestPermission();
  permissionGranted = permission === 'granted';
}

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L348


sendNotification()

function sendNotification(options): void

Sends a notification to the user.

Parameters

Parameter Type
options string | Options

Returns

void

Example

import { isPermissionGranted, requestPermission, sendNotification } from '@tauri-apps/plugin-notification';
let permissionGranted = await isPermissionGranted();
if (!permissionGranted) {
  const permission = await requestPermission();
  permissionGranted = permission === 'granted';
}
if (permissionGranted) {
  sendNotification('Tauri is awesome!');
  sendNotification({ title: 'TAURI', body: 'Tauri is awesome!' });
}

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/notification/guest-js/index.ts#L370

@tauri-apps/plugin-opener

Open files and URLs using their default application.

Security

This API has a scope configuration that forces you to restrict the files and urls to be opened.

Restricting access to the open | open API

On the configuration object, open: true means that the open API can be used with any URL, as the argument is validated with the ^((mailto:\w+)|(tel:\w+)|(https?://\w+)).+ regex. You can change that regex by changing the boolean value to a string, e.g. open: ^https://github.com/.

Functions

openPath()

function openPath(path, openWith?): Promise<void>

Opens a path with the systems default app, or the one specified with openWith.

Parameters

Parameter Type Description
path string The path to open.
openWith? string The app to open the path with. If not specified, defaults to the system default application for the specified path type.

Returns

Promise<void>

Example

import { openPath } from '@tauri-apps/plugin-opener';


// opens a file using the default program:
await openPath('/path/to/file');
// opens a file using `vlc` command on Windows.
await openPath('C:/path/to/file', 'vlc');

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/opener/guest-js/index.ts#L71


openUrl()

function openUrl(url, openWith?): Promise<void>

Opens a url with the systems default app, or the one specified with openWith.

Parameters

Parameter Type Description
url string | URL The URL to open.
openWith? string The app to open the URL with. If not specified, defaults to the system default application for the specified url type. On mobile, openWith can be provided as inAppBrowser to open the URL in an in-app browser. Otherwise, it will open the URL in the system default browser.

Returns

Promise<void>

Example

import { openUrl } from '@tauri-apps/plugin-opener';


// opens the given URL on the default browser:
await openUrl('https://github.com/tauri-apps/tauri');
// opens the given URL using `firefox`:
await openUrl('https://github.com/tauri-apps/tauri', 'firefox');

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/opener/guest-js/index.ts#L42


revealItemInDir()

function revealItemInDir(path): Promise<void>

Reveal a path with the systems default explorer.

Platform-specific:

  • Android / iOS: Unsupported.

Parameters

Parameter Type Description
path string | string[] The path to reveal.

Returns

Promise<void>

Example

import { revealItemInDir } from '@tauri-apps/plugin-opener';
await revealItemInDir('/path/to/file');
await revealItemInDir([ '/path/to/file', '/path/to/another/file' ]);

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/opener/guest-js/index.ts#L96

@tauri-apps/plugin-os

Provides operating system-related utility methods and properties.

Type Aliases

Arch

type Arch:
  | "x86"
  | "x86_64"
  | "arm"
  | "aarch64"
  | "mips"
  | "mips64"
  | "powerpc"
  | "powerpc64"
  | "riscv64"
  | "s390x"
  | "sparc64";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/os/guest-js/index.ts#L42


Family

type Family: "unix" | "windows";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/os/guest-js/index.ts#L97


OsType

type OsType:
  | "linux"
  | "windows"
  | "macos"
  | "ios"
  | "android";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/os/guest-js/index.ts#L40


Platform

type Platform:
  | "linux"
  | "macos"
  | "ios"
  | "freebsd"
  | "dragonfly"
  | "netbsd"
  | "openbsd"
  | "solaris"
  | "android"
  | "windows";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/os/guest-js/index.ts#L28

Functions

arch()

function arch(): Arch

Returns the current operating system architecture. Possible values are 'x86', 'x86_64', 'arm', 'aarch64', 'mips', 'mips64', 'powerpc', 'powerpc64', 'riscv64', 's390x', 'sparc64'.

Returns

Arch

Example

import { arch } from '@tauri-apps/plugin-os';
const archName = arch();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/os/guest-js/index.ts#L138


eol()

function eol(): string

Returns the operating system-specific end-of-line marker.

  • \n on POSIX
  • \r\n on Windows

Returns

string

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/os/guest-js/index.ts#L62


exeExtension()

function exeExtension(): string

Returns the file extension, if any, used for executable binaries on this platform. Possible values are 'exe' and '' (empty string).

Returns

string

Example

import { exeExtension } from '@tauri-apps/plugin-os';
const exeExt = exeExtension();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/os/guest-js/index.ts#L152


family()

function family(): Family

Returns the current operating system family. Possible values are 'unix', 'windows'.

Returns

Family

Example

import { family } from '@tauri-apps/plugin-os';
const family = family();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/os/guest-js/index.ts#L109


hostname()

function hostname(): Promise<string | null>

Returns the host name of the operating system.

Returns

Promise<string | null>

Example

import { hostname } from '@tauri-apps/plugin-os';
const hostname = await hostname();

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/os/guest-js/index.ts#L181


locale()

function locale(): Promise<string | null>

Returns a String with a BCP-47 language tag inside. If the locale couldnt be obtained, null is returned instead.

Returns

Promise<string | null>

Example

import { locale } from '@tauri-apps/plugin-os';
const locale = await locale();
if (locale) {
   // use the locale string here
}

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/os/guest-js/index.ts#L169


platform()

function platform(): Platform

Returns a string describing the specific operating system in use. The value is set at compile time. Possible values are 'linux', 'macos', 'ios', 'freebsd', 'dragonfly', 'netbsd', 'openbsd', 'solaris', 'android', 'windows'

Returns

Platform

Example

import { platform } from '@tauri-apps/plugin-os';
const platformName = platform();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/os/guest-js/index.ts#L79


type()

function type(): OsType

Returns the current operating system type. Returns 'linux' on Linux, 'macos' on macOS, 'windows' on Windows, 'ios' on iOS and 'android' on Android.

Returns

OsType

Example

import { type } from '@tauri-apps/plugin-os';
const osType = type();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/os/guest-js/index.ts#L123


version()

function version(): string

Returns the current operating system version.

Returns

string

Example

import { version } from '@tauri-apps/plugin-os';
const osVersion = version();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/os/guest-js/index.ts#L93

@tauri-apps/plugin-positioner

Enumerations

Position

Well known window positions.

Enumeration Members

BottomCenter
BottomCenter: 5;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L18

BottomLeft
BottomLeft: 2;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L15

BottomRight
BottomRight: 3;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L16

Center
Center: 8;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L21

LeftCenter
LeftCenter: 6;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L19

RightCenter
RightCenter: 7;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L20

TopCenter
TopCenter: 4;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L17

TopLeft
TopLeft: 0;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L13

TopRight
TopRight: 1;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L14

TrayBottomCenter
TrayBottomCenter: 14;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L27

TrayBottomLeft
TrayBottomLeft: 10;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L23

TrayBottomRight
TrayBottomRight: 12;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L25

TrayCenter
TrayCenter: 13;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L26

TrayLeft
TrayLeft: 9;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L22

TrayRight
TrayRight: 11;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L24

Functions

handleIconState()

function handleIconState(event): Promise<void>

Parameters

Parameter Type
event TrayIconEvent

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L55


moveWindow()

function moveWindow(to): Promise<void>

Moves the Window to the given Position using WindowExt.move_window() All positions are relative to the current screen.

Parameters

Parameter Type Description
to Position The Position to move to.

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L36


moveWindowConstrained()

function moveWindowConstrained(to): Promise<void>

Moves the Window to the given Position using WindowExt.move_window_constrained()

This move operation constrains the window to the screen dimensions in case of tray-icon positions.

Parameters

Parameter Type Description
to Position The (tray) Position to move to.

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/positioner/guest-js/index.ts#L49

@tauri-apps/plugin-process

Perform operations on the current process.

Functions

exit()

function exit(code): Promise<void>

Exits immediately with the given exitCode.

Parameters

Parameter Type Default value Description
code number 0 The exit code to use.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example

import { exit } from '@tauri-apps/plugin-process';
await exit(1);

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/process/guest-js/index.ts#L25


relaunch()

function relaunch(): Promise<void>

Exits the current instance of the app then relaunches it.

Returns

Promise<void>

A promise indicating the success or failure of the operation.

Example

import { relaunch } from '@tauri-apps/plugin-process';
await relaunch();

Since

2.0.0

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/process/guest-js/index.ts#L41

@tauri-apps/plugin-sql

Classes

default

Database

The Database class serves as the primary interface for communicating with the rust side of the sql plugin.

Constructors

new default()
new default(path): default
Parameters
Parameter Type
path string
Returns

default

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/sql/guest-js/index.ts#L29

Properties

Property Type Defined in
path string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/sql/guest-js/index.ts#L28

Methods

close()
close(db?): Promise<boolean>

close

Closes the database connection pool.

Parameters
Parameter Type Description
db? string Optionally state the name of a database if you are managing more than one. Otherwise, all database pools will be in scope.
Returns

Promise<boolean>

Example
const success = await db.close()

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/sql/guest-js/index.ts#L162

execute()
execute(query, bindValues?): Promise<QueryResult>

execute

Passes a SQL expression to the database for execution.

Parameters
Parameter Type
query string
bindValues? unknown[]
Returns

Promise<QueryResult>

Example
// for sqlite & postgres
// INSERT example
const result = await db.execute(
   "INSERT into todos (id, title, status) VALUES ($1, $2, $3)",
   [ todos.id, todos.title, todos.status ]
);
// UPDATE example
const result = await db.execute(
   "UPDATE todos SET title = $1, completed = $2 WHERE id = $3",
   [ todos.title, todos.status, todos.id ]
);


// for mysql
// INSERT example
const result = await db.execute(
   "INSERT into todos (id, title, status) VALUES (?, ?, ?)",
   [ todos.id, todos.title, todos.status ]
);
// UPDATE example
const result = await db.execute(
   "UPDATE todos SET title = ?, completed = ? WHERE id = ?",
   [ todos.title, todos.status, todos.id ]
);

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/sql/guest-js/index.ts#L108

select()
select<T>(query, bindValues?): Promise<T>

select

Passes in a SELECT query to the database for execution.

Type Parameters
Type Parameter
T
Parameters
Parameter Type
query string
bindValues? unknown[]
Returns

Promise<T>

Example
// for sqlite & postgres
const result = await db.select(
   "SELECT * from todos WHERE id = $1", [ id ]
);


// for mysql
const result = await db.select(
   "SELECT * from todos WHERE id = ?", [ id ]
);

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/sql/guest-js/index.ts#L141

get()
static get(path): default

get

A static initializer which synchronously returns an instance of the Database class while deferring the actual database connection until the first invocation or selection on the database.

Sqlite

The path is relative to tauri::path::BaseDirectory::App and must start with sqlite:.

Parameters
Parameter Type
path string
Returns

default

Example
const db = Database.get("sqlite:test.db");

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/sql/guest-js/index.ts#L72

load()
static load(path): Promise<default>

load

A static initializer which connects to the underlying database and returns a Database instance once a connection to the database is established.

Sqlite

The path is relative to tauri::path::BaseDirectory::App and must start with sqlite:.

Parameters
Parameter Type
path string
Returns

Promise<default>

Example
const db = await Database.load("sqlite:test.db");

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/sql/guest-js/index.ts#L48

Interfaces

QueryResult

Properties

Property Type Description Defined in
lastInsertId? number The last inserted id. This value is not set for Postgres databases. If the last inserted id is required on Postgres, the select function must be used, with a RETURNING clause (INSERT INTO todos (title) VALUES ($1) RETURNING id). Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/sql/guest-js/index.ts#L18
rowsAffected number The number of rows affected by the query. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/sql/guest-js/index.ts#L9

@tauri-apps/plugin-store

Classes

LazyStore

A lazy loaded key-value store persisted by the backend layer.

Implements

  • IStore

Constructors

new LazyStore()
new LazyStore(path, options?): LazyStore

Note that the options are not applied if someone else already created the store

Parameters
Parameter Type Description
path string Path to save the store in app_data_dir
options? StoreOptions Store configuration options
Returns

LazyStore

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L104

Methods

clear()
clear(): Promise<void>

Clears the store, removing all key-value pairs.

Note: To clear the storage and reset it to its default value, use reset instead.

Returns

Promise<void>

Implementation of

IStore.clear

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L132

close()
close(): Promise<void>

Close the store and cleans up this resource from memory. You should not call any method on this object anymore and should drop any reference to it.

Returns

Promise<void>

Implementation of

IStore.close

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L177

delete()
delete(key): Promise<boolean>

Removes a key-value pair from the store.

Parameters
Parameter Type Description
key string
Returns

Promise<boolean>

Implementation of

IStore.delete

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L128

entries()
entries<T>(): Promise<[string, T][]>

Returns a list of all entries in the store.

Type Parameters
Type Parameter
T
Returns

Promise<[string, T][]>

Implementation of

IStore.entries

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L148

get()
get<T>(key): Promise<undefined | T>

Returns the value for the given key or undefined if the key does not exist.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
key string
Returns

Promise<undefined | T>

Implementation of

IStore.get

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L120

has()
has(key): Promise<boolean>

Returns true if the given key exists in the store.

Parameters
Parameter Type Description
key string
Returns

Promise<boolean>

Implementation of

IStore.has

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L124

init()
init(): Promise<void>

Init/load the store if its not loaded already

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L112

keys()
keys(): Promise<string[]>

Returns a list of all keys in the store.

Returns

Promise<string[]>

Implementation of

IStore.keys

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L140

length()
length(): Promise<number>

Returns the number of key-value pairs in the store.

Returns

Promise<number>

Implementation of

IStore.length

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L152

onChange()
onChange<T>(cb): Promise<UnlistenFn>

Listen to changes on the store.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
cb (key, value) => void
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event.

Since

2.0.0

Implementation of

IStore.onChange

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L171

onKeyChange()
onKeyChange<T>(key, cb): Promise<UnlistenFn>

Listen to changes on a store key.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
key string
cb (value) => void
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event.

Since

2.0.0

Implementation of

IStore.onKeyChange

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L164

reload()
reload(options?): Promise<void>

Attempts to load the on-disk state at the stores path into memory.

This method is useful if the on-disk state was edited by the user and you want to synchronize the changes.

Note:

  • This method loads the data and merges it with the current store, this behavior will be changed to resetting to default first and then merging with the on-disk state in v3, to fully match the store with the on-disk state, set ignoreDefaults to true
  • This method does not emit change events.
Parameters
Parameter Type
options? ReloadOptions
Returns

Promise<void>

Implementation of

IStore.reload

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L156

reset()
reset(): Promise<void>

Resets the store to its default value.

If no default value has been set, this method behaves identical to clear.

Returns

Promise<void>

Implementation of

IStore.reset

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L136

save()
save(): Promise<void>

Saves the store to disk at the stores path.

Returns

Promise<void>

Implementation of

IStore.save

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L160

set()
set(key, value): Promise<void>

Inserts a key-value pair into the store.

Parameters
Parameter Type Description
key string
value unknown
Returns

Promise<void>

Implementation of

IStore.set

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L116

values()
values<T>(): Promise<T[]>

Returns a list of all values in the store.

Type Parameters
Type Parameter
T
Returns

Promise<T[]>

Implementation of

IStore.values

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L144


Store

A key-value store persisted by the backend layer.

Extends

  • Resource

Implements

  • IStore

Accessors

rid
get rid(): number
Returns

number

Inherited from

Resource.rid

Source: undefined

Methods

clear()
clear(): Promise<void>

Clears the store, removing all key-value pairs.

Note: To clear the storage and reset it to its default value, use reset instead.

Returns

Promise<void>

Implementation of

IStore.clear

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L267

close()
close(): Promise<void>

Destroys and cleans up this resource from memory. You should not call any method on this object anymore and should drop any reference to it.

Returns

Promise<void>

Implementation of

IStore.close

Inherited from

Resource.close

Source: undefined

delete()
delete(key): Promise<boolean>

Removes a key-value pair from the store.

Parameters
Parameter Type Description
key string
Returns

Promise<boolean>

Implementation of

IStore.delete

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L260

entries()
entries<T>(): Promise<[string, T][]>

Returns a list of all entries in the store.

Type Parameters
Type Parameter
T
Returns

Promise<[string, T][]>

Implementation of

IStore.entries

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L283

get()
get<T>(key): Promise<undefined | T>

Returns the value for the given key or undefined if the key does not exist.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
key string
Returns

Promise<undefined | T>

Implementation of

IStore.get

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L245

has()
has(key): Promise<boolean>

Returns true if the given key exists in the store.

Parameters
Parameter Type Description
key string
Returns

Promise<boolean>

Implementation of

IStore.has

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L253

keys()
keys(): Promise<string[]>

Returns a list of all keys in the store.

Returns

Promise<string[]>

Implementation of

IStore.keys

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L275

length()
length(): Promise<number>

Returns the number of key-value pairs in the store.

Returns

Promise<number>

Implementation of

IStore.length

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L287

onChange()
onChange<T>(cb): Promise<UnlistenFn>

Listen to changes on the store.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
cb (key, value) => void
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event.

Since

2.0.0

Implementation of

IStore.onChange

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L310

onKeyChange()
onKeyChange<T>(key, cb): Promise<UnlistenFn>

Listen to changes on a store key.

Type Parameters
Type Parameter
T
Parameters
Parameter Type Description
key string
cb (value) => void
Returns

Promise<UnlistenFn>

A promise resolving to a function to unlisten to the event.

Since

2.0.0

Implementation of

IStore.onKeyChange

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L299

reload()
reload(options?): Promise<void>

Attempts to load the on-disk state at the stores path into memory.

This method is useful if the on-disk state was edited by the user and you want to synchronize the changes.

Note:

  • This method loads the data and merges it with the current store, this behavior will be changed to resetting to default first and then merging with the on-disk state in v3, to fully match the store with the on-disk state, set ignoreDefaults to true
  • This method does not emit change events.
Parameters
Parameter Type
options? ReloadOptions
Returns

Promise<void>

Implementation of

IStore.reload

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L291

reset()
reset(): Promise<void>

Resets the store to its default value.

If no default value has been set, this method behaves identical to clear.

Returns

Promise<void>

Implementation of

IStore.reset

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L271

save()
save(): Promise<void>

Saves the store to disk at the stores path.

Returns

Promise<void>

Implementation of

IStore.save

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L295

set()
set(key, value): Promise<void>

Inserts a key-value pair into the store.

Parameters
Parameter Type Description
key string
value unknown
Returns

Promise<void>

Implementation of

IStore.set

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L237

values()
values<T>(): Promise<T[]>

Returns a list of all values in the store.

Type Parameters
Type Parameter
T
Returns

Promise<T[]>

Implementation of

IStore.values

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L279

get()
static get(path): Promise<null | Store>

Gets an already loaded store.

If the store is not loaded, returns null. In this case you must load it.

This function is more useful when you already know the store is loaded and just need to access its instance. Prefer Store.load otherwise.

Parameters
Parameter Type Description
path string Path of the store.
Returns

Promise<null | Store>

Example
import { Store } from '@tauri-apps/api/store';
let store = await Store.get('store.json');
if (!store) {
  store = await Store.load('store.json');
}

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L231

load()
static load(path, options?): Promise<Store>

Create a new Store or load the existing store with the path.

Parameters
Parameter Type Description
path string Path to save the store in app_data_dir
options? StoreOptions Store configuration options
Returns

Promise<Store>

Example
import { Store } from '@tauri-apps/api/store';
const store = await Store.load('store.json');

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L204

Type Aliases

ReloadOptions

type ReloadOptions: object;

Options to IStore.reload a IStore

Type declaration

Name Type Description Defined in
ignoreDefaults boolean To fully match the store with the on-disk state, ignoring defaults Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L461

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L457


StoreOptions

type StoreOptions: object;

Options to create a store

Type declaration

Name Type Description Defined in
autoSave boolean | number Auto save on modification with debounce duration in milliseconds, its 100ms by default, pass in false to disable it Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L28
createNew boolean Force create a new store with default values even if it already exists. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L40
defaults object Default value of the store Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L24
deserializeFnName string Name of a deserialize function registered in the rust side plugin builder Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L36
overrideDefaults boolean When creating the store, override the store with the on-disk state if it exists, ignoring defaults Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L44
serializeFnName string Name of a serialize function registered in the rust side plugin builder Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L32

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L20

Functions

getStore()

function getStore(path): Promise<Store | null>

Gets an already loaded store.

If the store is not loaded, returns null. In this case you must load it.

This function is more useful when you already know the store is loaded and just need to access its instance. Prefer Store.load otherwise.

Parameters

Parameter Type Description
path string Path of the store.

Returns

Promise<Store | null>

Example

import { getStore } from '@tauri-apps/api/store';
const store = await getStore('store.json');

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L82


load()

function load(path, options?): Promise<Store>

Create a new Store or load the existing store with the path.

Parameters

Parameter Type Description
path string Path to save the store in app_data_dir
options? StoreOptions Store configuration options

Returns

Promise<Store>

Example

import { Store } from '@tauri-apps/api/store';
const store = await Store.load('store.json');

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/store/guest-js/index.ts#L59

@tauri-apps/plugin-stronghold

Classes

Client

Constructors

new Client()
new Client(path, name): Client
Parameters
Parameter Type
path string
name ClientPath
Returns

Client

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L265

Properties

Property Type Defined in
name ClientPath Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L263
path string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L262

Methods

getStore()
getStore(): Store
Returns

Store

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L280

getVault()
getVault(name): Vault

Get a vault by name.

Parameters
Parameter Type Description
name VaultPath
Returns

Vault

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L276


Location

Constructors

new Location()
new Location(type, payload): Location
Parameters
Parameter Type
type string
payload Record<string, unknown>
Returns

Location

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L86

Properties

Property Type Defined in
payload Record<string, unknown> Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L84
type string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L83

Methods

counter()
static counter(vault, counter): Location
Parameters
Parameter Type
vault VaultPath
counter number
Returns

Location

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L98

generic()
static generic(vault, record): Location
Parameters
Parameter Type
vault VaultPath
record RecordPath
Returns

Location

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L91


Store

Constructors

new Store()
new Store(path, client): Store
Parameters
Parameter Type
path string
client ClientPath
Returns

Store

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L289

Properties

Property Type Defined in
client ClientPath Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L287
path string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L286

Methods

get()
get(key): Promise<null | Uint8Array>
Parameters
Parameter Type
key StoreKey
Returns

Promise<null | Uint8Array>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L294

insert()
insert(
   key,
   value,
lifetime?): Promise<void>
Parameters
Parameter Type
key StoreKey
value number[]
lifetime? Duration
Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L302

remove()
remove(key): Promise<null | Uint8Array>
Parameters
Parameter Type
key StoreKey
Returns

Promise<null | Uint8Array>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L316


Stronghold

A representation of an access to a stronghold.

Properties

Property Type Defined in
path string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L388

Methods

createClient()
createClient(client): Promise<Client>
Parameters
Parameter Type
client ClientPath
Returns

Promise<Client>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L428

loadClient()
loadClient(client): Promise<Client>
Parameters
Parameter Type
client ClientPath
Returns

Promise<Client>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L421

save()
save(): Promise<void>

Persists the stronghold state to the snapshot.

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L439

unload()
unload(): Promise<void>

Remove this instance from the cache.

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L415

load()
static load(path, password): Promise<Stronghold>

Load the snapshot if it exists (password must match), or start a fresh stronghold instance otherwise.

Parameters
Parameter Type Description
path string -
password string
Returns

Promise<Stronghold>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L405


Vault

A key-value storage that allows create, update and delete operations. It does not allow reading the data, so one of the procedures must be used to manipulate the stored data, allowing secure storage of secrets.

Extends

  • ProcedureExecutor

Constructors

new Vault()
new Vault(
   path,
   client,
   name): Vault
Parameters
Parameter Type
path string
client ClientPath
name VaultPath
Returns

Vault

Overrides

ProcedureExecutor.constructor

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L340

Properties

Property Type Description Inherited from Defined in
client ClientPath - - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L336
name VaultPath The vault name. - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L338
path string The vault path. - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L335
procedureArgs Record<string, unknown> - ProcedureExecutor.procedureArgs Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L107

Methods

deriveSLIP10()
deriveSLIP10(
   chain,
   source,
   sourceLocation,
outputLocation): Promise<Uint8Array>

Derive a SLIP10 private key using a seed or key.

Parameters
Parameter Type Description
chain number[] The chain path.
source "Seed" | "Key" The source type, either Seed or Key.
sourceLocation Location The source location, must be the outputLocation of a previous call to generateSLIP10Seed or deriveSLIP10.
outputLocation Location Location of the record where the private key will be stored.
Returns

Promise<Uint8Array>

Inherited from

ProcedureExecutor.deriveSLIP10

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L145

generateBIP39()
generateBIP39(outputLocation, passphrase?): Promise<Uint8Array>

Generate a BIP39 seed.

Parameters
Parameter Type Description
outputLocation Location The location of the record where the BIP39 seed will be stored.
passphrase? string The optional mnemonic passphrase.
Returns

Promise<Uint8Array>

Inherited from

ProcedureExecutor.generateBIP39

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L200

generateSLIP10Seed()
generateSLIP10Seed(outputLocation, sizeBytes?): Promise<Uint8Array>

Generate a SLIP10 seed for the given location.

Parameters
Parameter Type Description
outputLocation Location Location of the record where the seed will be stored.
sizeBytes? number The size in bytes of the SLIP10 seed.
Returns

Promise<Uint8Array>

Inherited from

ProcedureExecutor.generateSLIP10Seed

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L120

getEd25519PublicKey()
getEd25519PublicKey(privateKeyLocation): Promise<Uint8Array>

Gets the Ed25519 public key of a SLIP10 private key.

Parameters
Parameter Type Description
privateKeyLocation Location The location of the private key. Must be the outputLocation of a previous call to deriveSLIP10.
Returns

Promise<Uint8Array>

A promise resolving to the public key hex string.

Since

2.0.0

Inherited from

ProcedureExecutor.getEd25519PublicKey

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L223

insert()
insert(recordPath, secret): Promise<void>

Insert a record to this vault.

Parameters
Parameter Type
recordPath RecordPath
secret number[]
Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L358

recoverBIP39()
recoverBIP39(
   mnemonic,
   outputLocation,
passphrase?): Promise<Uint8Array>

Store a BIP39 mnemonic.

Parameters
Parameter Type Description
mnemonic string The mnemonic string.
outputLocation Location The location of the record where the BIP39 mnemonic will be stored.
passphrase? string The optional mnemonic passphrase.
Returns

Promise<Uint8Array>

Inherited from

ProcedureExecutor.recoverBIP39

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L175

remove()
remove(location): Promise<void>

Remove a record from the vault.

Parameters
Parameter Type Description
location Location The record location.
Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L374

signEd25519()
signEd25519(privateKeyLocation, msg): Promise<Uint8Array>

Creates a Ed25519 signature from a private key.

Parameters
Parameter Type Description
privateKeyLocation Location The location of the record where the private key is stored. Must be the outputLocation of a previous call to deriveSLIP10.
msg string The message to sign.
Returns

Promise<Uint8Array>

A promise resolving to the signature hex string.

Since

2.0.0

Inherited from

ProcedureExecutor.signEd25519

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L244

Interfaces

AddressInfo

Properties

Property Type Defined in
peers Map<string, PeerAddress> Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L43
relays string[] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L44

ClientAccess

Properties

Property Type Defined in
cloneVaultDefault? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L52
cloneVaultExceptions? Map<VaultPath, boolean> Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L53
readStore? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L54
useVaultDefault? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L48
useVaultExceptions? Map<VaultPath, boolean> Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L49
writeStore? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L55
writeVaultDefault? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L50
writeVaultExceptions? Map<VaultPath, boolean> Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L51

ConnectionLimits

Properties

Property Type Defined in
maxEstablishedIncoming? number Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L31
maxEstablishedOutgoing? number Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L32
maxEstablishedPerPeer? number Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L33
maxEstablishedTotal? number Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L34
maxPendingIncoming? number Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L29
maxPendingOutgoing? number Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L30

Duration

A duration definition.

Properties

Property Type Description Defined in
nanos number The fractional part of this Duration, in nanoseconds. Must be greater or equal to 0 and smaller than 1e+9 (the max number of nanoseoncds in a second) Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L79
secs number The number of whole seconds contained by this Duration. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L77

NetworkConfig

Properties

Property Type Defined in
addresses? AddressInfo Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L69
connectionTimeout? Duration Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L65
connectionsLimit? ConnectionLimits Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L66
enableMdns? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L67
enableRelay? boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L68
peerPermissions? Map<string, Permissions> Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L70
permissionsDefault? Permissions Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L71
requestTimeout? Duration Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L64

PeerAddress

Properties

Property Type Defined in
known string[] Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L38
use_relay_fallback boolean Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L39

Permissions

Properties

Property Type Defined in
default? ClientAccess Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L59
exceptions? Map<VaultPath, ClientAccess> Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L60

Type Aliases

ClientPath

type ClientPath: string | Iterable<number> | ArrayLike<number> | ArrayBuffer;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L7


RecordPath

type RecordPath: string | Iterable<number> | ArrayLike<number> | ArrayBuffer;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L17


StoreKey

type StoreKey: string | Iterable<number> | ArrayLike<number> | ArrayBuffer;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L22


VaultPath

type VaultPath: string | Iterable<number> | ArrayLike<number> | ArrayBuffer;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/stronghold/guest-js/index.ts#L12

@tauri-apps/plugin-updater

Classes

Update

Extends

  • Resource

Constructors

new Update()
new Update(metadata): Update
Parameters
Parameter Type
metadata UpdateMetadata
Returns

Update

Overrides

Resource.constructor

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L77

Properties

Property Type Description Defined in
available boolean Deprecated This is always true, check if the return value is null instead when using check Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L69
body? string - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L73
currentVersion string - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L70
date? string - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L72
rawJson Record<string, unknown> - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L74
version string - Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L71

Accessors

rid
get rid(): number
Returns

number

Inherited from

Resource.rid

Source: undefined

Methods

close()
close(): Promise<void>

Destroys and cleans up this resource from memory. You should not call any method on this object anymore and should drop any reference to it.

Returns

Promise<void>

Overrides

Resource.close

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L138

download()
download(onEvent?, options?): Promise<void>

Download the updater package

Parameters
Parameter Type
onEvent? (progress) => void
options? DownloadOptions
Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L88

downloadAndInstall()
downloadAndInstall(onEvent?, options?): Promise<void>

Downloads the updater package and installs it

Parameters
Parameter Type
onEvent? (progress) => void
options? DownloadOptions & InstallOptions
Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L122

install()
install(options?): Promise<void>

Install downloaded updater package

Parameters
Parameter Type
options? InstallOptions
Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L106

Interfaces

CheckOptions

Options used when checking for updates

Properties

Property Type Description Defined in
allowDowngrades? boolean Allow downgrades to previous versions by not checking if the current version is greater than the available version. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L28
headers? HeadersInit Request headers Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L12
proxy? string A proxy url to be used when checking and downloading updates. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L20
target? string Target identifier for the running application. This is sent to the backend. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L24
timeout? number Timeout in milliseconds Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L16

DownloadOptions

Options used when downloading an update

Properties

Property Type Description Defined in
headers? HeadersInit Request headers Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L36
timeout? number Timeout in milliseconds Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L40

Type Aliases

DownloadEvent

type DownloadEvent: object | object | object;

Updater download event

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L61

Functions

check()

function check(options?): Promise<Update | null>

Check for updates, resolves to null if no updates are available

Parameters

Parameter Type
options? CheckOptions

Returns

Promise<Update | null>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/updater/guest-js/index.ts#L145

@tauri-apps/plugin-upload

Enumerations

HttpMethod

Enumeration Members

Patch
Patch: "PATCH";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/upload/guest-js/index.ts#L19

Post
Post: "POST";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/upload/guest-js/index.ts#L17

Put
Put: "PUT";

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/upload/guest-js/index.ts#L18

Functions

download()

function download(
   url,
   filePath,
   progressHandler?,
   headers?,
body?): Promise<void>

Parameters

Parameter Type
url string
filePath string
progressHandler? ProgressHandler
headers? Map<string, string>
body? string

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/upload/guest-js/index.ts#L53


upload()

function upload(
   url,
   filePath,
   progressHandler?,
   headers?,
method?): Promise<string>

Parameters

Parameter Type
url string
filePath string
progressHandler? ProgressHandler
headers? Map<string, string>
method? HttpMethod

Returns

Promise<string>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/upload/guest-js/index.ts#L22

@tauri-apps/plugin-websocket

Classes

default

Constructors

new default()
new default(id, listeners): default
Parameters
Parameter Type
id number
listeners Set<(arg) => void>
Returns

default

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L63

Properties

Property Type Defined in
id number Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L60

Methods

addListener()
addListener(cb): () => void
Parameters
Parameter Type
cb (arg) => void
Returns

Function

Returns

void

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L92

disconnect()
disconnect(): Promise<void>
Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L119

send()
send(message): Promise<void>
Parameters
Parameter Type
message string | number[] | Message
Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L100

connect()
static connect(url, config?): Promise<default>
Parameters
Parameter Type
url string
config? ConnectionConfig
Returns

Promise<default>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L68

Interfaces

CloseFrame

Properties

Property Type Defined in
code number Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L48
reason string Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L49

ConnectionConfig

Properties

Property Type Description Defined in
acceptUnmaskedFrames? boolean When set to true, the server will accept and handle unmasked frames from the client. According to the RFC 6455, the server must close the connection to the client in such cases, however it seems like there are some popular libraries that are sending unmasked frames, ignoring the RFC. By default this option is set to false, i.e. according to RFC 6455. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L35
headers? HeadersInit Additional connect request headers. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L39
maxFrameSize? number | "none" The maximum size of a single incoming message frame. The string “none” means no size limit. The limit is for frame payload NOT including the frame header. The default value is 16 MiB which should be reasonably big for all normal use-cases but small enough to prevent memory eating by a malicious user. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L31
maxMessageSize? number | "none" The maximum size of an incoming message. The string “none” means no size limit. The default value is 64 MiB which should be reasonably big for all normal use-cases but small enough to prevent memory eating by a malicious user. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L27
maxWriteBufferSize? number The max size of the write buffer in bytes. Setting this can provide backpressure in the case the write buffer is filling up due to write errors. The default value is unlimited. Note: The write buffer only builds up past write_buffer_size when writes to the underlying stream are failing. So the write buffer can not fill up if you are not observing write errors. Note: Should always be at least write_buffer_size + 1 message and probably a little more depending on error handling strategy. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L23
readBufferSize? number Read buffer capacity. The default value is 128 KiB. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L11
writeBufferSize? number The target minimum size of the write buffer to reach before writing the data to the underlying stream. The default value is 128 KiB. If set to 0 each message will be eagerly written to the underlying stream. It is often more optimal to allow them to buffer a little, hence the default value. Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L16

MessageKind<T, D>

Type Parameters

Type Parameter
T
D

Properties

Property Type Defined in
data D Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L44
type T Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L43

Type Aliases

Message

type Message:
  | MessageKind<"Text", string>
  | MessageKind<"Binary", number[]>
  | MessageKind<"Ping", number[]>
  | MessageKind<"Pong", number[]>
| MessageKind<"Close", CloseFrame | null>;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/websocket/guest-js/index.ts#L52

@tauri-apps/plugin-window-state

Enumerations

StateFlags

Enumeration Members

ALL
ALL: 63;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/window-state/guest-js/index.ts#L15

DECORATIONS
DECORATIONS: 16;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/window-state/guest-js/index.ts#L13

FULLSCREEN
FULLSCREEN: 32;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/window-state/guest-js/index.ts#L14

MAXIMIZED
MAXIMIZED: 4;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/window-state/guest-js/index.ts#L11

POSITION
POSITION: 2;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/window-state/guest-js/index.ts#L10

SIZE
SIZE: 1;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/window-state/guest-js/index.ts#L9

VISIBLE
VISIBLE: 8;

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/window-state/guest-js/index.ts#L12

Functions

filename()

function filename(): Promise<string>

Get the name of the file used to store window state.

Returns

Promise<string>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/window-state/guest-js/index.ts#L44


restoreState()

function restoreState(label, flags?): Promise<void>

Restore the state for the specified window from disk.

Parameters

Parameter Type
label string
flags? StateFlags

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/window-state/guest-js/index.ts#L28


restoreStateCurrent()

function restoreStateCurrent(flags?): Promise<void>

Restore the state for the current window from disk.

Parameters

Parameter Type
flags? StateFlags

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/window-state/guest-js/index.ts#L38


saveWindowState()

function saveWindowState(flags?): Promise<void>

Save the state of all open windows to disk.

Parameters

Parameter Type
flags? StateFlags

Returns

Promise<void>

Source: https://github.com/tauri-apps/plugins-workspace/blob/v2/plugins/window-state/guest-js/index.ts#L21

Webview Versions

WebView2 (Windows)

Tauri uses WebView2 which is based on Microsoft Edge and therefore Chromium. WebView2 can update itself, you are guaranteed a relatively recent chromium build on all Windows targets.

WebView2 is supported on Windows 7 and newer and comes preinstalled on Windows 11. On versions older than Windows 11 the installer generated by Tauri takes care of ensuring WebView2 is installed on the system.

Android WebView (Android)

Tauri uses the system Android WebView, which is based on Chromium. Tauri does not bundle a WebView with your app, so the runtime version depends on the devices currently selected WebView provider.

On most production Android devices, WebView is an updatable system component. Some Android images can use a different preinstalled provider or allow switching providers in developer settings, so web platform support is tied to that providers Chromium/WebView version.

To check the version used by a development build, open the Android Web Inspector and inspect the running WebView with Chrome DevTools. You can also check the selected WebView provider and app version in Androids developer settings.

WebKit (macOS, iOS, & Linux)

Tauri uses WebKit on macOS (through WKWebView) and Linux (through webkit2gtk).

Interpreting WebKit Version Numbers

Webkit version numbers are quite complicated, so below is some helpful information to understand them.

WebKit version numbers are made up of 5 segments and a numeric prefix indicating which OS WebKit is built for:

$(SYSTEM_VERSION_PREFIX)$(MAJOR_VERSION).$(MINOR_VERSION).$(TINY_VERSION).$(MICRO_VERSION).$(NANO_VERSION)

The numeric prefix is called the SYSTEM_VERSION_PREFIX and seems to be only present for macOS and iOS builds (not for Linux). Furthermore, if the last two segments are both 0 they can be omitted (so a version like 613.2.7.0.0 would be referred to as 613.2.7).

As an example, the WebKit version shipped with Safari 15.5 on macOS Monterey (12.x) has the version number 17613.2.7.1.8. You can interpret it like this:

  • SYSTEM_VERSION_PREFIX: 17
  • MAJOR_VERSION: 613
  • MINOR_VERSION: 2
  • TINY_VERSION: 7
  • MICRO_VERSION: 1
  • NANO_VERSION: 8

Here is what the SYSTEM_VERSION_PREFIX values map to:

macOS version SYSTEM_VERSION_PREFIX
sdk=iphone* 8
14.0 19
13.0 18
12.0 17
11.0 16
10.15 15
10.14 14
10.13 13
10.12 12
10.11 11

macOS & iOS

On macOS, Tauri uses the webview that comes preinstalled with macOS since version 10.10 (Yosemite). It is considered a core component and is therefore updated with the regular OS updates. This means unsupported macOS versions do not receive WebKit updates.

To find the WebKit version used by WKWebView on your version of macOS you can use this command in the terminal:

awk '/CFBundleVersion/{getline;gsub(/<[^>]*>/,"");print}' /System/Library/Frameworks/WebKit.framework/Resources/Info.plist

WebKit Versions in Safari

The table below maps an OS version to the corresponding WebKit Safari versions so that you can use sites like caniuse to figure out if a specific web platform feature is supported.

OS Name OS Version WebKit Version Safari Version Notes
Sonoma 14.0 (Beta) 616.1.14.11.11 17.0 Verified on a 2023 M2 14“ MacBook Pro
Ventura 13.4.1 615.2.9.11.7 16.5.1 Verified on a 2023 M2 14“ MacBook Pro
13.3.1 615.1.26.11.23 Verified on a 2023 M2 14“ MacBook Pro
13.3 615.1.26.11.22 16.4 Verified on a 2023 M2 14“ MacBook Pro
13.2.1 614.4.6.1.6
13.2 ? 16.3
13.1 614.3.7.1.5 16.2 Verified on a 2020 M1 13“ MacBook Pro
13.0.1 Verified on a 2020 M1 13“ MacBook Pro
13.0 614.2.9.1.12 16.1 Verified on a 2020 M1 13“ MacBook Pro
Monterey 12.6 Verified on a 2020 M1 13“ MacBook Pro
12.5.1 613.3.9.1.16 15.6.1 Verified on a 2020 M1 13“ MacBook Pro
12.5 613.3.9.1.5 15.6 Verified on a 2020 M1 13“ MacBook Pro
12.4 613.2.7.1.8 15.5 Verified on a 2020 M1 13“ MacBook Pro
12.3.1 613.1.17.1.13
12.3 613.1.17.1.6 15.4
12.2.1 612.4.9.1.8
12.2 612.4.9.1.5 15.3
12.1.1
12.1 612.3.6.1.6 15.2
12.0.1 612.2.9.1.20 15.1
12.0 612.1.29.41.4 15.0
Big Sur 11.6.7
11.6.6
11.6.5
11.6.2
11.6.1
11.6
11.5.2 611.3.10.1.6
11.5.1
11.5 611.3.10.1.3 14.1.2
11.4 611.2.7.1.4 14.1.1
11.3.1
11.3 611.1.21.161.3 14.1 24“ M1 iMac received a special WebKit version 611.1.21.1.12
11.2.3 610.4.3.1.7
11.2.2
11.2.1
11.2 610.4.3.1.4 14.0.3
11.1 610.3.7.1.9 14.0.2
11.0.1 610.2.11.51.8
11.0 610.2.11.1.3 14.0.1 Safari 14.0 was only ever available on iPhones
Catalina 10.15.7 Security Update 2022-004 609.4.1.1.1
10.15.7 609.4.1 13.1.3
10.15.6 609.3.5.1.3 13.1.2
10.15.5 609.2.9.1.2 13.1.1
10.15.4 609.1.20.111.8 13.1
10.15.3 608.5.11 13.0.5
10.15.2 608.4.9.1.3 13.0.4
10.15.1 608.3.10.1.4 13.0.3 Verified on a 2014 15“ MacBook Pro
10.15 608.2.30.1.1 13.0.2
Mojave 10.14.6 608.1.49 13.0
10.14.4 607.1.40.1.5 12.1
10.14.3 606.4.5 12.0.3
10.14.2 606.3.4 12.0.2
10.14.1 606.2.104.1.1 12.0.1
10.14 606.2.11 12.0
High Sierra 10.13.6 605.3.8 11.1.2
10.13.5 605.2.8 11.1.1
10.13.4 Security Update 2018-001 605.1.33.1.4 11.1
10.13.4 605.1.33.1.2 11.1
10.13.3 604.5.6 11.0.3
10.13.2 Supplemental Update 604.4.7.1.6 11.0.2 27“ iMac Pro received a special WebKit version 604.4.7.10.6
10.13.2 604.4.7.1.3 11.0.2 27“ iMac Pro received a special WebKit version 604.4.7.10.4
10.13.1 604.3.5 11.0.1
10.13 604.1.38.1.6 11.0

Linux

The diverse nature of the Linux ecosystem means it is very hard to compile accurate information about WebKitGTK on the various distros. The table below is a very incomplete list of the most commonly used distributions and their WebKit versions. You should always check your distros repositories for up-to-date information.

Distro webkitgtk Version WebKit Version Safari Equivalent
Debian 11 (with update), Ubuntu 20.04 (with update), Ubuntu 22.04 2.36 614.1.6 TP 140 (16.0)
Debian 10 (with update) 2.34 613.1.1 15.4
Debian 11, Ubuntu 18.04 (with update), centos 8 (non-stream) 2.32 612.1.6 15.0
Ubuntu 20.04 2.28 610.1.1 14.0
Debian 9 (with backport), Debian 10 2.24 608.1.6 13.0
Ubuntu 18.04 2.20 606.1.4 12.0

Tauri RSS Feeds

All updatesGet notified about any updates across the entire site.

Blog updatesStay up-to-date with the latest blog posts and articles.

Pages updatesReceive updates for the main website pages.

Security

High-level concepts and security features at the core of Tauri's design and ecosystem that make you, your applications and your users more secure by default

This page is designed to explain the high-level concepts and security features at the core of Tauris design and ecosystem that make you, your applications and your users more secure by default.

It also includes advice on best practices, how to report vulnerabilities to us and references to detailed concept explanations.

Note

It is important to remember that the security of your Tauri application is the sum of the overall security of Tauri itself, all Rust and npm dependencies, your code, and the devices that run the final application. The Tauri team does its best to do their part, the security community does its part and you should also follow some important best practices.

Trust Boundaries

Trust boundary is a term used in computer science and security which describes a boundary where program data or execution changes its level of “trust,” or where two principals with different capabilities exchange data or commands. 1

Tauris security model differentiates between Rust code written for the applications core and frontend code written in any framework or language understood by the system WebView.

Inspecting and strongly defining all data passed between boundaries is very important to prevent trust boundary violations. If data is passed without access control between these boundaries then its easy for attackers to elevate and abuse privileges.

The IPC layer is the bridge for communication between these two trust groups and ensures that boundaries are not broken.

IPC Diagram

Any code executed by the plugins or the application core has full access to all available system resources and is not constrained.

Any code executed in the WebView has only access to exposed system resources via the well-defined IPC layer. Access to core application commands is configured and restricted by capabilities defined in the application configuration. The individual command implementations enforce the optional fine-grained access levels also defined in the capabilities configuration.

Learn more about the individual components and boundary enforcement:

Permissions

Scopes

Capabilities

Runtime Authority

Tauri allows developers to choose their own frontend stack and framework. This means that we cannot provide a hardening guide for every frontend stack of of choice, but Tauri provides generic features to control and contain the attack surface.

Content Security Policy (CSP)

Isolation Pattern

(Not) Bundling WebViews

Tauris approach is to rely on the operating system WebView and not bundling the WebView into the application binary.

This has a multitude of reasons but from a security perspective the most important reason is the average time it takes from publication of a security patched version of a WebView to being rolled out to the application end user.

IPC Diagram

We have observed that WebView packet maintainer and operating system packet maintainers are in average significantly faster to patch and roll out security patched Webview releases than application developers who bundle the WebView directly with their application.

There are exceptions from this observation and in theory both paths can be taken in a similar time frame but this involves a larger overhead infrastructure for each application.

Bundling has its drawbacks from a Tauri application developer experience and we do not think it is inherently insecure but the current design is a trade off that significantly reduces known vulnerabilities in the wild.

Ecosystem

The Tauri organization provides and maintains more than just the Tauri repository, and to ensure we provide a reasonable secure multi platform application framework, we make sure to go some extra miles.

To learn more about how we secure our development process, what you could adapt and implement, what known threats your application can face and what we plan to improve or harden in the future, you can check out the following documents:

Ecosystem Security

Application Lifecycle Threats

Future Work

Coordinated Disclosure

If you feel that there is a security concern or issue with anything in Tauri or other repositories in our organization, please do not publicly comment on your findings. Instead, reach out directly to our security team.

The preferred disclosure method is via Github Vulnerability Disclosure on the affected repository. Most of our repositories have this feature enabled but if in doubt please submit via the Tauri repository.

Alternatively you can contact us via email at: security@tauri.app.

Although we do not currently have a budget for security bounties, in some cases, we will consider rewarding coordinated disclosure with our limited resources.

Footnotes

  1. https://en.wikipedia.org/wiki/Trust_boundary.

Asset protocol scope

Configure app.security.assetProtocol so the WebView can load local files safely, including FsScope, requireLiteralLeadingDot, and dynamic paths.

Tauri can serve files from disk into the WebView through the asset custom protocol (for example when you use convertFileSrc in the frontend). Whether a path is allowed is controlled by app.security.assetProtocol in tauri.conf.json.

You must set enable to true and define a scope that lists which filesystem paths may be exposed. Paths resolved at runtime must match that scope, or the WebView will refuse the load (often with an error such as “asset protocol not configured to allow the path”).

Content Security Policy for asset: sources is documented on the Content Security Policy (CSP) page. This page focuses on scope and how it interacts with globs and hidden path segments.

How scope is defined

assetProtocol.scope uses the same FsScope type as filesystem-related configuration elsewhere: either a JSON array of allowed glob patterns, or a JSON object with allow, optional deny, and optional requireLiteralLeadingDot. For how “scopes” fit into Tauris security model more broadly, see Command scopes.

Patterns may start with a base directory variable (for example $HOME, $CACHE, $APPCACHE, $APPDATA, $RESOURCE). See the path / base directory APIs for the full set of variables your app can rely on.

Paths resolved when loading assets are usually absolute (on Linux, often under /home/...). A pattern like ["*/**"] typically does not match those paths, because it does not line up with a leading / or a base-directory variable. Prefer patterns such as $HOME/**/*, /home/username/**/*, or another form that mirrors the resolved path.

Array form (allowed paths only)

Use a list when you only need a fixed allow list and default glob behavior is enough:

src-tauri/tauri.conf.json

{
  "app": {
    "security": {
      "assetProtocol": {
        "enable": true,
        "scope": ["$APPCACHE/**/*", "$RESOURCE/**/*"]
      }
    }
  }
}

With the array form you cannot set requireLiteralLeadingDot; for that, use the object form below.

Object form (allow, deny, requireLiteralLeadingDot)

Use an object when you need deny rules or to change leading-dot matching:

src-tauri/tauri.conf.json

{
  "app": {
    "security": {
      "assetProtocol": {
        "enable": true,
        "scope": {
          "allow": ["$APPCACHE/**/*"],
          "deny": ["$APPCACHE/**/secrets/**"]
        }
      }
    }
  }
}

deny takes precedence over allow when both match.

Unix: path segments starting with .

On Unix, requireLiteralLeadingDot defaults to true. Then wildcard tokens such as *, ?, **, and [...] do not match a path component that starts with . (dotfiles and dot-directories such as .cache or .ssh).

So a pattern like $HOME/** can allow /home/user/Documents/file.png but not /home/user/.cache/myapp/preview.png, because .cache is a dot-prefixed component. A pattern that names the segment literally (for example $HOME/.cache/myapp/**) does match.

To allow dot-prefixed components under a broad glob, you can set requireLiteralLeadingDot to false on the object scope (this widens what the WebView can load; review carefully):

src-tauri/tauri.conf.json

{
  "app": {
    "security": {
      "assetProtocol": {
        "enable": true,
        "scope": {
          "requireLiteralLeadingDot": false,
          "allow": ["$HOME/**/*"]
        }
      }
    }
  }
}

Still blocked on Linux-style paths?

Community members often hit this when a path goes through a dot-directory (for example ~/.cache/...) while the allow pattern only uses ** under $HOME. See the discussion in tauri#13788 for concrete examples and fixes.

Prefer **/* over bare ** for “all files under here”

For globs that should match files under a tree, prefer **/* (and variants like $DIR/**/*) rather than bare **, consistent with other Tauri path examples. Bare ** is easy to misuse when you intend “everything under this directory recursively.”

Highly permissive configuration (use with extreme care)

If you intentionally need the broadest possible access and dot-prefixed segments, a maintainer-suggested shape looks like this. This is not a default recommendation; it increases exposure of hidden and sensitive files.

src-tauri/tauri.conf.json

{
  "app": {
    "security": {
      "assetProtocol": {
        "enable": true,
        "scope": {
          "requireLiteralLeadingDot": false,
          "allow": ["**/*"]
        }
      }
    }
  }
}

Caution

Prefer narrow directories ($APPCACHE, $RESOURCE, a single app subfolder under $HOME, etc.) instead of broad $HOME/**/* or **/* unless you have a strong reason and understand the security tradeoffs.

Static config vs dynamically chosen paths

Entries in tauri.conf.json describe static allow/deny patterns. They do not replace runtime workflows where the user picks arbitrary folders or files (for example with the dialog plugin): those paths may need to be persisted across restarts using the persisted-scope plugin.

To persist asset / protocol-related scope with that plugin, enable its protocol-asset Cargo feature in src-tauri/Cargo.toml, for example:

tauri-plugin-persisted-scope = { version = "2", features = ["protocol-asset"] }

Register tauri_plugin_fs before tauri_plugin_persisted_scope as described in the plugin guide.

Troubleshooting

Symptom Things to check
“asset protocol not configured to allow the path” Path must match an allow pattern; deny overrides allow. Use absolute patterns or $VAR/$HOME style variables that match how the path is resolved on disk.
Works for normal folders but not under .cache / .config On Unix, default requireLiteralLeadingDot behavior: use a literal .segment in the pattern, or set requireLiteralLeadingDot: false in the object scope (see tauri#13788).
User picked a folder at runtime; still blocked after restart You may need persisted-scope with the protocol-asset feature, not only tauri.conf.json entries.
Broad ** seems wrong Try **/* for file-oriented globs; see Embedding Additional Files for similar ** vs **/* guidance in bundle resources.
Scope like ["*/**"] never matches on Linux Resolved paths are absolute; use $... variables, a leading /, or another pattern that matches the real path (see above).

The authoritative Rust types for assetProtocol and FsScope live in Tauris config.rs (AssetProtocolConfig, FsScope). The generated configuration reference may render nested FsScope fields in a compact or hard-to-read way; if something looks unclear there, cross-check this page and the file system plugin requireLiteralLeadingDot section (plugin config uses the same option name for its own scopes). If the reference still does not document those fields clearly, consider opening an issue on the tauri-docs repository so the config generator can be improved.

Capabilities

Tauri provides application and plugin developers with a capabilities system, to granually enable and constrain the core exposure to the application frontend running in the system WebView.

Capabilities define which permissions are granted or denied for which windows or webviews.

Capabilities can affect multiple windows and webviews and these can be referenced in multiple capabilities.

Security Tip

Windows and WebViews which are part of more than one capability effectively merge the security boundaries and permissions of all involved capabilities.

Capability files are either defined as a JSON or a TOML file inside the src-tauri/capabilities directory.

It is good practice to use individual files and only reference them by identifier in the tauri.conf.json but it is also possible to define them directly in the capabilities field.

All capabilities inside the capabilities directory are automatically enabled by default. Once capabilities are explicitly enabled in the tauri.conf.json, only these are used in the application build.

For a full reference of the configuration scheme please see the references section.

The following example JSON defines a capability that allows the main window use the default functionality of core plugins and the window.setTitle API.

src-tauri/capabilities/default.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "main-capability",
  "description": "Capability for the main window",
  "windows": ["main"],
  "permissions": [
    "core:path:default",
    "core:event:default",
    "core:window:default",
    "core:app:default",
    "core:resources:default",
    "core:menu:default",
    "core:tray:default",
    "core:window:allow-set-title"
  ]
}

These snippets are part of the Tauri configuration file.

This is likely the most common configuration method, where the individual capabilities are inlined and only permissions are referenced by identifier.

This requires well defined capability files in the capabilities directory.

src-tauri/tauri.conf.json

{
  "app": {
    "security": {
      "capabilities": ["my-capability", "main-capability"]
    }
  }
}

Inline capabilities can be mixed with pre-defined capabilities.

src-tauri/tauri.conf.json

{
  "app": {
    "security": {
      "capabilities": [
        {
          "identifier": "my-capability",
          "description": "My application capability used for all windows",
          "windows": ["*"],
          "permissions": ["fs:default", "allow-home-read-extended"]
        },
        "my-second-capability"
      ]
    }
  }
}

By default, all commands that you registered in your app (using the tauri::Builder::invoke_handler function) are allowed to be used by all the windows and webviews of the app. To change that, consider using AppManifest::commands.

src-tauri/build.rs

fn main() {
    tauri_build::try_build(
        tauri_build::Attributes::new()
            .app_manifest(tauri_build::AppManifest::new().commands(&["your_command"])),
    )
    .unwrap();
}

Target Platform

Capabilities can be platform-specific by defining the platforms array. By default the capability is applied to all targets, but you can select a subset of the linux, macOS, windows, iOS and android targets.

For example a capability for desktop operating systems. Note it enables permissions on plugins that are only available on desktop:

src-tauri/capabilities/desktop.json

{
  "$schema": "../gen/schemas/desktop-schema.json",
  "identifier": "desktop-capability",
  "windows": ["main"],
  "platforms": ["linux", "macOS", "windows"],
  "permissions": ["global-shortcut:allow-register"]
}

And another example of a capability for mobile. Note it enables permissions on plugins that are only available on mobile:

src-tauri/capabilities/mobile.json

{
  "$schema": "../gen/schemas/mobile-schema.json",
  "identifier": "mobile-capability",
  "windows": ["main"],
  "platforms": ["iOS", "android"],
  "permissions": [
    "nfc:allow-scan",
    "biometric:allow-authenticate",
    "barcode-scanner:allow-scan"
  ]
}

Remote API Access

By default the API is only accessible to bundled code shipped with the Tauri App. To allow remote sources access to certain Tauri Commands it is possible to define this in the capability configuration file.

This example would allow to scan for NFC tags and to use the barcode scanner from all subdomains of tauri.app.

src-tauri/capabilities/remote-tags.json

{
  "$schema": "../gen/schemas/remote-schema.json",
  "identifier": "remote-tag-capability",
  "windows": ["main"],
  "remote": {
    "urls": ["https://*.tauri.app"]
  },
  "platforms": ["iOS", "android"],
  "permissions": ["nfc:allow-scan", "barcode-scanner:allow-scan"]
}

Caution

On Linux and Android, Tauri is unable to distinguish between requests from an embedded <iframe> and the window itself.

Please consider usage of this feature very carefully and read more into the specific security implications for your targeted operating system in the reference section of this feature.

Security Boundaries

What does it protect against?

Depending on the permissions and capabilities it is able to:

  • Minimize impact of frontend compromise
  • Prevent or reduce (accidential) exposure of local system interfaces and data
  • Prevent or reduce possible privilege escalation from frontend to backend/system

What does it not protect against?

  • Malicious or insecure Rust code
  • Too lax scopes and configuration
  • Incorrect scope checks in the command implementation
  • Intentional bypasses from Rust code
  • Basically anything which was written in the rust core of an application
  • 0-days or unpatched 1-days in the system WebView
  • Supply chain attacks or otherwise compromised developer systems

Security Tip

The security boundaries are depending on window labels (not titles). We recommend to only expose of the window creation functionality to higher privileged windows.

Schema Files

Tauri generates JSON schemas with all the permissions available to your application through tauri-build, allowing autocompletion in your IDE. To use a schema, set the $schema property in your configuration file (either .json or .toml) to one of the platform-specific schemas located in the gen/schemas directory. Usually you will set it to ../gen/schemas/desktop-schema.json or ../gen/schemas/mobile-schema.json though you can also define a capability for a specific target platform.

Configuration Files

Simplified example of an example Tauri application directory structure:

tauri-app
├── index.html
├── package.json
├── src/
├── src-tauri/
│   ├── Cargo.toml
│   ├── capabilities/
│   │  └── <identifier>.json/toml
│   ├── src/
│   ├── tauri.conf.json

Everything can be inlined into the tauri.conf.json but even a little more advanced configuration would bloat this file and the goal of this approach is that the permissions are abstracted away whenever possible and simple to understand.

Core Permissions

A list of all core permissions can be found on the Core Permissions page.

Content Security Policy (CSP)

Tauri restricts the Content Security Policy (CSP) of your HTML pages. This can be used to reduce or prevent impact of common web based vulnerabilities like cross-site-scripting (XSS).

Local scripts are hashed, styles and external scripts are referenced using a cryptographic nonce, which prevents unallowed content from being loaded.

Caution

Avoid loading remote content such as scripts served over a CDN as they introduce an attack vector. In general any untrusted file can introduce new and subtle attack vectors.

The CSP protection is only enabled if set on the Tauri configuration file. You should make it as restricted as possible, only allowing the webview to load assets from hosts you trust, and preferably own. At compile time, Tauri appends its nonces and hashes to the relevant CSP attributes automatically to bundled code and assets, so you only need to worry about what is unique to your application.

This is an example CSP configuration taken from the api example of Tauri, but every application developer needs to tailor this to their own application needs.

tauri/examples/api/src-tauri/tauri.conf.json

  "csp": {
        "default-src": "'self' customprotocol: asset:",
        "connect-src": "ipc: http://ipc.localhost",
        "font-src": ["https://fonts.gstatic.com"],
        "img-src": "'self' asset: http://asset.localhost blob: data:",
        "style-src": "'unsafe-inline' 'self' https://fonts.googleapis.com"
      },

Tip

When using Rust to develop your frontend, or if your frontend otherwise uses WebAssembly, remember to include 'wasm-unsafe-eval' as a script-src.

See script-src, style-src and CSP Sources for more information about this protection.

Tauri Ecosystem Security

Our Tauri organization ecosystem is hosted on GitHub and facilitates several features to make our repositories more resilient against adversaries targeting our source code and releases.

To reduce risk and to comply with commonly adopted best practices we have the following methods in place.

Build Pipelines

The process of releasing our source-code artifacts is highly automated in GitHub build pipelines using GitHub actions, yet mandates kickoff and review from real humans.

Signed Commits

Our core repositores require signed commits to reduce risk of impersonation and to allow identification of attributed commits after detection of possible compromise.

Code Review

All Pull Requests (PRs) merged into our repositories need approval from at least one maintainer of the project, which in most cases is the working group. Code is generally reviewed in PRs and default security workflows and checks are run to ensure the code adheres to common standards.

Release Process

Our working group reviews code changes, tags PRs with scope, and makes sure that everything stays up to date. We strive to internally audit all security relevant PRs before publishing minor and major releases.

And when its time to publish a new version, one of the maintainers tags a new release on dev, which:

  • Validates core
  • Runs tests
  • Audits security for crates and npm
  • Generates changelogs
  • Creates artifacts
  • Creates a draft release

Then the maintainer reviews the release notes, edits if necessary, and a new release is forged.

Future Work

This section describes topics we started or would like to tackle in the future to make Tauri apps even more secure. If you feel interested in these topics or have pre-existing knowledge we are always happy to welcome new contributors and advice via GitHub or other community platforms like Discord.

Binary Analysis

To allow pentesters, auditors and automated security checks do to their job properly it is very valuable to provide insight even from compiled binaries. Not all companies are open source or provide source code for audits, red-teams and other security testing.

Another often overlooked point is that providing inbuilt metadata empowers users of your application to audit their systems for known vulnerabilities at scale without dedicating their lifetime and efforts into it.

If your threatmodel depends on security by obscurity this section will be providing some tools and points which hopefully will make you reconsider.

For Rust there is cargo-auditable to create SBOMs and provide exact crate versions and dependencies of a binary without breaking reproducible builds.

For the frontend stack we are not aware of similar solutions, so extracting the frontend assets from the binary should be a straightforward process. Afterwards it should be possible to use tooling like npm audit or similar. There are already blog posts about the process but no simple tooling is available.

We are planning to provide such tooling or make it easier to extract assets, when compiling a Tauri app with certain features.

To use pentesting tools like Burpsuite, Zap or Caido it is necessary to intercept traffic from the webview and pass it through the testing proxy. Currently Tauri has no inbuilt method to do so but there is ongoing work to ease this process.

All of these tools allow to properly test and inspect Tauri applications without source code access and should be considered when building a Tauri application.

We are planning to further support and implement related features in the future.

WebView Hardening

In Tauris current threat model and boundaries we are not able to add more security constraints to the WebView itself and since it is the biggest part of our stack which is written in an memory unsafe language, we are planning to research and consider ways to further sandbox and isolate the webview processes.

Inbuilt and external sandboxing methods will be evaluated to reduce attack impact and to enforce the IPC bridge for system access. We believe that this part of our stack is the weak link but current generation WebViews are improving in their hardening and exploit resilience.

Fuzzing

To allow more efficient and simplify the process of fuzzing Tauri applications we aim to further implement our mock runtimes and other tooling to make it easier to configure and build for individual Tauri applications.

Tauri is supporting a multitude of Operating Systems and CPU architectures, usually apps have only few or no possible memory unsafe code. No pre-existing fuzzing tooling and libraries support these uncommon fuzzing use case, so we need to implement it and support existing libraries like libAFL to build Tauri fuzzing frameworks.

The goal is to make fuzzing accessible and efficient for Tauri application developers.

HTTP Headers

Since 2.1.0

A header defined in the configuration gets sent along the responses to the webview. This doesnt include IPC messages and error responses. To be more specific, every response sent via the get_response function in crates/tauri/src/protocol/tauri.rs ↗ will include those headers.

Header Names

The header names are limited to:

Note

Tauri-Custom-Header is not intended for production use.

Note

The Content-Security-Policy (CSP) is not defined here.

How to Configure Headers

  • with a string
  • with an array of strings
  • with an object/key-value, where the values must be strings
  • with null

The header values are always converted to strings for the actual response. Depending on how the configuration file looks, some header values need to be composed. Those are the rules on how a composite gets created:

  • string: stays the same for the resulting header value
  • array: items are joined by , for the resulting header value
  • key-value: items are composed from: key + space + value. Items are then joined by ; for the resulting header value
  • null: header will be ignored

Example

src-tauri/tauri.conf.json

{
 //...
  "app":{
    //...
    "security": {
      //...
      "headers": {
        "Cross-Origin-Opener-Policy": "same-origin",
        "Cross-Origin-Embedder-Policy": "require-corp",
        "Timing-Allow-Origin": [
          "https://developer.mozilla.org",
          "https://example.com",
        ],
        "X-Content-Type-Options": null, // gets ignored
        "Access-Control-Expose-Headers": "Tauri-Custom-Header",
        "Tauri-Custom-Header": {
          "key1": "'value1' 'value2'",
          "key2": "'value3'"
        }
      },
      // notice how the CSP is not defined under headers
      "csp": "default-src 'self'; connect-src ipc: http://ipc.localhost",
    }
  }
}

Note

Tauri-Custom-Header is not intended for production use. For Tests: Remember to set Access-Control-Expose-Headers accordingly.

In this example Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy are set to allow for the use of SharedArrayBuffer ↗. Timing-Allow-Origin grants scripts loaded from the listed websites to access detailed network timing data via the Resource Timing API ↗.

For the helloworld example, this config results in:

access-control-allow-origin:  http://tauri.localhost
access-control-expose-headers: Tauri-Custom-Header
content-security-policy: default-src 'self'; connect-src ipc: http://ipc.localhost; script-src 'self' 'sha256-Wjjrs6qinmnr+tOry8x8PPwI77eGpUFR3EEGZktjJNs='
content-type: text/html
cross-origin-embedder-policy: require-corp
cross-origin-opener-policy: same-origin
tauri-custom-header: key1 'value1' 'value2'; key2 'value3'
timing-allow-origin: https://developer.mozilla.org, https://example.com

Frameworks

Some development environments require extra settings, to emulate the production environment.

Note

In order to get headers to work for these frameworks, you may need to define them in both the frameworks configuration (for development mode) and the Tauri config (for build mode). This is because:

  • The frameworks wont include headers defined in their config files at build time.
  • Tauri cant inject headers into the frameworks dev server it can only inject headers to the final build output.

JavaScript/TypeScript

For setups running the build tool Vite (those include Qwik, React, Solid, Svelte, and Vue) add the wanted headers to vite.config.ts.

vite.config.ts

import { defineConfig } from 'vite';


export default defineConfig({
  // ...
  server: {
      // ...
      headers: {
        'Cross-Origin-Opener-Policy': 'same-origin',
        'Cross-Origin-Embedder-Policy': 'require-corp',
        'Timing-Allow-Origin': 'https://developer.mozilla.org, https://example.com',
        'Access-Control-Expose-Headers': 'Tauri-Custom-Header',
        'Tauri-Custom-Header': "key1 'value1' 'value2'; key2 'value3'"
      },
    },
})

Sometimes the vite.config.ts is integrated into the frameworks configuration file, but the setup stays the same. In case of Angular add them to angular.json.

angular.json

{
  //...
  "projects":{
    //...
    "insert-project-name":{
      //...
      "architect":{
        //...
        "serve":{
          //...
          "options":{
            //...
            "headers":{
              "Cross-Origin-Opener-Policy": "same-origin",
              "Cross-Origin-Embedder-Policy": "require-corp",
              "Timing-Allow-Origin": "https://developer.mozilla.org, https://example.com",
              "Access-Control-Expose-Headers": "Tauri-Custom-Header",
              "Tauri-Custom-Header": "key1 'value1' 'value2'; key2 'value3'"
            }
          }
        }
      }
    }
  }
}

And in case of Nuxt to nuxt.config.ts.

nuxt.config.ts

export default defineNuxtConfig({
  //...
  vite: {
    //...
    server: {
      //...
      headers:{
        'Cross-Origin-Opener-Policy': 'same-origin',
        'Cross-Origin-Embedder-Policy': 'require-corp',
        'Timing-Allow-Origin': 'https://developer.mozilla.org, https://example.com',
        'Access-Control-Expose-Headers': 'Tauri-Custom-Header',
        'Tauri-Custom-Header': "key1 'value1' 'value2'; key2 'value3'"
      }
    },
  },
});

Next.js doesnt rely on Vite, so the approach is different. Read more about it here ↗. The headers are defined in next.config.js.

next.config.js

module.exports = {
  //...
  async headers() {
    return [
      {
        source: '/*',
        headers: [
          {
            key: 'Cross-Origin-Opener-Policy',
            value: 'same-origin',
          },
          {
            key: 'Cross-Origin-Embedder-Policy',
            value: 'require-corp',
          },
          {
            key: 'Timing-Allow-Origin',
            value: 'https://developer.mozilla.org, https://example.com',
          },
          {
            key: 'Access-Control-Expose-Headers',
            value: 'Tauri-Custom-Header',
          },
          {
            key: 'Tauri-Custom-Header',
            value: "key1 'value1' 'value2'; key2 'value3'",
          },
        ],
      },
    ]
  },
}

Rust

For Yew and Leptos add the headers to Trunk.toml

Trunk.toml

#...
[serve]
#...
headers = {
  "Cross-Origin-Opener-Policy" = "same-origin",
  "Cross-Origin-Embedder-Policy" = "require-corp",
  "Timing-Allow-Origin" = "https://developer.mozilla.org, https://example.com",
  "Access-Control-Expose-Headers" = "Tauri-Custom-Header",
  "Tauri-Custom-Header" = "key1 'value1' 'value2'; key2 'value3'"
}

Application Lifecycle Threats

Tauri applications are composed of many pieces at different points in time of the application lifecycle. Here we describe classical threats and what you SHOULD do about them.

All of these distinct steps are described in the following sections.

Threat Stages During Development

Note

The weakest link in your application lifecycle essentially defines your security. Each step can compromise the assumptions and integrity of all subsequent steps, so it is important to see the whole picture at all times.

Upstream Threats

Tauri is a direct dependency on your project, and we maintain strict authorial control of commits, reviews, pull requests, and releases. We do our best to maintain up-to-date dependencies and take action to either update or fork and fix. Other projects may not be so well maintained, and may not even have ever been audited.

Please consider their health when integrating them, otherwise, you may have adopted architectural debt without even knowing it.

Keep Your Applications Up-To-Date

When releasing your app into the wild, you are also shipping a bundle that has Tauri in it. Vulnerabilities affecting Tauri may impact the security of your application. By updating Tauri to the latest version, you ensure that critical vulnerabilities are already patched and cannot be exploited in your application. Also be sure to keep your compiler (rustc) and transpilers (nodejs) up to date, because there are often security issues that are resolved. This also is true for your development system in general.

Evaluate Your Dependencies

While NPM and Crates.io provide many convenient packages, it is your responsibility to choose trustworthy third-party libraries - or rewrite them in Rust. If you do use outdated libraries which are affected by known vulnerabilities or are unmaintained, your application security and good nights sleep could be in jeopardy.

Use tooling like npm audit and cargo audit to automate this process, and lean on the security communitys important work.

Recent trends in the rust ecosystem like cargo-vet or cargo crev can help to further reduce likelihood of supply chain attacks. To find out on whose shoulders you stand, you can use the cargo supply chain tool.

One practice that we highly recommend, is to only ever consume critical dependencies from git using hash revisions at best or named tags as second best. This holds for Rust as well as the Node ecosystem.

Development Threats

We assume that you, the developer, care for your development environment. It is on you to make sure that your operating system, build toolchains, and associated dependencies are kept up to date and reasonable secured.

A genuine risk all of us face is what is known as “supply-chain attacks”, which are usually considered to be attacks on direct dependencies of your project. However, a growing class of attacks in the wild directly target development machines, and you would be well off to address this head-on.

Development Server

Tauri application frontends can be developed using a number of web frameworks. Each of these frameworks usually ship their own development server, which is exposing the frontend assets via an open port to the local system or network. This allows the frontend to be hot-reloaded and debugged in the WebView or Browser.

In practice this connection is often neither encrypted nor authenticated by default. This is also the case for the built-in Tauri development server and exposes your frontend and assets to the local network. Additionally, this allows attackers to push their own frontend code to development devices in the same network as the attacker. Depending on what kind of functionality is exposed this could lead to device compromise in the worst case.

You should only develop on trusted networks where you can safely expose your development device. If this is not possible you MUST ensure that your development server uses mutual authentication and encryption (e.g. mTLS) for connections with your development devices.

Note

The built-in Tauri development server does not support mutual authentication and transport encryption at the moment and should not be used on untrusted networks.

Harden Development machines

Hardening your development systems depends on various factors and on your personal threat model but some generic advice we recommend to follow:

  • Never use administrative accounts for day to day tasks like coding
  • Never use production secrets on development machines
  • Prevent secrets to be checked into source code version control
  • Use security hardware tokens or similar to reduce impact of compromised systems
  • Keep your system up to date
  • Keep your installed applications to a minimum

A more practical collection of procedures can be found in an awesome security hardening collection.

You can of course virtualise your development environment to keep attackers at bay, but this wont protect you from attacks that target your project rather than just your machine.

Ensure Source Control Authentication and Authorization

If you are working like the majority of developers, using source code version control tools and service providers is an essential step during development.

To ensure that your source code can not be modified by unauthorized actors it is important to understand and correctly set up up access control for your source code version control system.

Also, consider requiring all (regular) contributors to sign their commits to prevent situations where malicious commits are attributed to non-compromised or non-maliocious contributors.

Buildtime Threats

Modern organizations use CI/CD to manufacture binary artifacts.

You need to be able to fully trust these remote (and third party owned) systems, as they have access to source code, secrets and are able to modify builds without you being able to verifiably prove that the produced binaries are the same as your local code. This means either you trust a reputable provider or host these systems on your own and controlled hardware.

At Tauri, we provide a GitHub Workflow for building on multiple platforms. If you create your own CI/CD and depend on third-party tooling, be wary of actions whose versions you have not explicitly pinned.

You should sign your binaries for the platform you are shipping to. While this can be complicated and somewhat costly to set up, end users expect that your app is verifiably from you.

If cryptographic secrets are properly stored on hardware tokens, a compromised build system wont be able to leak involved signing keys, but could use them to sign malicious releases.

Reproducible Builds

To combat backdoor injection at build time, you need your builds to be reproducible, so that you can verify that the build assets are exactly the same when you build them locally or on another independent provider.

The first problem is that Rust is by default not fully reliably producing reproducible builds. It supports this in theory, but there are still bugs, and it recently broke on a release.

You can keep track of the current state in the rust projects public bug tracker.

The next problem you will encounter is that many common frontend bundlers do not produce reproducible output either, so the bundled assets may also break reproducible builds.

This means that you cannot fully rely on reproducible builds by default, and sadly need to fully trust your build systems.

Distribution Threats

We have done our best to make shipping hot updates to the app as straightforward and secure as possible. However, all bets are off if you lose control of the manifest server, the build server, or the binary hosting service.

If you build your own system, consult a professional OPS architect and build it properly.

If you are looking for another trusted distribution solution for Tauri apps our partner CrabNebula has an offering: https://crabnebula.dev/cloud

Runtime Threats

We assume the webview is insecure, which has led Tauri to implement several protections regarding webview access to system APIs in the context of loading untrusted userland content.

Using the Content Security Policy will lockdown types of communication that the Webview can undertake. Furthermore, Capabilities can prevent untrusted content or scripts from accessing the API within the Webview.

We also recommend to setup an easy and secure way to report vulnerabilities similar to our process.

Permissions

Permissions are descriptions of explicit privileges of commands.

[[permission]]
identifier = "my-identifier"
description = "This describes the impact and more."
commands.allow = [
    "read_file"
]


[[permission.scope.allow]]
my-scope = "$HOME/*"


[[permission.scope.deny]]
my-scope = "$HOME/secret"

It can enable commands to be accessible in the frontend of a Tauri application. It can map scopes to commands and defines which commands are enabled. Permissions can enable or deny certain commands, define scopes or combine both.

To grant or deny a permission to your apps window or webview, you must reference the permission in a capability.

Permissions can be grouped as a set under a new identifier. This is called a permission set. This allows you to combine scope related permissions with command related permissions. It also allows to group or bundle operating specific permissions into more usable sets.

As a plugin developer you can ship multiple, pre-defined, well named permissions for all of your exposed commands.

As an application developer you can extend existing plugin permissions or define them for your own commands. They can be grouped or extended in a set to be re-used or to simplify the main configuration files later.

Permission Identifier

The permissions identifier is used to ensure that permissions can be re-used and have unique names.

Tip

With name we refer to the plugin crate name without the tauri-plugin- prefix. This is meant as namespacing to reduce likelihood of naming conflicts. When referencing permissions of the application itself it is not necessary.

  • <name>:default Indicates the permission is the default for a plugin or application
  • <name>:<command-name> Indicates the permission is for an individual command

The plugin prefix tauri-plugin- will be automatically prepended to the identifier of plugins at compile time and is not required to be manually specified.

Identifiers are limited to ASCII lower case alphabetic characters [a-z] and the maximum length of the identifier is currently limited to 116 due to the following constants:

const IDENTIFIER_SEPARATOR: u8 = b':';
const PLUGIN_PREFIX: &str = "tauri-plugin-";


// https://doc.rust-lang.org/cargo/reference/manifest.html#the-name-field
const MAX_LEN_PREFIX: usize = 64 - PLUGIN_PREFIX.len();
const MAX_LEN_BASE: usize = 64;
const MAX_LEN_IDENTIFIER: usize = MAX_LEN_PREFIX + 1 + MAX_LEN_BASE;

Configuration Files

Simplified example of an example Tauri plugin directory structure:

tauri-plugin
├── README.md
├── src
│  └── lib.rs
├── build.rs
├── Cargo.toml
├── permissions
│  └── <identifier>.json/toml
│  └── default.json/toml

The default permission is handled in a special way, as it is automatically added to the application configuration, as long as the Tauri CLI is used to add plugins to a Tauri application.

For application developers the structure is similar:

tauri-app
├── index.html
├── package.json
├── src
├── src-tauri
│   ├── Cargo.toml
│   ├── permissions
│      └── <identifier>.toml
|   ├── capabilities
│      └── <identifier>.json/.toml
│   ├── src
│   ├── tauri.conf.json

Note

As an application developer the capability files can be written in json/json5 or toml, whereas permissions only can be defined in toml.

Examples

Example permissions from the File System plugin.

plugins/fs/permissions/autogenerated/base-directories/home.toml

[[permission]]
identifier = "scope-home"
description = """This scope permits access to all files and
list content of top level directories in the `$HOME`folder."""


[[permission.scope.allow]]
path = "$HOME/*"

plugins/fs/permissions/read-files.toml

[[permission]]
identifier = "read-files"
description = """This enables all file read related
commands without any pre-configured accessible paths."""
commands.allow = [
    "read_file",
    "read",
    "open",
    "read_text_file",
    "read_text_file_lines",
    "read_text_file_lines_next"
]

plugins/fs/permissions/autogenerated/commands/mkdir.toml

[[permission]]
identifier = "allow-mkdir"
description = "This enables the mkdir command."
commands.allow = [
    "mkdir"
]

Example implementation extending above plugin permissions in your app:

my-app/src-tauri/permissions/home-read-extends.toml

[[set]]
identifier = "allow-home-read-extended"
description = """ This allows non-recursive read access to files and to create directories
in the `$HOME` folder.
"""
permissions = [
    "fs:read-files",
    "fs:scope-home",
    "fs:allow-mkdir"
]

Runtime Authority

The runtime authority is part of the Tauri Core. It holds all permissions, capabilities and scopes at runtime to enforce which window can access which command and passes scopes to commands.

Whenever a Tauri command is invoked from the webview the runtime authority receives the invoke request, makes sure that the origin is allowed to actually use the requested command, checks if the origin is part of capabilities and if scopes are defined for the command and applicable then they are injected into the invoke request, which is then passed to the proper Tauri command.

If the origin is not allowed to call the command, the runtime authority will deny the request and the Tauri command is never invoked.

IPC Diagram

Command Scopes

A scope is a granular way to define (dis)allowed behavior of a Tauri command.

Scopes are categorized into allow or deny scopes, where deny always supersedes the allow scope.

The scope type needs be of any serde serializable type. These types are plugin-specific in general. For scoped commands implemented in a Tauri application the scope type needs to be defined in the application and then enforced in the command implementation.

For instance, the Fs plugin allows you to use scopes to allow or deny certain directories and files and the http plugin uses scopes to filter URLs that are allowed to be reached.

The scope is passed to the command and handling or properly enforcing is implemented by the command itself.

Caution

Command developers need to ensure that there are no scope bypasses possible. The scope validation implementation should be audited to ensure correctness.

Examples

These examples are taken from the Fs plugin permissions:

The scope type in this plugin for all commands is a string, which contains a glob compatible path.

plugins/fs/permissions/autogenerated/base-directories/applocaldata.toml

[[permission]]
identifier = "scope-applocaldata-recursive"
description = '''
This scope recursive access to the complete `$APPLOCALDATA` folder,
including sub directories and files.
'''


[[permission.scope.allow]]
path = "$APPLOCALDATA/**"

plugins/fs/permissions/deny-webview-data.toml

[[permission]]
identifier = "deny-webview-data-linux"
description = '''
This denies read access to the
`$APPLOCALDATA` folder on linux as the webview data and
configuration values are stored here.
Allowing access can lead to sensitive information disclosure and
should be well considered.
'''
platforms = ["linux"]


[[permission.scope.deny]]
path = "$APPLOCALDATA/**"


[[permission]]
identifier = "deny-webview-data-windows"
description = '''
This denies read access to the
`$APPLOCALDATA/EBWebView` folder on windows as the webview data and
configuration values are stored here.
Allowing access can lead to sensitive information disclosure and
should be well considered.
'''
platforms = ["windows"]


[[permission.scope.deny]]
path = "$APPLOCALDATA/EBWebView/**"

The above scopes can be used to allow access to the APPLOCALDATA folder, while preventing access to the EBWebView subfolder on windows, which contains sensitive webview data.

These can merged into a set, which reduces duplicate configuration and makes it more understandable for anyone looking into the application configuration.

First the deny scopes are merged into deny-default:

plugins/fs/permissions/deny-default.toml

[[set]]
identifier = "deny-default"
description = '''
This denies access to dangerous Tauri relevant files and
folders by default.
'''
permissions = ["deny-webview-data-linux", "deny-webview-data-windows"]

Afterwards deny and allow scopes are merged:

[[set]]
identifier = "scope-applocaldata-reasonable"
description = '''
This scope set allows access to the `APPLOCALDATA` folder and
subfolders except for linux,
while it denies access to dangerous Tauri relevant files and
folders by default on windows.
'''
permissions = ["scope-applocaldata-recursive", "deny-default"]

These scopes can be either used for all commands, by extending the global scope of the plugin, or for only selected commands when they are used in combination with a enabled command inside a permission.

Reasonable read only file access to files in the APPLOCALDATA could look like this:

[[set]]
identifier = "read-files-applocaldata"
description = '''
This set allows file read access to the `APPLOCALDATA` folder and
subfolders except for linux,
while it denies access to dangerous Tauri relevant files and
folders by default on windows.'''
permissions = ["scope-applocaldata-reasonable", "allow-read-file"]

These examples only highlight the scope functionality itself. Each plugin or application developer needs to consider reasonable combinations of scope depending on their use cases.

create-tauri-app Version 3 Released

hero image

A new major version of create-tauri-app has been released. This version adds support for the alpha version of Tauri 2.0, the ability to initialize iOS and Android projects and removes some less commonly used templates to make the project more maintainable.

Tauri 2.0 Alpha & Mobile Support

The first alpha version of Tauri 2.0 was published almost 3 months ago which brought initial mobile support for Android and iOS. Previously there wasnt an easy way to create a new project to test either the changes in the alpha version nor the mobile support. Well, that ends now!

Starting with version 3 of create-tauri-app, you can now pass --beta flag and it will bootstrap an app that uses tauri@2.0.0-beta. When adding the --beta flag it will automatically prompt you if youd like to add mobile support. You can also use the --mobile flag to automatically make it mobile compatible.

To get started:

# pnpm
pnpm create tauri-app --alpha


# yarn
yarn create tauri-app --alpha


# npm
npm create tauri-app -- --alpha


# Cargo
cargo install create-tauri-app --locked
cargo create-tauri-app --alpha


# Bash
sh <(curl https://create.tauri.app/sh) --alpha


# Powershell
$env:CTA_ARGS="--alpha";iwr -useb https://create.tauri.app/ps | iex

Prompt Improvements

With version 2 of create-tauri-app we also focused on improving the flow and experience of the prompted questions.

Previously the second prompt would ask “Choose your package manager”. This was a bit vague and could leave some with unanswered questions:

  • What is cargo?
  • Is it a new Node.js package manager?
  • Why choose it over pnpm or yarn?

This would be even more vague if we decided to add a new frontend language (such as a webassembly Golang web application). We added a prompt asking to choose the package manager to ask which language would you prefer. It looks something like this:

? Choose which language to use for your frontend 
  Rust
 TypeScript / JavaScript  (pnpm, yarn, npm)

After choosing the frontend language create-tauri-app will then prompt for package manager to use if the language has multiple (such as Node.js with npm, yarn, and pnpm).

Another prompt that we felt problematic was the template selection prompt. It contained a lot of templates to choose from and was only growing with time:

✔ Choose your package manager · pnpm
? Choose your UI template 
  vanilla
  vanilla-ts
  vue
 vue-ts
  svelte
  svelte-ts
  react
  react-ts
  solid
  solid-ts
  next
  next-ts
  preact
  preact-ts
  angular
  clojurescript
  svelte-kit
  svelte-kit-ts

We decided to split this up into 2 prompts. The first will ask which UI template to use:

✔ Choose your package manager · pnpm
? Choose your UI template 
  Vanilla
 Vue
  Svelte
  React
  Solid
  Angular
  Next
  SvelteKit
  ClojureScript
  Preact

And then the second will then ask any additional choices that are specific to that template (such as choosing between TypeScript or JavaScript for Vue):

✔ Choose your package manager · pnpm
✔ Choose your UI template · Vue - (https://vuejs.org)
? Choose your UI flavor 
 TypeScript
  JavaScript

Even with these refinements the list of templates was still quite large and would only grow over time. The next thing to look at was the list of templates themselves.

Removing Templates

When create-tauri-app version 2 was launched it quickly received PRs to add additional templates beyond what it originally launched with. While it was exciting to receive so much support from the community, it did bring up a couple of new challenges:

  • It made it almost impossible to fit them in a single prompt
  • Maintaining all the templates was becoming more difficult

It was a hard balance between showing how flexible Tauri is but also making sure that the project was maintainable and had the DX that we wanted.

We decided to focus on the most popular frontend frameworks and used guidance from community surveys like The State of JS and our own Tauri community feedback. With this we removed the next, next-ts, preact, preact-ts, clojurescript, svelte-kit and svelte-kit-ts templates and also closed PRs which aimed to add more templates.

Community-Maintained Templates & Previous Versions

We want to make sure that we offer a place for the Tauri community to provide their own templates for the frameworks they love. The templates section of awesome-tauri is just the place for that. We invite the community to submit a PR to the awesome-tauri repo with their templates so that they can be shared with the Tauri community. Well also be creating a section on the Tauri website to highlight and showcase these community templates.

If youd still like to use the previous templates from version 2 of create-tauri-app they are still published to npm and crates.io. Heres how you can use a previous version:

# pnpm
pnpm create tauri-app@2


# yarn
yarn create tauri-app@2


# npm
npm create tauri-app@2


# Cargo
cargo install create-tauri-app --version 2.8.0 --locked
cargo create-tauri-app


# Bash
sh <(curl https://create.tauri.app/v/2.8.0/sh)


# Powershell
iwr -useb https://create.tauri.app/v/2.8.0/ps | iex

However, as time goes, these templates will become out of date as Tauri and the frontend frameworks move forward. Wed recommend you look at the community templates in the awesome-tauri repo and welcome submissions if something is missing.


We hope that these changes make it easier for the community to try out the alpha and beta versions of Tauri 2.0 and also make the process to create a new Tauri app easier for everyone! Wed love to hear your feedback and invite you to join the conversation on the GitHub Discussion for this post.

Rust Security Advisory CVE-2024-24576

The Rust Security Response WG announced CVE-2024-24576, which affects the Rust Standard Library on Windows.

TL;DR: Upgrade your Rust version to 1.77.2.

How Does it Affect Tauri as a Library?

Some Tauri organization repositories use batch files (cmd.exe under the hood) for developer environment tooling such as build scripts. No reviewed repositories use batch files for runtime code.

We dont see additional risks for the Tauri project based on this CVE.

Nevertheless, we will update our CI systems to use the latest Rust version.

Is My Tauri App Affected?

In general you are possibly affected if you fulfil all of the below criteria:

  • You ship your app on Windows
  • Your project enables the Tauri v1 shell feature with "execute": true or the v2 shell-plugin with allow-execute permission
  • You allow arguments in the scope element of the shell feature
  • You pass untrusted input to cmd.exe or .bat/.cmd files and improperly validate the scope (🚩)

If any of these criteria are not fulfilled in your application you are likely NOT affected.

If you implement custom commands or logic written in your application that directly exposes the Rust Command with arguments provided at runtime, you may be affected. While not Tauri specific, this pattern could affect any Rust project.

Conclusion

Please upgrade your Rust version to 1.77.2 as soon as possible and distribute updates to your users.

This investigation and writeup was performed in cooperation with our partner CrabNebula ❤️.


Read more about this security advisory here. This affects many programming languages, this specific CVE is just the one filed for Rust.

Strengthening Tauri: Our Partnership with CrabNebula

Hero Image

As an open-source project, Tauris primary mission has always been to provide a secure, efficient framework for multi-platform application development. Understanding the concerns and needs of our community, we are excited to share insights into our partnership with CrabNebula and how it bolsters the stability and future of Tauri.

CrabNebulas Contribution to Stability and Security

CrabNebulas role in Tauris journey over the past year has been pivotal. By dedicating full-time engineers to work explicitly on Tauris development and maintenance, they are helping us enhance the frameworks stability and security. They are literally being paid to resolve bugs and issues, pushing forward on the 2.0 release, and offering their support in the many Discord discussions.

Specifically, we would like to call out some folks from CrabNebula for helping drive the community and the code forward: Daniel, Lucas, Elizabeth, Yu-Wei, Tillmann, Amr, Chip, Fabian-Lars, Alve, Atila, Eleftheria, Tejas, Lorenzo, Robin, David, Jason, and Te-Kai.

Their efforts in conducting thorough security audits of minor releases are particularly crucial. These audits not only help us identify and fix vulnerabilities but also reinforce our commitment to delivering a secure framework for all users. Collaborative features developed with Impierce and Kino AI under this partnership further expand Tauris capabilities, which will help it to remain cutting-edge and reliable.

A Partnership Model Focused on Open Source Values

Our collaboration with CrabNebula is grounded in open-source principles. Its designed not just for mutual benefit but to serve as a sustainable model for future collaborations. We understand the importance of maintaining the integrity and independence of Tauri as an open-source project. This partnership respects these values, ensuring that Tauri continues to be driven by community needs and open-source innovation.

Long-Term Impact on the Tauri Ecosystem

The partnership is more than just a short-term alliance; its a strategic move to secure the long-term future of Tauri. By bringing additional resources and diverse perspectives, were enhancing the frameworks robustness. Importantly, involvement of companies using Tauri, facilitated by this partnership, gets cycled directly into the development process. This feedback loop is vital for addressing real-world usage challenges, because it is important to all of us that Tauri remains relevant and continues to evolve according to the needs of its users.

Creating Channels for Community Engagement

In line with our commitment to community engagement, we will be launching a #crabnebula channel on Tauris Discord. This will be a dedicated space for direct communication, collaboration, and feedback. We want to make sure that our communitys voice is heard and integrated into the ongoing development of Tauri.

Call to Action

To our developers, contributors, users, and donors - we invite you to engage with us on this journey. Your input is invaluable as we continue to develop Tauri in partnership with CrabNebula. Together, we are not just building a framework; we are seeking ways to enhance its longevity and relevance in the ever-changing world of technology.

If you like, go over to the CrabNebula blog and read their perspective on this partnership.

Roadmap to Tauri 2.0

Hero Image

Tauri 1.0 was released in June 2022 and introduced an app toolkit for developers to build apps using HTML, CSS, and JavaScript with the security and performance of Rust. Tauri has been pivotal in redefining and asking the question: “What is an app?”

Version 1.0 launched with support for Linux, macOS, and Windows and has been updated with new features, DX improvements, and bug fixes to bring us to Tauri 1.4 that is available now.

But theres one question the Tauri Working Group gets asked time and time again. We affectionately refer to it as “Mobile when?!?” and today wed like to outline the path ahead of us to get to Tauri 2.0 and to answer that question.

What is Tauri 2.0?

In essence, the 2.0 release of Tauri is The Mobile Update. But 2.0 is so much more than just mobile. Here are a few of the features that will be included:

  • Powerful Plugins: Many of the Tauri APIs have been shifted to use the Tauri plugin system. This allows us to make Tauri code more modular, more maintainable, but also enables us to make the plugin system more powerful for developers to build their own plugins.
  • Swift and Kotlin Bindings for Plugins: Now you can write platform-specific code in Swift and Kotlin. Tauri has offered a bridge between Rust and JavaScript code since version 1.0. With Tauri 2.0, plugin developers will be able to write code in Swift and Kotlin to integrate more closely with the systems theyre developing for.
  • Support for iOS and Android: Youll be able to build Tauri apps and run them on iOS and Android.

Weve already seen developers doing amazing things with the prerelease version of Tauri 2.0 and were excited to move forward to a stable version to get it in the hands of everyone.

Path to Tauri 2.0 Stable

Right now, we are in the 2.0 alpha phase. Here are the 3 key milestones to get us to Tauri 2.0 stable:

  1. Beta
  2. Release Candidate
  3. Stable

Below are the steps within each of those milestones that the Tauri Working Group are driving towards.

Beta

To enter a beta phase Tauri 2.0 must be feature-complete and working with no known major issues. This means that the Tauri Working Group are satisfied with the public Tauri APIs and dont anticipate any breaking changes (although they are possible as we receive community feedback).

Once weve entered beta then we will lock down the code base and move onto an auditing phase. No new features will be targeted for Tauri 2.0 after this point.

Security is very important to Tauri. We work with external auditors to review Tauri code so that it can be as secure as possible for Tauri developers and their users. A similar approach was taken with Tauri 1.0 in collaboration with Radically Open Security (Tauri 1.0 Security Audit Report).

More details on the security audit for 2.0 are to come in the future.

Release Candidate

Once all of the audit findings are resolved then we will move on to the release candidate phase. This is where well ask the Tauri community to give it a test drive, see if there are any bugs, and to provide feedback in preparation for the stable release.

The RC phase will be time-locked so that early adopters can help us discover pain points and low-hanging fruit that can be resolved quickly. This will also include a documentation sprint in order to align what we know with what we show. More details on this will be shared as we get get closer to the release candidate phase.

Stable

Tauri 2.0 will be released and generally available for everyone to build amazing things with. We will also continue fixing bugs and releasing updates in line with our current approach of publishing patches and minor updates.

Where We Are

There are a lot of moving parts in moving towards a stable release. The two main parts are the findings and fixes from the security audit alongside the feedback and adjustments from the community. These two pieces are incredibly important and we want to be sure we can prioritize those without sacrificing the security and quality of Tauri.

Because of those priorities we dont yet have hard timelines for a Tauri 2.0 stable release. We have internal targets that were aiming for to keep us on track, but we want to be sure that were flexible to accommodate feedback.

What we can share right now is that were roughly targeting the stable release of Tauri 2.0 in early 2024. Were driving sharply ahead to enter the beta phase as soon as possible.

As we make progress towards Tauri 2.0 well be sure to share updates to the community. The primary way to keep up to date is to watch for the Tauri releases as they move through the beta, release candidate, and lastly stable phases. You can also keep an eye on Twitter, Mastodon, and Discord.

Getting Involved

While were working towards Tauri 2.0 stable there are a lot of ways for the community to get involved. The more involvement and feedback we have, the better Tauri 2.0 will be for everyone. Here are just a few ways to get involved:

  • Test prerelease versions of Tauri and give feedback via Discord and GitHub issues.
  • Contribute to documentation and translations on https://v2.tauri.app.
  • Help in the Tauri community by supporting others in Discord and GitHub issues and giving feedback for major issues that arise.
  • Begin planning content around Tauri 2.0 (although we recommend waiting until at least 2.0 beta). Reach out to the Tauri Working Group on Discord if you would like to collaborate on content ideas such as videos, blogs, courses, or anything else.

We hope this provides a bit of transparency about where were at, where were headed, and what you can do to help us get there. Give us your feedback by joining us on Discord and joining the GitHub Discussion for this post. Happy building!

Tauri 1.0 Release

Tauri 1.0 Launch Hero Image

After 9 months of betas and 4 months of release candidates, Tauri version 1.0 is now available!

What is Tauri?

Tauri is an app construction toolkit that lets you build software for all major desktop operating systems using web technologies. The core libraries have been written for you in Rust and the user interface can be written using virtually any frontend framework. It includes an optional and tree-shakeable JavaScript API for comfortable low-level system access, a desktop binary bundler with code signing and artifact verification, a secure updater to keep your users on the latest version, an extensive plugin system, and support for OS-level integrations such as notifications and app trays.

Tauri is as simple to use as it is easy to extend. For those new to the Rust programming language, Tauri provides a comfortable learning environment that will grow with you. Once you have installed Rust, creating your first app is a mere running of create-tauri-app. But you dont have to use Node.js at all, if you would prefer to remain in the safety and comfort of 100% Rust.

See our Quick Start guides to start building with Tauri.

Tauri Philosophy

We built Tauri for the security-focused, privacy-respecting, and environmentally-conscious software engineering community.

Security

The entire project has been horizontally and vertically audited by an independent third party, and we maintain a very strict approach to updating the core. We want you to be confident that major versions are as safe to use as they are ergonomic.

Printed sweatshirt

Hoodie by jprovost

Privacy

Tauri allows you to build “local first” applications without a webserver, so your users dont have to share their data with big tech. Using local databases and rust based cryptography have never been easier.

Johannes Schickling at Worker Conf 2022 (photo by @TejasKumar)

Johannes Schickling at Worker Conf 2022 (photo by{' '} @TejasKumar via Twitter)

Environment

The apps you make are lean and performant, which reduces electricity, storage space, and general natural resource consumption. Every byte saved is a leaf on a tree that gets to grow.

To illustrate this, we compiled some numbers on the ecological impact of your apps size. As you can see, even small increases in size have a hefty impact on the environment!

App Size Unit Time (100Mb/s) Downloads Transit Total Time (100Mb/s) Electricity Use (kWh) CO2 Produced (kg) Trees Needed 🌳
3 MB 240 milliseconds 1,000 3 GB 24 minutes 0.3 0.18 1
3 MB 240 milliseconds 100,000 300 GB 1.7 days 30 18 1
3 MB 240 milliseconds 10,000,000 30 TB 167 days 3,000 1,800 11
200 MB 16 seconds 1,000 200 GB 4.45 hours 20 12 1
200 MB 16 seconds 100,000 20 TB 18.5 days 2,000 1,200 7
200 MB 16 seconds 10,000,000 2 PB 5 years 200,000 120,000 720
600 MB 48 seconds 1,000 0.6 TB 13 hours 60 36 1
600 MB 48 seconds 100,000 60 TB 54.2 days 6,000 3,600 22
600 MB 48 seconds 10,000,000 6 PB 14.8 years 600,000 360,000 2,160

The transmission of 1 GB of information takes an estimated 0.1kWh, which is equal to 0.06 kilograms of CO2. (https://www.emergeinteractive.com/insights/detail/does-irresponsible-web-development-contribute-to-global-warming/)

Although the carbon absorption capacity can vary, it is generally considered that a tree can store about 167 kg of CO2 per year, or 1 ton of CO2 per year for 6 mature trees (https://climate.selectra.com/en/news/co2-tree)

Community

We know that open source software is a means of fostering equality and collaboration, which is why we placed the ownership of the code at the Commons Conservancy. You can rest assured knowing that the code base will never be rug-pulled or locked behind open-core pay-to-play feature gates. We believe in open collaboration and safe spaces for all. We have an open working group, accessible to any competent contributors. And we love you all. ❤️

Accolades

Here are some of the things people are saying about Tauri:

Spacedrive Logo

“Spacedrive had to feel native across all platforms, all while being lightweight, instant to launch and extremely fast to use. This just wasnt possible with a web-based UI — until now, thanks to Tauri.” - Jamie Pine, Spacedrive Founder

Prism Logo

“Tauri has the potential to unlock a new generation of desktop software that feels native to users but is as easy to build as web apps.”

- Johannes Schickling, Prisma Founder

OSSC Logo

“Tauri stands to reduce the disastrously negative environmental costs of bloated and memory-hogging applications on the internet by orders of magnitude. Any rough approximation of monetary value that could result in, would easily reach hundreds of billions in cost savings for our modern era of grossly underutilized local compute and storage resources.”

- Joseph Jacks, OSS Capital Founder / GP

Padloc Logo

“With its security-focused design and low memory footprint, Tauri is the electron alternative weve been waiting for. Tauri has allowed us to build a more secure, more performant desktop app while using the same web technologies, which we love. Thanks to the team for their amazing work! P.S.: Cant wait for mobile support!”

- Martin Kleinschrodt, Padloc Founder

Feedback

You can visit our code base, file a bug-report, request a feature, or join the discussion on GitHub. Theres lots of things that people make, and visiting the awesome-tauri repo on GitHub is a great place to discover and share. If you need support or just want to hang out, you can join our Discord server.

Tauri is one of the top 200 projects on GitHub in all programming languages.

github

People love to discuss what is great and terrible about Tauri on orange websites:

hackernews

Tauri entered at the top of the charts for the 2021 edition of State of JS:

State of JS 2021

Engineers at big companies seem to be eying up Tauri for future projects.

hackernews

OSS Insight

Whats Next?

Fresh off the heels of the 1.0 release, the team is already setting our sights on the next steps for Tauri. While we continuously work on improving our documentation, were also working on:

  • Mobile support for both iOS and Android
  • Alternative renderers
  • IPC enhancements to enable improved debugging
  • Runtime plugins
  • Support for additional bindings in other languages

Were also inspired by the community to see which features are being used and what new features will enable them to develop even more amazing applications. Your feedback is the most important thing to Tauris future innovation!

Thank You

A special thanks to all our contributors who volunteered their precious time to make Tauri awesome and all our sponsors whose generous donations made Tauri possible (and financed a large portion of our audit!)!

The support of industry giants has been really helpful keeping the lights on. Heres an alphabetical list:

  • Cloudflare for sponsoring unlimited workers for the OSS updater service (coming soon)
  • DigitalOcean for comping the droplets that run our bots and search
  • GitHub for the extra minutes of CI
  • Netlify for our website hosting
  • NLNET who has financially supported Tauri development via grants
  • PACKT who will be publishing our books

Here are a few notable contributors wed like to thank explicitly:

GitHub Profile Contribution Repository
@malyn Fixed http stream wry
@wravery windows-rs support, webview2-rs tao, wry
@liushuyu Added headers feature to webkit2gtk wry
@emirror-de System tray support tao
@lorenzolewis tauri.app updates tauri-docs
@probablykasper Support for more accelerators, restructured documentation tao, tauri-docs
@grbd Added an example to use tauri as a C++ DLL tauri
@youngsing Added macOS vibrancy tauri-plugin-vibrancy
@lemarier Updater, menus, system tray, iOS, clipboard api, bytes-stream & ++ wry, tao, tauri
@JonasKruckenberg Tauri plugin upgrades and documentation overhaul tauri-plugin-*, tauri-docs
@ImmaZoni Code signing guides for macOS and Windows tauri-docs
@chippers Isolation pattern, shell scope, compile-time code generation and several other security features tauri
@fabianlars Community support, AppImage fixes, code review all repos, mainly tauri, tauri-docs
@amrbashir TAO and WRY features and fixes, overall OS guru tao, wry
@wusyong TAO and WRY founder and researcher tao, wry
@nklayman custom protocol tauri

Wed like to wrap up by highlighting comments from just a small handful of core Tauri contributors:

Amr Bashir

What feature are you most excited about?

The customizations we offer for the window but thats because it is what I mostly worked on. I am also excited about how Tauri will change the mindset of some people and help them build secure apps by default.

What is your proudest moment/contribution with Tauri?

Probably when I removed about 20 lines of code in favor of only 3 lines. I wrote both and thats why it felt special, because it was an indicator of how much Ive grown as a developer.

Chip Reed

What feature are you most excited about?

Not needing to use --locked when installing the CLI.

What is your proudest moment/contribution with Tauri?

Building the Isolation Pattern

Didrik Nordström

What feature are you most excited about?

File drag & drop.

What is your proudest moment/contribution with Tauri?

Quality/stability: Tracking down and fixing a segmentation fault: https://github.com/h4llow3En/mac-notification-sys/pull/40

Fabian-Lars

What feature are you most excited about?

Is “All of them” a valid answer?

What is your proudest moment/contribution with Tauri?

Hmm, probably when I was asked to join the team. Fixing AppImages again and again and again is a close second…

Jonas Kruckenberg

What feature are you most excited about?

The auto-updater is pretty great but plugins are very dear to me and definitely the most promising feature of Tauri!

What is your proudest moment/contribution with Tauri?

Moderating the tauri-awesome repo. Seeing so many strangers build cool things with and for the work youve been doing. Thats a really great feeling.

Kasper Henningsen

What inspired you to join Tauri?

I was making a few Tauri apps, and just found some features/improvements I wanted to go for.

Laegel

What feature are you most excited about?

It may sound silly but I love customizing stuff, so the possibility to make almost anything with our windows appearance is neat.

What is your proudest moment/contribution with Tauri?

Creating the foundations of Tauri docs as we know them today and trying to provide clean and easy to understand docs.

lemarier

What feature are you most excited about?

Pretty much everything, getting Tauri out of a proof of concept to something stable is a huge milestone.

What is your proudest moment/contribution with Tauri?

TAO and all under laying features (menus, trays, etc..), benchmarks and the proof of concept for iOS.

Lorenzo Lewis

What feature are you most excited about?

Overall resource efficiency. Weve all been where we have a handful of “native” web apps running on our machine and it grinds to a halt. Im ready for those small bundle sizes!

What is your proudest moment/contribution with Tauri?

The overall tauri.app website. It was in a really good place when I joined, but I knew I could help boost it up to the next level. Even things like picking a title for a sidebar can take a long time with all the discussions, but at the end of the day we all have the best output from putting our heads together.

Lucas Nogueira

What feature are you most excited about?

Plugins!

What are you most excited about now that the launch is through?

MOBILE and the upcoming egui integration launch

Noah Klayman

What feature are you most excited about?

Auto-updater. Its really hard to get something that complex right and Tauri has done a fantastic job.

What is your proudest moment/contribution with Tauri?

Getting the custom protocol based asset loader to work, especially on Windows.

secdude

What feature are you most excited about?

Conditional compilation of features by default.

What is your proudest moment/contribution with Tauri?

🤷 v1 I guess

Wu Yu-Wei

What feature are you most excited about?

Auto-updater I think. A built-in OTA feature feels pretty handy.

What is your proudest moment/contribution with Tauri?

Published wry crate and particular in this commit: https://github.com/tauri-apps/wry/commit/722e1212a4795f5f81638667cbd31bc53a5d27ed

Announcing Tauri 1.1.0

Tauri 1.1 Launch Hero Image

After 113 pull requests and nearly two months of work, the Tauri team is pleased to announce the 1.1.0 release. The changes were internally audited and no security issues were found.

You can update the dependencies with:

  • npm

    npm install @tauri-apps/cli@latest @tauri-apps/api@latest
    
  • yarn

    yarn upgrade @tauri-apps/cli @tauri-apps/api --latest
    
  • pnpm

    pnpm update @tauri-apps/cli @tauri-apps/api --latest
    
  • cargo

    cargo update
    

Whats New in 1.1.0

Security patch

This release includes a patch for a security vulnerability reported by @martin-ocasek. The readDir function was able to return entries outside the configured scope when a symlink is found. The patch is also available in Tauri 1.0.6. See the issue on GitHub for more details.

Icon Generation

We have been recommending to use the tauricon project to generate icons for your Tauri application using a single source PNG. Several issues have been reported, and we decided to “Rewrite It In Rust” to enhance its stability. This allowed us to move this functionality to the main Tauri CLI, so now you can use the tauri icon command.

cargo-binstall Support for Tauri CLI

The Tauri CLI can now be installed using cargo-binstall, a mechanism to download and install pre-built Rust binaries. The binaries are available for the main targets and can be installed with:

$ cargo install cargo-binstall
$ cargo binstall tauri-cli
$ cargo tauri dev # run any Tauri command!

Create System Trays at Runtime

The system tray APIs (previously only available in tauri::Builder::system_tray) can now be used at runtime with tauri::SystemTray giving you control over its lifetime and even create multiple trays.

Heres a quick example on how to use it:

use tauri::{Builder, CustomMenuItem, SystemTray, SystemTrayEvent, SystemTrayMenu};
Builder::default()
    .setup(|app| {
        let handle = app.handle();
        SystemTray::new()
            .with_id("main")
            .with_menu(
                SystemTrayMenu::new().add_item(CustomMenuItem::new("quit", "Quit"))
            )
            .on_event(move |event| {
                let tray_handle = handle.tray_handle_by_id("main").unwrap();
                if let SystemTrayEvent::MenuItemClick { id, .. } = event {
                    if id == "quit" {
                        tray_handle.destroy().unwrap();
                    }
                }
            })
            .build(&handle)
            .expect("unable to create tray");
    });

TOML Configuration Support

In the 1.0 releases Tauri supports the JSON configuration format by default, and JSON5 when the config-json5 Cargo feature is enabled, meaning the following configurations are valid:

tauri.conf.json

{
  "build": {
    "devPath": "http://localhost:8000",
    "distDir": "../dist"
  }
}
{
  build: {
    // devServer URL (comments are allowed!)
    devPath: 'http://localhost:8000',
    distDir: '../dist',
  },
}

The 1.1.0 release includes TOML support behind the config-toml Cargo feature. Now you can define your Tauri configuration in a Tauri.toml file:

Tauri.toml

[build]
dev-path = "http://localhost:8000"
dist-dir = "../dist"

Dependency Updates

This release includes some dependency updates that must be handled in your app if you implement platform-specific functionalities using these crates. The most important updates are:

  • windows updated to 0.39.0
  • webview2-com updated to 0.19.1
  • raw-window-handle updated to 0.5.0

Make sure you also update plugins such as window-vibrancy and window-shadows to latest.

Contributors to 1.1.0

The Tauri team thanks the following contributors for the 1.1.0 release:

Other Changes

There are a lot of smaller changes and bug fixes in this release. You can see a summary of the release notes in the following sections. The complete changelog can be found on the releases page.

New

  • tauri icon command
  • exists API in the fs module
  • Option to disable the dev watcher with tauri dev --no-watch
  • Automatically use any .taurignore file as ignore rules for dev watcher and app path finder
  • Add support to cargo-binstall for the Tauri CLI
  • TOML configuration format (Tauri.toml)
  • Theme APIs on Linux
  • Create system trays at runtime
  • beforeBundleCommand configuration
  • beforeDevCommand and beforeBuildCommand now has an option to configure the current working directory
  • api::Command::encoding method to set the stdout/stderr encoding
  • Added native-tls-vendored and reqwest-native-tls-vendored Cargo features to compile and statically link to a vendored copy of OpenSSL on Linux
  • Implement raw_window_handle::HasRawDisplayHandle for App and AppHandle

Fixes

  • CLI parser ignoring inner subcommands.
  • Updater breaking the app icon in Finder.
  • Fix root of codegen output when using the CodegenContext API.

Security

  • Fix fs.readDir recursive option reading symlinked directories that are not allowed by the scope

Improvements

  • Validate updater signature against configured public key
  • Return an error if a sidecar is configured with the same file name as the application.
  • Keep the created windows in a RefCell instead of a Mutex, avoiding deadlocks
  • Prompt for beforeDevCommand and beforeBuildCommand in tauri init.
  • Use cargo metadata to detect the workspace root and target directory.
  • Allow configuring the before_dev_command to force the CLI to wait for the command to finish before proceeding.
  • Avoid re-downloading AppImage build tools on every build.
  • Retain command line arguments in api::process::restart
  • Enhance the dialog style on Windows via the manifest dependency Microsoft.Windows.Common-Controls v6.0.0.0.
  • Rerun codegen if assets or icons change
  • Only rewrite temporary icon files when the content change, avoid needless rebuilds.

Announcing Tauri 1.2.0

Tauri 1.2 Launch Hero Image

The Tauri team is happy to announce the 1.2.0 release. It includes a security fix, so we encourage new and existing users to update to one of the fixed versions. Other changes were internally audited and no security issues were found.

Make sure to update both NPM and Cargo dependencies to the 1.2.0 release. You can update the dependencies with:

  • npm

    npm install @tauri-apps/cli@latest @tauri-apps/api@latest
    
  • yarn

    yarn upgrade @tauri-apps/cli @tauri-apps/api --latest
    
  • pnpm

    pnpm update @tauri-apps/cli @tauri-apps/api --latest
    
  • cargo

    cargo update
    

Whats in 1.2.0

Security patch

This release includes a patch for a security vulnerability reported by MessyComposer. Due to incorrect escaping of special characters in paths selected via the file dialog and drag and drop functionality, it was possible to partially bypass the fs scope definition. It was not possible to traverse into arbitrary paths, as the issue was limited to neighboring files and sub folders of already allowed paths. A successful bypass requires the user to select a pre-existing malicious file or directory during the file picker dialog and an adversary controlled logic to access these files. This means the issue by itself can not be abused and requires further intentional or unintentional privileges. The patch is also available in 1.0.7 and 1.1.2. See the advisory for more details.

Rust version update

This release includes a minimum supported Rust version bump. Tauri now requires at least Rust 1.59 to compile. This was necessary due to several dependency updates that demanded this change.

Custom protocol headers on Linux

The Linux webview binding has been updated and it now has support to custom protocol headers when running on webkit2gtk version 2.36 or above. This fixes CORS issues on production when manually fetching a build asset.

Enhanced titlebar configuration on macOS

We finally merged one of the most awaited pull requests, introducing the titlebar style configuration. Your application can now define a transparent or overlay titlebar, hide the window title text and define the window to accept first mouse events so it can be focused immediately after receiving a click event to be dragged.

Window with overlay titlebar style

Window with transparent titlebar style (uses the window background color)

Other changes

There are a lot of smaller changes and bug fixes in this release. You can see a summary of the release notes in the following sections. The complete changelog can be found on the releases page.

New

  • Allow configuring the user agent when creating a window (#5317)
  • Reimplemented the option to create unfocused windows (#5338)
  • Added the acceptFirstMouse window option (macOS) (#5374)
  • Added the tabbingIdentifier window option (macOS) (#5399)
  • Enhanced the app-specific directory APIs (#5272)
  • Added show and hide methods on the app module (macOS) (#3689)
  • Expose set_title for MacOS tray (#5182)
  • hotreload support for frontend static files (#5256)
  • Add a configuration option for the bundle publisher (#5283)

Enhancements

  • Validate the package name (#5262)
  • Drop the WebContext on WebView drop (#5240)
  • Set the correct mimetype when streaming files through asset: protocol (#5210)

Fixes

  • Fix HTML template tags in custom protocol (#5247)
  • Fix scope check when reading resource files on macOS (#5218)
  • Fix incorrect return type on fs/exists (#5252)
  • Initialize Monitor instances with the correct classes for position and size fields instead of plain object (#5313)
  • Fix dialog.save return type (#5373)
  • Use correct code ja-JP for japanese instead of jp-JP (#5346)
  • Clear environment variables on the WiX light.exe and candle.exe commands to avoid “Windows Installer Service could not be accessed” error. Variables prefixed with TAURI are propagated. (#4819)
  • Fix regression in SystemTray::with_menu_on_left_click (#5235)
  • Fix regression introduce in tauri@1.1 which prevented removing tray icon when the app exits on Windows (#5245)
  • Fix access to the WebviewWindow.getByLabel function in a tauri://window-created event listener (#5458)
  • Fix a deadlock when modifying the menu in the on_menu_event closure. (#5257)
  • Fixes __TAURI_PATTERN__ object freeze (#5307)

Announcing Tauri 1.3.0

Tauri 1.3 Launch Hero Image

The Tauri team is excited to announce the 1.3 release. This version includes security improvements, new features and important bug fixes.

Upgrading

Make sure to update both NPM and Cargo dependencies to the 1.3.0 release. You can update the dependencies with:

  • npm

    npm install @tauri-apps/cli@latest @tauri-apps/api@latest
    
  • yarn

    yarn upgrade @tauri-apps/cli @tauri-apps/api --latest
    
  • pnpm

    pnpm update @tauri-apps/cli @tauri-apps/api --latest
    
  • cargo

    cargo update
    

Whats in 1.3.0

NSIS

The Tauri CLI can now create Windows application installers using NSIS. This new bundle target is also available on macOS and Linux as an experimental feature, so you can cross-compile your Windows installer. Documentation on the latter will be published soon.

Tauri 1.3 Audit

The internal audit was performed by @tweidinger and @chippers, who are involved in most security topics at the Tauri project. It was performed during paid time at CrabNebula and we are grateful to be able to spend parts of our work time contributing to the open source project and making it a more secure environment ❤️.

We manually audited over 45 PRs. Some PRs (e.g. #5544) lead us to diving into very old RFCs (RFC6068 and RFC3966), NSIS documentation (e.g. #6039) and many other external resources. We documented questions, notes and findings in markdown files and shared these notes with the responsible developers to ensure appropriate fixes.

The changes from a security perspective and findings of the audit are summarized in the following sub-sections.

External API Access #5918

This was by far the most impactful and time consuming PR we investigated. This PR introduces a streamlined way for applications to allow external domains access to the Tauri IPC layer1 and usage majorly impacts the security model of a Tauri application. Security impact2 depends on exposure3 of the feature, enabled Tauri commands and the capabilities of an adversary4.

We consider this new feature similar to driving a very fast race car without any safety features enabled and urge developers to very very carefully consider if they really need this exposure.

Before this addition was merged, a semi-known vulnerability was (ab)used by application developers to achieve the same functionality. To make the whole community aware of this risk we published a security advisory to give a heads up. Applications are affected if they allow users to navigate to arbitrary domains or have an open redirect vulnerability5. If you implement such a feature you should update to the 1.3 release as fast as possible.

The initial PR changes allowed wildcards (https://*) and glob patterns, which we believe are helpful but shouldnt be exposed to all Tauri developers. We concluded that the risk of over-exposure, like the allow list toggle to enable all Tauri API endpoints, does not justify this permissive exposure. The final implementation allows to configure specified (sub)domains6 (eg: example.com) to gain remote access to the Tauri IPC.

The few edge use cases, which require wildcards or even further exposure can be implemented by custom Rust code which is able to dynamically modify the IPC access. We now expose this remote IPC scope in a similar fashion as the fs or http scope.

Assuming a fully trusted web service on https://trusted.example it is now possible to configure the security scope to allow certain windows or even plugins access to custom implemented commands and optionally the inbuilt Tauri API:

"security": {
  "dangerousRemoteUrlIpcAccess": [
    {
      "windows": ["main", "settings"],
      "domain": "trusted.example",
      "plugins": ["trusted-plugin"],
      "enableTauriAPI": false
    },
  ],
}

Shared domains MUST NOT be used for this in any circumstances. We do not limit access to paths or specific files. You can only scope with trusted (sub)domains6. Another very risky catch is that developers must be sure that the domain ownership does not change over the lifetime of the application. Domain takeover could lead to compromised user devices.

Browser Arguments #5799

Due to certain webview features not enabled nor being accessible, a community contribution introduced the possibility to add additional arguments to the webview process, which is created in a new window.

This feature was exposed to the frontend in the window endpoint. We found that this exposure was highly risky, as most webviews have very impactful features and flags that can be allowed via the process arguments.

All of the following threat model assumptions are based on the Tauri window creation being allowed in the allowlist of the tauri.conf and therefore exposed to the frontend. This PR affects Windows only, therefore there is no impact on the other supported operating systems.

An adversary with the capabilities to create windows and pass command line arguments to the webview can elevate their privileges to escape the strict sandboxing of Tauri and the webview.

The flags allow to enable several dangerous webview features, from loading profiles outside of the current default profile folder (stealing browser sessions from the device) to disabling security measurements of the webview (eg: certificate validation, sandboxing, webdriver/headless mode, device management endpoints, …).

We found an old but gold and still unique documentation reference at https://peter.sh/experiments/chromium-command-line-switches/, which helped us understand possible risks on Windows, as the Webview2 uses the same flags.

The feature was then changed to be only exposed on the rust side. Tauri application developers can use this to implement custom commands to invoke webview windows with use case specific arguments.

Possible ZipSlip #4674

We found that the components to extract remote bundler files like the Webview2 installer were manually extracting single files with the extract_zip function, which uses ZipFile::name() instead of ZipFile::enclosed_name() as recommended in the documentation. Files which had names like ../../../../foo.sh could be extracted outside of the intended directory on the filesystem. This kind of vulnerability is called ZipSlip.

As the function was only used on verified and trusted files the impact here was nearly zero. Regardless we changed the implementation to facilitate the proper extraction method.

Bundler Hardening #6039

The bundler was not escaping content passed to the handlebars::Handlebars::render(), which could cause unwanted code execution during the bundler phase. This was also a low impact issue but was promptly fixed.

Other changes

New

  • additional_browser_args option when creating windows #5799
  • Add is_minimized() window method. #5618
  • Add title getter on window. #5515
  • content protection APIs #5513
  • Added Builder::device_event_filter and App::set_device_event_filter methods. #5562
  • Add WindowsAttributes::app_manifest to specify the application manifest on Windows. #5730
  • Add support for Cargos workspace inheritance. #5775 #6144
  • Added windows url() getter. #5914
  • Added Window::on_navigation. #5686
  • Allow setting the text of the dialog buttons. #4383
  • Implement SystemTray::with_tooltip and SystemTrayHandle::set_tooltip for Windows and macOS. #5938
  • Add dylib support to tauri.bundle.macOS.frameworks. #5732

Enhancements

  • On Windows, the msi installers Launch App checkbox will be checked by default. #5871
  • Add --png option for the icon command to generate custom icon sizes. #5246
  • On Windows, change webview theme based on Window theme for more accurate prefers-color-scheme support. #5874
  • Remove default features from Cargo.toml template. #6074
  • Add a method to the WindowBuilder struct to recreate windows from tauri.conf.json configurations.#6073
  • Improve the error message when rustc couldnt be found. #6021
  • Added support for pre-release identifiers and build numbers for the .msi bundle target. Only one of each can be used and it must be numeric only. The version must still be semver compatible according to https://semver.org/. #6096
  • Add --ci flag and respect the CI environment variable on the signer generate command. In this case the default password will be an empty string and the CLI will not prompt for a value. #6097
  • Skip the password prompt on the build command when TAURI_KEY_PASSWORD environment variable is empty and the --ci argument is provided or the CI environment variable is set. d4f89af18d69fd95a4d8a1ede8442547c6a6d0ee

Fixes

  • Fix tauri info panicking when parsing crates version on a newly created project without a Cargo.lock file. #5873
  • Fix building apps with unicode characters in their productName. #5872
  • Sync __TAURI_METADATA__.__windows across all windows. #5615
  • Fix resize glitch when double clicking a custom titlebar in the top resize area. #5966
  • Disable cursor mouse events on Linux. #6025
  • Fix serialization of js Map when used in invoke. #6099

Footnotes

  1. Inter-Process Communication, in this instance the communication between the Tauri core and the frontend code run inside the webview.

  2. Security Impact: What is the theoretical biggest impact of this threat combination? This highly depends on correct scoping of Tauri API endpoints and hardening of custom implemented Tauri commands.

  3. Exposure: Describes the exposed scope items of this feature to either an user or adversary. It is possible to restrict exposure to only certain domains, windows or only to custom implemented commands.

  4. Adversary Capabilities: Which kind of privileges has the adversary? Can range from tricking user into entering malicious input to code execution in the frontend via cross-site-scripting (which is the highest privilege for frontend code in our case). Common capabilities are described in the OWASP documentation.

  5. An application can be exploited if it parses user input for making an URL redirection decision, which is then not properly validated. Wikipedia Source

  6. see the Reqwest reference ↩2

Announcing Tauri 1.4.0

Tauri 1.4 Launch Hero Image

The Tauri team is excited to announce the 1.4 release. This version includes several new features and important bug fixes such as CLI completions, unit testing capabilities and Windows installer improvements.

Upgrading

Make sure to update both NPM and Cargo dependencies to the 1.4.0 release. You can update the dependencies with:

  • npm

    npm install @tauri-apps/cli@latest @tauri-apps/api@latest
    
  • yarn

    yarn upgrade @tauri-apps/cli @tauri-apps/api --latest
    
  • pnpm

    pnpm update @tauri-apps/cli @tauri-apps/api --latest
    
  • cargo

    cargo update
    

Whats in 1.4.0

CLI completions

The Tauri CLI now can generate shell completions for Bash, Zsh, PowerShell and Fish. See the documentation for more information.

Disabling window controls

The windows maximize, minimize and close buttons now can be disabled via configuration or API calls. Check out set_maximizable, set_minimizable and set_closable for the Rust APIs and setMaximizable, setMinimizable and setClosable for the JavaScript APIs.

NSIS improvements

The 1.4.0 release includes several NSIS bundle enhancements:

  • Custom language files
  • Custom installer template (.nsi file)
  • Support for the dutch, japanese, korean, persian, swedish and turkish languages
  • If your application is installed via WiX, the installer will prompt the user to uninstall it
  • Improved support to updater install modes

See the installer customization guide and installer internationalization for more information.

MSRV change

Tauri 1.4 still has a minimum supported Rust version of 1.60, but due to some dependency incompatibility issues we are no longer pinning the patch version of the time, ignore, and winnow crates. If you are still using Rust 1.60, you will need to pin these versions manually with cargo update.

Unit tests

The tauri crate now exposes the test module under the test Cargo feature. This module is still unstable but allows you to unit test your application by creating a tauri::App instance that can execute without spawning windows. See the documentation for more information and examples.

Other changes

Starting on v1.4.0, our changelog format has been improved. Check out the entire list of changes:

Audit

The internal1 audit was performed by Tillmann @tillmann-crabnebula and Chip @chip-crabnebula, who are also involved in security topics at the project under their private handles (@tweidinger and @chippers).

It was performed during paid time at CrabNebula Ltd. and we are grateful to be able to spend parts of our work time contributing to the open source project and making it a more secure environment ❤️.

For this release we manually audited a selection of PRs instead of all PRs coming into the release. The new approach means the reviewers and developers need to decide on their own if a PR is introducing any security relevant change. A review can be triggered by anyone involved in the change, by adding a label to the PR.

For the first time we also audited after the official release due to time constraints. This resulted in a security patch release, fixing the only impactful issue (CVE-2023-34460) discovered during auditing. In general this release was more focused on fixing and improving the NSIS features and introduced less new features and security relevant changes.

Footnotes

  1. It is internal in the sense that we are also involved in the project itself but performed with the help of an external entity. Calling it external security audit would create false impressions.

Announcing Tauri 1.5.0

Tauri 1.5 Launch Hero Image

The Tauri team is excited to announce the 1.5 release. This version includes several new features and important bug fixes such as improved resources bundling, code signing enhancements, notarytool migration on macOS and Bun support.

Upgrading

Make sure to update both NPM and Cargo dependencies to the 1.5.0 release. You can update the dependencies with:

  • npm

    npm install @tauri-apps/cli@latest @tauri-apps/api@latest
    
  • yarn

    yarn upgrade @tauri-apps/cli @tauri-apps/api --latest
    
  • pnpm

    pnpm update @tauri-apps/cli @tauri-apps/api --latest
    
  • cargo

    cargo update
    

Whats in 1.5.0

Notarytool

At WWDC 2021 Apple introduced notarytool, a new tool for interacting with the Apple notary service. Before the 1.5 release, Tauri used altool to notarize your application, but that tool has been deprecated and will stop working for notarization on 2023-11-01. You must upgrade your Tauri CLI to 1.5 before that.

If you are using API keys for authentication with the notary service, notarytool no longer automatically searches for your APi key .p8 file. We recommend users to define its path via the APPLE_API_KEY_PATH environment variable, though to avoid breaking changes we perform the same lookup done by altool to find your key file in case you did not set the environment variable. In the future, this might change, so please adjust your publish pipelines accordingly.

Bun support

The Tauri CLI now supports the Bun package manager.

We would like to thank @colinhacks for submitting the pull requests for this feature!

Code signing improvements

Starting on Tauri 1.5, our bundler now signs all executables (including sidecars, app executables and NSIS uninstaller) and macOS frameworks. We also improved our notarization algorithm adding support to the APPLE_TEAM_ID environment variable to properly define the team ID associated with your account in case you belong to multiple teams.

We would like to thank @tr3ysmith for submitting the pull requests for this feature!

macOS frameworks

This release comes with enhanced macOS frameworks support by code signing all custom frameworks you inject via tauri.conf.json > tauri > bundle > macOS > frameworks and defining the @rpath value fixing a crash when updating your app.

We would like to thank @tr3ysmith for submitting the pull requests for this feature!

Mixed content on Windows

We now offer a configuration option to switch our custom protocol on Windows to use the http scheme instead of https. This reduces the security of your application on Windows since it allows connecting to insecure endpoints such as ws://url, but it matches the behavior on Linux and macOS custom protocols. To enable it, set the tauri.conf.json > tauri > security > dangerousUseHttpScheme to true.

Other changes

Check out the entire list of changes:

Announcing Tauri 1.6.0

The Tauri team is happy to announce the 1.6 release. This version includes several new features and important bug fixes such as improved code signing on macOS, updater enhancements and an event loop crash on all platforms.

Upgrading

Make sure to update both NPM and Cargo dependencies to the 1.6.0 release. You can update the dependencies with:

  • npm

    npm install @tauri-apps/cli@latest @tauri-apps/api@latest
    
  • yarn

    yarn upgrade @tauri-apps/cli @tauri-apps/api --latest
    
  • pnpm

    pnpm update @tauri-apps/cli @tauri-apps/api --latest
    
  • cargo

    cargo update
    

Whats in 1.6.0

Event loop crash

We finally got a good stack trace and got a fix for a long standing crash on all platforms. This crash was a challenge to fix since it only happened when the application is running for a long time, so we thank everyone that made sure the fix works.

Code signing improvements

Tauri now detects nested dylib, app, xpc and frameworks inside your macOS app bundle and codesigns each of them. This ensures your app can use some external libraries and be codesigned and notarized.

Updater enhancement

The auto updater now keeps the command line arguments on Windows.

Other changes

Check out the entire list of changes:

Announcing Tauri 1.7.0

The Tauri team is happy to announce the 1.7 release. This version includes several bug fixes, performance improvements and features backported from the upcoming v2 release.

Upgrading

Make sure to update both NPM and Cargo dependencies to the 1.7.0 release. You can update the dependencies with:

  • npm

    npm install @tauri-apps/cli@latest @tauri-apps/api@latest
    
  • yarn

    yarn upgrade @tauri-apps/cli @tauri-apps/api --latest
    
  • pnpm

    pnpm update @tauri-apps/cli @tauri-apps/api --latest
    
  • cargo

    cargo update
    

Whats in 1.7.0

Shell API performance improvement

The shells Command::execute API has been optimized to only use the IPC a single time instead of streaming data, improving usage of verbose shell scripts.

Feature backport from v2

Thanks to community effort we have backported a few bundler features from v2 into the v1 release.

Custom Windows codesign script

By default the Windows packaging uses SignTool, which only works on Windows so its not useful when cross compiling. In this release we have backported the custom sign command feature, which allows using osslsigncode, relic and other alternatives that can run on Unix systems and support hardware tokens, Azure Key Vault and more.

RPM bundle

RPM packaging have been available to Tauri v2 users for a while, and it is now also available on the v1 channel.

DMG configuration

DMG installers are now configurable: you can change the position of the icons and the window size to fit better within a custom background.

Other changes

Check out the entire list of changes:

Migration to webkit2gtk-4.1 on Linux port

Hello everybody! We just released Tauri v2.0.0-alpha3 recently. While it doesnt bring any major feature, it does bring some huge impacts on Linux port. We will use WebKit2GTK4.1 in 2.0 from now on.

What does this mean?

If you are using Tauri version 1.x, theres nothing to worry about. Everything you need is still the same. But if you are using Tauri version 2.0 alpha version starting from alpha.3, you will need to install the new WebKit2GTK package with API version 4.1. We will update the prerequisites in our site soon. But if you want to know how to install such version, here are some instructions from wry:

# On Arch Linux / Manjaro:
sudo pacman -S webkit2gtk-4.1
# On Debian / Ubuntu:
sudo apt install libwebkit2gtk-4.1-dev
# On Fedora:
sudo dnf install webkit2gtk4.1-devel

Will this bring breaking changes to my code?

The main difference between version 4.0 and 4.1 are the soup library. WebKit2GTK-4.0 uses soup2 and WebKit2GTK-4.1 uses soup3. So if you didnt use any soup2-specific APIs, your applications should continue to work fine.

The reason behind this change is because we aim to add flatpak support, but Gnome runtime uses webkit2gtk-4.1. There are also some subtle bugs like this that only happen in soup2 and they can be fixed by upgrading to soup3.

What other breaking changes we are going to expect?

The major one will be the MSRV. With Tauri v2.0.0-alpha.3 released, MSRV is bumped to 1.64. We will also update windows-rs in the future. This Rust version should satisfy the latest version of windows-rs. We do plan to update our MSRV with minor releases after 2.0. This could ease the friction to stick to any fixed Rust version while updating dependencies.

Tauri 2.0.0-alpha.4 Released

Tauri 1.2 Launch Hero Image

A new alpha release for the 2.0 has been published. This release includes all changes from the upcoming Tauri 1.3 release, an important breaking change on the HTTP client and native mobile capabilities for Tauri plugins.

Updating dependencies

Make sure to update both NPM and Cargo dependencies to the latest alpha release. You can update the NPM dependencies with:

  • npm

    npm install @tauri-apps/cli@next @tauri-apps/api@next
    
  • yarn

    yarn upgrade @tauri-apps/cli@next @tauri-apps/api@next
    
  • pnpm

    pnpm update @tauri-apps/cli@next @tauri-apps/api@next
    
  • cargo

    cargo add tauri@2.0.0-alpha.4
    cargo add tauri-build@2.0.0-alpha.2 --build
    cargo install tauri-cli --version "^2.0.0-alpha" --locked
    

Recreate the mobile projects to use the new features:

rm -r src-tauri/gen
tauri android init
tauri ios init

HTTP Client Breaking Change

The default HTTP client using attohttpc has been removed due to issues with the development server proxy on Windows. All reqwest-* feature flags have been removed because reqwest is now the client we use.

Native Mobile Functionality for Tauri Plugins

A Tauri plugin now can access iOS via Swift and Android APIs via Kotlin or Java code, simplifying usage of platform interfaces such as camera or geolocation. To bootstrap the iOS and Android projects on an existing plugin, run tauri plugin ios add and tauri plugin android add. New plugins automatically include all the configuration needed to write native mobile code.

Heres an example of a plugin that takes a string value and resolves an object:

Android plugin:

ExamplePlugin.kt

package com.plugin.example


import android.app.Activity
import app.tauri.annotation.Command
import app.tauri.annotation.TauriPlugin
import app.tauri.plugin.JSObject
import app.tauri.plugin.Plugin
import app.tauri.plugin.Invoke


@TauriPlugin
class ExamplePlugin(private val activity: Activity): Plugin(activity) {
    @Command
    fun ping(invoke: Invoke) {
        val value = invoke.getString("value") ?: ""
        val ret = JSObject()
        ret.put("value", value)
        invoke.resolve(ret)
    }
}

iOS plugin:

ExamplePlugin.swift

import UIKit
import WebKit
import Tauri


class ExamplePlugin: Plugin {
  @objc public func ping(_ invoke: Invoke) throws {
    let value = invoke.getString("value")
    invoke.resolve(["value": value as Any])
  }
}


@_cdecl("init_plugin_example")
func initPlugin(name: SRString, webview: WKWebView?) {
  Tauri.registerPlugin(webview: webview, name: name.toString(), plugin: ExamplePlugin())
}

Rust code to initialize the plugin:

use tauri::{
  plugin::{Builder, TauriPlugin},
  Manager, Runtime,
};


#[cfg(target_os = "ios")]
tauri::ios_plugin_binding!(init_plugin_example);


pub fn init<R: Runtime>() -> TauriPlugin<R> {
  Builder::new("example")
    .setup(|app, api| {
      #[cfg(target_os = "android")]
      api.register_android_plugin("com.plugin.example", "ExamplePlugin")?;
      #[cfg(target_os = "ios")]
      api.register_ios_plugin(init_plugin_example)?;
      Ok(())
    })
    .build()
}

Frontend code to call the plugin command:

import { invoke } from '@tauri-apps/api/tauri';
invoke('plugin:example|ping', { value: 'Tauri' }).then(({ value }) =>
  console.log('Response', value)
);

Check out the upcoming camera plugin and path plugin.

Announcing the Tauri v2 Beta Release

Hero Image

Tauri v2 has been in progress for over a year and it is now ready to take the next step towards being stable! We have just released Tauri v2.0.0-beta.0 which represents a major milestone from our roadmap.

The v2 release introduces mobile support to Tauri and also comes with several new features that have been requested by the community. Lets get a high level overview of the major changes:

Mobile

Developing an application for desktop and mobile has never been easier. Tauri v2 is a huge statement on cross platform development now that we support Android and iOS. You can bring your existing desktop implementation and seamlessly port it to mobile, with access to native APIs and the great developer experience of the Tauri CLI.

Permissions

The v1 allowlist is a good tool for securing your frontend from accessing unnecessary APIs, but its configuration is not fine grained and it lacks multiwindow support. The 2.0.0-beta.0 release includes a new approach for command access based on Access Control List. It is now possible to allow commands and define scopes for specific windows or even remote URLs.

New Features

v2 includes many of the most requested features by the Tauri community:

Revamped IPC

The v1 Inter-Process Communication (IPC) which is responsible for delivering messages between the Rust and JavaScript layers uses a very rudimentary webview interface which forces us to serialize all messages to strings and is super slow to deliver responses. The new v2 IPC uses custom protocols, which is more reminiscent in function and performance to how the webview handles regular HTTP based communication, see the pull request for more information.

Additionally, there is a new channel API so you can quickly send data from Rust to your frontend.

Multiwebview

Tauri now supports adding multiple webviews to a single window. This is also a highly anticipated feature request. Note this is still an unfinished feature that is hidden behind an unstable Cargo feature flag while we review the API design together with the community.

Menu and tray icon JavaScript APIs

Previously you could only configure window menus and tray icons via Rust code. Now you can do so on the JavaScript side too, which is a lot easier! We also added APIs to manage the macOS application menu specifically.

Context Menus

One of the most requested features is native context menus. It is finally available with both Rust and JavaScript APIs powered by muda.

Window APIs

Several new window APIs have been implemented, making your app much more configurable.

Mobile APIs

The v2 release comes with some mobile native API support by default. Currently there is support for notifications, dialogs, NFC, barcode reading, biometric authentication, clipboard and deep link. More APIs will be added soon after the stable release.

Audit

We are currently being audited to ensure v2 is safe, similar to what we did for the v1 stable release.

Stability

The API is not stable yet, but no major changes are expected. As soon as the audit is completed and the changes are done, we will promote to a Release Candidate and a v2 stable release soon after that. Stay tuned!

Tauri 2.0 Release Candidate

We are very proud to finally announce the first release candidate for the new major version of Tauri.

After over half a year of beta versions, following over a year of alpha versions we are finally at the point where we consider Tauri 2 stabilized and do no longer expect breaking changes.

We want to use a comparably short release candidate time frame to focus on our documentation and important bug fixes, which have been reported by our awesome community and working group members.

A simplified TL;DR can be found at the end of this post.

The Road to Stable and Beyond

With this release candidate we want to communicate our expectations and timeline for the stable release.

We have been asked countless times “Wen Tauri 2.0?” and always gave broad answers. Especially in open source projects overpromising can be a quick way to burn out developers and maintainers or lead to angry comments from disappointed adopters.

This is one of the reasons for the long alpha and beta stage and why we waited with the release candidate, as we strive to get things right and simple to use.

Another reason is that we made the mistake of overpromising this major version with “mobile as a first class citizen” and realized over the past months that we can only build the foundation for mobile on our own and need to iterate on this together with the community and our adopters to get it right.

This doesnt mean that mobile is broken and unsupported. We have mobile plugins in our official plugin repository and have seen developers who have built cool apps on Android and iOS with Tauri.

Our partner CrabNebula also provided us with feedback on how easy (or complicated) the developer experience was when they built or supported mobile applications for customers. They even contributed multiple mobile plugins (NFC, Barcode Scanner, Biometric, Haptics, Geolocation) as part of their work.

We see improvements to be made in the development experience for mobile and we acknowledge that not all of our desktop features and plugins are ported or available on mobile yet.

This causes us to say that we dont want to raise expectations that Tauri 2.0 will be themobile as a first class citizen” release but we want to make clear that you can develop production ready mobile applications with Tauri NOW.

What you can expect from stable after this release candidate is:

  • Clearer and comprehensive documentation
  • Less critical bugs preventing productive usage

We plan to release the stable version for 2.0 in the end of August. This will, at the time of writing, allow for a ~4 week release candidate cycle.

After the stable release our focus will be shifting to providing feature parity wherever possible and to improve the development process for mobile. This will happen in minor releases of Tauri.

Feature parity and plugin development will be aligned with major versions of Tauri but will be mostly independent from Tauri core features and happen in our plugin-workspace repository.

Developer experience is a very important topic for us. If you have improvement suggestions or want to improve the status quo on your own please do not hesitate to reach out with PRs, issues or friendly conversations on our discord server.

Breaking Changes

Before we enter the “no more breaking changes” expectation phase we discussed and planned some from our perspective necessary breaking changes a while ago.

These changes affect a lot of developers, so we wanted to bundle them and make it as painless as possible to upgrade from the latest beta to release candidate or stable.

For app developers we have breaking changes in how core plugins are referenced in the permissions.

You should be able to automatically migrate from the latest beta to release candidate. For this to succeed you must be sure to be on the latest (RC not beta) version of the Tauri CLI.

Automated Migrate

  • npm

    npm install @tauri-apps/cli@next
    npm run tauri migrate
    
  • yarn

    yarn upgrade @tauri-apps/cli@next
    yarn tauri migrate
    
  • pnpm

    pnpm update @tauri-apps/cli@next
    pnpm tauri migrate
    
  • cargo

    cargo install tauri-cli --version "^2.0.0-rc" --locked
    cargo tauri migrate
    

Otherwise please read the detailed section below explaining the changes and how to manually migrate.

For downstream consumers of Tauri as a library or app developers fiddling with the internals of Tauri we have a bigger refactor you should check out.

Tauri Core Plugins

With Tauri 2.0 we migrated most of the 1.x core functionality into separate plugins, which allows us to iterate on these independently of Tauris core and lowers the barrier for first contributors on functionality.

This migration also included keeping some functionality inside Tauri as pseudo plugins. Fully qualified plugins need to implement the Plugin Trait and need to be individual crates following the tauri-plugin-<plugin name> naming scheme. For core plugins, the second condition was not possible as we would have circular dependencies on Tauri. So we created pseudo plugins, which are always initialized by Tauri itself and only implement the plugin trait. These are for example window, path or webview. Right now these are allowed in the capabilities of your Tauri application in the following way:

...
"permissions": [
    "path:default",
    "event:default",
    "window:default",
    "app:default",
    "image:default",
    "resources:default",
    "menu:default",
    "tray:default"
]
...

This has multiple problems:

  • Any plugin crate which has a colliding name will break our build process (e.g. tauri-plugin-window crate) and our cli for adding plugins (e.g. cargo tauri add window)
  • We cant use any core pseudo plugin naming that is already used by existing plugins (e.g. if we would ever want to createtauri-plugin-mobile-core and it is already used we will encounter the first problem)
  • It is unclear for developers what is a core plugin and what is a dedicated plugin when looking at capabilities

Our approach is to use a fixed namespace for core plugins, which is documented and enforced by the Tauri core. All plugins starting with core: or the plugin name core are now considered core pseudo plugins and will only be initialized if they are in the Tauri codebase.

This will cause a breaking change to all capabilites enabling Tauri core features. The above example will be changed to look like this:

...
"permissions": [
    "core:path:default",
    "core:event:default",
    "core:window:default",
    "core:app:default",
    "core:image:default",
    "core:resources:default",
    "core:menu:default",
    "core:tray:default"
]
...

We also added a new special core:default permission set which will contain all default permissions of all core plugins, so you can simplify the permissions boilerplate in your capabilities config.

...
"permissions": [
    "core:default"
]
...

We consider the core default exposure to be reasonably secure and safe to enable by default, with limited impact in case of a compromised frontend.

To migrate from the latest beta version you need to prepend all core permission identifiers in your capabilities with core: or switch to the core:default permission and remove old core plugin identifiers.

Development Server for Mobile

We introduced changes to the network exposure of the built-in development server PR #10437 and PR #10456. With the changes shipped in the 2.0.0-rc.0 release of the Tauri CLI, we can connect to your development server running on localhost when targetting Android and iOS (previously this was only possible when developing a desktop application).

This means you no longer need to expose your development server on the public network.

Note

When running your app on a physical iOS device we actually need to bind the development server on a TUN address provided by the device.

This kind of connection is currently only possible when Xcode is opened and connected to your device, so we do not use this interface by default - we have to bind your development server to your public network address while we find out a way to connect to the device ourselves.

To use the iOS devices address instead of the public network, run tauri ios dev --force-ip-prompt to select the iOS devices TUN address (ends with ::2).

The IP address your frontend must listen to is provided by the TAURI_DEV_HOST environment variable.

Heres an example of a Vite configuration migration:

  • 2.0.0-beta:
import { defineConfig } from 'vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';
import { internalIpV4Sync } from 'internal-ip';


const mobile = !!/android|ios/.exec(process.env.TAURI_ENV_PLATFORM);


export default defineConfig({
  plugins: [svelte()],
  clearScreen: false,
  server: {
    host: mobile ? '0.0.0.0' : false,
    port: 1420,
    strictPort: true,
    hmr: mobile
      ? {
          protocol: 'ws',
          host: internalIpV4Sync(),
          port: 1421,
        }
      : undefined,
  },
});
  • 2.0.0-rc:
import { defineConfig } from 'vite';
import Unocss from 'unocss/vite';
import { svelte } from '@sveltejs/vite-plugin-svelte';


const host = process.env.TAURI_DEV_HOST;


export default defineConfig({
  plugins: [svelte()],
  clearScreen: false,
  server: {
    host: host || false,
    port: 1420,
    strictPort: true,
    hmr: host
      ? {
          protocol: 'ws',
          host: host,
          port: 1430,
        }
      : undefined,
  },
});

Note

This means the internal-ip NPM package is no longer required, you can directly use the TAURI_DEV_HOST value instead.

Rust API Surface Refactor

With a coordinated effort between multiple working group members we partially changed our Rust API exposure. This affects only consumers of our Rust API and should have no breaking change impact for Tauri application developers.

This was motivated by a recent security advisory CVE-2024-35222, as the fix needed to introduce additional fields to a structure that was directly publicly exposed and caused breaking changes to some projects and internal usage.

We concluded that this overexposure will hinder us in the future and will cause unnecessary breaking changes, so we decided that going from beta to RC will be the last chance for us to implement this until we start down the road of Tauri 3.0.

We reduced the amount of publicly exposed components, which are meant for internal use. Additionally, we made our publicly exposed structures either non-exhaustive or transformed them into exposing builder patterns or constructors. In some cases we added a new extend field to allow dynamic additions in the future. Finally, we made sure to document which modules of Tauri are considered unstable.

This will help us to provide (security) fixes or changes without breaking interfaces that are considered stable.

Please take a closer look at the introduced and discussed changes in the #10158 pull request.

External Security Audit

TL;DR

The audit concluded some time ago and all issues were fixed and retested. Report is here. Please upgrade to the release candidate to ensure fixes for the reported issues.

We have been quiet on this front for some time as we have been busy fixing and discussing issues discovered during the beta versions.

We never marketed version 2 beta releases as production ready but were aware of some apps deployed into production. This caused us to announce and distribute a security patch for one of the findings (CVE-2024-35222) which was also independently discovered by a Tauri community member.

All other findings were fixed in multiple beta versions but we did not create advisories for these. We concluded a full heads up could wait until the release candidate, as the findings mainly affect the development phase or have no critical severity.

With the release candidate we will add the full report to our repository. Please take your time to read the report and learn more about the awesome work of @gronke and @pcwizz from RadicallyOpenSecurity.

The whole audit was funded by the great folks at NLNet and we are super grateful to be in the privileged position to get fully funded external security audits.

Call to Action

All of the above topics share a common theme. These would not have been possible without the continuous support of the community, our working group and other movements working towards improving the status quo.

Before we are going to release Tauri 2.0 we want to make sure that your voices are heard, your PRs are acknowledged and the documentation is helpful for YOU so that you can build the next generation of cross platform apps.

Currently we have over 30 people in our working group on Github but even more involved in our Discord. These awesome people are mostly working on Tauri in their free time with very few exceptions. We currently see a number of issues, PRs and discussions being unsolved and open for longer than we would like to.

To improve this situation we ask YOU to get involved into the Tauri project.We have all kinds of situations where we are able to accept event the tiniest contribution.

If you are familiar with Tauri and have used it already during your journey, please take your time to check out the Github Discussions, Github Issues and our Discord Support. Maybe you have already solved the issues your fellow newcomers to Tauri are experiencing right now.

If you think that some of these problems you have seen are generic and should be documented somewhere we probably have the perfect place for it in our official documentation.

To contribute improvements or additions we are open for PRs in the tauri-docs repository. Please make sure youve read the guidelines for contribution though.

If you are in the position to understand and translate the current documentation into your native language we appreciate content translations to our documentation.

If you have followed our project for a while but never made a contribution we would be happy to understand what has prevented you from doing so and how we could improve this. Please reach out to us in our Discord or in our Github Discussions.

Too Long Didnt Read

  • Tauri 2.0 Release Candidate out now!
  • Some migration from beta is needed. Check out tauri migrate.
  • External Security Audit for 2.0 is available here
  • All findings are fixed and fixes were verified
  • Documentation is our focus until stable release
  • Tauri is looking for more contributors and community involvement

Tauri 2.0 Stable Release

We are very proud to finally announce the stable release for the new major version of Tauri. Welcome to Tauri 2.0!

What is Tauri?

Definition

Tauri is a framework for building tiny and fast binaries for all major desktop (macOS, linux, windows) and mobile (iOS, Android) platforms.

Developers can integrate any frontend framework that compiles to HTML, JavaScript, and CSS for building their user experience while leveraging languages such as Rust, Swift, and Kotlin for backend logic when needed.

In a Tauri application the frontend is written in your favorite web frontend stack. This runs inside the operating system WebView and communicates with the application core written mostly in Rust.

a graph showing the IPC bridge between the Application Core and the System’s WebView

No Rust Skills Needed!

You dont need to write Code in Rust, Swift or Kotlin in most cases. Tauri already offers an extensive JavaScript API.

When Should I Use Tauri?

If you check any of the boxes below, you should use Tauri:

  • Do you want a single UI codebase for all platforms?
  • Do you want to reach as many users as possible on their platform (eg. Windows, MacOS, Linux, Android, iOS)?
  • Are you a frontend web developer and want to write native applications?
  • Are you a Rust developer looking to write applications with a nice looking UI with the option to do it in Rust?
  • Do you have an existing team of web developers and want to expand to native application markets with low upfront investment?
  • Do you have an existing team of rustaceans and want everything written in Rust?

a graph showing the progression of Tauri GitHub stars over the years, starting with 0 at 2019 and continuing to grow past 80.000 in 2024

On GitHub the Tauri repository has ~4,878 Pull Requests and ~3,570 Issues closed and around 1000 discussions, at the time of writing. To get a more detailed insight take a look at the OSSinsight analysis of the Tauri repository.

Our Discord Server currently has ~17,700 members. We are seeing a lot of individual user support, questions on Tauri itself, questions directly to the working group or just discussions between fellow Tauri app developers.

We are very happy about the positive and supportive community and grateful to all the community members answering or helping others in Discord or GitHub.

We maintain a curated list of Tauri related projects, applications, plugins, guides and more at awesome-tauri. Check this out if you want to get inspiration, see what others are building and ideally create a PR to add your project.

Of course this is only a representative sample set and we dont know exactly who else is building on Tauri.

How Did We Get to 2.0?

In June 2022 we released Tauri 1.0 with a great impact on the desktop operating system market and how cross platform applications can be built.

In the end of 2022 we released our initial alpha version of 2.0 to get initial feedback and to test out how mobile interaction should be defined.

After the initial alpha we spent close to two years refining and changing the architecture of Tauri in public. After we saw the broad picture clear enough ourselves we released the beta in Februrary this year. At the same time we collaborated and worked with external security auditors to check our decisions, architecture changes and much more.

This August we published the release candidate version of 2.0 to iron out major bugs and to get more feedback from productive use. At the same time the external audit was concluded and made public.

The release candidate time frame was considerably shorter and consisted mainly of high impact bugfixes and documentation improvements. Some breaking changes we had to make during the release candidate phase were bundled up until the end and are now included in the stable release. Take a look at the migration section if your main concern is upgrading from a previous version.

In total we spent over two years working on improvements, new features, bugfixes, documentation, rewrites and a lot of discussions.

This all happened while we released 8 minor versions of the Tauri 1.x branch and backported security fixes and other important bug fixes in several patch releases.

Who Made This Release Possible?

This release and Tauri itself is only possible due to massive amount of contributions from Lucas, who has provided a constant stream of code changes over the years ❤️.

Lucas’ contribution graph, with 2744 commits, over 896.000 additions and 688.000 deletions.

Obviously, Lucas is not the only individual working and contributing to Tauri, but we feel he deserves a very special mention for carrying, starting, and supporting the project and its community throughout the years.

We have had major contributions to the Tauri repository in 2.0 from Amr, Fabian-Lars, Tony, Chip, Jason, YuWei, icb , Simon, Oliver Lemasle and many more contributors (source data).

We received an increasing number of drive-by contributors (one or very few PRs). We are grateful for these, but naming everyone would make this a very long list here.

We have a lot(!) of repositories in our organization, which are supporting the success of Tauri and without community and working group contributions Tauri would not be where it is now. A big thank you to everyone involved!

Another special shout out and thanks for their constant involvement in the community goes to Fabian-Lars and Simon. If you have been involved in Tauris Discord or Github discussions you likely know their name or avatar.

If you ever searched on Google or YouTube for Tauri, you have probably seen one of Jacobs streams. If thats not the case please make sure to check it out and subscribe as his sessions are beyond just educational.

Another special place in our heart has the Tauri Board, highlighting Daniel Yvetot-Thompson for the numerous hours, sweat, blood and dedication to make Tauri known and sustainable.

One important thing we should not forget, is that we acquired support from a stable partner of this open source project.

CrabNebula Logo

CrabNebula granted multiple people mentioned above and others that are not mentioned here, the privilege to work on the Tauri ecosystem not only in their private time, but also during work time. You can find the partnership announcement on our blog and we have been more than happy about this collaboration over the last year.

In 2024 alone they spent over 2,870 work hours on this project, which massively pushed the progress and allows us to announce the stable 2.0 release today.

If you were not aware of CrabNebula yet, make sure to check out their products and services and consider the symbiotic relationship with Tauri if you are interested in not only improving your workflows, but also supporting the Tauri ecosystem.

What Makes 2.0 Great?

With this major release we improved and changed several aspects of how and where you can build, develop and publish your Tauri app. In the following sections we have more detailed insight. This does not cover everything, but should give you a decent impression on what you can expect from Tauri.

Getting Started Experience

One thing you are always going to go through when starting with a new framework or tool is the initial onboarding or getting started process.

We value developer experience (DX) and try to make this initial process as seamless as building and distributing your final application.

For this we created another project, which is called create-tauri-app or in short CTA. This tool allows developers to start from scratch and get to a running Tauri app in a few minutes instead of hours.

  • Bash

    sh <(curl https://create.tauri.app/sh)
    
  • PowerShell

    irm https://create.tauri.app/ps | iex
    
  • Fish

    sh (curl -sSL https://create.tauri.app/sh | psub)
    
  • npm

    npm create tauri-app@latest
    
  • Yarn

    yarn create tauri-app
    
  • pnpm

    pnpm create tauri-app
    
  • deno

    deno run -A npm:create-tauri-app
    
  • bun

    bun create tauri-app
    
  • Cargo

    cargo install create-tauri-app --locked
    cargo create-tauri-app
    

Of course you need to install some prerequisites on your development system before you can start building your application. For this we have extensive guides with operating system specific sections in our official documentation.

This whole onboarding experience has been improved and now also bootstraps mobile development templates for iOS and Android.

Hot-Module Replacement

After the initial onboarding you will regularly develop and debug your Tauri application. We considered what would improve your development process already in 1.x of Tauri and extended the Hot-Module Replacement (HMR) to mobile devices and emulators.

This means that all changes to the frontend of your application do not require a rebuild of your whole application and you can live preview how it will look like in the device or operating system your are developing for.

Your browser does not support the video tag.

Plugins

With Tauri 2.0 we built a more advanced plugin system. We transferred a lot of our previous functionality into our official plugins (see plugins-workspace), to allow the community an easier entry into contributing to Tauri. We also hope to attract more maintainers for plugins and to speed up the process of implementing new features.

This move to plugins has another benefit. We are going to be able to define a definition of done for Tauris core. We hope to stabilize the core functionality and offer a stable framework, where the moving parts are mostly plugins offering access to system specific functionality.

You no longer need to understand all of Tauri to improve or implement specific features. The plugins usually do not depend on other plugins, with some exceptions. This means to implement a new file system access functionality it is only required to contribute to the fs plugin instead of Tauri itself.

As this release also targets mobile platforms, the plugin system also supports mobile plugins. You can write or re-use native code in Swift on iOS and Kotlin on Android and directly expose functions to the Tauri frontend using Annotations (@Command on Android), implementing a Subclass (YourPluginClass: Plugin) on iOS, or by invoking the Swift or Kotlin code from a Rust based Tauri command. Check out the documentation on how to write your own plugin.

As we are releasing Tauri as 2.0, the official plugins will follow the major version of Tauri to make compatibility with Tauris major version visible at a glance. Not all plugins are as stable as Tauri itself though.

Each plugins stableness is defined per plugin and documented (soon) in the plugin documentation. The plugin API can possibly break in minor versions, but we will try to keep these changes to a minimum, especially for plugins considered stable.

Tip

You can pin your plugin versions to only patch updates if you need absolute stable interfaces. We generally try to backport security updates and will announce advisories on GitHub.

Autostart

Automatically launch your app at system startup.

Barcode Scanner

Allows your mobile application to use the camera to scan QR codes, EAN-13 and other types of barcodes.

Biometric

Prompt the user for biometric authentication on Android and iOS.

Clipboard

Read and write to the system clipboard.

Command Line Interface (CLI)

Parse arguments from the command line interface.

Deep Linking

Set your Tauri application as the default handler for an URL.

Dialog

Native system dialogs for opening and saving files along with message dialogs.

File System

Access the file system.

Geolocation

Get and track the device's current position, including information about altitude, heading, and speed (if available).

Global Shortcut

Register global shortcuts.

Haptics

Haptic feedback and vibrations on Android and iOS

HTTP Client

Access the HTTP client written in Rust.

Localhost

Use a localhost server in production apps.

Logging

Configurable logging.

NFC

Read and write NFC tags on Android and iOS.

Notifications

Send native notifications to the user.

Opener

Open files and URLs in external applications.

OS Information

Read information about the operating system.

Persisted Scope

Persist runtime scope changes on the filesystem.

Positioner

Move windows to common locations.

Process

Access the current process.

Shell

Access the system shell to spawn child processes.

Single Instance

Ensure that a single instance of your Tauri app is running at a time.

SQL

Tauri Plugin providing an interface for the frontend to communicate with SQL databases through sqlx.

Store

Persistent key value storage.

Stronghold

Encrypted, secure database.

Updater

In-app updates for Tauri applications.

Upload

File uploads through HTTP.

Websocket

Open a WebSocket connection using a Rust client in JavaScript.

Window State

Persist window sizes and positions.

Mobile Support

A very much awaited part of this release is the mobile operating system support. The previous version of Tauri allowed to have a single UI code base for desktop operating systems but now this extends to iOS and Android.

We have investigated and experimented with different solutions to support mobile and decided on using the operating system native language (Swift and Kotlin) to build an interface for the Rust code and to allow developers to write part of their functionality in these languages.

This means you can re-use existing logic of your Swift or Kotlin app that interacts with the system and expose it to Rust or the frontend. Right now this works as mentioned above via the plugin system.

We support development with an emulator or a real device and provide a lot of tooling to make the process as seamless as possible. We are not completely happy about the developer experience at the moment but are actively improving to bring it up to par with the desktop experience.

On mobile not all of the official plugins are supported. Some are by design not a good fit for mobile and some are just not implemented to support mobile yet. If you would like to contribute on this part check the last section of this post.

The Allowlist is Dead, Long Live the Allowlist

Yes, there is no allowlist anymore, as we hit the limits of this system pretty quickly. We made it exclusive for Tauri core features and it did not even cover all of Tauris APIs. Our new system not only covers all of Tauris core API surface, it also supports app and plugin developers to implement their own access control and scoping with a unified approach.

The new system we implemented is using permissions - “On-off toggles for Tauri commands”, scopes - “Parameter validation for Tauri commands” and capabilities - “Attaching permissions and scopes to Windows and WebViews”, to create a flexible but simple to use access control system.

It allows the creation of named permission or scoping files and to re-use and combine them with other named permissions or scopes. This makes it possible to build more fine grained descriptive sets containing several simple or complex permissions and scopes.

As a plugin developer you can abstract away several base permissions into a default permission. This can be based on your default security assumptions and threat model. All official Tauri plugin default permissions are reasonably secure by default.

As an app developer you can use, extend or reduce plugin permissions. Of course you can also build permissions and scopes for your own application.

With this addition, Tauris core is now able to understand if a command invoke message from a frontend WebView is allowed to reach the command function. It is also able to attach the configured scope to the message.

The command implementation is responsible for interpreting and enforcing the scope. You can read more about our Threat Model and approach to security in our documentation.

External Security Audit

The major changes and architecture of v2 was independently audited by Radically Open Security during the beta and release candidate period. Please take your time to read the report and learn more about the awesome work of @gronke and @pcwizz.

The whole audit was funded by the great folks at NLNet via funding from NGI and we are super grateful to be in the privileged position to get fully funded external security audits for major releases.

The results of this audit caused us to rewrite parts of how our dev server is exposed, specifically for mobile development. Without the help and guidance of the auditors this rewrite would not have been possible ❤️.

Additionally, we hardened our iFrame API exposure, fixed scope validation and resource identifier access for the fs and http plugin, improved our inter-process communication stability, and many other security related fixes and improvements.

Inter Process Communication (IPC) Rewrite

With the rewrite of our IPC layer we now support a long wished feature of Raw Payloads and generally changed how it works under the hood.

Previously all IPC payloads were json serialized and deserialized which caused an overhead. This was noticeable once more than a few kilobytes were transfered between frontend and backend.

The new system supports Raw Requests. These speed up the transfer of large data from backend to frontend and vice versa, where you can either use raw bytes directly or use your own (de)serialization process (eg. bson, protobuf, avro and others).

For directly reading files from the filesystem into the WebView we still recommend the convertFileSrc functionality, as it is most likely still faster if you do not need to process the data on the Rust backend.

Distribution Guides

With Tauri 2.0 the distribution diversity greatly increased. Partially, due to the mobile ecosystem and partially due to our community contributions.

We have official guides on how to ship to the Apple Appstore, Google Play, Microsoft Store, CrabNebula Cloud, Flathub, Snapcraft, AUR and more distribution formats in our distribution docs.

Github Action

Our GitHub action (tauri-action) is in progress to support automated building for the mobile operating systems but does not support it yet.

Changelog

This section contains all changes going from 1.x in a concise list.

Show the Full List

Added

  • Added Mobile support.

  • Added multiwebview support behind the unstable feature flag. See WindowBuilder and WebviewBuilder for more information.

  • Added rustls-tls cargo feature flag

  • Added shadow option when creating a webview window,WebviewWindow::set_shadow method in Rust and equivalent API in JS.

  • Added tauri::Webview, tauri::WebviewBuilder, tauri::WebviewWindow, tauri::WebviewWindowBuilder structs in Rust and equivalent classes in Js. The old tauri::Window and tauri::WindowBuilder behaviors have moved to tauri::WebviewWindow and tauri::WebviewWindowBuilder.

  • Added tauri::scope::fs module

  • Added tauri::App/AppHandle::default_window_icon method.

  • Added tauri::ipc module with IPC primitives.

  • Added tauri::ipc::Channel type and equivalent JS Channel type to send data across the IPC.

  • Added incognito option when creating a webview window.

  • Added windowEffects option when creating a webview window and WebviewWindow::set_effects to try and change effects at runtime.

  • Added tauri::path::PathResolver

  • Added tauri::Manager::path method to access the new PathResolver

  • Added visibleOnAllWorkspaces option when creating a webview window.

  • Added tauri::App/AppHandle::primary_monitor and App/AppHandle::available_monitors methods.

  • Added tauri::plugin::Builder::on_navigation and tauri::plugin::Plugin::on_navigation.

  • Added tauri::WebviewWindow::navigate method

  • Added tauri::RunEvent::Opened on macOS and iOS for deep link support.

  • Added file associations support in bundler.

  • Added tauri::App/AppHandle::cleanup_before_exit to manually call the cleanup logic. You should always exit the tauri app immediately after this function returns and not use any tauri-related APIs.

  • On Linux, add tauri::WebviewWindow::default_vbox method to get a reference to the gtk::Box that contains the menu bar and the webview.

  • Added linux-libxdo cargo feature flag (disabled by default) to enable linking to libxdo which is used to make Cut, Copy, Paste and SelectAll native menu items work on Linux.

  • On macOS, add tauri::WebviewWindow::ns_view method to get a pointer to the NSWindow content view.

  • Added tauri::Builder::register_asynchronous_uri_scheme_protocol to allow resolving a custom URI scheme protocol request asynchronously to prevent blocking the main thread.

  • Included drop and hover position for drag and drop events.

  • Added tauri::WebviewWindow::set_progress_bar method

  • Added tauri::WebviewWindow::set_always_on_bottom method and alwaysOnTop option when creating a webview window.

  • Added tauri::WebviewWindowBuilder::on_page_load method.

  • Added common-controls-v6 cargo feature flag (enabled by default).

  • Added Window::destroy to force close a window.

  • Added tauri::EventId type

  • Added tauri::WindowBuilder::on_download to handle download request events.

  • Added tauri::WebviewWindowBuilder::parent which is a convenient wrapper around parent functionality for Windows, Linux and macOS.

  • Added tauri::WebviewWindowBuilder::owner on Windows only.

  • Added tauri::WebviewWindowBuilder::transient_for and tauri::WebviewWindowBuilder::transient_for_raw on Linux only.

  • Added tauri::WebviewWindow::start_resize_dragging and tauri::ResizeDirection enum.

  • Added tauri::WebviewWindowBuilder::proxy_url method.

  • Added tauri::WebviewEvent enum

  • Added tauri::RunEvent::WebviewEvent variant.

  • Added tauri::Builder::on_webview_event and tauri::Webview::on_webview_event methods.

  • Added tauri::image module which includestauri::image::Image and tauri::image::JsImage types and tauri::image::include_img! macro.

  • Added tauri::is_dev function to determine whether the app is running in development mode or not.

  • Added tauri::Assets::setup method on tauri::Assets trait that lets you run initialization code for your custom asset provider.

  • Added tauri::Rect struct.

  • Added tauri::WebviewWindow::set_zoom method

  • Added zoomHotkeys option when creating a webview window.

  • Added window.isTauri JS global function to check whether running in tauri or not.

  • Added specta feature flag which adds specta support for AppHandle, State, Window, Webview and WebviewWindow types.

  • Added tauri::App/AppHandle/WebviewWindow::cursor_position getter to get the current cursor position.

  • Added tauri::App/AppHandle/WebviewWindow::monitor_from_point(x,y) getter to get the monitor from a given point..

  • Added tauri::RunEvent::Reopen to handle click on dock icon on macOS.

  • Added defaultWindowIcon to the JS app module to retrieve the default window icon in JS.

  • Added tauri::WebviewWindow::set_title_bar_style to set title bar at runtime on macOS.

  • Add APIs to enable setting window size constraints separately:

    • Added tauri::WindowBuilder::inner_size_constraints and tauri::WebviewWindowBuilder::inner_size_constraints
    • Added tauri::WindowSizeConstraints struct
    • Added tauri::Window::set_size_constraints and tauri::WebviewWindow::set_size_constraints

Enhancements

  • Use custom protocols on the IPC implementation to enhance performance.

  • Enhance centering a newly created window, it will no longer jump to center after being visible.

  • The custom-protocol Cargo feature is no longer required on your application and is now ignored. To check if running on production, use #[cfg(not(dev))] instead of #[cfg(feature = "custom-protocol")].

  • Improved the JS path APIs to return simplified paths on Windows when possible, i.e removing UNC (\\?\) prefix.

  • Improved the error message that is shown when deserializing the Tauri plugin config.

  • Set the gtk application id to the identifier defined in tauri.conf.json to ensure the app uniqueness. This can be disabled by setting enableGtkAppId option to false.

  • On Windows, handle resizing undecorated windows natively which improves performance and fixes a couple of annoyances with previous JS implementation:

    • No more cursor flickering when moving the cursor across an edge.
    • Can resize from top even when data-tauri-drag-region element exists there.
    • Upon starting rezing, clicks dont go through elements behind it so no more accidental clicks.
  • Mark AppHandle::restart and process::restart as diverging functions

Bug Fixes

  • No longer unpacking and flattening the payload over the IPC so that commands with arguments called cmd, callback, error, options or payload arent breaking the IPC.
  • Fix calling set_activation_policy when the event loop is running.
  • Fix can not prevent closing a window from another webview.
  • On Windows, fix decorated window not transparent initially until resized.
  • Resolve symlinks on the filesystem scope check.
  • Fix the JS basename(path, 'ext') API implementation removing all occurances of ext where it should only remove the last one.
  • Fix window white flashing on exit on Windows
  • Apply minWidth, minHieght, maxWidth and maxHeight constraints separately, which fixes a long standing bug where these constraints were never applied unless width and height were constrained together.

Changed

  • The window creation and setup hook are now called when the event loop is ready.
  • Renamed the default-tls feature to native-tls and.
  • Changed the plugin setup hook to take a second argument of type PluginApi
  • Changed tauri::Window struct behavior and moved its old behavior to the new tauri::WebviewWindow type.
  • Moved tauri::api::path module to tauri::path
  • Moved all functions from tauri::api::path to be methods on tauri::path::PathResolver
  • Renamed system-tray feature flag to tray-icon.
  • Changed tauri::App::handle and tauri::Manager::app_handle methods to return a reference to an AppHandle instead of an owned value.
  • Changed tauri::Builder::register_uri_scheme_protocol to return a http::Response instead of Result<http::Response>. To return an error response, manually create a response with status code >= 400.
  • The custom protocol on Windows and Android now uses the http scheme instead of https.
  • Changed tauri::Env.args to tauri::Env.args_os and now uses OsString instead of String
  • Changed TAURI_AUTOMATION env var to TAURI_WEBVIEW_AUTOMATION
  • Changed tauri::Builder::invoke_system to take references instead of owned values.
  • Changedtauri::Builder::invoke_system, tauri::Builder::on_page_load hooks to take a tauri::Webview argument instead of a tauri::Window.
  • Moved the tauri::command module items to the tauri::ipc module so its import name does not clash with the tauri::command macro.
  • Changed tauri::App::run_iteration to take a callback and removed its return value.
  • Changed AppHandle::exit and AppHandle::restart to trigger RunEvent::ExitRequested and RunEvent::Exit
  • Renamed tauri::WebviewWindowBuilder::owner_window to tauri::WebviewWindowBuilder::owner_raw and tauri::WebviewWindowBuilder::parent_window to tauri::WebviewWindowBuilder::parent_raw.
  • Renamed the window-data-url feature flag to webview-data-url.
  • Changed tauri::WebviewWindow::close to trigger a close requested event instead of forcing the window to be closed. Use tauri::WebviewWindow::destroy to force close.
  • Renamed icon-ico and icon-png feature flags to image-ico and image-png respectively.
  • Removed tauri::Icon enum, use the new tauri::Image type instead. All APIs that previously accepted tauri::Icon have changed to accept tauri::Image instead.
  • Changed tauri::Context struct and tauri::Assets trait to have a R: Runtime generic.
  • Renamed tauri::Context::assets_mut to tauri::Context::set_assets
  • Changed tauri::Context type to not have <A: Assets> generic so the assets implementation can be swapped with Context::set_assets.
  • Changed tauri::Context::assets to return &dyn Assets instead of &A generic.
  • Renamed tauri::FileDropEvent enum to tauri::DragDropEvent and renamed its variants. Also renamed the js events
  • Renamed tauri::WindowEvent::FileDrop enum variant to tauri::WindowEvent::DragDrop
  • Renamed file drop emitted events to tauri://drag-enter, tauri://drag-over, tauri://drag-drop, and tauri://drag-leave
  • Renamed tauri::WebviewWindow::disable_file_drop_handler to tauri::WebviewWindow::disable_drag_drop_handler.
  • Changed tauri::WebviewWindow::url getter to return a result.
  • Changed tauri::Env.args_os, to include the binary path, previously it was skipped.
  • Renamed getAll and getCurrent to getAllWindows and getCurrentWindow in the JS window module but you probably want getAllWebviewWindows and getCurrentWebviewWindow from the webviewWindow module.

Removed

  • The reqwest-* Cargo features were removed
  • UpdaterEvent
  • Removedtauri::api module and moved them into standalone plugins in plugins-workspace repo.
  • Removed tauri::scope::IpcScope
  • Removed tauri::scope::ipc module and all its types.
  • Removed tauri::scope::FsScope, use tauri::scope::fs::Scope
  • Removed tauri::scope::GlobPattern, use tauri::scope::fs::Pattern
  • Removed tauri::scope::FsScopeEvent, use tauri::scope::fs::Event
  • Removed tauri::scope::HttpScope
  • Removed tauri::scope::ShellScope
  • Removed tauri::scope::ShellScopeAllowedCommand
  • Removed tauri::scope::ShellScopeAllowedArg
  • Removed tauri::scope::ExecuteArgs
  • Removed tauri::scope::ShellScopeConfig
  • Removed tauri::scope::ShellScopeError
  • Removed linux-protocol-headers cargo feature flag, now enabled by default.
  • Removed tauri::path::Error and tauri::path::Result and added its variants to tauri::Error
  • Removed tauri::path::Result and tauri::plugin::Result aliases, you should use tauri::Result or your own Result type.
  • Changed tauri::Builder::on_page_load handler to take references. The page load hook is now triggered for load started and finished events, to determine what triggered it see tauri::PageLoadPayload::event field.
  • Removed tauri::GlobalWindowEvent struct, and unpacked its fields to be passed directly to tauri::Builder::on_window_event.
  • Removed tauri::EventHandler type.
  • Renamed tauri::Context::default_window_icon_mut to tauri::Context::set_default_window_icon and changed it to accept Option<T>.

Config restructure

Restructured Tauri config per RFC#5:

  • Moved package.productName, package.version and tauri.bundle.identifier fields to the top-level.
  • Removed package object.
  • Renamed tauri object to app.
  • Moved tauri.bundle object to the top-level.
  • Renamed build.distDir field to frontendDist.
  • Renamed build.devPath field to devUrl and will no longer accepts paths, it will only accept URLs.
  • Moved tauri.pattern to app.security.pattern.
  • Removed tauri.bundle.updater object, and its fields have been moved to the updater plugin under plugins.updater object.
  • Moved build.withGlobalTauri to app.withGlobalTauri.
  • Moved tauri.bundle.dmg object to bundle.macOS.dmg.
  • Moved tauri.bundle.deb object to bundle.linux.deb.
  • Moved tauri.bundle.appimage object to bundle.linux.appimage.
  • Removed all license fields from each bundle configuration object and instead added bundle.license and bundle.licenseFile.
  • Renamed AppUrl to FrontendDist and refactored its variants to be more explicit.
  • Renamed tauri.window.fileDropEnabeld to app.window.dragDropEnabled

Migration

As we try to make the migration from previous Tauri versions as smooth as possible, we have documentation available to guide you through the process.

If you are migrating from a 1.x release please check out this migration guide.

For upgrading from a 2.0 beta or release candidate version check out this migration guide.

The Tauri v2 CLI includes a migrate command that automates most of the process and helps you finish the migration:

  • npm

    npm install @tauri-apps/cli@next
    npm run tauri migrate
    
  • yarn

    yarn upgrade @tauri-apps/cli@next
    yarn tauri migrate
    
  • pnpm

    pnpm update @tauri-apps/cli@next
    pnpm tauri migrate
    
  • cargo

    cargo install tauri-cli --version "^2.0.0" --locked
    cargo tauri migrate
    

Rust Migration

We can not automatically migrate your Rust code, so make sure to go through the documentation and rust docs of the 2.0 version.

Call To Action

If you are familiar with Tauri and have used it already during your journey, please take your time to check out the Github Discussions, Github Issues. Maybe you have already solved the issues your fellow newcomers to Tauri are experiencing right now.

If you think that some of these problems you have seen are generic and should be documented somewhere we probably have the perfect place for it in our official documentation.

To contribute improvements or additions we are open for PRs in the tauri-docs repository. Please make sure youve read the guidelines for contribution though.

If you are in the position to understand and translate the current documentation into your native language we appreciate content translations to our documentation.

The repositories surrounding Tauri are also looking for contributors, especially we would love more maintainers and contributors to the plugin-workspace.

The plugins are now a major part of the development and user experience of Tauri and all kind of help is welcome there. From discussing new plugin ideas, collaborating with others to write new plugins, contributing PRs to fix bugs in existing plugins or documenting weird workarounds and knowledge in the plugin readme or code.

Roadmap

You probably expect solid plans for the future and new cool ideas from us. We currently have some in mind but have not committed to a roadmap beyond 2.x yet.

We mainly want to focus on improving this major version with a better developer experience, better documentation and less impactful bugs. We want to improve especially the mobile development experience and make the whole flow from idea to published application as seamless as possible.

Things on our radar for the future we feel we should mention at least:

  • Providing or Bundling Chromium Embedded Framework (CEF) for Linux as an alternative to WebKit2GTK
  • Servo as Tauri WebView (POC in Wry)

If you want to collaborate on these ideas, please let us know and we will figure it out together.

Tauri Board Elections 2024

The Tauri Programme is celebrating its third anniversary of Tauri becoming a programme within The Commons Conservancy. We are hard at work bringing v2 to a stable release, and now the next round of Tauri Board Director elections is upon us! Want to get involved in other ways and help Tauri towards v2? We would love your contributions especially to help evolve the documentation!

Board Elections

The Tauri Board of Directors is the central decision-making body for the Tauri Programme and is responsible for its overall health and stability. Additional details can be found on the Tauri Governance page.

In order to provide continuity from one year to another, the elections of seats are staggered over the course of 2 years. This means that one year a portion of the seats are elected, and the following year the remaining seats are elected. A Tauri Director seat is an elected position with a term of 2 years. The Board has a minimum of 3 Directors and a maximum of 7. This year there are 2 seats open for election.

Applying for Candidacy

There are 3 steps to express interest and apply for candidacy:

  1. Learn about the role of a Tauri Board Director on the Governance page.
  2. Prepare a written introduction about yourself that covers who you are, your history and relevance for Tauri, and what you would like to bring to the Board.
  3. Apply prior to July 5th, 2024 by emailing board@tauri.app, messaging the @board role on the Tauri Discord, or by directly messaging Jacob Bolda on Discord (@jacobbolda) or email (jacob@tauri.app).

Voting will take place starting on July 7th through July 12th, 2024 where Tauri Working Group Members will cast their votes. Were expecting to announce the results on or before July 16, 2024. If elected, well ask you to sign this pledge if you havent done so previously.

If you have any questions or would like more information please reach out by emailing board@tauri.app, messaging the @board role on the Tauri Discord, or by directly messaging Jacob Bolda on Discord (@jacobbolda) or email (jacob@tauri.app).

Interested In Getting Involved?

If joining the Board isnt for you, we are always looking to enable involvement at any level within Tauri. The documentation for v2 is a large focus of the remaining effort. See the issues within the tauri-apps/tauri-docs repo. Additionally reach out and follow along within Discord. Add a @notify-* role to stay apprised of news and questions from the team, or follow along and ask questions in the #dev or #docs channels under the CONTRIBUTORS section.

Prepared for some more responsibility? A Domain in the Working Group represents a specific area of interest.

  • Development: Developing and maintaining the Tauri software
  • Community: Looks after the broader community resources and the public presence of Tauri
  • Governance & Guidance: Involved with all things organizational in nature
  • Operations: Responsible for all the tooling and infrastructure Tauri needs to get work done

This gives clear entry points for a new member of the Working Group to jump into right away. It also allows us to continue growing our core competency of core Tauri development while giving additional focus to all areas which support the Tauri organization as a whole. Each of these domains will be represented by Domain Members and Domain Leads, but membership is not mutually exclusive.

All domains within Tauri are equally important to providing the best experience possible, as well as the wonderful support of the community. ❤️


With your help, we can continue to improve and catalyze the growth and sustainability of the organization. You can learn more in the Governance and Guidance repo on GitHub.

Tauri Board Elections 2025

As we continue to be amazed by all the applications youve created with Tauri v2, its been 4 years since Tauri has become a Programme within The Commons Conservancy! This means were preparing for a new round of Tauri Board Director elections for the next term.

Board Elections

The Tauri Board of Directors is the central decision-making body for the Tauri Programme and is responsible for its overall health and stability. Additional details can be found at the Tauri Governance page.

In order to provide continuity from one year to another, the elections of seats are staggered over the course of 2 years. This means that one year a portion of the seats are elected, and the following year the remaining seats are elected. A Tauri Director seat is an elected position with a term of 2 years. The Board has a minimum of 3 Directors and a maximum of 7.

This year there are 5 seats open for election.

Applying for Candidacy

There are 3 steps to express interest and apply for candidacy:

  1. Learn about the role of a Tauri Board Director on the Governance page.
  2. Prepare a written introduction about yourself that covers who you are, your history and relevance to Tauri, and what you would like to bring to the Board. (Examples from previous years can be found at https://github.com/tauri-apps/governance-and-guidance).
  3. Apply prior to July 7th, 2025 by emailing board@tauri.app or messaging the @board role on the Tauri Discord.

Voting will take place starting on July 7th through July 14th, 2025 where Tauri Working Group Members will cast their votes. Were expecting to announce the results on or before July 19, 2025. If elected, well ask you to sign this pledge if you havent done so previously.

If you have any questions or would like more information please reach out by emailing board@tauri.app, messaging the @board role on the Tauri Discord.

Interested In Getting Involved?

If joining the Board isnt for you but still want to help, here are some ways to do so! (Thank you ❤️)

Reach out on our Discord by enabling the roles youre interested in like “Contribute to Tauri Code” or “Contribute to Documentation”. This reveals the Contributors channels where you can chat with other contributors. While youre there, consider enabling Discord notification roles to stay apprised of news and questions from the team.

Or on GitHub maybe you can help with these good first issues?

Additionally were very grateful to all the teams and individuals who sponsor us on GitHub or open collective!

Tauri Board Elections 2026

As we continue to be amazed by all the applications youve created with Tauri v2, its been 5 years since Tauri has become a Programme within The Commons Conservancy! This means were preparing for a new round of Tauri Board Director elections for the next term.

Board Elections

The Tauri Board of Directors is the central decision-making body for the Tauri Programme and is responsible for its overall health and stability. Additional details can be found at the Tauri Governance page.

In order to provide continuity from one year to another, the elections of seats are staggered over the course of 2 years. This means that one year a portion of the seats are elected, and the following year the remaining seats are elected. A Tauri Director seat is an elected position with a term of 2 years. The Board has a minimum of 3 Directors and a maximum of 7.

This year there are 3 seats open for election.

Applying for Candidacy

There are 3 steps to express interest and apply for candidacy:

  1. Learn about the role of a Tauri Board Director on the Governance page.
  2. Prepare a written introduction about yourself that covers who you are, your history and relevance to Tauri, and what you would like to bring to the Board. (Examples from previous years can be found at https://github.com/tauri-apps/governance-and-guidance).
  3. Apply prior to July 7th, 2026 by emailing board@tauri.app or messaging the @board role on the Tauri Discord.

Voting will take place starting on July 7th through July 14th, 2026 where Tauri Working Group Members will cast their votes. Were expecting to announce the results on or before July 19, 2026. If elected, well ask you to sign this pledge if you havent done so previously.

If you have any questions or would like more information please reach out by emailing board@tauri.app, messaging the @board role on the Tauri Discord.

Interested In Getting Involved?

If joining the Board isnt for you but still want to help, here are some ways to do so! (Thank you ❤️)

Reach out on our Discord by enabling the roles youre interested in like “Contribute to Tauri Code” or “Contribute to Documentation”. This reveals the Contributors channels where you can chat with other contributors. While youre there, consider enabling Discord notification roles to stay apprised of news and questions from the team.

Or on GitHub maybe you can help with these good first issues?

Additionally were very grateful to all the teams and individuals who sponsor us on GitHub or open collective!

Tauri Board Elections & Governance Update

The Tauri Programme is celebrating its two year anniversary of Tauri becoming a programme within The Commons Conservancy as well as the one year milestone of the Tauri 1.0 release. This also means were preparing for the next round of Tauri Board Director elections to welcome in the next chapter of Tauri.

We wanted to celebrate these milestones but also use this as a chance to reflect on how weve grown since the Tauri 1.0 launch and how to continue evolving Tauri. The Tauri Working Group has been building the next iteration of the governance model for the past several months to make it more accessible for new and existing contributors, and ultimately sustainable for the future of Tauri.

Board Elections

The Tauri Board of Directors is the central decision-making body for the Tauri Programme and is responsible for the overall health and stability of the Tauri Programme. Additional details can be found on the Tauri Governance page.

In order to provide continuity from one year to another, the elections of seats are staggered over the course of 2 years. This means that one year a portion of the seats are elected, and the following year the remaining seats are elected. A Tauri Director seat is an elected position with a term of 2 years. The Board has a minimum of 3 Directors and a maximum of 7. This year there are 5 seats open for election.

Diversity

This year wed like to focus on diversifying the Tauri Board. Were looking for candidates that may be a developer whos worked on Tauri, a stakeholder in Tauris future, experienced individuals from industry, or a person with a passion for regulatory and legal aspects within open source. If any or all of these are of interest to you then wed invite you to apply as a candidate.

Applying for Candidacy

There are 3 steps to express interest and apply for candidacy:

  1. Learn about the role of a Tauri Board Director on the Governance page.
  2. Prepare a written introduction about yourself that covers who you are, your history and relevance for Tauri, and what you would like to bring to the Board.
  3. Apply prior to July 2nd, 2023 by emailing board@tauri.app, messaging the @board role on the Tauri Discord, or by directly messaging Daniel Thompson-Yvetot on Discord (@Denjell) or email (denjell@tauri.app).

Voting will take place starting on July 5th through July 12th, 2023 where Tauri Working Group Members will cast their votes. Were expecting to announce the results on or before July 16, 2023. If elected, well ask you to sign this pledge if you havent done so previously.

If you have any questions or would like more information please reach out by emailing board@tauri.app, messaging the @board role on the Tauri Discord, or by directly messaging Daniel Thompson-Yvetot on Discord (@Denjell) or email (denjell@tauri.app).


Governance Update

Tauri has always had a Working Group thats responsible for the day-to-day direction and execution, but as we grew it became clear that we needed to evolve the Working Group. We also wanted to give new Working Group members a clear places to jump in and get started. We thought of how we could achieve this while building and iterating on the existing framework. With these goals in mind, we created two new concepts within the Working Group: Domains and Domain Leads.

Domains

A Domain in the Working Group represents a specific area of interest. Were starting with these 4 domains:

  • Development: Developing and maintaining the Tauri software
  • Community: Looks after the broader community resources and the public presence of Tauri
  • Governance & Guidance: Involved with all things organizational in nature
  • Operations: Responsible for all the tooling and infrastructure Tauri needs to get work done

This gives clear entry points for a new member of the Working Group to jump into right away. It also allows us to continue growing our core competency of core Tauri development while giving additional focus to all areas which support the Tauri organization as a whole. Each of these domains will be represented by Domain Members and Domain Leads, but membership is not mutually exclusive.

Domain Leads

Within a domain, there is a position for 2-3 Domain Leads. These are core individuals in the Working Group that are critical to their respective Domain. They help by setting the direction and priorities for their domain while also serving as key leaders for the Working Group as a whole.

Leads are appointed twice a year, in the spring and in the fall. Since this governance update is being rolled out mid-term were appointing interim leads that have been key members of the Working Group. This fall well reflect on the initial experience and host a new round to appoint the Domain Leads. Well announce information for that process when were closer to “appointment season”.


We hope that these changes provide the foundation to continue the journey the Tauri Working Group has been on while also catalyzing the continued growth and sustainability of the organization. You can learn more about these updates in the Governance and Guidance repo on GitHub. Give us your feedback on the GitHub Discussion for this post.

Tauri Community Growth & Feedback

Community growth and feedback hero image

Tauri has had an amazing past year. We launched Tauri 1.0, announced the alpha version of Tauri Mobile and gathered a lot of valuable feedback from our community and users in the 2022 Tauri Community Survey.

Tauri Community Survey Results

This year, we had over 600 responses to the Tauri Community Survey (over 3x more than the previous surveys responses). Wed like to extend a very special thank you to Wu Yu Wei and DK Liao for translating the survey from English into Simplified and Traditional Chinese so that we could include more people from the community and their feedback in the survey. You can download the public data for the survey here.

Weve heard your feedback and have started a couple of projects to directly address it. The first one wed like to talk about is search.

Search Improvements on Tauri.app

Without searching, can you ever find something? And if your telescope is cracked, can you see the planets or stars? We know that our search lens was dusty and scratched; it felt sometimes like a roll of the dice, and some folks even resorted to using ChatGPT to find answers.

Search has been a project that weve taken a few runs at over the years, but weve also learned that its not quite as easy as it first seems. Ken from the Tauri Working Group did inspirational work with the previous tauri-search project. He created a lot of the foundation and research in the previous project for us to understand what goes into search.


With the next iteration of search, we had three goals in mind:

  1. Keep it maintainable
  2. Keep it working
  3. Keep it open source

Search Engine

First, we needed to choose a backend search engine to store and serve the search index. When evaluating search engines, we wanted to make sure we used something that shared our values of open source software and a small footprint. After comparing and researching players in the search market (and also learning from our previous approach with Meilisearch), we decided on Meilisearch because we knew it fit both of those goals.

Meilisearch have a passion for open source software and even has their search engine built in Rust which has a tiny footprint and great performance. Theyve recently announced Meilisearch 1.0 and now also have a cloud offering for those who would like a managed instance.

We decided to partner up with Meilisearch to use their engine and their Meilisearch Cloud offering to host our search engine. They graciously sponsored a hosted plan that they manage for us. This lets us focus on building Tauri, knowing that the maintenance and upkeep of the search engine are in trusted hands.

Search Ingestion & Indexing

The next piece of the puzzle is to actually get the content indexed and ingested into the search engine. Fabian from the Tauri Working Group set up the project using the docs-scraper project from Meilisearch.

Previously, we had a setup that would take our markdown documentation and JavaScript AST and use that to build the search index. Although it led to much faster indexing times, it meant we had a tightly coupled dependency between search indexing and the way we rendered content on our website. This would sometimes lead to the search results getting out of sync with the content on the live website. In order to update the website or optimize the indexer, someone would need to have knowledge of both, making it more difficult to maintain.

With the current version of the scraper, we can handle all of the configuration and tweaking of results with a single JSON file and let the scraper take care of the rest. We set up a GitHub action that would perform the scraping as part of our CI/CD pipeline and then send those results to our Meilisearch Cloud instance.

Search Frontend

The final step was to create the frontend UI that people visiting tauri.app would interact with. Amr from the Tauri Working Group created the meilisearch-docsearch project to help with this. This repo is compatible with Meilisearch 1.0 (were using it now on tauri.app).

Its inspired by the algolia/docsearch and meilisearch/docs-searchbar.js projects that provided a very solid foundation to begin with. The beauty of open source is that we can learn from each other and use that to give back to the ecosystem.

To talk through some of the details, Ill hand it over to Amr:


The meilisearch/docs-searchbar.js project was good, but I always felt it could use some improvements to get feature parity with algolia/docsearch. I also felt we could help with an update to help with UI/UX.

The main pain points with meilisearch/docs-searchbar.js were:

  1. On mobile screens, it needed UI/UX improvements so that the search results wouldnt go off-screen.
  2. On desktop, the search results would normally appear under the search input, which in the case of tauri.app was placed on the top-right. This caused a bad UX because youd have to keep moving your eyes between the page content in the middle and the search results in the top-right.
  3. It is missing a common keybinding. ctrl/command + K to start the search, ctrl/command + K is pretty common in the JS ecosystem documentation sites. It also doesnt have the ability to select text on the page and then trigger a search directly from that text.

I have been always a big fan of algolia/docsearch UI/UX. It checked all the features on my list, and I always wanted to have that for tauri.app. In fact, several months ago, I tried to change the meilisearch/docs-searchbar.js CSS on our end to improve point 1 and 2 above but I stopped mid-way because of the difficulty of building on top of existing css and fighting for highest specifity (plus CSS is hard 😉). Other projects also couldnt benefit from our modifications in an easy way.

Later, we were discussing how to improve the search UI and UX, and we decided that we could improve on the base Meilisearch UI. That project turned into meilisearch-docsearch.

Seeing It In Action

The good news is that all of these changes are live! You can see the new search on tauri.app. Wed love to hear your feedback on what works and what could use improvement in the GitHub Discussion for this blog post. We invite you to not only report bugs, but also if your search result wasnt expected or should be higher up on the list of results.

Search Preview

Wed like to wrap up by extending a special thank you to Ken for the original Tauri Search project, Amr for the meilisearch-docsearch project, Fabian for writing the revised index scraper and continuous testing, Meilisearch for their partnership and the Meilisearch Cloud instance and finally the Tauri community for their continual feedback to help us drive Tauri and the community forward.

Next Steps

Over the next year, the Tauri Working Group is excited to continue working towards Tauri 2.0. We also have a website rewrite in the works that well be launching in beta this spring. If youd like to get involved, you can reach out to us in the Tauri Discord and follow us on Mastodon and Twitter.

Announcing tauri-egui 0.1.0

The Tauri team is pleased to announce the first release of tauri-egui.

egui is a GUI library written in Rust. It leverages an OpenGL context via glutin.

tauri-egui is a Tauri plugin that connects with the Tauri runtime event loop to allow you to create glutin windows via our glutin fork and use egui through our egui-tao integration.

Setup

The first step is to add the crate to your dependencies in Cargo.toml:

[dependencies]
tauri-egui = "0.1"

Now you need to enable the plugin:

fn main() {
  tauri::Builder::default()
    .setup(|app| {
      app.wry_plugin(tauri_egui::EguiPluginBuilder::new(app.handle()));
      Ok(())
    })
}

Create an egui layout

To use egui, all you need to do is implement the tauri_egui::eframe::App trait to render elements using the egui API. In the following example, we will create a login layout.

  • Define the struct that will be used to render the layout:
use std::sync::mpsc::{channel, Receiver, Sender};
use tauri_egui::{eframe, egui};


pub struct LoginLayout {
  heading: String,
  users: Vec<String>,
  user: String,
  password: String,
  password_checker: Box<dyn Fn(&str) -> bool + Send + 'static>,
  tx: Sender<String>,
  texture: Option<egui::TextureHandle>,
}


impl LoginLayout {
  pub fn new(
    password_checker: Box<dyn Fn(&str) -> bool + Send + 'static>,
    users: Vec<String>,
  ) -> (Self, Receiver<String>) {
    let (tx, rx) = channel();
    let initial_user = users.iter().next().cloned().unwrap_or_else(String::new);
    (
      Self {
        heading: "Sign in".into(),
        users,
        user: initial_user,
        password: "".into(),
        password_checker,
        tx,
        texture: None,
      },
      rx,
    )
  }
}
  • Implement tauri_egui::eframe::App to use the egui APIs:
impl eframe::App for LoginLayout {
  // Called each time the UI needs repainting
  // see https://docs.rs/eframe/latest/eframe/trait.App.html#tymethod.update for more details
  fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
    let Self {
      heading,
      users,
      user,
      password,
      password_checker,
      tx,
      ..
    } = self;


    let size = egui::Vec2 { x: 320., y: 240. };
    // set the window size
    frame.set_window_size(size);


    // adds a panel that covers the remainder of the screen
    egui::CentralPanel::default().show(ctx, |ui| {
      // our layout will be top-down and centered
      ui.with_layout(egui::Layout::top_down(egui::Align::Center), |ui| {
        // we will start adding elements here in the next sections
      });
    });
  }
}
  • Define some helper functions we will use:
fn logo_and_heading(ui: &mut egui::Ui, logo: egui::Image, heading: &str) {
  let original_item_spacing_y = ui.style().spacing.item_spacing.y;
  ui.style_mut().spacing.item_spacing.y = 8.;
  ui.add(logo);
  ui.style_mut().spacing.item_spacing.y = 16.;
  ui.heading(egui::RichText::new(heading));
  ui.style_mut().spacing.item_spacing.y = original_item_spacing_y;
}


fn control_label(ui: &mut egui::Ui, label: &str) {
  let original_item_spacing_y = ui.style().spacing.item_spacing.y;
  ui.style_mut().spacing.item_spacing.y = 8.;
  ui.label(label);
  ui.style_mut().spacing.item_spacing.y = original_item_spacing_y;
}
  • Load an image, allocate it as a texture and add it to the UI (requires the png dependency):
let texture: &egui::TextureHandle = self.texture.get_or_insert_with(|| {
  let mut reader = png::Decoder::new(std::io::Cursor::new(include_bytes!("icons/32x32.png")))
  .read_info()
  .unwrap();
  let mut buffer = Vec::new();
  while let Ok(Some(row)) = reader.next_row() {
    buffer.extend(row.data());
  }
  let icon_size = [reader.info().width as usize, reader.info().height as usize];
  // Load the texture only once.
  ctx.load_texture(
    "icon",
    egui::ColorImage::from_rgba_unmultiplied(icon_size, &buffer),
    egui::TextureFilter::Linear,
  )
});
logo_and_heading(
  ui,
  egui::Image::new(texture, texture.size_vec2()),
  heading.as_str(),
);
  • Add the user selection ComboBox:
ui.with_layout(egui::Layout::top_down(egui::Align::Min), |ui| {
  control_label(ui, "User");
  egui::ComboBox::from_id_source("user")
    .width(ui.available_width() - 8.)
    .selected_text(egui::RichText::new(user.clone()).family(egui::FontFamily::Monospace))
    .show_ui(ui, move |ui| {
      for user_name in users {
        ui.selectable_value(user, user_name.clone(), user_name.clone());
      }
    })
    .response;
});
  • Add an entry for password input:
ui.style_mut().spacing.item_spacing.y = 20.;


let textfield = ui
  .with_layout(egui::Layout::top_down(egui::Align::Min), |ui| {
    ui.style_mut().spacing.item_spacing.y = 0.;
    control_label(ui, "Password");
    ui.horizontal_wrapped(|ui| {
      let field = ui.add_sized(
        [ui.available_width(), 18.],
        egui::TextEdit::singleline(password).password(true),
      );
      field
    })
    .inner
  })
  .inner;
  • Add a submit button:
let mut button = ui.add_enabled(!password.is_empty(), egui::Button::new("Unlock"));
button.rect.min.x = 100.;
button.rect.max.x = 100.;
  • Handle submit:
if (textfield.lost_focus() && ui.input().key_pressed(egui::Key::Enter)) || button.clicked()
{
  if password_checker(&password) {
    let _ = tx.send(password.clone());
    password.clear();
    frame.close();
  } else {
    *heading = "Invalid password".into();
    textfield.request_focus();
  }
}

Now that we have created the layout, lets put it on a window and show it in the Tauri application:

use tauri::Manager;
fn main() {
  tauri::Builder::default()
    .setup(|app| {
      app.wry_plugin(tauri_egui::EguiPluginBuilder::new(app.handle()));


      // the closure that is called when the submit button is clicked - validate the password
      let password_checker: Box<dyn Fn(&str) -> bool + Send> = Box::new(|s| s == "tauri-egui-released");


      let (egui_app, rx) = LoginLayout::new(
        password_checker,
        vec!["John".into(), "Jane".into(), "Joe".into()],
      );
      let native_options = tauri_egui::eframe::NativeOptions {
        resizable: false,
        ..Default::default()
      };


      app
        .state::<tauri_egui::EguiPluginHandle>()
        .create_window(
          "login".to_string(),
          Box::new(|_cc| Box::new(egui_app)),
          "Sign in".into(),
          native_options,
        )
        .unwrap();


      // wait for the window to be closed with the user data on another thread
      // you don't need to spawn a thread when using e.g. an async command
      std::thread::spawn(move || {
        if let Ok(signal) = rx.recv() {
          dbg!(signal);
        }
      });


      Ok(())
    })
    .run(tauri::generate_context!())
    .expect("error while running tauri application")
}

Heres how it will look on all platforms:

tauri_egui layout

To customize the look and feel of your egui application, check out the Context#set_style API.

Announcing the Tauri Mobile Alpha Release

Tauri 2.0 Launch Hero Image

Tauri mobile is here! The first alpha release 2.0.0-alpha.0 has been published.

Updating dependencies

Make sure to update both NPM and Cargo dependencies to the 2.0.0-alpha.0 release. You can update the dependencies with:

  • npm

    npm install @tauri-apps/cli@next @tauri-apps/api@next
    
  • yarn

    yarn upgrade @tauri-apps/cli@next @tauri-apps/api@next
    
  • pnpm

    pnpm update @tauri-apps/cli@next @tauri-apps/api@next
    
  • cargo

    cargo add tauri@2.0.0-alpha.0
    cargo add tauri-build@2.0.0-alpha.0 --build
    cargo install tauri-cli --version "^2.0.0-alpha" --locked
    

Preview

You can adapt your existing desktop application to run on mobile or start a fresh project. Tauri runs on the connected device or starts an emulator if available.

iOS PreviewAndroid Preview


Getting started

Read the complete guide on the next documentation website.

Known issues

  • TLS support has been moved behind a Cargo feature until we figure out how to cross compile OpenSSL on Windows.
  • Currently running on a device is not supported when using Xcode 14.

Tauri Programme Turns 1 and Board Elections

The one year anniversary for Tauri becoming a programme within The Commons Conservancy is upcoming on the 16th of July! On that anniversary, two of our Directors on the Tauri Board will be at the end of their first half-term. The Board will hold an election on the 15th of July to decide the Directors for the next two year term.

The Tauri Board has a minimum of three, and a maximum of seven people. Right at the start weve had seven people come on board. Meaning we cant add any more people during this election. So if youre applying it means youll compete with the two project founders for a seat on the Tauri Board.

Honestly those are big shoes to fill! So to avoid unnecessary disappointment, in this election we decided to add a requirement: You must be currently part of a working group to apply as a candidate.

If youre still with me, then here are some additional details:

  • Please notify the board before July 15th 00:00 UTC if you would like to apply as a candidate.
  • You can mention @board on Discord, or DM Beanow#5887 if you want your application to be kept private within the Board.
  • Optionally, you can include a short motivation for your application.
  • If there are multiple candidates, the Tauri Board will vote for their preferred candidates.
  • The Directors running for office again will have half a vote deducted from votes in their favor (one for each consecutive term served).
  • After voting on July 15th well share the results.

All this is governed by our statutes and core regulations if youre interested in seeing the fine print.

Well be back soon with an update.

Update: Election results

The results are in, so here is the reveal!

The existing Directors applied for another term and there were no additional applicants. Meaning no vote was necessary to select between candidates. For the Chair position Daniel ran as the only candidate.

The Tauri Board then voted unanimously in favor of the following:

  1. The Board appoints Daniel and Lucas for an additional full term (2 years) as Board Directors, starting the 16th of July.
  2. The Board appoints Daniel as Chairperson for the next term (1 year), starting the 16th of July.

Another election will be held around the same time July next year, now with extra time to apply and for the Board to vote. Well announce the specifics in due time.

Experimental Tauri Verso Integration

What is Verso?

So first off, what is Verso? Verso is a browser based on Servo, a web browser rendering engine written in Rust

Why using Verso instead of Servo directly?

I believe therere quite a lot of people having thought about using Servo but got intimidated by the complex APIs and just gave up, which frankly I was one of them, so the goal of building the Verso webview is to make it easy enough to understand and use so that people will actually start to experiment and use it

Servo itself is made to be relatively easy to embed compared to other browsers, but the APIs are still way too low level and its quite daunting to use, you can take a look at the minimal example for running Servo with Winit at (note this is not even a fully functional example): https://github.com/servo/servo/blob/8d39d7706aee50971e848a5e31fc6bfd7ef552c1/components/servo/examples/winit_minimal.rs

And compared to that, Versos API looks like this, which is much easier and ergonomic to use

use std::env::current_exe;
use std::thread::sleep;
use std::time::Duration;
use url::Url;
use verso::VersoBuilder;


fn main() {
    let versoview_path = current_exe().unwrap().parent().unwrap().join("versoview");
    let controller = VersoBuilder::new()
        .with_panel(true)
        .maximized(true)
        .build(versoview_path, Url::parse("https://example.com").unwrap());
    loop {
        sleep(Duration::MAX);
    }
}

https://github.com/versotile-org/verso/blob/2e853d4f3f4cb88274daa211b7a2eb3bd1517115/verso/src/main.rs

Its not to say Servos API is bad though, as they need to support a lot more use cases while we just need it for building applications with Tauri

tauri-runtime-verso

So lets talk about the integration with Tauri!

We choose to integrate Verso and Tauri through a new custom runtime tauri-runtime-verso for this time, this is similar to our default runtime tauri-runtime-wry.

With this approach, you can easily swap out the runtime and use Tauri like what youll normally do:

use tauri_runtime_verso::{
    INVOKE_SYSTEM_SCRIPTS, VersoRuntime, set_verso_path, set_verso_resource_directory,
};


fn main() {
    // You need to set this to the path of the versoview executable
    // before creating any of the webview windows
    set_verso_path("../verso/target/debug/versoview");
    // Set this to verso/servo's resources directory before creating any of the webview windows
    // this is optional but recommended, this directory will include very important things
    // like user agent stylesheet
    set_verso_resource_directory("../verso/resources");
    tauri::Builder::<VersoRuntime>::new()
        // Make sure to do this or some of the commands will not work
        .invoke_system(INVOKE_SYSTEM_SCRIPTS.to_owned())
        .run(tauri::generate_context!())
        .unwrap();
}

Just note that its not as feature rich and powerful as the current backends used by Tauri in production yet, but it still has a lot to it, and we have built an example show casing it at https://github.com/versotile-org/tauri-runtime-verso/tree/main/examples/api

Features you can see from the video:

  • We have all the functions the tauri-cli provides
  • Were using a modern framework, in this case React
  • We have our official log and opener plugins, they work exactly the same as if youre using Tauri with the other backends
  • Windowing functions work, including size, position, maximize, minimize, close, …
  • Vites css hot reload works as well
  • The data-tauri-drag-region attribute works

Future works

Right now, Verso and tauri-runtime-verso are still in active development so well need to see as we go, but we do have something planned to do next

Pre-built Verso executable

Releasing an easy to use pre-built Verso executable to help people get started with it quicker and easier, as currently you need to compile Verso yourself to get started

Also if possible, as a long term goal, we would like an evergreen shared Verso, similar to WebView2 on Windows which you would place it on the system and it would update itself automatically, and shared between multiple apps so you dont have to ship the browser inside your app to reduce the bundle size significantly

More windowing and webview features support

We currently only support a small subset of features in Tauri, and we would like to expand this to include more things, and we have currently planned to support window decorations, window titles and transparency

Initialization script without temporary files

Currently Servo can only take an userscript directory to run on document start which is ok but for the Tauris use case, we would like to do this programmatically without the help of files, as that could result in left over temporary files that we never clean up

We have a PR merged in Servo just a few days ago and we should just need to use in Verso and then the tarui-runtime-verso so this is a coming soon!

Customization unique to the Verso runtime

Tauri is largely made with the assumption of the underlying webview libraries, so therere very little ways to use many Verso specific futures right now, for example, setting the verso executable path and resources directory are being done through global variables, which is not really applicable to window specific features (for example setting rounded corners), so we would like to add support for that next

Thank you

At the end we want to thank NLNet for making this project possible by supporting it financially through grants!

Create Tauri app

  • Bash

    sh <(curl https://create.tauri.app/sh)
    
  • PowerShell

    irm https://create.tauri.app/ps | iex
    
  • Fish

    sh (curl -sSL https://create.tauri.app/sh | psub)
    
  • npm

    npm create tauri-app@latest
    
  • Yarn

    yarn create tauri-app
    
  • pnpm

    pnpm create tauri-app
    
  • deno

    deno run -A npm:create-tauri-app
    
  • bun

    bun create tauri-app
    
  • Cargo

    cargo install create-tauri-app --locked
    cargo create-tauri-app