Scripting Your Process Manager with oxmgr list --json and jq
Human-readable tables are great in a terminal and terrible in a script. The moment you try to grep and awk a process list, you’re parsing column positions that break the first time a process name gets long.
oxmgr list --json (alias oxmgr ls --json) skips all of that. It emits a clean JSON array — one object per process, with the full schema — that you pipe straight into jq. Empty lists emit [], so you never have to special-case “nothing running.”
The shape of the data
Each entry mirrors the internal process schema:
oxmgr ls --json | jq '.[0]' {
"id": "a1b2c3",
"name": "api",
"command": "node dist/server.js",
"args": [],
"status": "online",
"pid": 48213,
"cpu_percent": 2.4,
"memory_bytes": 78643200,
"restart_count": 0,
"cluster_mode": true,
"health_status": "healthy"
} Everything you’d want to assert on is there: status, pid, memory_bytes, restart_count, health_status. Now the recipes.
Recipe 1: Is everything online?
A deploy smoke test — exit non-zero if any process isn’t online:
if oxmgr ls --json | jq -e 'all(.[]; .status == "online")' > /dev/null; then
echo "✅ all processes online"
else
echo "❌ something is down"
oxmgr ls --json | jq -r '.[] | select(.status != "online") | .name'
exit 1
fi Drop this at the end of your deploy script and a failed boot fails the deploy instead of silently limping.
Recipe 2: Memory watchdog
Print any process over 500 MB, sorted by usage:
oxmgr ls --json
| jq -r '.[] | select(.memory_bytes > 500e6)
| "(.name)\t(.memory_bytes / 1e6 | floor)MB"'
| sort -k2 -n -r Wrap it in a cron job and you have a cheap memory-leak early warning. For hard caps that restart automatically, use resource limits instead — but this is a good way to find the threshold first.
Recipe 3: Restart-count alarm
A process that quietly restarts 40 times is “online” but not healthy:
oxmgr ls --json
| jq -r '.[] | select(.restart_count > 5)
| "⚠️ (.name) has restarted (.restart_count) times"' Restart count is the metric crash-looping apps reveal themselves through long before they page anyone.
Recipe 4: Health gate for a load balancer
Want your reverse proxy to only route to a box where the app reports healthy? Expose a tiny check:
#!/bin/sh
# healthy.sh — exit 0 only if "api" is online AND health is healthy
oxmgr ls --json
| jq -e '.[] | select(.name == "api")
| select(.status == "online" and .health_status == "healthy")'
> /dev/null Point an nginx/Caddy health check or your orchestration at this and rolling deploys become safe by construction.
Recipe 5: A one-line status for CI
CI logs love flat key/value output:
oxmgr ls --json | jq -r '.[] | "(.name)=(.status)"'
# api=online
# worker=online
# scheduler=stopped Recipe 6: Total footprint
Sum memory across everything Oxmgr manages — useful for right-sizing a VPS (see How Much VPS Do You Actually Need?):
oxmgr ls --json
| jq '[.[].memory_bytes] | add / 1e6 | floor | "(.)MB total"' Pairing with the event stream
oxmgr ls --json gives you a snapshot; the event bus gives you the changes. The two compose naturally: poll the JSON on a schedule for dashboards and reports, subscribe to events for anything that has to react instantly. A common pattern is to render a table from --json and refresh it whenever a process:* event arrives, so you get live state without a fast polling loop.
Why JSON output matters
The point of --json isn’t the flag — it’s that it makes Oxmgr a composable tool. A process manager that only speaks to humans forces you to build brittle scrapers. One that speaks JSON drops into pipelines, CI, cron, and dashboards without ceremony. Anything you can express in jq, you can now assert about your running processes — which is most of the operational questions you actually ask.