Execra
Execra is a typed job runtime for Rust apps that wrap external CLI tools. It owns process lifecycle, output decoding, process-group cancellation, timeouts, optional persistence, and structured event streaming.
The narrow target is deliberate: Rust backends, especially Tauri apps, that need to build a GUI around a real command-line program without rewriting job plumbing for every button.
Install
[]
= "1"
# For Tauri apps:
= { = "1", = ["tauri"] }
Default Runtime::new() is in-memory only. It does not open SQLite, create
raw log directories, or run retention logic. Opt into persistence explicitly
with Runtime::builder().
Quick Start
use ;
async
Tauri
Enable the tauri feature and install the plugin:
Use app.execra() from commands:
use ExecraExt;
use ;
use AppHandle;
.channel(name) forwards each serialized Event to the Tauri event bus under
one channel name. Frontends match on the event's kind field.
Use typed hooks when the Rust backend also needs to mirror events into its own state:
async
For persisted Tauri history, pass your own runtime:
default
.plugin;
Core Concepts
Runtime - the cloneable process runtime. Runtime::new() is in-memory;
Runtime::builder() opts into history, raw logs, concurrency, retention, and
grace-period tuning.
Command - a program plus args, env, cwd, stdin policy, label, tags,
timeout, and optional interpreter. Command::new is shell-agnostic; explicit
helpers such as Command::powershell, Command::cmd, and Command::sh wrap
shell use when you need it.
JobHandle - returned by Runtime::spawn. It exposes id(), cancel(),
subscribe(), and implements Future<Output = Outcome>.
Event - the wire protocol. Consumers see JobCreated, JobStarted,
OutputAppended, phase/progress/finding events, Exited, Finalized, and
Cancelled.
Interpreter - optional per-job logic that maps output lines and final
exit code into typed events. Execra does not guess what a CLI means.
Outcome - final verdict: Succeeded, Failed, or Cancelled.
Outcome::is_success(), Outcome::message(), and Outcome::into_result()
cover the common consumer mapping.
Persistence
Persistence is off by default:
let rt = new; // no files are created
Opt in:
let rt = builder
.history
.log_dir
.raw_output
.max_concurrent
.build?;
history(path) enables SQLite job/event history. log_dir(path) enables raw
stdout/stderr log files and implies RawOutputPolicy::Persist unless you set
another raw-output policy. With the default gzip feature, you can choose
RawOutputPolicy::PersistGzipOnFinalize.
Feature Flags
bundled-sqlite(default) - build SQLite intorusqlite.gzip(default) - enableRawOutputPolicy::PersistGzipOnFinalize.tauri- enableexecra::tauri, the built-in Tauri plugin and extension trait.
Non-goals
Execra is not a shell parser, a task DAG, a generic workflow engine, a
distributed runner, or a catalogue of built-in interpreters. Callers decide
what to run and chain jobs with .await.
Docs
- RUNTIME.md - runtime, Tauri plugin, cancellation, persistence.
- INTERPRETER.md - interpreter contract.
- examples/ - reference interpreters and acceptance snippets.
License
Licensed under the Apache License, Version 2.0 (LICENSE.md or http://www.apache.org/licenses/LICENSE-2.0).