Show HN: Supervice – process supervisor for agentic processes. zero dependencies Supervice, a zero-dependency, pure-Python process supervisor for Unix-like systems built on asyncio, has been released on GitHub, offering automatic restart, health checks, process grouping, hot config reload, and a Unix socket RPC interface for Python 3.10+ environments. The tool supports daemon mode, graceful shutdown, process group kill, log rotation, uptime tracking, retry with backoff, and user switching, with a command-line interface (supervicectl) for status, start/stop/restart, group operations, and hot reload. It is positioned as a production-ready alternative to traditional supervisors like supervisord, with no external dependencies beyond the Python standard library. A modern, lightweight, and fully async process supervisor for Unix-like systems. Zero dependencies. Pure Python. Production-ready. Supervice manages long-running processes with automatic restart, health checking, process grouping, hot config reload, and a Unix socket RPC interface — all built on Python's asyncio with no external packages. Async-first — Built entirely on asyncio for efficient I/O multiplexing Zero dependencies — Pure Python stdlib; nothing to install beyond Python 3.10+ Process groups — Organize related processes and control them as a unit Health checks — TCP connectivity and script-based health monitoring with auto-restart Hot reload — Add/remove programs without restarting the daemon supervicectl reload Daemon mode — Proper double-fork daemonization with PID file locking Graceful shutdown — SIGTERM/SIGINT triggers orderly stop of all child processes Process group kill — Stops entire process trees, not just the main PID Log rotation — Built-in RotatingFileHandler with configurable size and backup count Uptime tracking — Per-process wall-clock uptime displayed in status output Retry with backoff — Configurable start retries with automatic FATAL state on exhaustion User switching — Run processes as a specific user requires root Type-safe — Fully type-hinted, passes mypy --strict Requirements: Python 3.10+ on a Unix-like OS Linux, macOS . From source git clone https://github.com/yourusername/supervice.git cd supervice pip install . Development install includes docs dependencies pip install -e ". docs " supervisord.conf supervice loglevel = INFO logfile = supervice.log pidfile = supervice.pid program:webapp command = python3 -u app.py autostart = true autorestart = true stdout logfile = webapp.log stderr logfile = webapp err.log program:worker command = python3 -u worker.py numprocs = 4 autostart = true autorestart = true stdout logfile = worker % process num s.log stderr logfile = worker err % process num s.log Foreground development supervice -c supervisord.conf -n Background production — default supervice -c supervisord.conf Check status supervicectl status Output: NAME STATE PID UPTIME -------------------------------------------------------- webapp RUNNING 12345 1:23:45 worker:00 RUNNING 12346 1:23:44 worker:01 RUNNING 12347 1:23:44 worker:02 RUNNING 12348 1:23:44 worker:03 RUNNING 12349 1:23:44 Start / stop / restart individual processes supervicectl stop worker:00 supervicectl start worker:00 supervicectl restart worker:00 supervicectl restart worker:00 --force SIGKILL instead of graceful Group operations supervicectl stopgroup workers supervicectl startgroup workers Hot reload add/remove programs without restart supervicectl reload Use a custom socket path supervicectl -s /var/run/supervice.sock status | Option | Default | Description | |---|---|---| logfile | stdout | Daemon log file; empty logs to stdout in foreground, supervice.log when daemonized | loglevel | INFO | Log level: DEBUG , INFO , WARNING , ERROR , CRITICAL | pidfile | supervice.pid | Path to the PID/lock file; set to none or empty to disable | socket | runtime dir | RPC socket; defaults to $XDG RUNTIME DIR/supervice.sock root: /run/supervice.sock , else ~/.supervice.sock | shutdown timeout | 30 | Seconds to wait for graceful shutdown | log maxbytes | 52428800 | Max log file size before rotation bytes, 0 = no rotation | log backups | 10 | Number of rotated log backup files to keep | | Option | Default | Description | |---|---|---| command | required | Command to execute supports shell-style quoting | numprocs | 1 | Number of instances to run creates NAME:00 , NAME:01 , ... | autostart | true | Start automatically when daemon starts | autorestart | true | Restart automatically when process exits | startsecs | 1 | Seconds a process must run to be considered successfully started | startretries | 3 | Max consecutive start attempts before entering FATAL state | stopsignal | TERM | Signal to send when stopping TERM , INT , QUIT , KILL , etc. | stopwaitsecs | 10 | Seconds to wait after stop signal before sending SIGKILL | stdout logfile | none | File for stdout rotated by the daemon; supports % process num s | stderr logfile | none | File for stderr rotated by the daemon; supports % process num s | stdout logfile maxbytes / stderr logfile maxbytes | 50MB | Child log rotation threshold 0 disables | stdout logfile backups / stderr logfile backups | 10 | Rotated child log backups to keep | pdeathsig | true | Linux/FreeBSD: SIGKILL the direct child if the supervisor dies. One generation only — grandchildren are never covered; see | reconcile | auto | Orphans of a crashed supervisor found at startup: auto , kill , warn , off . Matches on identity, not pid — see | environment | none | Environment variables: KEY=VAL,KEY2="val with,comma" | env file | none | Comma-separated KEY=VALUE secrets files comments, quotes stripped ; read as the supervisor before the privilege drop. Later files win; environment overrides env file | directory | none | Working directory for the process | user | none | Run as this user requires root privileges | | Option | Default | Description | |---|---|---| programs | required | Comma-separated list of program names | | Option | Default | Description | |---|---|---| healthcheck type | none | Health check type: none , tcp , script | healthcheck interval | 30 | Seconds between health checks | healthcheck timeout | 10 | Seconds to wait for health check response | healthcheck retries | 3 | Consecutive failures before marking unhealthy | healthcheck start period | 10 | Seconds to wait before starting health checks | healthcheck port | none | TCP port to check required for tcp type | healthcheck host | 127.0.0.1 | TCP host to check | healthcheck command | none | Script to run required for script type | Example with health checks: program:api command = python3 -u api server.py autostart = true autorestart = true healthcheck type = tcp healthcheck port = 8080 healthcheck interval = 15 healthcheck retries = 3 healthcheck start period = 5 STOPPED ──┐ EXITED ──┼── STARTING ── RUNNING ── STOPPING ── STOPPED FATAL ──┤ │ │ BACKOFF ──┘ │ EXITED ▼ UNHEALTHY health check failures │ ▼ auto-restart if autorestart=true | State | Description | |---|---| STOPPED | Process is not running initial or manually stopped | STARTING | Process has been spawned, waiting for confirmation | RUNNING | Process is running and healthy | BACKOFF | Process exited too quickly, waiting before retry | STOPPING | Stop signal sent, waiting for process to exit | EXITED | Process has exited normally or abnormally | FATAL | Process failed to start after exhausting retries | UNHEALTHY | Process is running but health checks are failing | ┌─────────────────────────────────────────────────┐ │ supervice │ │ │ │ ┌──────────┐ ┌───────────┐ ┌──────────┐ │ │ │ Config │───▶│ Supervisor │───▶│ Process │ │ │ │ Parser │ │ core │ │ Manager │ │ │ └──────────┘ └─────┬─────┘ └────┬─────┘ │ │ │ │ │ │ ┌────▼────┐ ┌─────▼─────┐ │ │ │ RPC │ │ EventBus │ │ │ │ Server │ │ pub/sub │ │ │ └────┬────┘ └───────────┘ │ │ │ │ └────────────────────────┼─────────────────────────┘ │ Unix Socket ┌────▼────┐ │supervice│ │ ctl │ └─────────┘ | Platform | Status | |---|---| | Linux | First-class — full feature set, including pdeathsig via prctl 2 direct child only | | FreeBSD | Supported 15.x, 13.x — all features, including pdeathsig via procctl 2 direct child only ; see the FreeBSD notes below | | macOS | Supported for supervision, without — no kernel equivalent exists; supervice logs a warning if you request it. Children survive an abrupt supervisor kill pdeathsig | Field notes from the first production FreeBSD deployment live in PORTABILITY-FREEBSD.md /rodmena-limited/supervice/blob/main/PORTABILITY-FREEBSD.md . Run the supervisor itself as root from rc.d with no ${name} user and no daemon -u — FreeBSD's rc.subr wraps the whole command in su -m when ${name} user is set, so combining it with daemon -u