cmd / procman
procman is a process manager for local development on macOS.
It is open source.
Install:
go install github.com/croaky/procman@latest
Define your process definitions in Procfile.dev. For example:
clock: bundle exec ruby cmd/clock.rb
esbuild: bun run buildwatch
queues: bundle exec ruby cmd/queues.rb
web: bundle exec ruby cmd/web.rb
Run processes by naming them in a comma-delimited list:
procman esbuild,web
You must list at least one process. There are no options or flags.
The output from multiple processes will be combined. For example:
esbuild |
esbuild | > buildwatch
esbuild | > node build.mjs --watch
esbuild |
esbuild | watching...
web | [67296] Puma starting in cluster mode...
web | [67296] * Puma version: 6.4.2 (ruby 3.3.0-p0) ("The Eagle of Durango")
web | [67296] * Min threads: 12
web | [67296] * Max threads: 12
web | [67296] * Environment: development
web | [67296] * Master PID: 67296
web | [67296] * Workers: 2
web | [67296] * Restarts: (✔) hot (✖) phased
web | [67296] * Preloading application
web | [67296] * Listening on http://0.0.0.0:3000
web | [67296] Use Ctrl-C to stop
web | [67296] - Worker 1 (PID: 67331) booted in 0.9s, phase: 0
web | [67296] - Worker 0 (PID: 67330) booted in 0.9s, phase: 0
procman will run its processes until it receives a SIGINT (Ctrl+C),
SIGTERM, or SIGHUP.
If one of the processes finishes, it will send a SIGINT to all remaining
running processes, wait 5s, and then send a SIGKILL to all remaining processes.
procman runs exactly one process per definition.
It runs the processes in Procfile.dev "as-is";
It does not load environment variables from .env before running.
File watching
Add # watch: PATTERNS to automatically restart a process when files change:
clock: bundle exec ruby cmd/clock.rb # watch: lib/**/*.rb
esbuild: bun run buildwatch
queues: bundle exec ruby cmd/queues.rb # watch: lib/**/*.rb
web: bundle exec ruby cmd/web.rb # watch: lib/**/*.rb,ui/views/**/*.haml
Patterns are relative to the directory containing Procfile.dev.
Glob patterns support * (single directory) and ** (recursive).
Multiple patterns can be comma-separated.
Processes without a watch annotation run without file watching.
On change, procman sends SIGINT, waits for the process to exit, then restarts.
Changes are debounced (100ms) to avoid rapid restarts during multi-file saves.
Concurrent restarts are serialized per process to avoid races.
This approach handles code reloading at the process manager level, benefiting projects in any language without requiring framework support.