mmon
An interactive, live-updating system monitor for the terminal, in the style
of htop. It shows CPU, memory, GPU, disk, and network utilization in a
single ncurses screen — without the process list.
Features
- CPU — aggregate bar split into user/nice/system/IRQ/softirq/steal, plus a per-core grid with each logical CPU's own bracket bar and percentage. CCD (core-complex die) grouping when the topology exposes it, with cores laid out at least two per row in every view.
- Memory / Swap — used/total bars with percentages; the memory bar is segmented like htop (used + kernel buffers + page cache).
- GPU — works with NVIDIA, AMD, and Intel GPUs. Utilization, VRAM, temperature, power, fan, and clocks (when the source provides them).
- Disk — an interactive mount tree: every drive is a root row with a
total-space usage bar and R/W throughput. Single-partition drives show
their mount point directly; multi-partition drives expand to partitions.
ZFS pools are shown as drives (capacity + summed I/O) expanding to their
physical member disks and dataset mounts. Type tags distinguish drives:
[zfs] pool members, [cd] optical, [usb] removable/flash; devices without
a filesystem show their raw size instead of "no data" (an unloaded optical
drive shows "EMPTY"), and roles like SLOG/swap are labelled. Panel layout
is remembered in an XDG-style config file (
$XDG_CONFIG_HOME/mmon/mmon.conf). Columns aligned to the widest mount point. Scrollable. - Network — per-interface throughput plus accumulated RX/TX totals for the duration of the run.
- Remote monitoring & JSON API — serve the live snapshot as JSON over
HTTP (
--listen/--serve, default port 7331) from the TUI or headless (--headless), monitor another mmon instance (--remote, or thec/dkeys), with optional bearer-token auth andmmon.confsettings (serve,serve_port,serve_bind,serve_token,remote,remote_token). - Encrypted push & remote control —
--push URLPOSTs the snapshot to a server as gzip-compressed JSON sealed with ChaCha20-Poly1305 (key =SHA-256(token), token never sent); mmon also accepts pushed frames onPOST /pushfor relaying, and the receiving server can reply with encrypted commands mmon executes as if pressed in the TUI (focus, theme, connect, serve, resize, reorder, ...). Protocol:SERVER.md. - CPU sensors — temperature, power, and fan when hwmon/thermal sensors are exposed.
- Themes — 12 built-in color themes cycled with
F10(name shown top-right of the header), written to~/.config/mmon/themes/on first run where they can be edited or replaced; custom*.confthemes are picked up automatically. Themes map named color roles (header, active, text, dim, CPU/GPU bar colors, selection colors) tofg/fg:bgspecs with globalbackground/foregroundkeys, and paint the full screen background. Temperature/power color thresholds are configurable inmmon.conf. - Live 0.25-second refresh (configurable), bracket-style meters, flicker-free incremental redraw, terminal resize support, and keyboard/mouse-driven panels with focus, scrolling, expand/collapse, and resizable splits.
Downloads
Prebuilt packages for all supported architectures and distros (including native Windows) are available from the mmon release repository:
- Release page: https://apt.2it.onl/browse.php?pkg=mmon
Requirements
- Linux (any CPU architecture supported by the kernel), or Windows 10/11
- g++ (C++17) and cmake
- ncurses development headers (
libncurses-dev) — Linux only - For NVIDIA GPU data: the NVIDIA driver (NVML or
nvidia-smi) - For AMD/Intel GPU data: DRM sysfs + hwmon on Linux, or DXGI on Windows
Build
Linux / WSL
sudo apt install -y libncurses-dev # if not present
cmake -S . -B build
cmake --build build
Native Windows (cross-compile from Linux/WSL with MinGW-w64)
sudo apt install -y g++-mingw-w64-x86-64 # if not present
./build-win.sh # fetches PDCursesMod, builds mmon.exe
build-win.sh produces build-win/mmon.exe, a native Windows console app
built with PDCursesMod (a drop-in curses.h), so it runs in Windows
Terminal / cmd / PowerShell without WSL. It reads real Windows CPU, memory,
network (GetIfTable2), disk throughput (PDH), filesystem (GetDiskFreeSpaceEx),
and GPU (NVML / nvidia-smi / DXGI) data. Copy the .exe to any Windows
machine and run it.
Run
./build/mmon
Usage
Usage: mmon [OPTIONS]
Options:
-h, -?, --help show this help and exit
-V, --version print version and exit
-i, --interval SEC refresh interval in seconds (default 0.25)
-f, --fallback force nvidia-smi / DRM sysfs GPU source
instead of NVML
-l, --listen PORT serve the JSON metrics API on PORT (default 7331)
--serve serve the JSON metrics API (config port)
-r, --remote HOST[:PORT]
monitor a remote mmon instance
-t, --token TOKEN bearer token for serve, remote and push
-b, --bind ADDR address to bind the server to (default 0.0.0.0)
-d, --headless run without a TUI (requires --serve)
--push URL POST encrypted frames to URL (relay/store)
--push-token TOKEN shared secret for push encryption
--push-interval SEC push cadence (default: the -i sample interval)
--selftest run crypto/gzip/JSON self-tests and exit
--gen-token print a random 32-char base64 token and exit
--write-config with --gen-token, save it as serve_token
in the settings file
Environment:
MMON_FORCE_FALLBACK=1 same as --fallback
MMON_HWMON_PATH=PATH override sensor root (debug)
Controls:
Tab / Shift+Tab cycle focus (forward/backward)
PgUp/PgDn move selected item up/down (drives, net interfaces); r resets
j/k scroll/select (selection moves first, scrolls at edges)
space expand/collapse (disk drive, CPU grid)
+/- resize focused panel
mouse click to focus/select; drag the dashed divider above the disk
panel to resize the CPU grid, or above the network panel to
resize the disk/net split
F10 cycle color theme (name shown top-right of the header)
c connect to a remote mmon (prompts for host:port)
d disconnect from the remote, back to local
s toggle the JSON API server (prompts for port and bind)
q quit
Remote Monitoring & JSON API
mmon can both serve its metrics as JSON and monitor another mmon instance. Run a headless server on the machine you want to watch from afar:
mmon --headless --serve # default port 7331
mmon --headless --listen 7331 --token hunter2
Then point a local mmon at it (TUI):
mmon --remote myserver:7331 --token hunter2
or connect at runtime with c (disconnect with d). A curl client works
too: GET http://host:7331/ returns the full snapshot (CPU, memory, load,
sensors, net, disk tree, ZFS pools, filesystems, GPUs) as a single JSON
object, and GET http://host:7331/gz returns the same data gzip-compressed.
The remote client auto-detects gzip (header or magic bytes) and decompresses
transparently. Serving/remote can also be configured in mmon.conf (serve,
serve_port, serve_bind, serve_token, remote, remote_token).
Push encrypted frames to a relay/store server and let it send commands back:
mmon --headless --push http://myserver:8080/push --push-token hunter2
The payload is gzip + ChaCha20-Poly1305 (key = SHA-256(token)); the token
is never sent (decryption = authentication). mmon can also receive pushes
(POST /push) so it acts as a relay. See SERVER.md for the wire protocol.
GPU Support
The GPU backend is selected automatically at startup, in order:
- NVML (NVIDIA) — loaded dynamically from the NVIDIA driver.
- nvidia-smi — CSV queries.
- DRM sysfs — generic AMD/Intel path under
/sys/class/drm.
Only the fields a source actually provides are shown. For example, on a bare-metal NVIDIA system you get temperature/power/fan/clocks; on a DRM-only Intel system you get utilization and VRAM if exposed.
Data Sources
| Metric | Source |
|---|---|
| CPU | /proc/stat, /proc/loadavg, /proc/uptime |
| Memory | /proc/meminfo |
| Network | /proc/net/dev |
| Disk | /proc/diskstats, /proc/mounts, statvfs(3) |
| CPU sensors | /sys/class/hwmon, /sys/class/thermal |
| GPU | NVML (dlopen), nvidia-smi, /sys/class/drm |
Notes / Troubleshooting
- WSL2: CCD topology, CPU sensors, and NVML fan readings are typically
hidden by the hypervisor — the tool degrades gracefully (single CPU grid,
no sensor line,
Fan N/A). Thenvidia-smifallback usually provides fan speed. To test CPU sensors on such systems, pointMMON_HWMON_PATHat a directory containinghwmon*/sensor trees. - Windows: the load average is approximated from an EMA of CPU busy
(Windows has no load average); CCD grouping is not exposed, so a single
grid is shown; CPU power/fan are not available (only temperature, via WMI
MSAcpi_ThermalZoneTemperature, when present). Disk throughput reflects physical-disk I/O via PDH counters. The JSON API, remote monitoring, and headless mode work on Windows too (Winsock). Troubleshooting: runmmon.exefrom a terminal (cmd/PowerShell), not by double-clicking, so error messages stay visible. If it still exits immediately, runset MMON_DEBUG=1(cmd) or$env:MMON_DEBUG="1"(PowerShell), run it again, and check the generatedmmon.log; a crash is also recorded there. - Disk: throughput reflects Linux block-device I/O. Traffic through 9p
mounts (e.g.
/mnt/c) is not counted. - Resize: the layout reflows on terminal resize; on very short terminals the bottom sections clip gracefully.
Documentation
- Full manual:
man mmon(ordocs/mmon.1) - Markdown manual:
docs/mmon.md
Project Layout
CMakeLists.txt build configuration
src/
main.cpp CLI, refresh loop, rendering
sys_metrics.* /proc, sysfs, hwmon, CPUID sampling
gpu_metrics.* NVML / nvidia-smi / DRM sysfs backends
ui.* ncurses drawing helpers
docs/
mmon.1 man page
mmon.md markdown manual
CHANGELOG.md
README.md
License
MIT
