Initial commit: kmod-tui v1 — kernel module inspector TUI
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
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
# 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/module` directly.
|
||||
(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 to `modinfo` lazily 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)
|
||||
1. Module list from /proc/modules with columns: #, name, size (human-readable),
|
||||
refcnt, used-by, state.
|
||||
2. Detail pane for highlighted module: filename, license, description, author,
|
||||
depends, holders, parameters (name + current value), coresize, initsize,
|
||||
refcnt, srcversion, taint, vermagic.
|
||||
3. Vim-style navigation: j/k or ↑/↓ to move, Enter for full detail, Esc/q back.
|
||||
4. Live filter (`/` then type, fuzzy or substring match on name).
|
||||
5. Sort cycle (`s`): name, size, refcnt, dependents-count.
|
||||
6. Footer help bar.
|
||||
7. Color: state (Live=green, Loading/Unloading=yellow), refcnt>0 (bold),
|
||||
module-with-dependents highlighted.
|
||||
8. 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/<n>/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<Module> (once on startup; refresh on 'r')
|
||||
App holds Vec<Module> + 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)
|
||||
1. Shelling out to `modinfo` for 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.
|
||||
2. Read-only for v1 (no rmmod/modprobe)? Recommend: YES, read-only v1.
|
||||
3. Project location: /root/kmod-tui ? Recommend: yes.
|
||||
4. Install Rust via rustup (recommended) or apt rustc package?
|
||||
Recommend: rustup (stable toolchain, latest ratatui).
|
||||
5. Naming: `kmod-tui` ok?
|
||||
|
||||
## 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.
|
||||
Reference in New Issue
Block a user