Skip to content

meta: fetcher roadmap - Local / System #62

Description

@unhappychoice

Local-only, on-disk / host / process fetchers. Part of the widget catalog index in #41.

All entries here are Safety::Safe — no network, or fixed host. See AGENTS.md for the fetcher contract and shape mapping.

clock_* — local time / date / calendar derivatives

Base clock handles now-as-text (Lines), year/month/day/… rollup (Entries), and month grid (Calendar). Siblings cover the rest of the local-only temporal surface (all realtime).

system_* — host rollup and hardware (realtime via sysinfo unless noted)

Fastfetch / neofetch parity is the rough target for this section: hardware identification (CPU / GPU / board / chassis), desktop environment (DE / WM / theme / font), audio / display / locale, plus the dynamic counterparts (usage, temperatures, throughput).

Family naming (post-#227): every system_* fetcher follows the pattern system_{info|monitor}_{subject}. info_* returns static identifiers (single Text, kind selects the field). monitor_* returns dynamic measurements (Ratio / Entries / Bars / ...). Sub-modules live under src/fetcher/system/, one file per fetcher.

Hardware ID (static, system_info_*)

Dynamic (system_monitor_*)

Desktop / display / audio

  • system_info_display — connected displays (Entries / TextBlock: name / resolution / refresh / scaling / primary); Text default = primary WxH @ Hz; X11 / Wayland / Quartz / Win32
  • system_monitor_brightness — display brightness (realtime; Ratio / Text); macOS IODisplayConnect, Linux /sys/class/backlight, Windows WMI
  • system_info_dpi — primary display DPI / scaling factor (Text + kind: dpi / scale)
  • system_monitor_audio — default output device + volume + mute (realtime; Text + kind: device / volume / muted); CoreAudio / PulseAudio / PipeWire / WASAPI
  • system_monitor_media — currently-playing media (Text default title - artist / Entries: player / title / artist / album / position / length); MPRIS over DBus on Linux, NowPlaying on macOS, SMTC on Windows
  • Extend system_info_desktop with de_version / wm_version / wm_theme kinds — de / wm / init are already shipped (refactor(fetcher)!: split system into system_{info,monitor}_* family #227).
  • system_info_theme — desktop theme bundle (Entries: gtk_theme / qt_theme / icons / cursor / cursor_size / font); gsettings / defaults / registry, no subprocess
  • system_info_terminal_font — terminal emulator font + size (Text); queried via terminfo / OSC where supported
  • system_monitor_terminal_size — terminal columns × rows + pixel size (realtime; Text + kind: cols / rows / pixel_width / pixel_height / wxh)
  • system_info_terminal_theme — detected light / dark / true-color support (Text + Badge)
  • system_info_cursor — pointer device list (Entries: name / type / dpi); separate from system_info_theme (that's the cursor image theme)
  • system_info_input — connected keyboards / mice / trackpads / gamepads (Entries / TextBlock)

Software environment

  • system_info_packages — installed-package counts per manager (Text sum / Entries per-manager / Bars); supports brew, apt (dpkg), pacman, dnf / rpm, nix, flatpak, snap, cargo, npm (global), pip, gem, go, pkg (FreeBSD), port (MacPorts); parses state files only — no subprocess
  • system_info_runtime — language runtime versions resolved via version managers (Entries / TextBlock); reads .tool-versions (asdf / mise), ~/.nvm/alias/default, pyenv version-file, rbenv version, rustup toolchain file — no subprocess
  • Extend system_info_locale with multi-field kinds (lc_all / lang / lc_time / lc_messages) or an Entries shape — current single-Text resolves LC_ALL > LC_CTYPE > LANG already shipped (refactor(fetcher)!: split system into system_{info,monitor}_* family #227).
  • system_monitor_users — currently-logged-in users (Text count / Entries: user → tty + since / TextBlock); utmp / WTMP on Unix, WTS on Windows
  • system_info_who_am_i — current user identity (Text + kind: user / uid / gid / home / groups)
  • Extended init-system rollup beyond system_info_desktop kind="init" (Entries with flavour / generation / service counts) — single-Text init already shipped (refactor(fetcher)!: split system into system_{info,monitor}_* family #227, reads /proc/1/comm on Linux, launchd / wininit on macOS / Windows).
  • system_monitor_services — failed / running unit count (Entries: running / failed / inactive); systemd / launchd / SC manager
  • system_info_security — SIP / Gatekeeper (macOS) / SELinux / AppArmor (Linux) / Defender (Windows) status (Text + Badge)
  • system_info_secureboot — Secure Boot state (Badge: enabled / disabled / setup)
  • system_info_tpm — TPM presence + version (Text + Badge)
  • system_info_virtualization — detected hypervisor / container (Text + Badge: bare-metal / vm:kvm / vm:vmware / container:docker / container:wsl / container:lima)

Graphics / compute capabilities

  • system_info_vulkan — Vulkan API version + primary device (Text + kind: api_version / device / driver); skipped if loader absent
  • system_info_opengl — OpenGL version + renderer + vendor (Text + kind: version / renderer / vendor / glsl_version)
  • system_info_opencl — OpenCL platforms + devices (Entries / TextBlock)
  • system_info_metal — Metal feature set (macOS only; Text)
  • system_info_directx — DirectX feature level (Windows only; Text)

Connectivity (host-side, see also net_*)

  • system_monitor_bluetooth — paired and connected devices (Text count / Entries: device → status + battery%); BlueZ / IOBluetooth / WinRT
  • system_info_camera — webcams enumerated (Entries: name / id / in-use); AVFoundation / V4L2 / DirectShow
  • system_info_usb — USB devices (Entries / TextBlock: vendor / product / port); libusb / IOKit
  • system_info_pci — PCI devices (Entries / TextBlock); /sys/bus/pci / IOKit / Setup API
  • system_monitor_power_adapter — AC adapter wattage + state (Text + Badge: plugged / unplugged)
  • system_monitor_swap — swap usage as standalone Ratio / Text (because some hosts disable swap and system_monitor_memory's swap field renders a 0/0 awkwardly); complements system_info_memory kind="swap_total" (already shipped).
  • system_info_tty — current terminal device + parent process chain (Text)
  • system_info_ssh_sessionSSH_CONNECTION / SSH_TTY rollup (Badge + Text); useful per-dir to flag "you're SSH'd into prod"

disk_* — storage

  • disk_usage — shipped in feat(fetcher): cross-platform system fetchers via sysinfo #50, renamed in refactor(fetcher): rename sysinfo fetchers to prefix_suffix convention #57 (was disk; cached, primary = largest disk, Ratio / Lines / Bars)
  • disk_mounts — mounted volumes list (Entries / TextBlock: mount → fs / size / used%); covers fastfetch's disk per-mount surface
  • disk_physical — physical drives (Entries: name / vendor / model / size / type=ssd / hdd / nvme); fastfetch physicaldisk
  • disk_io — disk read / write throughput + IOPS (realtime; Text + kind: read / write / total / iops_read / iops_write)
  • disk_smart — SMART health summary per disk (Text + Badge: healthy / warning / failing)
  • disk_zpool — ZFS pool health (Text + Entries; only when zpool present)
  • disk_raid — md / hardware RAID array state (Entries + Badge)

net_* — networking

  • net_ip — local IPv4 / IPv6 addresses. Shipped in feat(fetcher): add net_* fetcher family #234. kind = primary | v4 | v6 picks the Text field; TextBlock / MarkdownTextBlock / Entries list every addressed interface; Badge flags dual-stack / IPv4 / IPv6-only. 5 shapes.
  • net_public_ip — public IPv4 / IPv6 via fixed resolver (Text + kind: v4 / v6); Network class but host-fixed (icanhazip.com / ipify) so Safe per the host-fixed rule
  • net_gateway — default-route gateway. Shipped in feat(fetcher): add net_* fetcher family #234. kind = gateway | interface — the planned metric kind was dropped, netdev doesn't expose route metric cross-platform. 5 shapes.
  • net_mac — link-layer addresses per interface. Shipped in feat(fetcher): add net_* fetcher family #234. Option is interface (name, default = primary) rather than kind; Badge flags universal vs locally-administered (randomized) MACs via the U/L bit. 5 shapes.
  • net_interfaces — every interface with state / IP / MTU / MAC. Shipped in feat(fetcher): add net_* fetcher family #234. 7 shapes; Ratio = up/total, Bars ranks interfaces by total bytes transferred, Badge is online/offline. Note: netdev::get_interfaces() leaves stats unpopulated on Linux, so the shared snapshot calls update_stats() per interface.
  • net_wifi — SSID + BSSID + channel + security (Text + kind: ssid / bssid / channel / security)
  • net_signal — Wi-Fi signal strength (Ratio + Badge: excellent / good / fair / poor)
  • net_vpn — VPN status (realtime; Badge + Text: provider name when resolvable)
  • net_speedtest — measured internet bandwidth (download / upload / latency). Shipped in feat(fetcher): add net_* fetcher family #234. Real transfer test against the fixed speed.cloudflare.com (__down / __up) — host-fixed so Safe; the download phase is time-boxed so a slow link stays bounded. 6 shapes. Replaces the planned net_speed (instantaneous throughput): a single ~500ms sample frozen for the cache TTL is noise on a one-shot splash — capacity, not flow, is the splash-appropriate "network speed".
  • net_speed_history — up/down throughput as a strip (NumberSeries, one series per direction)
  • net_ping — latency to a fixed host (Ratio + Badge; Text shape = Ns ms)
  • net_dns — resolution check + configured resolvers (Text + Entries)
  • net_cert — SSL cert expiry (Network if URL is config-provided)
  • net_domain — whois domain expiry (Network)
  • net_tailscale — Tailscale node + peer status (Entries / Badge); Safe, reads local tailscaled socket
  • net_proxy$*_PROXY environment. Shipped in feat(fetcher): add net_* fetcher family #234. The one realtime fetcher in the family (pure env reads); prefers lowercase var names over uppercase on Unix; Badge is proxied (Warn) / direct (Ok). 5 shapes.
  • net_listening_ports — open listening sockets (Entries: port → process); per-dir "what is this project serving right now". Local realtime, Safe

docker_* / k8s_* — containers

  • docker_containers — running containers summary
  • docker_image_size — top images by size
  • k8s_context (realtime)
  • k8s_pods — pod health in current namespace
  • docker_compose_status — services declared in the cwd's docker-compose.yml and their up/down state (per-dir; Entries / Badge)
  • k8s_deployments — deployment readiness in the current namespace (Entries / Bars)

code_* — code-internal metrics (greps / parses tracked source files)

Walks the gix index of the discovered repo, so untracked / .gitignore-d files are skipped automatically; vendored trees that happen to be committed (node_modules / vendor / dist / target / build / third_party) are also filtered. Distinct from project_* (which is about project-level operational state like build artefacts, dependencies, license).

  • code_todos — TODO / FIXME comment grep, shipped in feat(fetcher): add code_todos #114 (was project_todo_in_code; trailing : required so prose / literals don't inflate the count)
  • code_lint — lint warning count (was project_linter_count)
  • code_loc — line count: total (Text) / per-language (Entries / Bars / TextBlock / MarkdownTextBlock) / dominance (Ratio = primary language's share with denominator) / size tier (Badge — toy / small / medium / large / huge Status-mapped) / sorted-desc distribution (NumberSeries). unit = "loc" | "kloc" | "percent" (alias %) toggles count formatting; subsumes code_languages's % breakdown via unit = percent. Lockfile / framework-cache / snapshot exclusions hardened in the same PR (benefits code_todos too). Shipped in feat(fetcher): add code_loc for tracked-line counts per language #167. Two follow-ups deliberately deferred: NumberSeries from commit history (LOC trend over time, not snapshot distribution) and a metric = "files" toggle for file-count-per-language as an alternative measure — open if anyone needs them.
  • code_coverage — read coverage report file (was project_test_coverage)
  • code_dead — dead-code report (was project_dead_code_report)
  • code_complexity — cyclomatic / cognitive complexity per file
  • code_files — Shipped in feat(fetcher): add code_files — top-level-dir ranking + headline file count #170. Walks the gix index via scan::for_each_tracked_path (no blob reads), counts tracked files and ranks them by top-level directory (root files grouped under (root)). 5 shapes: Text is the headline file count ("342 files"); TextBlock lists <dir> (<count>) rows; Entries exposes the same as key/value rows; Bars ranks them as bar values; MarkdownTextBlock formats them as a Markdown bullet list with emphasis on dir names. Multi-row shapes carry the per-dir ranking, not a fixed-K stat sheet — dir_count and max_depth from the original spec were dropped (Text already emits the headline file count, multi-row shapes deserve a real list). Family-wide vendored / lockfile exclusions inherited via scan helpers.
  • code_largest_files — Shipped in feat(fetcher): add code_largest_files for refactor-candidate hunting #171. Ranks tracked source files by line count or byte size via the shared for_each_tracked_file walker (lockfiles / vendored / binaries skipped). 7 shapes: Text headlines the single largest file ("src/render/mod.rs (1,234 LOC)"); TextBlock / MarkdownTextBlock / Entries / Bars carry the per-file ranking; NumberSeries sketches the size distribution; Badge flags refactor-candidate tier (tidy / big / bloated / monster — separate health signal from code_loc's repo-total tier). metric = "loc" | "bytes" (LOC default suits refactor hunting; bytes suits asset-weight audits). limit (default 10) caps multi-row shapes; Text always names just the core: Project scaffolding (Rust + Ratatui bootstrap) #1 file.
  • code_language_logo — Shipped in feat(fetcher): add code_language_logo for repo-language Devicon hero #169. Image-only fetcher: detects the dominant language across the repo's tracked files (file-count, no blob reads via the new for_each_tracked_path scan helper) and emits the matching bundled Devicon PNG. 35 languages bundled (Rust / Go / Python / Ruby / TypeScript / JavaScript / Java / Kotlin / Scala / Swift / C / C++ / C# / PHP / Elixir / Erlang / Haskell / Clojure / OCaml / Dart / Lua / R / Julia / Zig / Nim / Shell / PowerShell / HTML / CSS / Vue / Svelte / Dockerfile / Terraform / Perl / Groovy) plus a generic </> fallback. PNGs are 256×256, rasterised from upstream SVGs via rsvg-convert, ~480 KB total; both SVG sources and PNGs are committed under assets/logos/. Bundled bytes extract once into $SPLASHBOARD_HOME/cache/logos/<slug>.png so media_image (path-only) can render from a stable location. Optional language option overrides auto-detection (useful for polyglot repos and non-repo home dashboards). TextBlock shape from the original spec was dropped — Image is responsive via media_image's fit/max_width/max_height, ASCII art would be fixed-size in the same hero slot.
  • code_test_ratio — test-code LOC vs source LOC (heuristic test-path detection); pure structural count, no coverage report needed. Ratio / Text / Badge

project_* — project-level operational (build / config / metadata)

  • project_bundle_size
  • project_dependency_alerts — Dependabot / Snyk (Network)
  • project_license_check
  • project_dependencies — declared dependency count from Cargo.toml / package.json / Gemfile / pyproject.toml / go.mod. Text (total) / Entries (direct vs transitive, by ecosystem). Local-only, no registry calls.
  • project_scripts — runnable tasks discovered in the cwd (package.json scripts, Makefile / justfile targets, Cargo aliases, rake / composer); per-dir "what can I run here". Local, Safe. Entries / TextBlock
  • project_readme_excerpt — first paragraph / description from the repo README; per-dir, feeds text_markdown — "other / project" context for cloners
  • project_changelog_latest — latest CHANGELOG.md entry (version + date + bullets); per-dir. MarkdownTextBlock / TextBlock / Text
  • project_env_check — keys present in .env.example but missing from .env; onboarding sanity check. Local, Safe. Entries / Badge
  • project_lockfile_drift — lockfile older than its manifest (Cargo.lock vs Cargo.toml, package-lock.json vs package.json, …); "your lockfile is stale" nudge. Badge / Text
  • project_ci_config — which CI is wired up (.github/workflows, .gitlab-ci.yml, .circleci, …); per-dir Badge / Text
  • project_eol — runtime / framework / OS end-of-life dates via endoflife.date (free open API, fixed-host → Safe); auto-detects from the cwd (.nvmrc, .python-version, .ruby-version, go.mod, runtime files). "Node 18 reaches EOL in 6 weeks". Per-dir. Entries / Badge / Timeline

Standalone (local-only singletons)

  • ssh_agent_keys (realtime)
  • direnv_status — whether the cwd's .envrc is allowed / blocked / absent (realtime; Badge)
  • tmux_sessions — running tmux / screen / zellij sessions (realtime; Text count / Entries)

Metadata

Metadata

Assignees

No one assigned

    Labels

    widgetBuilt-in widget

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions