Repository navigation
feat(settings): System tab — host CPU, memory, disk, network IPs - #179
Merged
Merged
Conversation
New read-only Settings tab that surfaces host OS resources. Backend - New api_sysinfo.go (one file per feature, per the api package's CLAUDE.md rule) exposing GET /api/system/info. Returns hostname, uptime, CPU percent + cores, memory (total/used/percent), disk (root mount, total/used/percent), and one entry per UP non-loopback network interface with its non-loopback IPv4 + IPv6 addresses. - Added github.com/shirou/gopsutil/v4 for cross-platform CPU / memory / disk reads (works on the Linux Pi targets and the macOS dev machine alike). Network IPs use stdlib net.Interfaces() so loopback / down filtering stays in the standard library. - Route registered in api.go:routes() next to /api/health. Frontend - New web/settings/tabs/system.js. Render shows Host (hostname, uptime), CPU & memory (percentage + bar + cores / "X used of Y"), Disk (path + percent + bar + bytes detail), and Network. - Network defaults to IPv4-only with a "Show IPv6" checkbox; toggle re-renders from the cached payload (no extra fetch). Filter is string-based (presence of ":" → IPv6) — covers fe80::, ::1, IPv4-mapped ::ffff: forms. - After-render hook polls /api/system/info every 5 s, reusing the setInterval + window._timer pattern from ha.js / ev.js. Disk + network update on the same tick (free, same payload). - Tab button + script tag wired into web/index.html alongside the other tabs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new read-only System tab in the Settings modal and a backing API endpoint to display host diagnostics (CPU/memory/disk/network).
Changes:
- Add
GET /api/system/infoendpoint usinggopsutil+ stdlibnetto expose hostname/uptime/CPU/memory/disk and interface IPs. - Add new Settings → System tab that polls the endpoint every 5s and renders resource bars plus interface addresses (IPv4 default, optional IPv6).
- Wire the new tab into the Settings modal (button + script include).
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| web/settings/tabs/system.js | Implements the new System settings tab UI + 5s polling/rendering logic. |
| web/index.html | Adds “System” tab button and loads the new tab script. |
| go/internal/api/api_sysinfo.go | Implements /api/system/info and network interface IP collection. |
| go/internal/api/api.go | Registers the new route. |
| go/go.mod | Adds github.com/shirou/gopsutil/v4 dependency. |
| go/go.sum | Updates module checksums for new/updated dependencies. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
… escape, smoke test Three of five Copilot review comments were valid: - api_sysinfo.go: hardcoded "/" broke the windows/amd64 release target (make build-windows-amd64). Added diskRoot() which returns %SystemDrive%\ on Windows (fallback C:\) and "/" elsewhere, threaded through both the Disk.Path default and the disk.UsageWithContext call. - web/settings/tabs/system.js: renderNetwork() built HTML via innerHTML with raw interface names and IPs from the host. Low realistic threat (IFNAMSIZ + kernel charset limits) but inconsistent with the escHtml-everywhere pattern used by devices.js. Captured ctx.escHtml in after() and escape both fields. - api_sysinfo_test.go: new smoke test covering 200 + decodable shape + the two fields that don't depend on host probes (Cores, Disk.Path), plus a GOOS guard on diskRoot(). Follows the api_selfupdate_test.go pattern. The other two comments (ParseCIDR vs IPAddr, nil→null JSON slice) were resolved as wontfix: net.Interface.Addrs() only returns *IPNet on linux and darwin per stdlib source, and the frontend already guards Array.isArray(d.network) ? d.network : []. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
frahlg
added a commit
that referenced
this pull request
Oct 14, 2026
Move the pin to srcfl/device-drivers afc9739 (#179). Two Sungrow tests polled back to back and expected the running state on every poll; 1.6.0 reads it on a full read every five seconds, so they move the driver's clock five seconds before each poll. Signed-off-by: Fredrik Ahlgren <fredrik@sourceful-labs.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
GET /api/system/info(in its ownapi_sysinfo.goper the package's one-file-per-feature rule) backed bygithub.com/shirou/gopsutil/v4for cross-platform CPU/memory/disk reads. Network IPs use stdlibnet.Interfaces().setIntervalpattern asha.js/ev.js).Show IPv6checkbox; the toggle re-renders from the cached payload — no extra fetch round-trip.Notes
make devkeeps working on macOS as well as the Linux Pi targets — gopsutil is pure Go, no CGo.window.FTWSettings.tabs.system = { render, after }).Test plan
eth0/wlan0with the expected LAN IP.🤖 Generated with Claude Code