devices-common

module
v0.3.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 22, 2026 License: MIT

README

devices-common

Shared foundation for the jarvisfriends devices-* family — devices-cpu, devices-gpu, devices-memory, devices-drive, devices-bios, devices-monitor, devices-npu. Each category repo implements one small interface; this module turns that into four consumption surfaces:

  1. Library — typed snapshots from Go code.
  2. CLI — one shared flag set for every devices-* binary.
  3. TUI — a live dashboard built on snap (gradient gauges, sparklines, sortable tables), mountable as a tui-base router page.
  4. Web — a JSON + SSE API and an embeddable <jf-devices> web component.

The model

Values split along two axes:

  • KindStatic values are one-time lookups (model numbers, serial numbers, specs); the engine caches them after the first read. Dynamic values change over time (usage, temperatures, clocks, power) and are re-collected on every request.
  • Levelbasic (default) is the cheap common set every platform can produce. detailed and full progressively add values that cost more to retrieve: vendor CLIs, WMI queries, privileged files. You opt into the latency instead of paying it by default.

Everything works without cgo. Builds with cgo can add more (Snapshot.CGO says which build you got); values that cannot be read are reported as Gaps with reasons, never silently dropped.

Library

import (
    "github.com/jarvisfriends/devices-common/devices"
    "github.com/jarvisfriends/devices-cpu/cpu"
)

e := devices.New(cpu.New())

// On demand (static answers are cached after the first call).
snap, err := e.Snapshot(ctx, devices.Detailed)

// Async one-shot.
res := <-e.Request(ctx, devices.Basic)

// Every 0.25 seconds until ctx is canceled.
for res := range e.Stream(ctx, devices.Basic, devices.Every(0.25)) {
    fmt.Println(res.Snapshot.Taken, res.Snapshot.Fields)
}

CLI

Every devices-* binary speaks the same grammar — report by default, with tui and web subcommands:

$ devices-cpu                       # one snapshot, aligned text
$ devices-cpu --level full          # everything we know how to read
$ devices-cpu --static --json       # specs/serials as JSON, once
$ devices-cpu --every 0.25          # four samples a second until Ctrl-C
$ devices-cpu --json --every 1 --count 10   # NDJSON, ten samples
$ devices-cpu tui                   # live dashboard
$ devices-cpu tui --level detailed --every 0.5
$ devices-cpu web :8080             # HTTP API + web component

TUI

tui.Run(engine, level, every) runs the standalone dashboard. The main view stays readable by design: category-wide values render as gauge and sparkline rows, and devices render as sortable tables carrying only their Basic fields — grouped by field shape, so disks and volumes get separate, cleanly aligned tables instead of one sparse union. Everything deeper is one interaction away: Enter or double-click a row to open a live detail popup that collects at Full and shows every value for that one device, tagged by level.

Mouse works throughout: click a header to sort that column, click a row to select it, double-click to open details, wheel to scroll the table under the pointer. tab moves keyboard focus between tables, / filters, l cycles the level, p pauses, esc closes the popup, q quits.

The same model embeds snap/page.Base, so it drops straight into a tui-base app:

router.NewWithOptions(router.Options{
    AppName:    "hw",
    ExtraPages: []router.RegisteredPage{{Title: "CPU", Model: tui.NewModel(e, devices.Basic, time.Second)}},
})

Web

web.New(collectors...) hosts any number of categories:

  • GET /api/devices — hosted categories
  • GET /api/devices/{category}?level=basic&kind=all|static|dynamic
  • GET /api/devices/{category}/stream?level=basic&every=0.25 — SSE
  • GET /devices.js — the web component
  • GET / — a demo page with one component per category

Embed on any site:

<script src="http://host:8080/devices.js"></script>
<jf-devices category="cpu" every="0.5" level="detailed"></jf-devices>

web.Server is an http.Handler, so it also mounts inside a larger mux.

Implementing a category

type Collector interface {
    Category() string
    Static(ctx context.Context, level devices.Level) (devices.Snapshot, error)
    Dynamic(ctx context.Context, level devices.Level) (devices.Snapshot, error)
}

Build fields with the helpers (devices.Str, devices.Pct, devices.Bytes, …), put per-instance values on Device entries (stable IDs), report unreadable values as Gaps, and prefer well-maintained open source sources (gopsutil, ghw, cpuid, vendor CLIs) over hand-rolled platform code.

License

MIT — see LICENSE.

Directories

Path Synopsis
Package cli is the shared command line for every devices-* tool.
Package cli is the shared command line for every devices-* tool.
Package devices is the shared vocabulary for the jarvisfriends devices-* family (devices-cpu, devices-gpu, devices-memory, …).
Package devices is the shared vocabulary for the jarvisfriends devices-* family (devices-cpu, devices-gpu, devices-memory, …).
Package tui renders any devices.Collector as a live full-screen dashboard built from the snap component set.
Package tui renders any devices.Collector as a live full-screen dashboard built from the snap component set.
Package web serves device snapshots over HTTP three ways: a JSON API for programs, a Server-Sent Events stream for live consumers, and an embeddable web component (<jf-devices>) that any site can drop in to get live tables and gauges.
Package web serves device snapshots over HTTP three ways: a JSON API for programs, a Server-Sent Events stream for live consumers, and an embeddable web component (<jf-devices>) that any site can drop in to get live tables and gauges.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL