Skip to content

Pommersche92/narsil

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

narsil icon

Narsil

A terminal-based system resource monitor written in Rust — fast, readable, and GPU-aware.

Named after the reforged sword of Aragorn, narsil is built to be sharper than the tools that came before it. It targets developers and power users who live in the terminal and need real-time system insight without leaving it.

Platform support — narsil runs on Linux, Windows, and macOS. The GPU tab (AMD/NVIDIA) is Linux-only for now; all other tabs work on every supported OS.


📸 Screenshot

narsil screenshot


✨ Features

Current scope (v0.1)

Tab What you see Platform
🗺️ Overview CPU gauge, RAM gauge, live RX/TX sparklines, top processes (fills available height) all
🧠 CPU Global usage history chart (Braille), per-core gauges with colour-coded load all
💾 Memory RAM + Swap history charts, GiB usage gauges all
🌐 Network Combined RX/TX history chart, per-direction current throughput all
💿 Disks Per-partition usage bars at fixed height, scrollable when partitions exceed the terminal all
🔬 Processes Process table sorted by CPU, scrollable, fills available height all
🎮 GPU Per-GPU cards with utilisation + VRAM history charts, gauges, temperature and power draw Linux only

🔑 Key behaviours

  • 🎨 Split-colour gauges — the percentage label rendered inside every gauge automatically inverts its colour character-by-character at the fill boundary so it is always readable, even when the bar is exactly at 50%.
  • 📜 Scroll indicators — any panel that cannot display all items at once shows //▲▼ in its title.
  • 📐 Dynamic sizing — all panels adapt to the current terminal dimensions; no hard-coded row counts.
  • Configurable refresh rate — pass --interval <ms> on startup (default 1 000 ms) to tune between low-latency and low-CPU usage; key events are processed between ticks with zero busy-waiting.
  • ⌨️ Keyboard-first navigation: Tab / Shift+Tab wrap-around tab switching; 16 direct jump (17 on Linux); j/k or arrow keys for scrolling; q or Ctrl-C to quit.
  • 💬 Status bar — persistent one-line keybinding reference at the bottom, context-aware per tab.

🚀 Installation

Prerequisites

  • Linux, Windows 10+, or macOS 12+
  • GPU tab requires Linux with standard /sys mounts and amdgpu (AMD) or NVIDIA proprietary drivers
  • Rust toolchain ≥ 1.85 — needed only for cargo install or source builds (rustup update stable)

Official release channels

Channel Platforms Standard NVIDIA variant
crates.io all cargo install narsil cargo install narsil --features nvidia
AUR Arch Linux narsil · narsil-bin narsil-nvidia · narsil-nvidia-bin
AppImage Linux x86_64 narsil-{ver}-x86_64.AppImage narsil-nvidia-{ver}-x86_64.AppImage
Windows zip Windows x86_64 narsil-{ver}-x86_64-windows.zip narsil-nvidia-{ver}-x86_64-windows.zip
Linux tarball Linux x86_64 narsil-{ver}-x86_64.tar.gz narsil-nvidia-{ver}-x86_64.tar.gz
Source all cargo build --release cargo build --release --features nvidia

AppImage, Windows zip, and Linux tarball are attached to every GitHub release.

crates.io

cargo install narsil                      # standard
cargo install narsil --features nvidia    # with NVIDIA GPU support (Linux only)

AUR (Arch Linux)

Four packages are published to the AUR:

Package Type Description
narsil source standard, compiled from the crates.io source tarball
narsil-nvidia source like narsil but built with --features nvidia
narsil-bin binary standard, installs prebuilt tarball from GitHub Releases
narsil-nvidia-bin binary NVIDIA variant, installs prebuilt tarball from GitHub Releases
yay -S narsil              # standard, built from source
yay -S narsil-nvidia       # with NVIDIA GPU support, built from source
yay -S narsil-bin          # standard, prebuilt binary
yay -S narsil-nvidia-bin   # with NVIDIA GPU support, prebuilt binary

AppImage (Linux x86_64)

Download from the latest GitHub release, make executable and run:

chmod +x narsil-*-x86_64.AppImage
./narsil-*-x86_64.AppImage

Two variants per release: narsil-{version}-x86_64.AppImage (standard) and narsil-nvidia-{version}-x86_64.AppImage (with NVIDIA support).

Windows (x86_64)

Download narsil-{version}-x86_64-windows.zip or narsil-nvidia-{version}-x86_64-windows.zip from the latest GitHub release, extract, and run narsil.exe in PowerShell or cmd.

The GPU tab is not compiled into the Windows build.

Linux tarball (x86_64)

Download from the latest GitHub release:

tar xzf narsil-{version}-x86_64.tar.gz
./narsil-{version}/narsil

Both standard and NVIDIA variants are available.

Build from source

git clone https://github.com/Pommersche92/narsil
cd narsil
cargo build --release
./target/release/narsil        # Linux / macOS
.\target\release\narsil.exe    # Windows

# With NVIDIA GPU support (Linux only):
cargo build --release --features nvidia

🎮 GPU support matrix

GPU monitoring is Linux-only. On Windows and macOS the GPU tab is not compiled in; all other tabs work normally.

Vendor Driver Detected Utilisation Memory Temperature Power
🔴 AMD discrete amdgpu gpu_busy_percent ✅ VRAM ✅ hwmon ✅ hwmon
🔴 AMD iGPU (APU) amdgpu ⚠️ GTT (shared RAM)
🟢 NVIDIA proprietary + --features nvidia ✅ NVML ✅ NVML ✅ NVML ✅ NVML
🔵 Intel iGPU i915 / xe
🔵 Intel Arc discrete xe

⚠️ AMD APU note: the VRAM figures reflect GTT memory (system RAM dynamically assigned to the GPU), not dedicated video memory. The values are accurate but on-screen labels will stay as "VRAM" until the display is updated in a future release.

🗓️ Intel note: Intel GPU support is planned — see Roadmap below.


⌨️ Keybindings

Key Action Platform
Tab / Shift+Tab Next / previous tab (wraps around) all
16 Jump directly to tab all
7 Jump to GPU tab Linux only
/ l Next tab all
/ h Previous tab all
/ j Scroll down (Disks, Processes; + GPU on Linux) all
/ k Scroll up all
q / Ctrl-C Quit all

🏗️ Architecture

src/
├── main.rs               — terminal setup, raw-mode lifecycle, event + tick loop
├── app.rs                — App state dispatcher: calls each metrics::refresh on every tick
├── metrics/
│   ├── mod.rs            — HISTORY_LEN constant, push_history helper, re-exports
│   ├── cpu.rs            — CpuState, per-core + global history
│   ├── memory.rs         — MemState, RAM + swap
│   ├── network.rs        — NetState, RX/TX rates and history
│   ├── disks.rs          — DiskState, per-partition usage
│   ├── processes.rs      — ProcessEntry, top-100 by CPU
│   └── gpu/
│       ├── mod.rs        — GpuEntry, vendor dispatch
│       ├── amd.rs        — sysfs-based AMD metrics
│       └── nvidia.rs     — NVML-based NVIDIA metrics (feature-gated)
└── ui/
    ├── mod.rs            — draw() entry point
    ├── helpers.rs        — format_bytes, usage_color, scroll_indicator
    ├── statusbar.rs      — persistent keybinding bar
    ├── tab_bar.rs        — tab header row
    ├── widgets/
    │   └── split_gauge.rs — SplitGauge custom widget
    └── tabs/
        ├── overview.rs   — combined overview tab
        ├── cpu.rs
        ├── memory.rs
        ├── network.rs
        ├── disks.rs
        ├── processes.rs
        └── gpu.rs

Data flows in one direction:

app.on_tick()  →  App (shared state)  →  ui::draw()  →  ratatui frame

There is no async runtime; crossterm::event::poll provides the non-blocking event check.


🧪 Testing

The test suite lives in src/tests/ and is compiled only in test builds (#[cfg(test)]). It covers the full public API: metric structs, refresh functions, UI helpers, and the SplitGauge widget.

cargo test

Test coverage overview

Module What is tested
tests::push_history Ring-buffer eviction, growth to capacity, length invariant
tests::helpers format_bytes SI boundaries, usage_color/_f64 thresholds, scroll_indicator states
tests::cpu CpuState::new zeroed state & history dimensions; refresh valid range & history cap
tests::memory MemState::new zeroed state; refresh used ≤ total + history cap
tests::network NetState::new zeroed state; refresh history cap & rate consistency
tests::disks DiskState field storage; refresh non-empty result, used ≤ total, non-empty names/mounts
tests::processes ProcessEntry field storage; refresh ≤ 100 entries, CPU-descending sort, non-empty names
tests::gpu GpuEntry::new zeroed fields, history lengths; amd::refresh smoke test & invariants
tests::split_gauge Ratio clamping, full/empty/half fill, label centring, block inner area, zero-size no-panic

Running with NVIDIA feature

cargo test --features nvidia

📦 Dependencies

Crate Purpose
ratatui TUI layout and widget rendering
crossterm Cross-platform terminal control, raw mode, event stream
sysinfo CPU, RAM, swap, network, disk, process data
anyhow Ergonomic error handling
nvml-wrapper (optional) NVIDIA GPU metrics via NVML

🗺️ Roadmap

Items are loosely ordered by priority.

🔜 Near-term

  • 🔵 Intel GPU support — utilisation via GT frequency ratio (i915/xe sysfs), LMEM for Intel Arc cards, temperature via hwmon; shown with appropriate caveats for iGPUs
  • 🏷️ AMD APU label fix — distinguish GTT (shared) from dedicated VRAM and label accordingly
  • ⏱️ Configurable refresh rate — CLI flag --interval <ms> to tune between low-latency and low-CPU usage
  • 🎨 Colour themes — built-in dark/light/high-contrast theme switcher

🔧 Medium-term

  • 🔬 Per-process GPU attribution — show which processes hold GPU memory (via NVML or fdinfo on the DRM driver)
  • 🌡️ Temperature history charts — per-core CPU and GPU temperature sparklines, not just current values
  • 💨 Fan speed — hwmon fan RPM display in the GPU card and a new thermal overview section
  • 🌐 Network per-interface breakdown — drill-down view listing each interface (eth0, wlan0, lo…) separately with its own sparkline
  • 💽 Disk I/O throughput — read/write MB/s per device, not just partition usage percentages
  • 🔋 Battery / power panel — laptop-focused: charge level, rate of charge/discharge, estimated time remaining

🚀 Long-term / differentiators

  • 📋 Log tail panel — a dedicated tab that tails systemd journal or a user-specified log file in real time, with regex highlight rules; something htop and gotop completely lack
  • 🚨 Alert rules — user-defined thresholds (e.g. CPU > 90% for > 5 s, VRAM > 80%) that flash the affected panel border red and optionally send a desktop or webhook notification
  • 🔌 Plugin / script hooks — allow arbitrary shell scripts or Rust dynamic libraries to provide custom metric panels, making narsil extensible without a fork
  • 📼 Session recording & replay — record a metric session to a compact binary file and replay it later for post-mortem analysis
  • 🖥️ SSH-aware remote mode — connect to a remote host via SSH and display its metrics locally in the same TUI, without needing narsil installed on the remote
  • 🖱️ Mouse support — click tabs and scroll panels with the mouse alongside the existing keyboard navigation
  • 📊 Export — one-shot --json / --prometheus output mode for integration with external dashboards (Grafana etc.)

⚖️ Comparison with existing tools

Feature top htop gotop narsil
Language C C Go 🦀 Rust
GPU metrics partial ✅ AMD + NVIDIA (Linux)
Braille charts
Per-char label inversion
Disk usage bars
Status bar with keybindings
Log tail panel 🗓️ planned
Alert rules 🗓️ planned
Remote mode 🗓️ planned
Session replay 🗓️ planned

📄 License

GPL-3.0 — see LICENSE.

About

A terminal-based system resource monitor written in Rust — fast, readable, and GPU-aware. Named after the reforged sword of Aragorn, narsil is built to be sharper than the tools that came before it. It targets developers and power users who live in the terminal and need real-time system insight without leaving it.

Topics

Resources

License

Stars

Watchers

Forks

Contributors