A cross-platform terminal UI system monitor written in Rust. A learning project to get familiar with Rust before tackling embedded SDK work — the "prism" name comes from splitting one machine into multiple live views (CPU, memory, processes).
Built with ratatui for the TUI layer and sysinfo for cross-platform system stats.
Prebuilt binaries are published on the Releases page for macOS (Apple Silicon and Intel), Linux (x86_64 and aarch64), and Windows. No Rust toolchain required.
macOS / Linux:
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/rene-coding/prism/releases/latest/download/prism-installer.sh | sh
Windows (PowerShell):
powershell -ExecutionPolicy ByPass -c "irm https://github.com/rene-coding/prism/releases/latest/download/prism-installer.ps1 | iex"
Or grab a tarball/zip from the Releases page directly and drop the prism binary somewhere on PATH.
On macOS, downloaded binaries may be quarantined by Gatekeeper. If
prismwon't launch, runxattr -d com.apple.quarantine $(which prism)once.
Only needed if you're hacking on prism or want to build for a target not in the release matrix.
brew install rustup
The rustup formula is keg-only, so its binaries (cargo, rustc, rustfmt, clippy) install to /opt/homebrew/opt/rustup/bin/ rather than the usual /opt/homebrew/bin/. The first time you invoke cargo or rustup, the stable toolchain installs on demand.
On Linux/Windows, use the official installer at https://rustup.rs instead — the rest of this guide assumes
cargoandrustcare reachable onPATHafter that step.
Pick one of these. They're equivalent in effect; option B keeps your global PATH clean.
Option A — add to PATH (brew's own recommendation):
echo 'export PATH="/opt/homebrew/opt/rustup/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
Option B — alias cargo (cargo-only scope, with subprocess support):
cat >> ~/.zshrc <<'EOF'
cargo() { PATH="/opt/homebrew/opt/rustup/bin:$PATH" command cargo "$@"; }
EOF
source ~/.zshrc
This is a shell function rather than a plain alias cargo=... because cargo spawns rustc (and rustfmt, clippy) as subprocesses, and subprocess lookup uses PATH directly — shell aliases don't propagate. The function prepends PATH for the duration of each cargo invocation so the toolchain resolves correctly without polluting the rest of the shell.
git clone <repo-url> prism
cd prism
cargo build --release
cargo run --release
For the NVIDIA backend (Linux/Windows hosts with the NVIDIA driver installed):
cargo build --release --features gpu-nvidia
Releases are built by dist on tag pushes. To ship a new version, bump the version in Cargo.toml, commit, then push a matching tag:
git tag v0.1.0
git push origin v0.1.0
The Release workflow then cross-builds for all configured targets, uploads tarballs/zips and SHA256 checksums to a GitHub Release, and publishes the shell/PowerShell installer scripts. Targets and build options live in dist-workspace.toml; regenerate .github/workflows/release.yml with dist generate after editing.
This is the source of truth for what's pending. Tick items off as they're done and committed.
- Initialize cargo project (
cargo init --bin) - Add dependencies:
ratatui,crossterm,sysinfo - Enter/exit alternate screen cleanly (raw mode on, restored on quit)
- Render a minimal frame with a
prismtitle bar; quit onqorEsc
- Refresh loop driven by a tick interval (500 ms)
- CPU widget: overall usage gauge
- CPU widget: per-core breakdown
- Memory widget: used / total with a gauge
- Process list table: PID, name, CPU %, memory
- Scroll with arrow keys /
j/k - Sort toggle by CPU or memory (press
s)
- Multi-pane layout: CPU top-left, memory top-right, processes bottom
- Resize-aware: layout adapts to terminal size
- Tab/focus to switch which pane is "active"
- Help overlay (press
?) - Color theming
- CLI args (refresh rate, starting view) via
clap - Unit tests for non-UI logic (sorting, formatting)
- CI:
cargo fmt --check,cargo clippy -- -D warnings,cargo test
GPU stats are not in sysinfo, and there is no single cross-platform crate, so this is a per-platform job behind a common abstraction.
-
GpuBackendtrait + aNoGpustub that always reports "unavailable" - Wire the active backend into
Appand render it in the layout - macOS backend via
ioreg(parsesIOAcceleratorPerformanceStatistics for real-timeDevice Utilization %, no sudo required) - NVIDIA backend behind
--features gpu-nvidiavianvml-wrapper(utilization, VRAM, per-process GPU%) - Trait extended with
processes()so per-process GPU% can flow into the table when the backend supports it - CI builds with
gpu-nvidiafeature too (compile-check only; no NVIDIA hardware in runners)
cargo run --release
Options:
cargo run --release -- --refresh-ms 1000 --sort memory --focus cpu
Key bindings:
| Key | Action |
|---|---|
q |
Quit |
Esc |
Close modal / quit |
? |
Toggle help overlay |
Tab |
Switch focused pane |
j / Down |
Next process |
k / Up |
Previous process |
s |
Toggle sort (CPU / Memory) |
K |
Kill selected process (SIGTERM, with confirm) |
The macOS GPU backend is idle most of the time, so to confirm it's actually reading utilization, drive the GPU with a known workload and watch the bar move:
- WebGL aquarium: https://webglsamples.org/aquarium/aquarium.html — crank the fish count to 30k for a strong, steady load (the screenshot above was taken at ~63% GPU with this running).
ffmpeghardware encode:ffmpeg -f lavfi -i testsrc=duration=60:size=4096x2160:rate=60 -c:v h264_videotoolbox -b:v 50M -f null -- Cross-check against the system reading with
sudo powermetrics --samplers gpu_power -i 1000or Activity Monitor → Window → GPU History.
Licensed under the MIT License. You may use, copy, modify, and distribute this project, including commercially, as long as the copyright notice and license text are included with copies or substantial portions of the software.
