Oxmgr is a lightweight, language-agnostic process manager written in Rust.
It is a modern, production-minded alternative to PM2 for any executable (Node.js, Python, Go, Rust, shell commands, and more).
It can be used as a drop-in replacement for many PM2 setups because Oxmgr supports PM2 ecosystem config format (ecosystem.config.json).
Supported platforms: Linux, macOS, Windows.
- Docs Index
- User Guide
- Installation Guide
- CLI Reference
- Terminal UI Guide
- Pull and Webhook Guide
- Deployment Guide
- Service Bundles
- Oxfile Specification
- Oxfile vs PM2 Ecosystem
- Oxfile Examples
- Language-agnostic by design
- Rust performance and low overhead
- Durable daemon model with persistent state
- Explicit restart policies + health checks
- Idempotent config apply (
oxmgr apply) - Built-in per-process logs and runtime metrics
- Drop-in migration path via PM2 ecosystem config compatibility
- Start/stop/restart/reload/delete managed processes
- Named processes (
--name) with safe auto-generated names - Restart policies:
always,on-failure,never - Configurable max restart count (
--max-restarts) - Crash-loop cutoff: stop after
3auto restarts in5minutes by default (--crash-restart-limit) - Optional file watching restart loop (
--watch) - Background daemon with local IPC over localhost TCP
- CLI auto-starts daemon when needed
- Persistent state in JSON (
state.json) - Per-process stdout/stderr logs + tail mode
- Interactive terminal UI (
oxmgr ui) with keyboard + mouse controls, ESC menu, and help overlay - Automatic log rotation and retention policy
- Process statuses:
running,stopped,crashed,restarting,errored - Graceful shutdown (SIGTERM, then SIGKILL on timeout)
- Process-tree aware shutdown (Unix process groups / Windows taskkill tree)
- Node.js cluster mode (
--cluster,--cluster-instances) for network server fan-out - Health checks with automatic restart on repeated failures
- CPU/RAM monitoring in
listandstatus - Resource limits (
max_memory_mb,max_cpu_percent) with auto-restart - Optional Linux cgroup v2 hard limits (
--cgroup-enforce) and GPU deny env masking (--deny-gpu) - Exponential restart backoff with jitter and cooldown reset
- Ecosystem config import (
ecosystem.config.jsonstyle) for PM2 drop-in compatibility - Compact service export/import bundles (
.oxpkg) with local + HTTPS import support - Built-in git pull + no-downtime reload (
oxmgr pull) - Webhook API (
POST /pull/<name|id>) with per-service secret - Local/remote service transfer via compact
.oxpkgexport/import bundles - Idempotent config reconcile via
oxmgr apply - Reload without downtime (best-effort hot replacement)
- PM2-style remote deployment workflow (
oxmgr deploy ...)
npm install -g oxmgr
# or
yarn global add oxmgrbrew tap Vladimir-Urik/OxMgr
brew install oxmgrchoco install oxmgr -yecho "deb [trusted=yes] https://vladimir-urik.github.io/OxMgr/apt stable main" | sudo tee /etc/apt/sources.list.d/oxmgr.list
sudo apt update
sudo apt install oxmgrSigned-key setup (recommended when signing is enabled) is documented in docs/install.md.
git clone https://github.com/Vladimir-Urik/OxMgr.git
cd OxMgr
cargo build --releaseBinary:
./target/release/oxmgrcargo install --path .# Start process with restart policy
oxmgr start "node server.js" --name api --restart always --max-restarts 20 --crash-restart-limit 3
# Check fleet
oxmgr list
# Reconcile config idempotently (only changed apps restart)
oxmgr apply ./oxfile.toml --env prod
# Validate oxfile syntax + dependencies + expanded names
oxmgr validate ./oxfile.toml --env prod
# Run environment + daemon diagnostics
oxmgr doctor
# Install daemon service on current platform
oxmgr service install --system auto
# Detailed status (includes CPU/RAM + health)
oxmgr status api
# Launch interactive dashboard
oxmgr ui
# Reload with minimal disruption (best effort)
oxmgr reload api
# Pull git updates and hot-reload when changed
oxmgr pull api
# Logs
oxmgr logs api
oxmgr logs api -foxmgr ui is built for fast fleet operations from a terminal:
- Navigate with
j/kor arrow keys. - Open menu with
Esc, quit withq. nopens create-process modal directly in UI.- Run actions directly on selected service:
sstopddelete (with confirm modal)rreloadShift+Rrestartlfullscreen logspgit pull (with conditional reload/restart on change)tpreview latest log lineg/Spaceforce refresh?toggle help overlay- Mouse row selection and wheel scrolling are supported.
- Selected process gets a full-height right-side detail sidebar (status, health, cpu/ram bars, git/process info).
- Fullscreen log viewer supports scrolling, stdout/stderr switching, and live reload from disk.
More details: docs/UI.md.
Configure each service in oxfile.toml:
git_repo = "git@github.com:org/repo.git"
git_ref = "main"
pull_secret = "replace-with-random-secret"Then trigger updates:
oxmgr pull api
curl -X POST \
-H "X-Oxmgr-Secret: replace-with-random-secret" \
http://127.0.0.1:51234/pull/apiBehavior:
- unchanged commit: no restart/reload
- changed commit while running: reload
- changed commit while desired-running but currently stopped: restart
- changed commit while desired-stopped: checkout only
Full guide: docs/PULL_WEBHOOK.md.
oxmgr export produces compact .oxpkg bundles to move service definitions between hosts.
Security defaults for oxmgr import:
- remote URL import only allows
https:// - URL credentials/fragments are rejected
- remote payload size is capped
- strict schema validation is enforced
- internal checksum is validated
- optional explicit pinning via
--sha256
Bundle reference: docs/BUNDLES.md.
Start and register a process.
Options:
--name <name>--restart <always|on-failure|never>(default:on-failure)--max-restarts <n>(default:10)--crash-restart-limit <n>(default:3,0disables the 5-minute crash-loop cutoff)--cwd <path>--env KEY=VALUE(repeatable)--health-cmd <command>--health-interval <seconds>(default:30)--health-timeout <seconds>(default:5)--health-max-failures <n>(default:3)--kill-signal <signal>(for graceful stop, e.g.SIGINT)--stop-timeout <seconds>(default:5)--restart-delay <seconds>(default:0)--start-delay <seconds>(default:0)--watch(restart on working-directory file changes)--cluster(Node.js cluster mode)--cluster-instances <n>(optional worker count; default uses all CPUs)--namespace <name>--max-memory-mb <n>--max-cpu-percent <n>--cgroup-enforce(Linux only, requires cgroup permissions)--deny-gpu(sets common GPU visibility env vars to disable GPU use)
Example:
oxmgr start "python app.py" \
--name worker \
--restart on-failure \
--max-restarts 5 \
--crash-restart-limit 3 \
--health-cmd "curl -fsS http://127.0.0.1:8080/health" \
--health-interval 15 \
--health-timeout 3 \
--health-max-failures 3 \
--max-memory-mb 512 \
--max-cpu-percent 80 \
--cgroup-enforce \
--deny-gpuCluster mode notes:
- Cluster mode currently supports
node <script> [args...]. - Node runtime flags before script path are not supported in cluster mode.
--cluster-instancesrequires--cluster.
Crash-loop notes:
--crash-restart-limitcounts only daemon-triggered auto restarts after unexpected exits.- Manual
restart,reload,start, and config-driven operations reset the crash-loop counter. 0disables the cutoff completely.
Gracefully stop process.
Stop and start process using stored definition.
Start a replacement instance, then terminate the old one (best effort no-downtime reload).
Pull latest changes from configured git repository and reload/restart service only when commit changed.
Remove process definition (stops it first if running).
Show all managed processes with runtime metrics.
Columns include: ID NAME STATUS MODE PID UPTIME RESTARTS CPU% RAM(MB) HEALTH.
Show detailed process metadata, watch/cluster settings, logs, health state, CPU, and RAM.
Open interactive terminal dashboard.
Options:
--interval-ms <n>refresh interval in milliseconds (default800)
Show process logs.
Options:
-f, --followstream continuously--lines <n>number of lines from each log file (default100)
Export one managed service into a compact .oxpkg bundle.
Example:
oxmgr export api
oxmgr export 2 --out ./release/api.oxpkgImport process definitions from:
- local
ecosystem.config.json - local
oxfile.toml - local
.oxpkgbundle - remote
https://....oxpkgbundle
Example:
oxmgr import ./ecosystem.config.json
oxmgr import ./ecosystem.config.json --env prod --only api,worker
oxmgr import ./api.oxpkg
oxmgr import https://example.com/api.oxpkg --sha256 0123abcd... --only apiOptions:
--env <name>: applies profile overrides (env_<name>for ecosystem,[apps.profiles.<name>]for oxfile)--only <names>: comma-separated app names filter--sha256 <hex>: optional remote checksum pin (recommended for URL imports)- remote URL import requires
curlavailable inPATH
Oxmgr daemon exposes an HTTP webhook endpoint:
POST /pull/<name|id>- send secret via
X-Oxmgr-Secretheader (orAuthorization: Bearer <secret>) - configure daemon API bind address with
OXMGR_API_ADDR(defaults to localhost high port) - per-service secret is configured in
oxfile.tomlviapull_secret
Idempotently reconcile desired config with daemon state.
- unchanged and already running apps are not touched
- changed apps are recreated
- matching but stopped/crashed apps are restarted
- optional
--pruneremoves managed apps missing from config
Example:
oxmgr apply ./oxfile.toml --env prod --only api,worker
oxmgr apply ./ecosystem.config.json --pruneOptions:
--env <name>: profile selector (env_<name>or[apps.profiles.<name>])--only <names>: comma-separated app filter--prune: delete apps not present in desired config
Convert ecosystem config into Oxmgr-native TOML format.
Example:
oxmgr convert ecosystem.config.json --out oxfile.toml --env prodValidate native oxfile config without talking to daemon.
Checks include:
- TOML parse + profile resolution
- command syntax sanity
- cluster mode command validity (
node <script> ...when enabled) - duplicate app names
depends_onreferences- duplicate expanded names (
instancesexpansion)
Example:
oxmgr validate ./oxfile.toml
oxmgr validate ./oxfile.toml --env prod --only api,workerOptions:
--env <name>profile selector--only <names>comma-separated app filter
PM2-style deployment syntax:
oxmgr deploy <config_file> <environment> <command>Default config auto-discovery syntax:
oxmgr deploy <environment> <command>Supported commands:
setupupdaterevert [n]current|currprevious|prevlistexec|run "<cmd>"<ref>(deploy explicit git ref/tag/branch)
Flags:
--config <path>--force(forupdate/<ref>)
Full lifecycle hooks and multi-host examples: docs/DEPLOY.md
Run local environment diagnostics.
Checks include:
- base/log directories existence + writability
- daemon address resolution
- state file readability and JSON shape
- daemon IPC reachability (
ping) and process listing (if daemon is running)
Exit code is non-zero only when at least one check fails.
Print boot autostart setup instructions for daemon.
Run daemon in foreground mode. Normally unnecessary; CLI auto-start handles it.
Request graceful daemon shutdown.
Manage Oxmgr as an OS service directly.
oxmgr service install --system auto
oxmgr service status --system auto
oxmgr service uninstall --system autoOXMGR_HOME: override Oxmgr data directory (state/logs)OXMGR_DAEMON_ADDR: override daemon bind/connect address (default127.0.0.1:<derived-port>)OXMGR_API_ADDR: override webhook HTTP API bind address (default127.0.0.1:<derived-port>)OXMGR_LOG_MAX_SIZE_MB: log rotation size threshold in MB (default20)OXMGR_LOG_MAX_FILES: number of rotated files kept per log (default5)OXMGR_LOG_MAX_DAYS: maximum rotated log age in days (default14)
Oxmgr supports PM2-like config files with an apps array.
Supported fields per app:
namecmd(full command line) ORscript+argscwdenvautorestartrestart_policymax_restartscrash_restart_limithealth_cmd,health_interval,health_timeout,health_max_failures- or nested
health: { cmd, interval, timeout, max_failures } restart_delaydelay_start/start_delaystart_order/prioritykill_signal/pm2_kill_signalstop_timeout/kill_timeoutmax_memory_restart(e.g."256M"),max_memory_mb,max_cpu_percentexec_mode(cluster/cluster_mode) for PM2-style cluster importcluster_mode,cluster_instancesnamespaceinstances,instance_varenv_<profile>object overrides (used viaoxmgr import --env <profile>)
Cluster import note:
exec_mode: "cluster"maps to Oxmgr cluster mode.- in that mode, ecosystem
instancesis interpreted as cluster worker count.
Deployment note:
- top-level
deployenvironments are used byoxmgr deploy ...
Example:
{
"apps": [
{
"name": "api",
"cmd": "node server.js",
"cwd": "/srv/api",
"env": { "NODE_ENV": "production" },
"restart_policy": "always",
"max_restarts": 20,
"crash_restart_limit": 3,
"health_cmd": "curl -fsS http://127.0.0.1:3000/health",
"health_interval": 15,
"health_timeout": 3,
"health_max_failures": 3,
"max_memory_restart": "512M",
"max_cpu_percent": 80
},
{
"name": "worker",
"script": "python",
"args": ["worker.py"],
"autorestart": true,
"max_restarts": 10,
"crash_restart_limit": 5
},
{
"name": "api-cluster",
"cmd": "node api.js",
"exec_mode": "cluster",
"instances": 2,
"priority": 10,
"restart_delay": 5,
"delay_start": 3,
"pm2_kill_signal": "SIGINT",
"kill_timeout": 8,
"max_memory_restart": "256M",
"env_prod": {
"NODE_ENV": "production",
"instances": 6,
"priority": 1,
"max_memory_restart": "1024M"
}
}
]
}oxfile.toml is Oxmgr-native config with extra features (profiles and dependency ordering).
If you are deciding between PM2 ecosystem JSON and native TOML, see: docs/OXFILE_VS_PM2.md.
Example:
version = 1
[defaults]
restart_policy = "on_failure"
max_restarts = 10
crash_restart_limit = 3
stop_timeout_secs = 5
max_memory_mb = 256
[[apps]]
name = "db"
command = "docker compose up db"
start_order = 0
[[apps]]
name = "api"
command = "node server.js"
depends_on = ["db"]
cluster_mode = true
cluster_instances = 4
restart_delay_secs = 2
start_delay_secs = 1
stop_signal = "SIGINT"
stop_timeout_secs = 8
namespace = "backend"
max_cpu_percent = 80
[apps.env]
BASE = "1"
[apps.profiles.prod]
cluster_instances = 8
start_order = 1
max_memory_mb = 768
[apps.profiles.prod.env]
NODE_ENV = "production"Supported oxfile features include:
- global
[defaults] - per-app
depends_on(startup ordering) - per-profile overrides in
[apps.profiles.<name>] instancesandinstance_varcluster_modeandcluster_instances- restart/stop delay and signal settings
- crash-loop cutoff (
crash_restart_limit, default3auto restarts in5minutes) - namespace and health checks
- resource limits (
max_memory_mb,max_cpu_percent)
- Single-user localhost endpoint:
127.0.0.1:<derived-port> - CLI sends JSON IPC requests
- Daemon owns lifecycle, restart logic, health checks, and metrics refresh
- Child exits are handled asynchronously
- State is persisted after lifecycle changes
- On daemon restart, desired-running processes are restored
Per process logs:
~/.local/share/oxmgr/logs/<name>.out.log~/.local/share/oxmgr/logs/<name>.err.log
Use oxmgr logs <name> or oxmgr logs <name> -f.
Use:
oxmgr startup --system systemd
# or
oxmgr startup --system launchd
# or
oxmgr startup --system task-schedulerThis prints ready-to-use service definitions and activation commands.
Tagging vX.Y.Z triggers automated release pipeline in .github/workflows/release.yml:
- builds binaries for Linux/macOS/Windows
- creates
.debpackage - publishes GitHub release assets + checksums
- publishes npm package (when
NPM_TOKENexists) - updates Homebrew tap formula (when Homebrew secrets exist)
- publishes Chocolatey package (when
CHOCO_API_KEYexists) - publishes APT repository content to
gh-pages/apt
Required release secrets are documented in docs/RELEASE.md.
Current automated tests cover:
- restart policy behavior (
always,on-failure,never) - crash-loop cutoff scheduling and manual restart reset behavior
ecosystem.config.jsonparsing (cmd,script+args, health config)- ecosystem/oxfile resource limit parsing and serialization
- idempotent
applyplanning behavior (noop/recreate/restart/prune) - storage roundtrip and corrupted state recovery
- secure import URL validation and checksum pinning logic
.oxpkgbundle integrity + schema validation guards- pull workflow summary behavior (unchanged vs updated checkout)
- webhook auth and API request handling (
POST /pull/<name|id>) - terminal UI helper logic (layout, truncation, menu hitboxes)
Run:
cargo testCI runs the same checks on Linux/macOS/Windows via .github/workflows/ci.yml.
src/
main.rs CLI entrypoint + command dispatch
cli.rs clap command model
daemon.rs daemon loop, IPC listener, auto-start helper
oxfile.rs oxfile.toml parser + converter writer
process_manager.rs lifecycle + restart/reload + health + metrics
process.rs domain models/status/restart/health enums
ipc.rs request/response protocol
ecosystem.rs ecosystem.config.json import parser
storage.rs durable state load/save
logging.rs log handling and tail helpers
config.rs paths and filesystem layout
errors.rs domain errors
- Fork and create branch (
codex/<feature-name>) - Add/update tests for behavior changes
- Run:
cargo fmt
cargo clippy --all-targets --all-features -- -D warnings
cargo test- Open PR with:
- problem statement
- design summary
- migration/backward compatibility notes
Suggested license: MIT.
Author and lead developer: Vladimír Urík
This project is created under the open-source patronage of Empellio.com.