<div align="center">
<img src="icon.png" alt="narsil icon" width="128" /><br><br>
<h1>Narsil</h1>
</div>
> 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

---
## โจ Features
### Current scope (v0.1)
| ๐บ๏ธ **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; `1`โ`6` direct jump (`1`โ`7` 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
| **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](https://github.com/Pommersche92/narsil/releases).
### crates.io
```bash
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:
| [`narsil`](https://aur.archlinux.org/packages/narsil) | source | standard, compiled from the crates.io source tarball |
| [`narsil-nvidia`](https://aur.archlinux.org/packages/narsil-nvidia) | source | like `narsil` but built with `--features nvidia` |
| [`narsil-bin`](https://aur.archlinux.org/packages/narsil-bin) | binary | standard, installs prebuilt tarball from GitHub Releases |
| [`narsil-nvidia-bin`](https://aur.archlinux.org/packages/narsil-nvidia-bin) | binary | NVIDIA variant, installs prebuilt tarball from GitHub Releases |
```bash
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](https://github.com/Pommersche92/narsil/releases/latest), make executable and run:
```bash
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](https://github.com/Pommersche92/narsil/releases/latest), 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](https://github.com/Pommersche92/narsil/releases/latest):
```bash
tar xzf narsil-{version}-x86_64.tar.gz
./narsil-{version}/narsil
```
Both standard and NVIDIA variants are available.
### Build from source
```bash
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.
| ๐ด 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**: VRAM figures for APUs reflect GTT memory (system RAM dynamically assigned to the GPU). narsil detects this automatically and labels the memory panel **GTT** rather than VRAM.
> ๐๏ธ **Intel note**: Intel GPU support is planned โ see Roadmap below.
---
## โจ๏ธ Keybindings
| `Tab` / `Shift+Tab` | Next / previous tab (wraps around) | all |
| `1` โ `6` | 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 |
---
## ๐ Localisation
narsil ships with translations for four languages. The UI language is selected automatically from the OS locale and can be overridden at startup.
| English | `en` | default fallback |
| German | `de` | `LANG=de_DE.UTF-8`, `LANGUAGE=de`, โฆ |
| French | `fr` | `LANG=fr_FR.UTF-8`, `LANGUAGE=fr`, โฆ |
| Spanish | `es` | `LANG=es_ES.UTF-8`, `LANGUAGE=es`, โฆ |
### Detection priority
1. `--lang <code>` CLI flag
2. `LANGUAGE` environment variable (colon-separated preference list, GNU extension)
3. `LC_ALL` โ `LC_MESSAGES` โ `LANG`
4. Native OS locale API (`GetUserDefaultLocaleName` on Windows, `CFLocale` on macOS)
5. English fallback
```bash
narsil --lang de # force German
narsil --lang fr # force French
```
### Adding a new language
Translation strings live in plain TOML files under `locales/` โ no Rust knowledge needed to translate. See [locales/README.md](locales/README.md) for step-by-step instructions.
---
## ๐๏ธ 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.
```bash
cargo test
```
### Test coverage overview
| `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, `mem_is_gtt` initial value, history lengths; `amd::refresh` smoke test & invariants | Linux only |
| `tests::split_gauge` | Ratio clamping, full/empty/half fill, label centring, block inner area, zero-size no-panic |
| `tests::i18n` | `primary_code` subtag parsing, `is_bundled` case-insensitive lookup, `get_translations` for all 4 locales + region qualifiers + unknown fallback, all fields non-empty, parse no-panic, `detect_lang_code` smoke test |
### Running with NVIDIA feature
```bash
cargo test --features nvidia
```
---
## ๐ฆ Dependencies
| `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
| Language | C | C | Go | ๐ฆ **Rust** |
| GPU metrics | โ | โ | partial | **โ
AMD + NVIDIA (Linux)** |
| Braille charts | โ | โ | โ
| **โ
** |
| Per-char label inversion | โ | โ | โ | **โ
** |
| Disk usage bars | โ | โ | โ
| **โ
** |
| Status bar with keybindings | โ | โ | โ | **โ
** |
| Localised UI | โ | โ | โ | **โ
EN DE FR ES** |
| Log tail panel | โ | โ | โ | ๐๏ธ planned |
| Alert rules | โ | โ | โ | ๐๏ธ planned |
| Remote mode | โ | โ | โ | ๐๏ธ planned |
| Session replay | โ | โ | โ | ๐๏ธ planned |
---
## ๐ License
GPL-3.0 โ see [LICENSE](LICENSE).