Repository navigation
How It Works
retch gathers system information from many independent, often-slow sources (GPU
drivers, package managers, network interfaces, sensors, display EDID blocks, audio
servers, Bluetooth, etc.) and renders it as a themed report next to a distro logo.
The two design problems that shape the codebase are: don't block on slow queries
sequentially, and don't run slow queries at all unless the requested output mode
needs them.
Slow queries (GPU, package counts, IP resolution, active network interface detection,
motherboard/BIOS, displays, audio, Wi-Fi, Bluetooth, UI theme/fonts, camera, gamepad)
run concurrently using std::thread::scope rather than sequentially. This is the
difference between retch's ~200ms standard-mode runtime and multi-second runtimes if
each probe ran one after another. The fetch orchestration lives in
crates/sysinfo/src/fetch.rs.
retch has four output modes with increasing verbosity and acceptable runtime. Each
mode is a strict superset of the one above it — nothing is hidden or replaced when you
escalate, except the temperature view (see below).
| Mode | Flag | Typical runtime | Purpose |
|---|---|---|---|
| Short | --short |
<100ms | Hardware snapshot — fastest, scriptable |
| Standard | (none) | ~200ms | Daily-use system overview |
| Long | --long |
~500ms | Diagnostics — consolidated thermals, network detail, firmware |
| Full | --full |
~5s+ | Everything, including slow and cosmetic fields |
Fast hardware-only snapshot. No network calls, no sensors, no cosmetic fields.
Fields: os, kernel, host, cpu, gpu, memory, disk, net.
Full system overview suitable for daily use. No slow fields, no sensors, no cosmetic
fields. BIOS moves to --long (firmware detail, not needed at a glance); gamepad
moves to --full (cosmetic/slow).
Standard plus diagnostics — aimed at understanding system health and network
configuration. Adds bios, consolidated temp, domain, public-ip, wifi,
bluetooth, battery, shell, editor, terminal, terminal-size, desktop,
wm, dns, users, packages, locale, init, chassis, bootmgr.
Temperature consolidation: --long shows one representative reading per physical
unit (CPU, GPU, SSD/NVMe, WiFi adapter, System/Motherboard) — sensors are classified
by name pattern (k10temp/coretemp → CPU, amdgpu/nvidia → GPU, nvme → SSD,
ath/iwl → WiFi, acpitz/thinkpad → System) and the highest reading in each
category is reported, since that's the worst-case thermal indicator you actually care
about at a glance.
Long plus everything slow, verbose, or cosmetic. Suitable for reporting, screenshots, or deep diagnostics — expect multi-second runtimes. Adds:
-
temp(all sensors) — replaces the consolidated--longview with every reading -
domain-search— per-interface DNS search domains (viaresolvectl statusor equivalent) - Cosmetic fields:
theme,icons,cursor(font/terminal-fontstay in--long— theme/icon/cursor detection involves sqlite/gsettings queries and is purely cosmetic, not diagnostic) -
weather— current conditions via Open-Meteo (~4s network timeout) - FUSE mounts — disk detection re-enables
statvfsforfuse.*entries, skipped in every other mode to avoid 600ms+ hangs from cryfs/EncFS vaults
retch is a Cargo workspace split into a library and a CLI binary:
| Crate | Path | Description |
|---|---|---|
retch-sysinfo |
crates/sysinfo |
System info library — all detect_* logic, SystemInfo, CollectOptions, GPU, battery. No dependency on clap or the CLI. |
retch-cli |
. |
CLI binary — display logic, configuration, logo rendering |
retch-sysinfo can be used independently as a cross-platform system-information
library outside of retch itself.
Distro logos render through a fallback chain: full-color graphical protocols (Kitty,
iTerm2, Sixel) first, then Chafa-based Unicode symbol art, then plain ASCII art
(adapted from Fastfetch). Logo output is automatically suppressed whenever stdout is
not a terminal (e.g. retch | bat or retch > file), so piping never produces
garbled escape sequences in a file.
When the terminal is wide enough, the field list renders on the left and the logo is anchored to the right margin — its right edge sits on the terminal's last column, whatever the width. Two independent numbers drive this, and keeping them separate is what makes it correct:
| what it controls | |
|---|---|
| text column | whether the layout goes side-by-side at all, and the minimum room reserved for text (45–65 columns) |
| logo column | where the logo is drawn: terminal width − logo width
|
Field lines wrap to the space actually available: beside the logo that is
logo column − 2, and below it (where nothing overlaps) the full terminal width.
Before v0.9.3 the beside-logo case wrapped at the text column instead, so on a wide
terminal a long value could break at ~55 columns with the rest of the gap to the logo
left unused.
Before v0.9.2 these were the same value, so the logo was drawn wherever the text column happened to end — capped at column 65, which stranded everything to its right on any terminal wider than about 110 columns.
Below 95 columns, or when the text column and logo cannot both fit, the layout falls
back to stacked: the logo prints above the field list at column 0. Long lines that
sit below the logo (Wi-Fi, Net, Battery in --long/--full) never influence
the decision, since nothing overlaps them — only the field lines actually beside the
logo do.
Placement is logo-type agnostic. ASCII and Chafa are measured from their rendered text; the image protocols get their cell footprint from a single sizing function whose result feeds both the protocol escape and the layout, so the space reserved and the space drawn cannot disagree.
A field line too long for the space beside the logo wraps onto continuation lines indented to the value column. Two properties are preserved across a break, both fixed in v0.9.3:
-
The separator is kept. Breaking a comma-separated value leaves the comma on the
preceding line, so
American Megatrends International, LLC.cannot be misread as two separate values. - The colour continues. Lines are colourised before they are wrapped, so a split value's opening escape sits on the first line and its closing reset on the last. Continuation lines re-open the active colour and close it at each line end, which also stops a colour bleeding into the logo column.
Alignment is computed in terminal columns, not characters. A CJK ideograph or
Hangul syllable occupies two columns, a combining mark none, and an emoji with a
variation selector two. This matters for ordinary output, not just exotic input: the
media and player fields surface arbitrary track metadata, so a Japanese or Korean
song title is a normal value. Widths come from the unicode-width crate after ANSI
escape sequences are stripped.