- Make ServicesTab a VerticalScroll so the service list is scrollable.
- Preserve cursor position / selected unit across periodic refreshes.
- Add visible Start/Stop/Restart buttons.
- Show selected service in the status bar.
- Focus the service table when switching to F3.
- Bump version to 0.3.1.
- Extend LogCollector with ActiveBackup package and activity logs.
- Parse leading timestamps and render logs in timestamp/source/message columns.
- Add live text search in the Logs tab (/, ESC).
- Add F3 Services tab with systemctl-based start/stop/restart and confirmation modal.
- Keep services/disks summary inside Dashboard.
- Update README with new tabs and key bindings.
- Bump version to 0.3.0.
Synology logs often embed bracketed paths like
`[/var/packages/SynoFinder/etc/etc-volume/collect.data]`. Rich
interprets the leading `[/` as a closing tag, so RichLog crashed
with MarkupError the first time the Logs tab was resized and the
deferred-render queue was flushed.
Wrap line.raw in rich.markup.escape() so brackets render as text.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Network
- NetworkCollector now also runs `ip -o -4 addr show` and merges the
IPv4 address into each NetSample. Dashboard shows one line per
interface (iface + IP + rx + tx); the active one is marked with `●`
and is what the rx/tx braille graphs track.
- Hides loopback, docker*, veth*, br-*, virbr*, tap*, tun*, ovs-system,
dummy*, wg*. Folds the raw `ethN` away when an `ovs_ethN` exists for
the same NIC (Open vSwitch on Synology exposes both, only the ovs_
one carries the IP).
Storage
- Only `/volumeN` (digits) is shown. Previously bind-mounts created by
Container Manager under `/volume1/@appdata/.../all_shares/*` and other
subpath mounts were listed too, each repeating the pool's usage —
visually noisy and meaningless.
Verified against DS720+ (DSM 7.3.2) and a multi-NIC NAS running OvS +
Tailscale + Docker.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
`git checkout main` aborted on the v0.2.0 release because the
freshly-rendered Formula/dsmview.rb differed from the committed
version. Save it to /tmp first, then force-checkout main, then
restore. Release tap-push step already succeeded, so brew install
worked — only the back-commit refresh was missed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
UI
- F1 Dashboard now holds CPU/MEM/storage/network/services/disks in a
single dense view (was split across F1/F3/F4). F2 Logs stays separate.
- CPU and MEM rendered inline (label + bar + summary on one row) so the
dashboard fits more on screen.
- DataTables and Services list capped for compactness; services sorted
with interesting+running first.
Refresh
- Three tiers: fast (1s) for system+network, medium (5s) for storage+
services, slow (30s) for disks (smartctl is heavy). Each tier runs
in an exclusive worker group so overlaps are dropped, not queued.
Log filter
- Bindings (a / 1-4) moved from LogsTab container to the App, so they
fire regardless of focus. Pressing one auto-switches to the logs tab.
Synology DSM 7.3+ compatibility (verified against DS720+ / DSM 7.3.2)
- DSM version read from /etc/VERSION (synoinfo.conf no longer has
productversion on newer DSM).
- Disks discovered as /dev/sata{N} as well as /dev/sd{a..z} and NVMe;
smartctl runs with -d sat so SMART data is actually readable.
- SAS-style smartctl output (Vendor:/Product:) parsed as a fallback
when Device Model: is absent.
- Services collected via plain systemctl list-units, since
synoservicectl/synosystemctl are gone on recent DSM builds.
- Network primary() picks the interface with the most accumulated
traffic instead of hard-coded eth0.
Cleanup
- Removed ConfirmDialog and service start/stop/restart actions — the
app is now truly read-only, matching the stated philosophy and
eliminating a key conflict with `r`=refresh.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
poet (last release 2018) still hits the legacy pypi.io endpoint and
404s on names that don't normalize cleanly through PyPI's redirect.
Replace with a small inline Python script that walks the venv's
installed distributions, queries https://pypi.org/pypi/<name>/json,
picks the sdist file and emits Homebrew resource blocks. Hard-fails
when any package is missing an sdist.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
setuptools 81+ removed pkg_resources from the default install.
homebrew-pypi-poet is unmaintained and still does `import pkg_resources`
at module load, so we pin a setuptools that still ships it.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous workflow installed homebrew-pypi-poet system-wide while
dsmview lived in a venv, so poet's `import pkg_resources` resolved
against a stripped-down Python that no longer ships setuptools by
default (3.12+).
Consolidate into one step: create the venv, install setuptools/wheel
explicitly, then poet and the project, then run poet from the venv.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>