---
title: Single Instance
description: Ensure that a single instance of your Tauri app is running at a time.
plugin: single-instance
i18nReady: true
---

import PluginLinks from '@components/PluginLinks.astro';
import Compatibility from '@components/plugins/Compatibility.astro';

import { Tabs, TabItem, Steps } from '@astrojs/starlight/components';
import CommandTabs from '@components/CommandTabs.astro';

<PluginLinks plugin={frontmatter.plugin} showJsLinks={false} />

Ensure that a single instance of your tauri app is running at a time using the Single Instance Plugin.

## Supported Platforms

<Compatibility plugin={frontmatter.plugin} />

## Setup

Install the Single Instance plugin to get started.

<Tabs>
  <TabItem label="Automatic">

    Use your project's package manager to add the dependency:

    {' '}

    <CommandTabs
      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"
    />

  </TabItem>
    <TabItem label="Manual">
      <Steps>

        1. Run the following command in the `src-tauri` folder to add the plugin to the project's dependencies in `Cargo.toml`:

            ```sh frame=none
            cargo add tauri-plugin-single-instance --target 'cfg(any(target_os = "macos", windows, target_os = "linux"))'
            ```

        2.  Modify `lib.rs` to initialize the plugin:

            ```rust title="lib.rs" ins={5-6}
            #[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");
            }
            ```

      </Steps>
    </TabItem>

</Tabs>

:::info

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:

  <Steps>

1. **`app`:** The [AppHandle](https://docs.rs/tauri/2.0.0/tauri/struct.AppHandle.html) 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.

  </Steps>

So, the closure should look like below

```rust
.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:

```rust title="src-tauri/src/lib.rs" {1} {5-12}
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 won't 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.

Here's 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:

```yaml title="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:

```yaml title="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.
