What it is
Before it existed, updating the devices page required copy-pasting hardware output from each PC into the chat. blip-hw removes that. Each machine runs a one-shot script (PowerShell on Windows, bash on Linux), reports its specs to the Pi/m920q, and from then on Claude can rebuild /r/devices from live data.
The registry lives in a hw_devices SQLite table inside blip-ops. It upserts by hostname, so re-running the script on the same machine always updates rather than duplicates. There is no server-side agent, no background process, and no scheduler on the client. The script runs once and that is it until the hardware changes.
The nginx fragment labs-blip-hw.conf routes /blip-hw/* to blip-ops (port 8120). The endpoints have no authentication. They are intended to be called from machines on the local network or via Tailscale.
Endpoints
All endpoints are served at my.jetblip.com/blip-hw/ via the Cloudflare tunnel, or directly at http://<node-local-ip>:8120/blip-hw/ on the local network.
| Method + Path | What it does | Auth |
|---|---|---|
POST/blip-hw/report |
Upsert device specs. Body: JSON from the report script. Idempotent, re-run anytime to update. A GET returns 405 (POST only). | None |
GET/blip-hw/devices |
Returns all registered devices as JSON. Claude calls this to rebuild /r/devices. | None |
GET/blip-hw/devices/<hostname> |
Returns a single device by hostname. Hostname is lowercased automatically. | None |
Example POST body (same shape from both reporters)
{
"hostname": "m920q",
"label": "m920qLinux",
"os": "Ubuntu 24.04.4 LTS",
"cpu_name": "Intel(R) Core(TM) i5-8500T CPU @ 2.10GHz",
"cpu_cores": 6,
"cpu_threads": 6,
"cpu_mhz": 3500,
"ram_gb": 46.9,
"ram": [
{ "capacity_gb": 32, "speed_mhz": 2667, "manufacturer": "...",
"part_number": "...", "bank": "...", "slot": "DIMM 0" }
],
"gpu": [ { "name": "Intel UHD Graphics 630", "vram_bytes": null, "driver": null } ],
"disks": [ { "model": "Micron_3400_MTFDKBA1T0TFH", "size_gb": 953,
"interface": "nvme", "serial": "...", "media_type": "SSD" } ],
"mobo_manufacturer": "LENOVO",
"mobo_product": "..."
}
Example POST response
{ "ok": true, "hostname": "m920q", "label": "m920qLinux" }
Setup on a new machine
Windows PowerShell
Open PowerShell on the target PC and run:
irm https://infra.jetblip.com/r/blip-hw/blip-hw-report.ps1 -OutFile blip-hw-report.ps1
.\blip-hw-report.ps1 -Label "Custom Desktop"
Error: "running scripts is disabled on this system" · Windows blocks downloaded scripts by default. Either set the policy once for your user:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
or bypass for a single run: powershell -ExecutionPolicy Bypass -File .\blip-hw-report.ps1 -Label "..."
Linux bash (m920q, rpi5, any Linux node)
curl -fsSL https://infra.jetblip.com/r/blip-hw/blip-hw-report.sh -o blip-hw-report.sh
Needs lscpu, free, lsblk, lspci (pciutils) and python3 (stdlib only). dmidecode is optional but gives you the RAM stick + motherboard detail.
bash blip-hw-report.sh --label "m920qLinux"
Verified output on the m920q (the brain node):
Reporting: m920qLinux (m920q)
CPU: Intel(R) Core(TM) i5-8500T CPU @ 2.10GHz
RAM: 46.9 GB (2 sticks)
Disks:Micron_3400_MTFDKBA1T0TFH
Endpoint: https://my.jetblip.com/blip-hw/report
Done [200]: {"hostname":"m920q","label":"m920qLinux","ok":true}
RAM sticks / motherboard show empty? Those come from dmidecode, which needs root. Install it (sudo apt install dmidecode) and make sure passwordless sudo is set, or run the script as root. Everything else (CPU, RAM total, disks, GPU) works without root.
Say: "m920qLinux registered, update /r/devices". Claude calls GET /blip-hw/devices, reads live data for all machines, and ships a new CalVer version of the devices page.
If the CF tunnel is down, use the local fallback endpoint on either OS:
--endpoint "http://<node-local-ip>:8120/blip-hw/report" (bash) or -Endpoint "..." (PowerShell).
Get the Pi/m920q local IP: ssh m920q "hostname -I"
Label convention & owner prefixes
The label field is the human-readable name stored alongside each device. By using a prefix convention you get automatic per-owner pages with zero extra infrastructure, everything stays in the same hw_devices table.
| Label pattern | Shows up in | Example |
|---|---|---|
| No prefix (plain name) | /r/devices/, Jeremy's homelab | "Custom Desktop", "m920qLinux", "T580" |
thierry-* |
/r/thierry/devices/ | "thierry-hp-pavilion" |
| Any future prefix | A new page per prefix, no DB change needed | "work-macbook", "client-xyz-server" |
The page at /r/thierry/devices/ fetches live from the API and filters by label.startsWith("thierry-") in JavaScript, so it updates the moment the script runs on Thierry's PC.
Report scripts (full source)
blip-builders/tools/.blip-builders/tools/.Both produce the identical JSON payload shape (see Endpoints), so the registry and the devices page do not care which OS reported. Open either link to read the full source.
Claude workflow
Once one or more devices are registered, Claude can regenerate the devices page without any copy-paste:
Or any variation: "m920qLinux is registered now", "refresh /r/devices", etc.
ssh m920q "curl -s http://127.0.0.1:8120/blip-hw/devices"
(or via labs-rpi while the Pi still serves blip-ops).
Writes YYYYMMDD-devices.vNN.html to jetblip-infra, updates r/devices/index.html redirect, commits and pushes. CF Pages deploys in ~30s.
Run one script per machine (Windows or Linux). After that, the devices page is always one sentence away from being current.
Live status
Devices page: /r/devices/ · Thierry: /r/thierry/devices/
Páginas que usam blip-hw
Todas as páginas que consomem a API blip-hw. Clicar para navegar directamente.
thierry-*Para adicionar uma nova página por prefixo: criar /r/<prefixo>/devices/index.html que filtra label.startsWith("prefixo-"). Adicionar aqui depois.