npm.io
0.1.1 • Published 2d ago

@astrion-labs/vireo-win32-x64

Licence
Apache-2.0
Version
0.1.1
Deps
0
Size
8.1 MB
Vulns
0
Weekly
0
Stars
2

Vireo

A lightweight process manager & resource guardian for Node, Python and Docker.

Memory leaks, crash loops, runaway processes and restart storms waste developer machines and take down services. Existing process managers restart things after they die; Vireo watches resource usage continuously and acts before the crash — while staying tiny itself (a single ~8MB static binary, ~10MB RSS, <1% CPU).

What it does

  • Supervises anything — Node scripts, Python scripts, arbitrary commands, and Docker containers, under one tool with one config file.
  • Memory ceilings — soft limits with graceful restart on breach; OS-enforced hard limits where supported (Job Objects on Windows, cgroups via Docker).
  • Leak detection — Theil-Sen trend analysis over each app's memory history detects sustained growth (robust against GC sawtooth and spikes) and restarts the app gracefully before it OOMs. Warmup grace periods prevent false positives on JIT/cache-heavy startups.
  • Crash-loop breaking — restarts use decorrelated-jitter exponential backoff, and 5 crashes within 60 seconds halts the app instead of burning CPU forever.
  • Correct process-tree management — on Windows, Job Objects guarantee that killing npm run dev also kills the node it spawned (no orphans in Task Manager); on unix, process groups do the same.
  • Graceful shutdown everywhere — SIGTERM→SIGKILL on unix, CTRL_BREAK→terminate on Windows, docker stop semantics for containers, all with configurable grace windows.
  • Doesn't become the problem — fixed-size metric ring buffers, adaptive sampling cadence, a plain ndjson IPC protocol, zero heavy dependencies. Check it yourself: vireo status --self.

Why Vireo over PM2?

Vireo PM2
Footprint Single ~8MB static binary, ~10MB RSS, no runtime needed Node.js daemon — requires a Node runtime and tens of MB of RSS
Memory handling Detects sustained leaks (Theil-Sen trend) and restarts before OOM; OS-enforced hard caps max_memory_restart reacts only after a threshold is crossed
What it supervises Node, Python, arbitrary commands and Docker containers in one config Processes only — no container supervision
Windows First-class: Job Objects tree-kill, hard memory caps, graceful CTRL_BREAK Known orphan-process and signal-handling gaps

Install

npm

npm install -g @astrion-labs/vireo

pip

pip install vireo-pm

Docker

docker run -v ./vireo.yml:/etc/vireo/vireo.yml ghcr.io/astrion-labs/vireo

Binary — grab a release from GitHub Releases.

All three installs give you the same vireo command.

Quick start

Supervise something in the foreground (great for CI and containers):

vireo run --max-memory 512MB --restart on-failure -- node server.js
vireo run --leak-slope 5MB/min -- python worker.py

Or hand apps to the daemon so they outlive your shell:

vireo start --name api --max-memory 512MB -- node server.js
vireo list                # live table: state, uptime, restarts, mem, cpu, trend
vireo logs api -f         # follow logs
vireo status api          # detail incl. memory trend + recent events
vireo status --self       # the daemon's own footprint
vireo stop api

Ecosystem file

Define everything in a vireo.yml and start it with one command:

apps:
  - name: api
    cmd: node server.js
    max_memory: 512MB
    max_cpu: 150%
    restart: on-failure
    leak:
      slope: 5MB/min     # sustained growth beyond this is a leak
      action: restart    # restart gracefully before OOM

  - name: worker
    cmd: python worker.py
    env:
      QUEUE_URL: "${QUEUE_URL:-redis://localhost:6379}"
    restart: always

  - name: cache
    kind: docker
    image: redis:7
    ports: ["6379:6379"]
    mem_limit: 256MB     # enforced by the kernel via cgroups
vireo start          # detached under the daemon
vireo up             # or foreground (containers / CI)

How leak detection works

Every 5 seconds Vireo samples the RSS of each app's entire process tree. Over a rolling window (default 10 minutes) it computes the Theil-Sen estimator — the median of all pairwise slopes — which ignores GC sawtooth patterns and one-off spikes that fool least-squares fits. When the trend exceeds your threshold (slope: 5MB/min) continuously for the sustain period (default 3 min), Vireo warns; if the projected time-to-OOM gets close and action: restart is set, it restarts the app gracefully at a moment of its choosing rather than letting the OS kill it at the worst one. A warmup period (default 2 min) after every start prevents false positives from JIT compilation and cache filling.

Command reference

Command Description
vireo run -- <cmd> Supervise in the foreground, no daemon
vireo up [file] Supervise all apps from a config file, foreground
vireo start [file | -- <cmd>] Start app(s) under the daemon, detached
vireo stop/restart/delete <app> Lifecycle (restart also re-arms halted apps)
vireo list Table of all apps with live resources (--json for machines)
vireo status <app> Detail: limits, trend, recent events
vireo status --self The daemon's own resource usage
vireo logs <app> [-f] [-n N] Recent logs / live follow
vireo kill-daemon Stop the daemon and all apps

Key flags for run/start: --name, --max-memory 512MB, --max-cpu 150, --hard-limit, --restart always|on-failure|never, --stop-grace 10s, --leak-slope 5MB/min, --leak-action warn|restart, --leak-window, --leak-sustain, --leak-warmup, --cwd.

Docker integration

Vireo talks to the Docker Engine API directly (no docker CLI needed). Containers declared with kind: docker get: pull-if-missing, create, start, kernel-enforced memory limits, restart-on-exit with the same backoff/breaker logic as processes, restart-on-unhealthy (healthcheck integration), and the same leak detection driven by container stats. Set adopt: true to guard a container that already exists by name. If the Docker engine isn't running, everything else keeps working.

To guard sibling containers from inside a container, mount the socket:

docker run -v /var/run/docker.sock:/var/run/docker.sock \
           -v ./vireo.yml:/etc/vireo/vireo.yml ghcr.io/astrion-labs/vireo

Design notes

  • Single static Go binary, CGO-free, cross-compiled to Windows/Linux/macOS on amd64+arm64. The npm and pip packages just ship this binary (the esbuild/ruff model) — no runtime dependency on Node or Python beyond the shim.
  • Daemon on demand: vireo start/list/... auto-spawn a per-user daemon speaking ndjson over a unix socket (unix) or named pipe (Windows, ACL'd to your user). vireo run/vireo up never spawn one.
  • State survives restarts: the daemon persists desired state and relaunches your apps if it's restarted.
  • Windows is first-class: Job Objects for tree-kill and hard memory caps, CTRL_BREAK_EVENT for graceful shutdown (handle SIGBREAK in Node, signal.SIGBREAK in Python), named-pipe IPC.

Building from source

go build -ldflags "-s -w" -o vireo .
go test ./...

License

Apache-2.0 Astrion Labs