I like neofetch / fastfetch, but I wanted one with a genuinely empty
dependency graph — nothing pulled from crates.io. So I built purefetch: a small
system-info fetcher written entirely in Rust using only std plus raw Linux
syscalls.
Disclosure up front: purefetch was built largely with AI assistance
(Claude Code). I directed the design, and every change was reviewed and tested —
including running it on four architectures under QEMU — but most of the code is
AI-generated. I'd rather be honest about that than pretend otherwise.
_,met$$$$$gg. ooonea@unicorn
,g$$$$$$$$$$$$$$$P. ──────────────
,g$$P" """Y$$.". OS Debian GNU/Linux 13.5 (trixie) x86_64
,$$P' `$$$. Host ThinkPad P53 (20QQS0JD01)
',$$P ,ggs. `$$b: Kernel 6.12.94+deb13-amd64
`d$$' ,$P"' . $$$ Uptime 6 days, 15 hours, 30 mins
$$P d$' , $$P Packages 2477 (dpkg), 1 (flatpak)
$$: $$. - ,d$$' Shell zsh 5.9
$$; Y$b._ _,d$P' Display 1920x1080 (eDP-1)
Y$$. `.`"Y$$$$P"' DE GNOME 48.7
`$$b "-.__ WM Mutter (Wayland)
`Y$$ Terminal kitty 0.41.1
`Y$$. CPU Intel(R) Core(TM) i7-9850H @ 4.60 GHz
`$$b. GPU Quadro RTX 3000
`Y$$b. Memory 15.28 GiB / 62.61 GiB (24%)
`"Y$b._ Swap 0 B / 8.00 GiB (0%)
`""" Disk (/) 8.52 GiB / 489.57 GiB (2%)
Locale en_US.UTF-8
Battery 76% (Not charging)
Zero dependencies, really
No libc crate, no sysinfo, no nix, no color crate — nothing from crates.io.
Almost everything is just reading and parsing /proc and /sys. The result is a
single ~484 KiB binary that builds offline.
The only things std can't do are statfs (disk usage) and ioctl (terminal size
/ tty check). Instead of pulling in a binding crate, those are issued as raw Linux
syscalls via core::arch::asm!:
#[cfg(target_arch = "x86_64")]
unsafe fn syscall3(n: usize, a1: usize, a2: usize, a3: usize) -> isize {
let ret: isize;
core::arch::asm!(
"syscall",
inlateout("rax") n as isize => ret,
in("rdi") a1, in("rsi") a2, in("rdx") a3,
out("rcx") _, out("r11") _,
options(nostack),
);
ret
}
Four architectures
Each architecture gets its own syscall3 (a different instruction and register
convention) plus its syscall numbers. aarch64, riscv64 and loongarch64 share the
"asm-generic" table (statfs = 43, ioctl = 29); x86_64 has its own.
I validated all four end-to-end under qemu-user — cross-compiling to each
target and actually running the binary to confirm the raw syscalls work, not just
that they compile. Seeing the aarch64 build print correct disk and memory numbers
under QEMU was a nice moment.
A ZFS gotcha worth knowing
On ZFS-on-root, a naive MemTotal - MemAvailable massively over-reports used RAM,
because the ZFS ARC is kernel-slab cache that MemAvailable doesn't count as
reclaimable. purefetch subtracts the reclaimable ARC (arcstats size - c_min),
which lines up with what fastfetch and ZFS-aware htop show. On my box that's the
difference between "37 GiB used" (wrong) and "15 GiB used" (right).
The logo generator (and a bug it introduced)
The 24 distro logos live as plain text in assets/logos/*.txt, and a small Python
script generates src/logo.rs. Adding a logo is one text file plus a regen.
It also taught me a lesson. An early version of the generator emitted the color as
sgr: "215;7;81" instead of "38;2;215;7;81" — dropping the truecolor prefix. The
terminal then read \e[215;7;81m as "code 215 (ignored) + 7 (reverse video)", so
every logo rendered washed-out instead of its brand color. I missed it because my
render checks all ran with --no-color. Fixed in 0.1.2 — a good reminder to test the
thing your users actually see.
Install
cargo install purefetch
Source, issues and PRs: https://github.com/ooonea/purefetch (MIT OR Apache-2.0).
New distro logos and extra architectures are especially welcome — and I'm happy to
talk about the raw-syscall approach, or the AI-assisted workflow, in the comments.
Top comments (0)