Skip to main content

viper

Production-grade process manager for Python services on Linux servers. Start apps from the terminal, keep them alive, watch their memory, tail their logs — and never touch a process it didn't start itself.

Built for teams running Python/AI services (model servers, workers, APIs) who are tired of tmux sessions, nohup, and 3 a.m. surprises.

viper start "uvicorn app:app --port 8000" --name api -i 2 --max-memory 2G
viper ls
viper logs api -f

Why not pm2?

pm2 is great — and written in Node.js. viper is pure Python (psutil + asyncio), designed around what Python/AI services actually need: virtualenv auto-detection, memory watchdogs for leaky inference processes, a daemon that survives its own crash, and (on the roadmap) readiness probes for slow-loading models and GPU awareness.

Install

# apt (Debian/Ubuntu servers) — one-shot, installs python3 + all deps automatically:
curl -fsSL https://raw.githubusercontent.com/ramakrishnan2808/viper-pm/main/install.sh | sudo sh

# or pip/pipx (any Linux):
pipx install viper-pm        # or: pip install viper-pm

(The installer adds the project's signed apt repository once — apt can only install from repositories it knows, and viper-pm isn't in the official Debian/Ubuntu archive yet. After that, updates arrive via normal apt upgrade.)

From source:

git clone <repo> && cd viper && pip install -e .

Quickstart

# start anything: a command, a .py file, or a config file
viper start "uvicorn app:app --port 8000" --name api -i 2 --max-memory 1G
viper start worker.py --name worker
viper start viper.yml

viper ls                 # table of apps, workers, cpu, memory, uptime, restarts
viper logs api -f        # follow logs (per-worker prefixes)
viper events api         # audit trail: every start/exit/restart and *why*
viper reload api         # rolling restart: workers restart one at a time
viper stop api           # graceful stop (SIGTERM, grace period, then SIGKILL)
viper delete api         # stop + remove from management
viper kill               # stop everything and shut the daemon down

The daemon starts automatically on first use and runs per-user. If the daemon itself is killed, your apps keep running — the next viper command respawns it and it re-attaches to every live worker from its journal.

The team workflow: viper apply

Keep a viper.yml in each project repo; deploys become:

git pull && viper apply viper.yml

apply converges the server to the file: new apps start, changed apps restart with the new config, unchanged apps are left alone (--prune also removes apps missing from the file).

apps:
  - name: api
    cmd: uvicorn app:app --host 0.0.0.0 --port 8000
    cwd: /srv/api            # relative paths resolve against this file
    venv: auto               # finds .venv/ or venv/ in cwd (or give a path)
    workers: 2               # each worker gets VIPER_WORKER_ID=0,1,...
    max_memory: 2G           # restart a worker whose process tree exceeds this
    env_file: .env           # loaded fresh at every (re)start; env: below wins
    env:
      MODEL_PATH: /models/base
    stop_signal: SIGTERM
    stop_grace: 30           # seconds before SIGKILL
    autorestart: true
    max_restarts: 10         # consecutive fast crashes before giving up
    min_uptime: 10           # seconds that count as a "stable" run

  - name: worker
    cmd: celery -A tasks worker
    cwd: /srv/pipeline

cmd supports $VAR / ${VAR} from the final environment (including env_file), e.g. cmd: uvicorn app:app --port ${API_PORT} with API_PORT in .env. Apps can be addressed by name or by the numeric id from viper ls (e.g. viper restart 0).

Reboot persistence

viper startup     # one-time: installs a systemd service for the daemon

That's all a server needs: after a reboot, systemd starts the viper daemon and the daemon automatically restores every app that was running, from its journal. Your apps never need individual systemd services.

viper save / viper resurrect also exist (pm2-style) for explicit snapshots — e.g. save a known-good set before experimenting, resurrect to return to it. viper unstartup removes the boot service.

Guarantees

  • Never touches foreign processes. Every managed PID is stored with its process create-time and both are re-verified before any signal is sent — a recycled PID is never signalled. Workers run in their own process group, so signals reach the worker's own tree and nothing else.
  • Daemon crashes are non-events. Workers write logs straight to files and keep running; a restarted daemon re-attaches from the journal.
  • Honest restart behaviour. Exponential backoff (0.5s → 30s cap), a circuit breaker after max_restarts consecutive fast crashes (state errored, visible in viper ls), and every restart's reason recorded in viper events.

Environment your app sees

Variable Meaning
VIPER_APP_NAME the app's name
VIPER_WORKER_ID worker index 0..N-1 (use it to fan out ports)
PYTHONUNBUFFERED=1 set by default so logs stream live
VIRTUAL_ENV, PATH pointed at the detected/configured virtualenv

Files live under ~/.viper/ (override with VIPER_HOME): per-worker logs in logs/, the state journal, the events audit log, and the daemon log.

Roadmap

Readiness/liveness health checks with startup_grace for slow model loads → readiness-gated zero-downtime reload → viper monit live TUI → alert webhooks (Slack) → Prometheus metrics → GPU awareness (CUDA_VISIBLE_DEVICES assignment, GPU-memory watchdog) → viper startup systemd generation → apt repo + snap. See PLAN.md for the full plan and docs/PACKAGING.md for the apt/snap path.

Development

python3 -m venv .venv && .venv/bin/pip install -e .[dev]
.venv/bin/python -m pytest tests/

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

viper_pm-0.2.0.tar.gz (24.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

viper_pm-0.2.0-py3-none-any.whl (23.5 kB view details)

Uploaded Python 3

File details

Details for the file viper_pm-0.2.0.tar.gz.

File metadata

  • Download URL: viper_pm-0.2.0.tar.gz
  • Upload date:
  • Size: 24.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for viper_pm-0.2.0.tar.gz
Algorithm Hash digest
SHA256 fd8a148823ffbc8c07af2c169f37c8edc8f12dc56454784c7a93ed226d05d969
MD5 cf6835bcb5038d130056a42fffef1936
BLAKE2b-256 11c0c5fe2d65230291c184552985e28f01598f18dfb20c88fd11105356c3c8ae

See more details on using hashes here.

Provenance

The following attestation bundles were made for viper_pm-0.2.0.tar.gz:

Publisher: release.yml on ramakrishnan2808/viper-pm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file viper_pm-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: viper_pm-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 23.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for viper_pm-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a7aaad4f8793b68e08dc0d0b6231cf3209a6ba882d521bf44f7ffb5004e9196c
MD5 5d9782dbdefb3e42ab6bd4f3ed526098
BLAKE2b-256 2756d2db3b3a71673368b3971a733f9a32162845d2f0ba8a45a8d514792303b2

See more details on using hashes here.

Provenance

The following attestation bundles were made for viper_pm-0.2.0-py3-none-any.whl:

Publisher: release.yml on ramakrishnan2808/viper-pm

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page