Features: - Browse all loaded kernel modules from /proc/modules - Two-pane layout: scrollable list + detail pane - Full-screen detail view with modinfo, parameters, holders - Vim-style navigation (j/k, Enter, /, s, r, ?, q) - Edge-scrolling (cursor moves freely, viewport follows) - Filter by module name AND dependents (used_by) - Sort by name, size, refcnt, or dependents count - Lazy modinfo fetching (shells out only on selection) - 13 unit tests (parser, filter, scroll logic) Tech: Rust + ratatui + crossterm
6.9 KiB
kmod-tui — Kernel Module Inspector (Rust TUI)
A terminal UI for Linux sysadmins to browse and inspect loaded kernel modules.
Goal
Show all loaded kernel modules in a navigable, filterable list, with a detail view for each module's metadata, dependencies, parameters, and holders.
Data Sources (verified on this host, kernel 6.8.0-137-generic, 130 modules)
/proc/modules— one line per loaded module:name size refcnt used-by state addr(e.g.wireguard 114688 0 - Live 0xffffffffc125d000)/sys/module/<name>/— per-module sysfs dir with:refcnt,initstate,coresize,initsize,version,srcversion,taint,holders/(modules depending on this one),parameters/(tunable params)modinfo <name>— richest metadata: filename, license, description, author, depends, retpoline, intree, vermagic, signature info
Tech Stack
- Rust (stable)
ratatui— TUI rendering (modern maintained fork of tui-rs)crossterm— terminal backend (cross-platform, works everywhere)clap— CLI args (optional: --sort, --filter, --no-modinfo for speed)- No shell-out to
modinfo; parse/proc/modules+ walk/sys/moduledirectly. (Avoids a process spawn per module; modinfo data like license/description/author comes from the .ko file's modinfo section — we parse the relevant sysfs files and, where sysfs lacks it, read the module file's modinfo section directly. Decision: for v1, shell out tomodinfolazily only when a module is selected for detail — keeps the list fast and detail rich. Revisit later.)
UI Layout
┌─ kmod-tui — 130 modules loaded (kernel 6.8.0-137-generic) ──────────────┐
│ Filter: [_____________] Sort: name▼ Loaded only: on │
├────┬──────────────────┬────────┬──────┬────────────────────┬────────────┤
│ # │ Module │ Size │ Refc │ Used by │ State │
├────┼──────────────────┼────────┼──────┼────────────────────┼────────────┤
│ 1 │ cpuid │ 12288 │ 0 │ - │ Live │
│ 2 │ wireguard │ 114688 │ 0 │ - │ Live │
│ 3 │ curve25519_x86_64│ 36864 │ 1 │ wireguard │ Live │
│ .. │ .. │ .. │ .. │ .. │ .. │
├────┴──────────────────┴────────┴──────┴────────────────────┴────────────┤
│ Detail: wireguard │
│ Filename: /lib/modules/.../wireguard.ko.zst │
│ License: GPL Description: ... Author: ... │
│ Depends: (none) Holders: (none) Parameters: (none) │
│ Coresize: 114688 Initsize: 0 Refcnt: 0 Srcversion: ... │
└────────────────────────────────────────────────────────────────────────┘
↑/↓ move Enter expand / filter s sort q quit
Two-pane layout: scrollable module list (top ~70%), detail pane (bottom ~30%). Selecting a row populates the detail pane. Enter opens a full-screen detail view for the selected module with all sysfs fields, parameters, holders, and a dependency tree.
Features
v1 (MVP — the "nice looking, human-navigable" baseline)
- Module list from /proc/modules with columns: #, name, size (human-readable), refcnt, used-by, state.
- Detail pane for highlighted module: filename, license, description, author, depends, holders, parameters (name + current value), coresize, initsize, refcnt, srcversion, taint, vermagic.
- Vim-style navigation: j/k or ↑/↓ to move, Enter for full detail, Esc/q back.
- Live filter (
/then type, fuzzy or substring match on name). - Sort cycle (
s): name, size, refcnt, dependents-count. - Footer help bar.
- Color: state (Live=green, Loading/Unloading=yellow), refcnt>0 (bold), module-with-dependents highlighted.
- Header shows module count, kernel version (from
uname -r).
v1.1 (polish)
- Dependency tree view (expand a module → see what it depends on and what depends on it, recursively).
- Parameter inspection with current values read from /sys/module//parameters.
- Export current view to file (CSV/TSV).
- Config file (~/.config/kmod-tui/config.toml) for default sort, columns.
v2 (nice-to-have, later)
- Show ALL installable modules (from /lib/modules/$(uname -r)/), not just loaded — mark loaded vs available-not-loaded.
- Toggle between "loaded only" and "all available".
- modprobe/insmod/rmmod actions (guarded, with confirmation — but see note: this is read-only for v1; mutating is a separate, deliberate decision).
- Module loading state watch (inotify on /proc/modules, auto-refresh).
Architecture (v1)
src/
main.rs — CLI args, app bootstrap, event loop
app.rs — App state: module list, cursor, filter, sort mode, focus
model.rs — Module struct, data collection from /proc + /sys
ui/
mod.rs — frame composition, layout
list.rs — module list table rendering
detail.rs — detail pane + full detail view
help.rs — help bar / overlay
event.rs — crossterm input polling
config.rs — (v1.1) config file load
Data flow: collect_modules() → Vec (once on startup; refresh on 'r') App holds Vec + filter/sort/cursor state ratatui draws from App state each frame crossterm polls input; key handlers mutate App state; redraw on change (or redraw on a fixed tick — simpler: event-driven redraw)
Open Decisions (for Isaac)
- Shelling out to
modinfofor detail metadata (filename/license/desc/author) vs parsing .ko files directly? Recommend: shell out lazily on selection — simple and correct. We only parse /proc + /sys for the list. - Read-only for v1 (no rmmod/modprobe)? Recommend: YES, read-only v1.
- Project location: /root/kmod-tui ? Recommend: yes.
- Install Rust via rustup (recommended) or apt rustc package? Recommend: rustup (stable toolchain, latest ratatui).
- Naming:
kmod-tuiok?
Build & Run
cargo run --release
(or cargo build --release then ./target/release/kmod-tui)
Non-goals (v1)
- Editing module parameters (write to /sys) — risky, out of scope.
- Loading/unloading modules — risky, out of scope.
- Remote hosts — local only (could add SSH later).
- Persistent state — none needed.