{
  "$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"
}