Back to Blog

Run Shell Commands in Tauri Apps | Rust Process Spawning Tutorial

Sandy LaneSandy Lane

Video: Run Shell Commands in Tauri Apps | Rust Process Spawning Tutorial by Taught by Celeste AI - AI Coding Coach

Watch full page →

Run Shell Commands in Tauri Apps | Rust Process Spawning Tutorial

This tutorial shows how to execute shell commands from a Tauri desktop app using Rust’s std::process::Command. You’ll learn to run commands both synchronously and asynchronously, capture their output, and stream real-time output events to a React frontend for live display.

Code

use std::process::{Command, Stdio};
use std::io::{BufReader, BufRead};
use tauri::Manager;

// Struct to hold command result
#[derive(serde::Serialize)]
struct CommandResult {
  stdout: String,
  success: bool,
}

// Synchronous command execution
#[tauri::command]
fn run_command(cmd: String) -> CommandResult {
  let output = Command::new("sh")
    .arg("-c")
    .arg(&cmd)
    .output()
    .expect("failed to execute command");

  let stdout = String::from_utf8_lossy(&output.stdout).to_string();
  let success = output.status.success();

  CommandResult { stdout, success }
}

// Asynchronous streaming command execution
#[tauri::command]
async fn run_command_stream(window: tauri::Window, cmd: String) -> Result<(), String> {
  let mut child = Command::new("sh")
    .arg("-c")
    .arg(&cmd)
    .stdout(Stdio::piped())
    .spawn()
    .map_err(|e| e.to_string())?;

  if let Some(stdout) = child.stdout.take() {
    let reader = BufReader::new(stdout);
    for line in reader.lines() {
      let line = line.map_err(|e| e.to_string())?;
      // Emit each line as a real-time event to the frontend
      window.emit("command-line", line).map_err(|e| e.to_string())?;
    }
  }
  let status = child.wait().map_err(|e| e.to_string())?;
  if !status.success() {
    return Err("Command exited with error".into());
  }
  Ok(())
}

// Register commands in main.rs
fn main() {
  tauri::Builder::default()
    .invoke_handler(tauri::generate_handler![run_command, run_command_stream])
    .run(tauri::generate_context!())
    .expect("error while running tauri application");
}

Key Points

  • Use std::process::Command to spawn shell commands from Rust in Tauri apps.
  • Capture command output synchronously with output() and convert bytes to strings.
  • For real-time streaming, spawn the process with piped stdout and read output line-by-line using a buffered reader.
  • Emit output lines as events from Rust to the React frontend to update the UI live.
  • Register Rust commands with Tauri’s invoke handler to call them from the frontend.