Tauri Plugin single-window
Prevent duplicate desktop launches and redirect activation to the already running Tauri instance.
This plugin is designed for applications that must behave as a true single-instance desktop process. The primary instance creates a local IPC endpoint and records its process ID in a small runtime file derived from the Tauri package name. When a second launch occurs, the new process validates that recorded PID, signals the existing instance over the local socket, and exits. The running instance then brings its own window to the foreground. On Linux, the plugin also handles GTK remote activations forwarded by the desktop shell, which is important for GNOME dock launches that may never create a normal second process. This is substantially more reliable across Linux, macOS, and Windows than attempting to focus another process window externally.
| Platform | Supported |
|---|---|
| Linux | ✓ |
| Windows | ✓ |
| macOS | ✓ |
| Android | - |
| iOS | - |
Install
Add the plugin to your Tauri application:
src-tauri/Cargo.toml
[]
= "1.1.1"
Usage
Register the plugin during Tauri startup:
The plugin does not expose a frontend command API. Its behavior is automatic once registered.
If you want to customize behavior, use init_with(...) and configure the builder-style Config. The terminal notice template supports {{proc}} for the Tauri package name and {{pid}} for the primary process ID when it is known. You can also override which window label should be focused by calling with_target_window(...).
If you want to react to a duplicate launch inside the already running application, register a callback during setup. The callback runs on the primary instance after the plugin has requested window activation. It receives an AppHandle and an ActivationPayload containing the duplicate process name, process ID, argument vector, and current working directory. That makes it straightforward to emit a frontend event, restore application state, or open a specific route. On Linux, when activation arrives through GTK remote activation instead of the socket path, the payload still includes the process name and the current primary PID, but argv and cwd are empty because the desktop shell does not provide that launch context to the running process.
use ;
Behavior
On desktop targets, the plugin derives a socket name and PID file from app.package_info().name. The first instance becomes the primary owner of that runtime state. A later launch validates the recorded PID, connects to the existing instance over the local socket, and exits after requesting the already running process to activate its window. On Linux, the plugin also watches for repeated Ready events that GTK emits when a later launch is forwarded to the primary instance through GIO activation. That covers the GNOME path where the shell may activate the running application directly instead of leaving a duplicate process around long enough for startup-only detection.
When activation happens, the plugin tries to focus the configured target window label if one was provided. Otherwise it prefers the "main" webview window and falls back to the first available webview window if that label is not present. If you registered a callback, that callback is invoked on the primary instance with the activation payload received over the local socket or synthesized from a forwarded GTK activation. On Unix-like systems, the socket listener is created with overwrite enabled so a stale socket file left behind by a crash does not permanently block startup.
If you package a Linux application that truly has only one primary window, you should also ship a custom desktop entry with SingleMainWindow=true. That prevents GNOME from advertising a misleading “New Window” dock action for a single-window application. The example app in examples/tauri-app/src-tauri includes a desktop template that does exactly that for both Debian and RPM bundles.
On mobile targets, the plugin intentionally does nothing.