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