Heavy day-to-day use of the GPU — for graphics work and running local LLMs — on top of the usual CPU load, meant I needed a terminal-based resource monitor that could show how usage trends over time, not just an instantaneous snapshot. The scrolling history graphs are directly inspired by oscilloscope displays.
Demo
Terminal previewOverview
A zero-dependency TUI resource monitor written in LuaJIT
Zero-dependency TUI resource monitor written in LuaJIT, compiled into a single self-contained ELF binary.
From the maintainer
Maintainer profileresmon
Heavy day-to-day use of the GPU — for graphics work and running local LLMs — on top of the usual CPU load, meant I neede
A zero-dependency TUI resource monitor written in LuaJIT
Clone the repo and run make (needs libluajit-5.1-dev), then just launch ./resmon — it starts with three built-in modules (CPU load, memory, top processes) and needs no config file. From there, make install-config drops a starter config.lua and copies the custom modules (per-core graphs, GPU, temperature, clock frequency) into ~/.config/resmon/mods, so you can mix and match panes.
resmon compiles down to a single self-contained static ELF binary — LuaJIT is linked in, so there's no Lua/Python/Node runtime to install. Almost every data source is read directly via FFI from /proc//sys instead of shelling out to external tools (the one exception being GPU stats, which have no libc/FFI path). Custom modules are plain-text .lua files loaded at startup through the exact same contract as the built-in ones — writing your own panel means dropping one file in a directory, no recompilation needed.
Expand the number of built-in fetchers and modules.
Key details
- ›Low-CPU fixed-tick main loop; each data source is fetched once and shared across every module that needs it
- ›24-bit truecolor rendering for bars and scrolling graphs
- ›Configurable vertical/horizontal layout with proportional or fixed-size panes
- ›Custom fetchers and display modules as plain-text Lua files, loaded at startup with no recompilation
- ›Per-core CPU usage, clock frequency, and temperature history graphs
- ›GPU monitoring via amdgpu_top (AMD, tested) or intel_gpu_top (Intel, untested)
- ›Single self-contained static ELF binary, no runtime Lua/LuaJIT dependency
Documentation
resmon ships with a built-in help/introspection CLI: resmon --help covers the app itself, and resmon -h shows any fetcher's or module's own configuration options and their defaults, without needing to read the source or a config file first.
Demo notes
Every fetcher and module can be sampled or demoed standalone before adding it to your config: -s renders one static sample pane, -d runs a live animated demo full-screen.
Maintainer install notes
Between v0.3.0 and v0.4.0, custom module filenames dropped the "mod_" prefix (e.g. mod_cpu_cores.lua -> cpu_cores.lua). Re-running install.sh --upgrade over an existing v0.3.0 install migrates automatically: it renames the bundled addon files, backs up config.lua, and rewrites it in place to point at the new module names.
Installation
Official prebuilt binary + install script from the v0.4.0 GitHub Release, published by the project maintainer.
curl -fsSL https://github.com/pacrox/resmon/releases/download/v0.4.0/resmon-v0.4.0-linux-x86_64.tar.gz | tar xz && ./resmon-v0.4.0-linux-x86_64/install.sh
Latest Release
v0.4.0
Added
- Standalone addon CLI:
resmon <addon_name> [-i|-h|-s|-d]inspects,
samples, or live-demos any fetcher or module on its own, without a
config file; modes are cumulative, an optionalfetch./mod.prefix
disambiguates a name shared by both kinds. - Every fetcher/module now carries
info/optsmetadata (plusranges
for fetchers,samplefake-data templates for modules), validated by a
shared, tightened contract check. src/fake_fetcher.lua: seeded noise generator driving-s/-dfake
data from each module'ssampletemplate; history-graph modules get
their rolling window pre-filled before a static-srender.NONEsentinel for afetcher = {...}slot that should stay
intentionally empty.--list(enumerate every installed fetcher/module),--include <path>
(additive dev/test directory, takes priority on a name collision),
-o/--options <{lua-table}>(CLI-side config override),-r/--refresh
extended to also pace a module's fake-data tick.- Global path flags (
--config-dir/-c/--config-file/--fetchers-dir/
--modules-dir) now recognized anywhere on the command line. config/fetcher_addon_sample.lua,config/module_addon_sample.lua,
config/ADDON-AUTHORING.md: ready-to-copy addon skeletons and a
walkthrough, installed by bothmake install-configand the release
tarball'sinstall.sh.dist/install.sh: detects an existing install and its version;
automatically migrates a 0.3.0 config/addons to the new naming, or
backs up and resetsconfig.luafor anything older/unrecognized;
--upgradeskips the confirmation prompt.
Fixed
prefill_module_historyno longer re-polls a real (-f-attached)
fetcher during its synthetic history replay — was hanging on
pipe-based fetchers and corrupting delta-based ones.-don a module now actually respects its refresh rate, gated per
cache slot instead of ticking unconditionally.-d/-son a fetcher now render nested-table values and
embedded-JSON string fields legibly instead of skipping/dumping them
raw.-spane width now correctly reaches half the terminal width instead
of being capped too low.-shistory prefill now respects an-o-overriddeninterval
instead of always using the addon's static default.
Changed
- Custom module filenames and config
mod = "..."values dropped the
redundantmod_prefix (mods/clock_graph.lua,mod = "clock_graph");
fetcher naming is unchanged. - Standalone-CLI and
--help/--listoutput reformatted: a single
banner/trailing-blank-line per invocation, terminal-width-aware
word-wrapped tables, right-aligned-i/--infometadata,
[VALID]/[FAULT]dependency markers. - README overhauled throughout (new Standalone addon CLI section + demo
GIF, Built-in Monitors table, Contributing points at the
addon-authoring samples).
Discussions