← Back to blog
Product August 11, 2026 by Javier Arancibia

I have four machines. I wanted to see them all at once. So I built MiniStats.

Prometheus + Grafana takes an afternoon and 4 GB of RAM to show me what uptime already knows. MiniStats is a 25 MB binary that does the same thing in seconds — one server, N clients, a WebSocket, no database.

MiniStats dashboard — 4 machines in a compact 2-column grid showing CPU, memory, and disk metricsFour machines, one tab, zero config. The dashboard auto-updates every 5 seconds over WebSocket.


I run a few machines — a laptop, a couple of VPSes, a Proxmox host. The standard answer for "see what's happening on all of them" is Prometheus plus Grafana: a time-series database, a query language, a dashboard builder, exporters on every node, and an afternoon of YAML. It's powerful. It's also overkill when the question is just "is disk full on dk1?" or "what's the load on rbm21?"

So I built MiniStats — a real-time system metrics dashboard that fits in one binary and takes less than 30 seconds to set up across all your machines.

The design: three commands, no database

The whole thing is three commands:

# on the machine that shows the dashboard
ministats server --port 9094

# on every machine you want to monitor
ministats daemon start --name my-box --server http://YOUR_SERVER:9094

# open the dashboard
open http://localhost:9094

That's it. The server serves a single HTML page with a WebSocket. Each client connects, reads free, df, and uptime every 5 seconds, and sends a JSON blob over the socket. The dashboard renders it as a grid — one row per machine, CPU load, memory available, disk usage. No persistence, no history, no alerts. Just what's happening right now.

The architecture is deliberately trivial:

[ client ] --->\
[ client ] ----->  [ server ] ---> Web UI (WebSocket)
[ client ] --->/

Clients stream metrics in real-time. Server aggregates and broadcasts. No database required — the server is a Map<string, ClientMetrics> in memory. When a client disconnects, it's pruned after a TTL. When you close the tab, the server keeps running. When you reopen, you see the current state immediately.

Why not just use ___?

I've used all the usual suspects. Here's the honest comparison:

FeatureMiniStatsNetdataPrometheus + Grafana
Setup timesecondsminuteshours
Resource usage~25 MB binarymediumhigh
Persistencenoyesyes
Multi-machineyesyesyes
Complexityminimalmediumhigh

MiniStats doesn't have history, alerts, or custom dashboards. That's the point. If you need long-term metrics, alerts, and analytics — use the bigger tools. If you just want to see what's happening now across your machines — use MiniStats. It's monitoring you actually use, not monitoring you set up once and then forget how to query.

The build: one binary, zero dependencies on the target

MiniStats is built with Bun — TypeScript on the server side, compiled to a single native binary with bun build --compile. The result is a 25 MB compressed binary that includes the runtime, the WebSocket server, the HTTP server, and the dashboard HTML — all in one file. No Node.js to install, no npm dependencies to resolve, no Docker to pull. curl | bash and you're done.

The client is the same binary — ministats daemon start spawns a detached process that reconnects on failure. The daemon writes a PID file to /tmp, so ministats daemon stop can find and kill it. It survives shell exit, SSH disconnect, and reboots (if you add it to crontab).

The whole codebase is ~300 lines of TypeScript across 7 files. The server is a Bun.serve() with a WebSocket handler. The client is a WebSocket that reads three standard Unix commands and sends JSON. The dashboard is a single inline HTML string with vanilla JS — no framework, no build step, no CDN. It just renders what the socket sends.

What's new in v1.0.17

The June update (just released) adds three things that were missing from the original April release:

  • Daemon modeministats daemon start/stop/status. Clients now survive shell exit as detached processes with PID file management. No more screen or nohup needed.
  • Compact 2-column dashboard — redesigned UI with a tight grid, IBM Plex Mono, scanline overlay, and stale-client highlighting (machines that go silent get a pulsing warning badge).
  • Stale client pruning — clients that disconnect without closing the WebSocket are detected by timestamp and auto-pruned after a configurable TTL (default 24h).

The philosophy

MiniStats focuses on three things: simplicity over features, speed over completeness, usability over configurability. It's the monitoring tool I actually use every day — not the one I set up once and then open Grafana once a month to remember how to query it.

If you run a homelab, a few VPSes, or just want to see what's happening on your machines right now: github.com/javimosch/ministatscurl | bash, one server, N clients, done.


MiniStats is open source at github.com/javimosch/ministats — download the binary from the v1.0.17 release. Built by Javier Arancibia.

Enjoyed this post?

Follow for more on agent-first engineering, self-hosted systems, and building for autonomy.

Follow @javimosch