1 unstable release
| 0.2.0-rc.5 | Oct 7, 2025 |
|---|---|
| 0.2.0-rc.2 |
|
| 0.1.2 |
|
| 0.1.1 |
|
| 0.1.0 |
|
#1840 in Data structures
69KB
1K
SLoC
sys-mumu — System tools plugin for the Lava/MuMu language
Version: 0.2.0-rc.3 Repository:
https://gitlab.com/tofo/mumu-sys
License: MIT OR Apache-2.0
sys-mumu is a native (no external binaries) system plugin for the Lava/MuMu runtime. It exposes timestamps, hardware inventory, sensors (temperatures, fans, voltages), fan control, CPU inventory & frequencies, thermal zones, and a streaming watch API that plays nicely with your flow-style code. The public API is stable and namespaced under sys:* with sub-namespaces like sys:hw:* and sys:cpu:*.
This document covers everything in the repository: what it exposes to users, how the data is shaped, the internals that make it work, platform notes, and the legacy/demo assets that remain in the tree.
Table of contents
- Feature summary
- Public API (MuMu functions)
- Data shapes & error conventions
- Filters & backends
- Permissions & security
- Internals & layout
- Repository assets (examples & tests)
- Compatibility notes
- Contributing
- Acknowledgements
- License
Feature summary
- Native, no shell: does not invoke
bash,sensors, or any other external program in the plugin’s runtime paths. - Linux-first: implements
/procand/sysreaders for:hwmon(temperatures/fans/voltages)cpufreq(per-core frequencies)/proc/cpuinfo(per-logical-CPU inventory)/sys/class/thermal(thermal zones)
- Fan control: PWM duty writes (0..100%) when permitted.
- Streaming:
sys:hw:watch(interval_ms [, filter])yields an Iterator of sensor rows at a cadence — ergonomic with flow transforms. - Stable MuMu shapes: all functions return
KeyedArrayor arrays (MixedArray) ofKeyedArrayrows; row shapes are documented below. - Extensible: backend registry is pluggable; additional OS backends (macOS/Windows) can register later without changing the user API.
Public API (MuMu functions)
All functions are registered by exact name. Multi-segment names (e.g. sys:hw:info) are supported by the runtime.
Timestamps
-
sys:timestamp_ms() -> long
Milliseconds since UNIX epoch. -
sys:timestamp_micro() -> long
Microseconds since UNIX epoch.
Hardware: info & capabilities
-
sys:hw:info() -> keyed{ vendor: string, // e.g., "AuthenticAMD", "GenuineIntel" (best-effort) model: string, // model name (best-effort) family: string, // CPU family (best-effort) features: [string], // CPU flags when available backend: "linux-hwmon" | "null" } -
sys:hw:caps() -> keyed{ temps:bool, fans:bool, voltages:bool, clocks:bool, thermal:bool }
Hardware: sensors (snapshot)
-
sys:hw:sensors([filter]) -> [keyed]
Returns a snapshot list of sensor rows. Accepts an optionalfilterstring:- kinds:
"temp" | "fan" | "volt" | "clock" | "thermal" - or a backend name:
"linux-hwmon","linux-thermal", etc.
Row shape:
{ kind: "temp" | "fan" | "volt" | "clock" | "thermal", id: string, // e.g., "k10temp:temp1", "nct6798:fan3" label: string, // human-friendly label when available, else fallback value: float|int, // temps: °C, fans: rpm, voltages: V, clocks: MHz unit: "C" | "rpm" | "V" | "MHz", path: string, // sysfs path when applicable backend: string // e.g., "linux-hwmon", "linux-thermal" } - kinds:
Hardware: fan control
-
sys:hw:fan_list() -> [keyed]
Lists controllable PWM devices:{ id:"<chip>:pwmN", label:string, min:int(0), max:int(100), path:string, backend:"linux-hwmon" } -
sys:hw:fan_set(id, percent) -> bool | keyed(error)
Set PWM duty topercent(0..100). Accepts<chip>:pwmNor an absolutepwmNsysfs path.
On success:true. On failure (e.g., permission denied):{ type:"runtime", message:string, id:string, percent:int }
Permissions: writes usually require root or suitable udev rules. Reads do not.
Hardware: streaming watch (flow-friendly)
sys:hw:watch(interval_ms [, filter]) -> Iterator
Produces an Iterator that yields the same row shapes assys:hw:sensors()at a cadence. Between batches, the iterator yields"NO_MORE_DATA"so host poll loops remain responsive. Designed to plug into flow transforms andslogin the REPL.
CPU
-
sys:cpu:info() -> [keyed]
One row per logical CPU parsed from/proc/cpuinfo. Keys reflect kernel field names; values are auto-typed when possible. -
sys:cpu:frequency() -> [keyed]
Per-CPU current frequency (MHz) fromcpufreqif present:{ cpu:int, cur_freq_mhz:float, path:string, backend:"linux-cpufreq" }
Thermal zones
-
sys:thermal:list() -> [keyed]
Thermal zones from/sys/class/thermal:{ kind:"temp", id:"thermal_zoneN", label:string, value:float(C), unit:"C", path:string, backend:"linux-thermal" }
Data shapes & error conventions
-
KeyedArray (implemented with
indexmap) is used for all rows and single-object returns (inventory, caps, error objects). Ordering is stable for displays and tests. -
Errors are returned as standard keyed objects with at least:
{ type:"runtime", message:string, ... }This crate pins
core-mumu 0.8.1-rc.5, which does not define a dedicatedKeyedErrorvalue, so we useKeyedArrayconsistently. -
Streaming semantics: iterators return one item per
next_value()when available; otherwise they return"NO_MORE_DATA". This integrates with the REPL/host poller without blocking.
Filters & backends
The optional filter parameter in sys:hw:sensors and sys:hw:watch:
- If a kind (e.g.,
"temp"), only rows of that kind are returned. - If a backend name (e.g.,
"linux-hwmon"), only rows from that backend are returned.
Backends included today:
- Linux
hwmon(linux-hwmon) — temperatures, fans, voltages under/sys/class/hwmon/*. - Linux thermal (
linux-thermal) — OS thermal zones under/sys/class/thermal/*. - Linux cpufreq (
linux-cpufreq) — per-CPU scaling current frequency. - Null backend (
null) — present on non-Linux builds; reports empty snapshots.
Permissions & security
- Read-only APIs (
*info,*caps,*sensors,cpu:info,cpu:frequency,thermal:list) typically read world-readable files under/procand/sys. Missing nodes simply result in missing rows. - Fan writes (
sys:hw:fan_set) require privileges to writepwm*sysfs nodes. If the write fails (e.g.,EPERM), the function returns a keyed error with a helpful message. Typical solutions:- run with sufficient privileges
- add udev rules to grant group write access and run under that group
No public API in this plugin invokes external programs or shells.
Internals & layout
src/lib.rs — registration conduit
- Exposes
Cargo_lock(entrypoint for Lava/MuMu loader). - Re-exports modules:
pub mod share;— internals, not user-callablepub mod register;— bridges that register the MuMu functions
- Registers all
sys:*functions duringCargo_lock.
src/register/** — user-callable bridges
Each file registers one or more public functions with the interpreter. Bridges validate arguments, call the appropriate helpers under share/**, and return MuMu Value objects.
Bridges in this crate:
timestamp.rs→sys:timestamp_ms,sys:timestamp_microhw_info.rs→sys:hw:infohw_caps.rs→sys:hw:capshw_sensors.rs→sys:hw:sensors([filter])hw_fan_list.rs→sys:hw:fan_listhw_fan_set.rs→sys:hw:fan_set(id, percent)hw_watch.rs→sys:hw:watch(interval_ms [, filter])cpuinfo.rs→sys:cpu:infocpufreq.rs→sys:cpu:frequencythermal.rs→sys:thermal:list
All bridges use register::bind_dyn_only to (1) register a dynamic function by name and (2) bind a variable of the same name so calls like sys:hw:info() resolve naturally.
src/share/** — reusable internals
-
watch_iter.rs
A small engine for periodic producers: spawns a thread that calls a closure at a cadence and pushes producedValues into a channel. APluginIteratorpulls from that channel, returning"NO_MORE_DATA"when empty. -
hw/backend.rs
Minimal backend trait and a registry that merges multiple backends (ORs capability booleans, concatenates rows) with a Null fallback. -
hw/mod.rs
Owns the global backend registry. On Linux, it installs thelinux-hwmonbackend at startup and re-exports Linux helpers so bridges can reuse them (e.g.,linux_cpuinfo,linux_cpufreq,linux_thermal).
Linux backends
-
linux_hwmon.rs
Reads/sys/class/hwmon/*:- temperatures (
temp*_input) — millidegrees converted to °C - fans (
fan*_input) — rpm - voltages (
in*_input) — millivolts converted to V
Discovers PWM (pwmN,pwmN_enable) and exposes fan list/control.
- temperatures (
-
linux_cpuinfo.rs
Parses/proc/cpuinfointo oneKeyedArrayper logical CPU (auto-typing values). Also providessummarize_cpuinfo()used byhw:info. -
linux_cpufreq.rs
Readscpufreq/scaling_cur_freqper CPU and returns MHz rows. -
linux_thermal.rs
Reads/sys/class/thermal/thermal_zone*to provide OS thermal sensors.
Streaming iterator
sys:hw:watch uses share/watch_iter.rs to:
- spawn a producer thread that samples sensors at
interval_ms - enqueue rows as
Value::KeyedArray - expose a
PluginIteratorthat yields one item per call and returns"NO_MORE_DATA"when the queue is empty
This design makes it safe in the REPL and in interpreted runs and integrates with the host’s poll loop (and your flow transforms).
Repository assets (examples & tests)
-
examples/sys-command.mu
A legacy/demo example showing a shell-basedsys:commandpattern. The current plugin does not registersys:command(to keep runtime strictly native). This file is kept for historical reference. -
tests/sys_command_test.mu
A legacy test that exercisessys:command. Not run by default with this native build; keep it or adapt it behind a feature if you want to exercise shell execution locally.
All other code paths (timestamps, sensors, frequency, thermal, watch) are fully native and ready to use.
Compatibility notes
-
MuMu core: this crate targets
core-mumu = "0.8.1-rc.5". That version:- exposes
KeyedArraybut not a specialKeyedError; errors here are returned as keyed objects withtype:"runtime". - does not expose a namespace-reservation API; the plugin simply registers dynamic names and binds matching variables.
- exposes
-
OS support:
- Linux: full functionality.
- Non-Linux: APIs load and return empty arrays (
[]) when the platform backends are not available.
Contributing
Bug reports and merge requests are welcome at the GitLab repository. To help us reproduce issues quickly, please include:
- OS/distro and kernel version (e.g.,
uname -a) - Output of relevant
/procand/sysnodes (paths are reported in every row) - The exact
sys:*function and arguments used, including anyfilter - Whether the behavior is on snapshot (
sys:hw:sensors) or streaming (sys:hw:watch)
We welcome backends for additional platforms (macOS SMC/IOKit, Windows WMI/PDH). The backend trait is intentionally small; feel free to propose extensions.
Acknowledgements
- Tom Fotheringham (
@tofo) — author & maintainer of the MuMu/Lava ecosystem and this plugin. - All MuMu/Lava contributors for the interpreter, REPL, and flow tooling that make these bridges a joy to use.
License
Licensed under MIT OR Apache-2.0 (dual). See LICENSE for the full text of each license.
Dependencies
~3–5MB
~85K SLoC