A terminal-based system monitor written in C++20. Displays CPU, memory, GPU, and network usage as live gauges with dark/light theme support.
System Monitor [t] Theme [q] Quit
────────────────────────────────────────────────────────────────────────
╭──────────────────────────────────────────────────────────────────────╮
│ CPU │
│ Total ████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 8.3% │
│ Core 0 ██░░░░░░░░░░░░░░░░░░░░░░░░ 5.0% Core 4 ████ 15.0% │
│ Core 1 ██████████████████░░░░░░░░ 72.0% Core 5 ░░░░░░ 0.0% │
│ ... │
╰──────────────────────────────────────────────────────────────────────╯
╭──────────────────────────────────────────────────────────────────────╮
│ Memory │
│ RAM ████████░░░░░░░░░░░░░░░░░░░ 6.12 GB / 31.22 GB 19.6% │
╰──────────────────────────────────────────────────────────────────────╯
╭──────────────────────────────────────────────────────────────────────╮
│ GPU NVIDIA GeForce RTX 4070 Ti 45°C │
│ Core ████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 23.0% │
│ VRAM █████░░░░░░░░░░░░░░░░░░░░░░░░ 1658 / 12282 MiB 13.5% │
╰──────────────────────────────────────────────────────────────────────╯
╭──────────────────────────────────────────────────────────────────────╮
│ Network │
│ ↓ Recv ████████████░░░░░░░░░░░░░░░░░░░░░░░░ 12.54 MB/s │
│ ↑ Send ███░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 3.21 MB/s │
╰──────────────────────────────────────────────────────────────────────╯
| Dependency | Notes |
|---|---|
| C++20 compiler | GCC 13+ or Clang 16+ |
| CMake 3.14+ | FetchContent used to download FTXUI |
| FTXUI v5 | Fetched automatically at configure time |
nvidia-smi |
Optional — GPU section is hidden when unavailable |
Supported on Linux and Windows. Linux stats are read from /proc/stat,
/proc/meminfo, and /proc/net/dev. Windows stats are read from the native
Win32 APIs: CPU usage via NtQuerySystemInformation, memory via
GlobalMemoryStatusEx, and network counters via GetIfTable.
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)On Windows, use the same CMake flow from PowerShell or a developer shell:
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build buildThe binary is placed at build/monitor-tui on Linux and
build/monitor-tui.exe on Windows.
./build/monitor-tui| Key | Action |
|---|---|
t |
Toggle dark / light theme |
q |
Quit |
The display refreshes every second. All sections resize with the terminal window.
monitor-tui/
├── CMakeLists.txt # Build config; fetches FTXUI via FetchContent
└── src/
├── monitor.hpp # Data structs + Monitor class declaration
├── monitor.cpp # System stats collection
└── main.cpp # UI rendering and event loop
Four plain structs hold the latest snapshot of each subsystem:
CpuInfo — total usage (0–1) + per-core vector
MemInfo — used / total in kB, ratio (0–1)
GpuInfo — present flag, name, core usage, VRAM usage, temperature
NetInfo — rx_bps / tx_bps in bytes/s, peak_bps for gauge scaling
Monitor owns one instance of each and exposes a single update() method.
CPU (update_cpu) — on Linux, reads /proc/stat each call. On Windows,
queries per-processor performance counters with NtQuerySystemInformation.
Both paths compute usage per core as 1 - idle_delta / total_delta between
two consecutive snapshots. The first call only seeds the previous snapshot;
actual values appear from the second call onward.
Memory (update_mem) — on Linux, reads MemTotal and MemAvailable
from /proc/meminfo; used memory is MemTotal − MemAvailable (this accounts
for page cache, which the kernel reclaims under pressure). On Windows, reads
physical memory totals and availability with GlobalMemoryStatusEx.
GPU (update_gpu) — shells out to nvidia-smi with
--format=csv,noheader,nounits and parses the single output line. The
gpu.present flag is set to false on any failure, causing the GPU section to
be omitted from the UI entirely.
Network (update_net) — on Linux, reads /proc/net/dev; on Windows, reads
interface counters with GetIfTable. Both paths sum rx/tx byte deltas across
all active non-loopback interfaces and divide by elapsed seconds to get
bytes/s. peak_bps tracks the running maximum and decays by 1% per second so
the gauge scale slowly shrinks back after a burst.
Theme — a plain struct of ftxui::Color values. make_light() and
make_dark() return the two presets. usage_color() maps a 0–1 ratio to
green / yellow / red based on 50% and 85% thresholds.
build_ui() — pure function: takes a Monitor snapshot and a Theme,
returns an ftxui::Element tree. Each section is a vbox wrapped in
border. CPU cores beyond 4 are arranged in a 2-column grid via
core_pair(). Network gauge bars are scaled relative to peak_bps so the
bar always fills meaningfully rather than staying near zero.
Main loop — follows the standard FTXUI pattern:
main thread worker thread
──────────── ──────────────────────────────
screen.Loop() ←── sleep 1s → lock → monitor.update()
↑ └→ screen.PostEvent(Custom)
└── Renderer lambda reads monitor under the same mutex
A std::mutex serialises access to Monitor between the worker that writes
and the renderer that reads. std::atomic<bool> running signals the worker to
stop when q is pressed.