ZPM is a small, sharp process manager for apps you want to keep alive.
It gives you a daemon, named processes, crash restart, log following, clusters, environment profiles, health checks, log rotation, startup on boot, and ecosystem config files without turning your terminal into a carnival.
Linux/macOS (Bash):
curl -sL https://raw.githubusercontent.com/shellhaki/zpm/main/scripts/install.sh | bashWindows (PowerShell as Administrator):
iex (curl.exe -UseBasicParsing https://raw.githubusercontent.com/shellhaki/zpm/main/scripts/install-windows.ps1)- zpm - Command-line interface for managing processes
- zpmd - Background daemon (auto-starts on boot)
- PATH - Binary location automatically added to your system PATH
zpm --help # See available commands
zpmd # Start daemon (or auto-starts on boot)
zpm list # List managed processes
zpm start script.js # Start managing a process✅ Linux: amd64, arm64 (auto-detected)
✅ macOS: amd64 (Intel), arm64 (Apple Silicon) (auto-detected)
✅ Windows: amd64
| Platform | Managed By | Enable Command |
|---|---|---|
| Linux | systemd user service | systemctl --user enable zpmd |
| macOS | LaunchAgent | launchctl load ~/Library/LaunchAgents/com.zpm.daemon.plist |
| Windows | Task Scheduler | Auto-configured if installer run as Admin |
go build -o daemon/zpmd ./daemon
go build -o src/zpm ./src
ln -sf "$PWD/src/zpm" ~/.local/bin/zppKeep zpmd beside the CLI or set:
export ZPMD_PATH=/path/to/zpmdzpp daemon start
zpp daemon stop
zpp daemon reloadStart on login:
zpp startup install
zpp startup uninstallLinux uses user systemd, macOS uses LaunchAgent, Windows uses Task Scheduler.
zpp start "bun index" --name api --follow
zpp status
zpp stop api
zpp restart api
zpp start api
zpp purge apiZPM starts commands from the directory where you run zpp start, so package scripts work naturally.
{
"scripts": {
"serve:zpm": "zpp start \"bun index\" --name api --follow"
}
}zpp start "bun index" --name api --env production
zpp start "bun index" --name api --env PORT=3000
zpp start "bun index" --name api --instances 4
zpp start "bun index" --name api --restart-delay 1000 --max-restarts 10
zpp start "bun index" --name api --health "curl -fsS http://127.0.0.1:3000/health"
zpp start "bun index" --name api --log-max-size 20mb --log-backups 7Cluster instances are named api-0, api-1, etc. Group commands work:
zpp stop api
zpp restart api
zpp purge apiCreate 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:
zpp ecosystem start zpm.config.json --env productionZPM stores state in your user config directory:
registry.json
daemon.pid
daemon.log
logs/<process>.log
On Linux that is usually ~/.config/zpm.
The one-liner installers are cross-platform shell/PowerShell scripts that automate installation. This section describes how they work and the implementation details.
The universal installer (install.sh) detects your operating system and architecture, then routes to the appropriate platform-specific installer:
User runs: curl | bash
↓
install.sh (universal entry point)
↓
├─→ Linux? → install-linux.sh
├─→ macOS? → install-macos.sh
└─→ Windows? → install-windows.ps1
- Architecture detection: Auto-detects amd64 or arm64 via
uname -m - Download: Fetches
zpm-linux-{arch}.tar.gzfrom GitHub Releases - Installation: Extracts to
~/.local/bin/ - PATH setup: Adds export to
~/.bashrcor~/.zshrc(shell auto-detected) - Daemon: Creates systemd user service at
~/.config/systemd/user/zpmd.service - Error handling: Validates binaries and URLs, comprehensive error messages
- Architecture detection: Auto-detects amd64 or arm64 via
uname -m - Download: Fetches
zpm-darwin-{arch}.tar.gzfrom GitHub Releases - Installation: Extracts to
~/.local/bin/ - PATH setup: Adds export to
~/.zshrcor~/.bash_profile(shell auto-detected) - Daemon: Creates LaunchAgent at
~/Library/LaunchAgents/com.zpm.daemon.plist - Logging: Creates
~/.zpm/directory for daemon logs - Error handling: Validates binaries and URLs, color-coded output
- Architecture detection: Uses
PROCESSOR_ARCHITECTUREenvironment variable - Download: Fetches
zpm-windows-amd64.tar.gzfrom GitHub Releases - Installation: Extracts to
%LOCALAPPDATA%\zpm\bin - PATH setup: Updates User PATH environment variable (persists across sessions)
- Daemon: Creates Task Scheduler task "ZPM Daemon" (if run as Administrator)
- Error handling: Graceful handling when not run as Administrator
✅ No external tools - Uses only curl, tar, and basic shell utilities
✅ Auto-detection - OS, architecture, and shell all auto-detected
✅ User-level install - No sudo/admin required (except Windows Task Scheduler)
✅ Platform-native services - Uses systemd/LaunchAgent/Task Scheduler
✅ Error handling - Validates downloads, verifies binaries, helpful messages
✅ Color output - Clear, friendly terminal feedback
All scripts fetch from GitHub API:
https://api.github.com/repos/shellhaki/zpm/releases/latest
or
https://api.github.com/repos/shellhaki/zpm/releases/tags/{version}
Binary assets are matched by platform pattern:
- Linux:
zpm-linux-{arch}.tar.gz - macOS:
zpm-darwin-{arch}.tar.gz - Windows:
zpm-windows-amd64.tar.gz
Linux/macOS (specify custom directory as second argument):
curl -sL https://raw.githubusercontent.com/shellhaki/zpm/main/scripts/install.sh | bash -s latest /usr/local/binWindows PowerShell:
$InstallDir = "C:\Program Files\zpm"
# Download and edit the script with custom InstallDirLinux/macOS (specific version as first argument):
curl -sL https://raw.githubusercontent.com/shellhaki/zpm/main/scripts/install.sh | bash -s v0.1.0Command not found after install?
- Linux/macOS: Run
source ~/.bashrcorsource ~/.zshrc - Windows: Restart your terminal/PowerShell
Daemon won't start?
- Linux: Check with
systemctl --user status zpmd - macOS: Check with
launchctl list | grep zpm - Windows: Check Task Scheduler for "ZPM Daemon" task
Failed to download?
- Verify internet connection
- Check GitHub is accessible
- Try specifying an exact version instead of "latest"
Linux:
systemctl --user disable zpmd
rm ~/.local/bin/{zpm,zpmd}
# Edit ~/.bashrc or ~/.zshrc to remove ZPM PATH exportmacOS:
launchctl unload ~/Library/LaunchAgents/com.zpm.daemon.plist
rm -rf ~/.local/bin/{zpm,zpmd} ~/.zpm ~/Library/LaunchAgents/com.zpm.daemon.plist
# Edit ~/.zshrc or ~/.bash_profile to remove ZPM PATH exportWindows (PowerShell as Administrator):
Unregister-ScheduledTask -TaskName "ZPM Daemon" -Confirm:$false
Remove-Item "$env:LOCALAPPDATA\zpm" -Recurse
# Remove from User PATH environment variables manuallyLocated in the scripts/ directory:
- install.sh - Universal entry point (OS detection and routing)
- install-linux.sh - Linux-specific installer with systemd integration
- install-macos.sh - macOS-specific installer with LaunchAgent integration
- install-windows.ps1 - Windows PowerShell installer with Task Scheduler integration
- README.md - Detailed installation and troubleshooting guide
Push a tag to publish cross-platform builds:
git tag v0.1.0
git push origin v0.1.0The release pipeline builds:
- Linux amd64, arm64
- macOS amd64, arm64
- Windows amd64