Skip to content

ZPM — Process Manager

Keep your apps alive. Crash restart, clusters, log rotation, health checks, and ecosystem configs — without turning your terminal into a carnival.
Terminal window
curl -sL https://raw.githubusercontent.com/shellhaki/zpm/main/scripts/install.sh | bash

After installation:

Terminal window
zpm --help # see available commands
zpm list # list managed processes
zpm start script.js # start managing a process

Crash restart

Processes come back up automatically. Configure delay, max restarts, and backoff per process.

Clusters

Spin up N instances with --instances. Named api-0, api-1, etc. Group commands work on all of them.

Health checks

Run any shell command as a health probe. ZPM restarts unhealthy processes automatically.

Log rotation

Cap log file size and keep N backups. No manual cleanup, no disk surprises.

Environment profiles

Named env profiles in your ecosystem config. Switch between production, staging, and more at runtime.

Startup on boot

Native integration with systemd, LaunchAgent, and Task Scheduler. One command to install.

Ecosystem config

Declare all your processes in a single zpm.config.json. Version-controllable and shareable.

Built in Go

Single static binary. No runtime, no dependencies. Ships with a daemon and a CLI.


Terminal window
zpm start "bun index" --name api --follow
zpm status
zpm stop api
zpm restart api
zpm purge api

ZPM starts commands from the directory where you run zpm start, so package scripts work naturally:

{
"scripts": {
"serve:zpm": "zpm start \"bun index\" --name api --follow"
}
}

Terminal window
zpm start "bun index" --name api --env production
zpm start "bun index" --name api --env PORT=3000
zpm start "bun index" --name api --instances 4
zpm start "bun index" --name api --restart-delay 1000 --max-restarts 10
zpm start "bun index" --name api --health "curl -fsS http://127.0.0.1:3000/health"
zpm start "bun index" --name api --log-max-size 20mb --log-backups 7

Cluster instances are named api-0, api-1, etc. Group commands apply to all:

Terminal window
zpm stop api
zpm restart api
zpm purge api

Terminal window
zpm daemon start
zpm daemon stop
zpm daemon reload

Register the daemon to start on login:

Terminal window
zpm startup install
zpm startup uninstall
PlatformManaged byEnable command
Linuxsystemd user servicesystemctl --user enable zpmd
macOSLaunchAgentlaunchctl load ~/Library/LaunchAgents/com.zpm.daemon.plist
WindowsTask SchedulerAuto-configured when installer is run as Administrator

Create zpm.config.json:

{
"apps": [
{
"name": "api",
"command": "bun index",
"cwd": ".",
"instances": 2,
"auto_restart": true,
"restart_delay": 1000,
"max_restarts": -1,
"health_command": "curl -fsS http://127.0.0.1:3000/health",
"log_max_bytes": 10485760,
"log_backups": 5,
"env": {
"PORT": "3000"
},
"env_production": {
"NODE_ENV": "production"
}
}
]
}

Run it:

Terminal window
zpm ecosystem start zpm.config.json --env production

ZPM stores state in your user config directory (typically ~/.config/zpm on Linux):

registry.json
daemon.pid
daemon.log
logs/<process>.log

Linux

amd64, arm64 — auto-detected via uname -m.
Installs to ~/.local/bin/. Creates a systemd user service.
systemctl --user enable zpmd

macOS

amd64 (Intel), arm64 (Apple Silicon) — auto-detected.
Installs to ~/.local/bin/. Creates a LaunchAgent plist.
launchctl load ~/Library/LaunchAgents/com.zpm.daemon.plist

Windows

amd64 — installs to %LOCALAPPDATA%\zpm\bin.
Updates User PATH. Creates a Task Scheduler task when run as Administrator.


Push a tag to publish cross-platform builds via GitHub Actions:

Terminal window
git tag v0.1.0
git push origin v0.1.0

The pipeline builds: Linux amd64/arm64, macOS amd64/arm64, Windows amd64.


Terminal window
systemctl --user disable zpmd
rm ~/.local/bin/{zpm,zpmd}
# remove ZPM PATH export from ~/.bashrc or ~/.zshrc

Built by shellhakihaki.top · x.com/haki_xer