Expand description
Rusty development process manager like foreman, but better!
WIP: This project is a work-in-progress but it’s basically working. The API is subject to change. I plan to add improvements as I use it/as needed, including a possible TUI interface.
§Motivation
I wanted something to run multiple processes in my project like Ruby’s foreman (back in the day) but
without the drawbacks of:
- the complexity/sluggishness of wrapping every binary in a Docker container and maintaining a
docker-compose.yaml cargo baconhas tedious config and is meant for one-offcargo check/cargo test, not running multiple procs in parallel likedockerorforemancargo watchis abandonware (why not transfer the name to someone else?)justis great, but requires manualwatchexec, etc.- something like
foremanbut a bit smarter for restarts/crash handling, almost likedocker - shell scripts to combine logs and manage the procs +
awk+ control-C are a pain!
§Installation
cargo install prox
(Or use as a library in your dev-dependencies and create your own wrapper – see examples/basic_usage.rs)
§Usage
§Binary Usage:
Create a prox.toml (or .yaml or .json) file in your workspace/crate root:
[config]
readiness_fallback_timeout = 15
[[procs]]
name = "api"
command = "cargo"
args = ["run", "--bin", "api"]
working_dir = "api"
readiness_pattern = "Server listening"
# In a workspace, you can watch from the workspace root:
watch = ["Cargo.toml"]
# ... and/or relative to `working_dir`:
watch_rel = ["src"]
env_clear = true
env = { PORT = "3000", RUST_LOG = "debug" }
[[procs]]
name = "worker"
command = "cargo"
args = ["run", "--bin", "worker"]
working_dir = "tests/fixtures"
env_clear = trueThen just run prox!
§Library Usage:
Add prox to your [dev-dependencies] and create your own bin wrapper, e.g. dev.
See examples/basic_usage.rs for an example.
§Features:
- Run several commands in parallel
- Colored prefixes per process
- File watching with automatic restart (global + per-proc watch paths)
- Readiness pattern or fallback timeout
- Debounced output idle detection
- Clean shutdown & optional cleanup commands
- Config via Rust builders or TOML / YAML / JSON files
Events you can receive (via setup_event_rx()):
AllStartedwhen every proc is readyStarted,Restartedper processExited,StartFailedon failureIdleafter no output for the debounce periodSigIntReceivedon Ctrl-C (if enabled)
Runtime control (optional): send ProxSignal::Start, Restart, Shutdown through the signal_rx channel you provide.
Environment:
- Per process vars:
env(clears first ifenv_clear = true).
Colors:
- Auto-assigned from
config.colorsunless a proc setscolor.
Readiness:
- If
readiness_patternset, logs are scanned case-insensitively. - Otherwise, after
readiness_fallback_timeoutthe proc is assumed running.
IMPORTANT! Not a production supervisor! For local development only.
§Example:
examples/basic_usage.rs
use owo_colors::AnsiColors;
use prox::{Config, Proc, Prox};
use std::time::Duration;
use std::{collections::HashMap, path::PathBuf};
fn main() -> anyhow::Result<()> {
// Example: Simple process manager with multiple services
let mut manager = Prox::builder()
.config(
Config::builder()
.readiness_fallback_timeout(Duration::from_secs(15))
.build(),
)
.procs(
[
Proc::builder()
.name("api".into())
.command("cargo".into())
.args(vec!["run".into(), "--bin".into(), "api".into()])
.working_dir(PathBuf::from("./api"))
.readiness_pattern("Server listening".into())
.watch(vec![
PathBuf::from("./api/src"),
PathBuf::from("./shared/src"),
])
.env(HashMap::from_iter([("LOG_LEVEL".into(), "debug".into())]))
.color(AnsiColors::BrightGreen)
.build(),
Proc::builder()
.name("database".into())
.command("docker".into())
.args(["run".into()].into())
.env(
[
("POSTGRES_DB".into(), "myapp".into()),
("POSTGRES_PASSWORD".into(), "password".into()),
]
.into(),
)
.readiness_pattern("database system is ready to accept connections".into())
.build(),
Proc::builder()
.name("frontend".into())
.command("npm".into())
.args(vec!["run".into(), "dev".into()])
.working_dir(PathBuf::from("./frontend"))
.readiness_pattern("Local:".into())
.watch(vec![PathBuf::from("./frontend/src")])
.color(AnsiColors::BrightYellow)
.build(),
]
.into(),
)
.build();
println!("Starting development environment...");
// Start all processes - this will block until Ctrl+C or a process exits
manager.start()?;
Ok(())
}Modules§
- logging
- Logging utilities and macros
Macros§
- debug
- Log to the prox logger at debug level
- error
- Log to the prox logger at error level
- info
- Log to the prox logger at info level
- warn
- Log to the prox logger at warn level
Structs§
- Config
- Configuration for the process manager
- Proc
- A single process configuration for prox
- Prox
- Process manager that handles multiple processes
Enums§
- Proc
Status - Status of a managed process
- Prox
Event - Events emitted by the process manager (
Prox) - Prox
Signal - Signals that can be sent to the process manager (
Prox)