Managing Processes
Learn to control your Tauri application lifecycle by exiting, restarting, and accessing process metadata from a React frontend
Setup Requirement
The Process Plugin must be installed and configured before you can use any of the APIs described here. If you haven't set it up yet, follow the Process Plugin Introduction guide first. The plugin exposes two main capabilities from your frontend: exiting the application and restarting it. On the Rust side, you can also access basic information about the current binary.
Exiting the Application
Programmatic exit stops the entire Tauri process — all windows close, the Rust backend terminates, and the operating system reclaims every resource the app held. This is different from a user clicking the window's close button; it's a deliberate, immediate shutdown, similar to calling process.exit() in Node.js or std::process::exit() in Rust.
import { exit } from '@tauri-apps/plugin-process';
function QuitButton() {
const handleQuit = async () => {
// Persist any unsaved state here
await exit(0);
};
return <button onClick={handleQuit}>Quit App</button>;
}
The exit function takes a single number: the exit status code. By convention, 0 means success, and any non‑zero value signals an error. The operating system and any parent process that launched your app can inspect this code.
Unsaved Data Will Be Lost:
Calling exit terminates the process instantly. No confirmation dialog appears, no React cleanup hooks run, and any data that hasn't been written to disk disappears. Always persist critical state before calling exit, or present the user with a confirmation step.
Permission Configuration
To call exit from JavaScript, your app must explicitly allow it in the capabilities configuration. Without this permission, the call will throw an error.
// src-tauri/capabilities/default.json
{
"permissions": [
"process:allow-exit"
]
}
Missing Permission?:
If process:allow-exit is absent, the frontend will receive a runtime error when attempting to call exit. The same rule applies to restart — it requires process:allow-restart. Always double‑check your capabilities file after adding lifecycle commands.
Restarting the Application
Restarting closes the current process and immediately launches a new instance with the same command‑line arguments. The new instance is a completely fresh start: all memory, file handles, and window positions from the previous run are gone. This is useful for applying configuration changes or resetting the app to a known clean state.
import { relaunch } from '@tauri-apps/plugin-process';
function RestartButton() {
const handleRestart = async () => {
await relaunch();
};
return <button onClick={handleRestart}>Restart App</button>;
}
Once relaunch is called, the current process ends, and a new one starts. Because the new instance loads the frontend from scratch, any React state that wasn't persisted is lost.
Command-Line Arguments Are Preserved:
Any flags or parameters passed to the original executable (for example, --debug or a file path) are forwarded to the new process automatically. You don't need to re‑collect them manually.
Permission Configuration
Add process:allow-restart to the same capabilities file that already contains process:allow-exit.
{
"permissions": [
"process:allow-exit",
"process:allow-restart"
]
}
Getting Process Information
While the Process Plugin itself focuses on exit and restart, you may occasionally need details about the running binary — for instance, to display the executable path in an “About” dialog or to help a self‑updater locate itself. Tauri’s core process module in Rust provides current_binary() for exactly this purpose. You can expose that information to your React frontend with a custom command.
Rust side — add a command that returns the path of the current executable:
// src-tauri/src/lib.rs
use tauri::process::current_binary;
#[tauri::command]
fn get_binary_path() -> Result<String, String> {
let path = current_binary().map_err(|e| e.to_string())?;
Ok(path.display().to_string())
}
pub fn run() {
tauri::Builder::default()
.invoke_handler(tauri::generate_handler![get_binary_path])
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
Frontend side — invoke the command from your React component:
import { invoke } from '@tauri-apps/api/core';
function AppInfo() {
const [binaryPath, setBinaryPath] = React.useState('');
React.useEffect(() => {
invoke<string>('get_binary_path')
.then(setBinaryPath)
.catch(console.error);
}, []);
return <div>Running from: {binaryPath}</div>;
}
You Have Process Metadata:
If the correct absolute path appears on screen, you've successfully bridged Tauri's core process information to your frontend. This same pattern — creating a custom command to expose Rust data — works for any information the Tauri core provides.
Application Lifecycle Considerations
Managing when and how your app exits or restarts directly shapes the user experience. Keep the following guidelines in mind when you build lifecycle controls:
- Use exit codes meaningfully — Return
0for normal shutdowns and a non‑zero code when an error occurs. Scripts or launchers that wrap your Tauri app can use this to decide whether to retry or alert the user. - Avoid restart loops — If you call
relaunchunconditionally during startup (e.g., to force a fresh state), you risk an infinite cycle where every new instance immediately restarts itself. Always guard the restart with a condition, such as reading a “first‑run” flag from the Store Plugin. - Clean up external resources — Tauri will drop most resources when the process ends, but database connections, open network streams, or file locks might benefit from explicit cleanup before
exitorrestart. The SQL Plugin is a typical case where you close the pool first. - Persist state with the Store Plugin — Combine lifecycle commands with the Store Plugin to save user progress, preferences, or session data before shutting down. That way, a restart feels seamless rather than destructive.
By understanding these tools, you can build Tauri applications that handle shutdown and restart just as reliably as any native desktop program — with full control from your React frontend.