A native desktop process manager for developers who want one place to run a stack, watch logs, restart flaky services, and stop everything cleanly.
It is built for the annoying real-world cases:
- mixed stacks like
npm,uv, scripts, and Docker containers - runaway child processes that do not die when the parent exits
- local tools that need a loopback API for agents, scripts, or automation
- dev environments where fast feedback matters more than infrastructure theater
- Start your full local stack from one UI instead of juggling terminals.
- Watch live output for the selected process without leaving the app.
- Auto-start only the processes you opt into when the manager itself launches.
- Restart unstable services automatically with per-process managed restart and optional active hours.
- Start dormant services from simple per-process schedules.
- Stop process trees cleanly on Windows, including messy child-process chains.
- Mix normal commands and Docker containers in the same stack.
- Expose an optional localhost-only REST API for tooling and AI agents.
The main view is built for daily use: left-side process list, top-level stack controls, and live logs for the selected process.
Highlights visible here:
(M)marks entries with managed restart enabled(A)marks entries that auto-start when the app launchesStart All,Stop All, andRestart Allcontrol entries that opt into each global action- drag any process in the sidebar to reorder it, or right-click for move actions
- the selected process shows live output with warning/error color differentiation
- the header can expose a loopback API and copy an agent bootstrap payload
Each process entry can be updated in place. You do not need to delete and recreate it to change behavior.
This screen covers:
- command and working directory changes
- process vs Docker mode
- auto-start with app launch
- managed restart with optional active-hours windows
- scheduled start triggers for dormant entries
- Start All / Stop All / Restart All participation
- disk log capture and retention
Stack-wide settings stay out of the way but are easy to find.
This panel controls:
- stack name
- shared log directory
- portable layout for logs next to the executable when desired
The app can optionally expose a loopback-only control surface for local tooling.
This panel controls:
- localhost REST enable/disable
- port selection
- agent/tooling access without exposing the service on the network
- Start, stop, and restart the whole stack from the header.
- Start, stop, restart, edit, or delete individual entries from the process pane.
- Reorder processes from the sidebar by dragging them, or use the right-click
Move up/Move downmenu. - Keep one-off/manual entries independent by disabling their Start All, Stop All, and Restart All participation.
- Keep a mixed stack of regular commands and Docker containers in one place.
- Stream output for the selected process in real time.
- Visually differentiate system events, warnings, errors, and normal output.
- Keep the log view pinned to the bottom while new lines arrive.
- Click log rows to select whole lines; Shift-click selects a row range for structured copying.
- Double-click a log row to freeze it and enable text selection for that row only; click outside to return to row selection.
- Enable managed restart per entry for processes that should come back automatically.
- Limit managed restart to weekly active-hour windows, with an option to stop the process when a window ends.
- Enable scheduled runs for dormant entries with hourly, every-N-hours, daily, or selected-weekday cadence.
- Enable auto-start per entry when you want the stack to come up automatically after Process Manager launches.
- Disable global Start All, Stop All, or Restart All participation per entry without affecting manual controls, auto-start, or managed restart.
- On Windows, stop entire process trees with Job Objects so children are not orphaned.
- Keep Docker behavior explicit: regular processes are shut down on app close, containers persist unless you stop them.
- Store config in a portable
processes.jsonnext to the executable. - Edit existing entries in place.
- Persist logs to disk per process, with configurable retention.
- Migrate older config files forward automatically.
- Enable a localhost-only REST API for scripts, dashboards, and agents.
- Copy an agent bootstrap block that includes host, port, endpoints, and process ids.
- Use stable process ids for reliable external control.
git clone https://github.com/EnviralDesign/simple-rust-process-manager.git
cd simple-rust-process-manager
cargo build --releaseOutput binary:
- Windows:
target/release/simple-rust-process-manager.exe - Linux/macOS:
target/release/simple-rust-process-manager
See the Releases page.
- Launch the app. If
processes.jsondoes not exist next to the executable, it will be created. - Click
Addto create a process entry. - Choose a type:
Processfor normal commands likenpm run devoruv run devDockerfor container names controlled through Docker
- Optionally enable:
- auto-start with app launch
- managed restart
- managed restart active hours
- scheduled run
- Start All / Stop All / Restart All participation
- disk logging
- Select a process in the left sidebar to watch its logs.
- Drag a process in the sidebar, or right-click it, if you want to move it in the list.
- Use stack-wide controls in the header when you want to bring everything up or down together.
Commands are spawned directly, not through a shell.
Why that matters:
- process IDs stay tighter and cleanup is more reliable
- stop/kill behavior is more predictable
- shell operators like
&&,|, and>are not supported directly in the command field
If you need shell composition, wrap it in a script such as .cmd, .bat, .ps1, or another executable entrypoint and run that instead.
The app stores configuration in processes.json.
Example:
{
"stack_name": "My Stack",
"remote_control": {
"enabled": false,
"port": 47821
},
"log_directory": ".",
"processes": [
{
"id": "uuid-here",
"name": "Frontend Dev Server",
"command": "npm run dev",
"working_directory": "C:/projects/my-app/frontend",
"process_type": "Process",
"auto_start": false,
"auto_restart": true,
"restart_schedule": {
"enabled": false,
"stop_when_inactive": false,
"hours": []
},
"scheduled_run": {
"enabled": false,
"mode": "Daily",
"hour": 9,
"interval_hours": 1,
"weekdays": [true, true, true, true, true, false, false]
},
"respond_to_start_all": true,
"respond_to_stop_all": true,
"respond_to_restart_all": true,
"log_to_disk": true,
"log_rotation_count": 10
},
{
"id": "uuid-here",
"name": "PostgreSQL",
"command": "my-postgres-container",
"working_directory": "",
"process_type": "Docker",
"auto_start": false,
"auto_restart": false,
"restart_schedule": {
"enabled": false,
"stop_when_inactive": false,
"hours": []
},
"scheduled_run": {
"enabled": false,
"mode": "Daily",
"hour": 9,
"interval_hours": 1,
"weekdays": [true, true, true, true, true, false, false]
},
"respond_to_start_all": true,
"respond_to_stop_all": true,
"respond_to_restart_all": true,
"log_to_disk": false,
"log_rotation_count": 10
}
]
}Notes:
log_directoryis the shared base folder for persisted logs.resolves next to the executablerestart_schedule.hoursis a 168-entry Monday 00:00 through Sunday 23:00 hourly grid; missing or short lists are normalized automaticallyscheduled_runonly starts entries that are not already runningrespond_to_start_all,respond_to_stop_all, andrespond_to_restart_alldefault totruefor older configs- older config versions are migrated automatically on startup
When enabled, the manager starts a loopback-only HTTP server on 127.0.0.1:{port}.
Read endpoints:
GET /healthGET /processesGET /processes/{id}GET /processes/{id}/logs?limit=NGET /topology
Control endpoints:
POST /stack/startPOST /stack/stopPOST /stack/restartPOST /processes/{id}/startPOST /processes/{id}/stopPOST /processes/{id}/restart
Notes:
- the API binds only to
127.0.0.1 - use process
id, not display name, for per-process actions GET /processes/{id}/logs?limit=Ndefaults to200and caps at1000- control calls are fire-and-poll; poll
GET /processesorGET /healthfor updated state
| Shortcut | Action |
|---|---|
Ctrl+N |
Add new process |
Ctrl+S |
Start all processes |
Ctrl+X |
Stop all processes |
Ctrl+R |
Restart all processes |
Ctrl+C |
Copy selected log rows when row selection is active |
Escape |
Clear log row selection |
cargo run
cargo test
cargo build --releaseIf the app feels sluggish on one Windows machine but not another, or it only repaints correctly after switching windows, the issue is usually the graphics backend rather than process management.
Useful launch-time environment overrides:
PM_RENDERER=wgpu-dx12to force DirectX 12PM_RENDERER=wgpu-vulkanto force VulkanPM_RENDERER=glowto use the OpenGL backendPM_VSYNC=falseto disable vsyncPM_CAPTION_SYNC=startuporPM_CAPTION_SYNC=continuousto re-enable Windows title-bar color sampling if you specifically want that cosmetic behaviorPM_DIAGNOSTICS=trueto write a diagnostics log next to the executable
Examples in PowerShell:
$env:PM_RENDERER = "wgpu-dx12"
.\simple-rust-process-manager.exe$env:PM_RENDERER = "glow"
$env:PM_DIAGNOSTICS = "true"
.\simple-rust-process-manager.exeRust: application code and native desktop packagingegui/eframe: immediate-mode desktop UITokio: async runtime and background orchestrationSerde: config persistenceportable-pty: process output captureAxum: optional localhost REST API
MIT
If this saves you time, you can support the work here:
Issues and PRs are welcome.



