DeviceShelf Blog

Release history

Every DeviceShelf release on one page — newest first. Expand a version for the full notes.

Deutsch

← All posts

DeviceShelf 1.7.9 — a router that refuses you now says why Every failed router connection used to blame the password, even when no password could have helped. The app now tells the failures apart, and the four brands you have to open up first say so under the picker. Seventeen brands were re-checked against recorded answers. Threshold checks save as you edit, run on the first tick after a restart, and record what they measured.

A router that refuses you now says why. The connection test had one answer for every failure, and it named the password first. That sent people down the wrong path: a GL.iNet owner changed his password twice, but his OpenWrt never exposes the interface we talk to, so no password could ever have worked. Unreachable, no endpoint, refused, no data and no brand matched are separate answers now. OpenWrt reports its own diagnosis; the other brands fall back to a reachability probe, which at least separates "no answer at all" from "answered and said no". A guessed diagnosis would be worse than an honest coarse one.

Four brands need the router opened up before anything can connect, and the picker now says so on the spot: ubus for OpenWrt, an API key rather than an account password for UniFi, the applications switch on a FRITZ!Box, www-ssl on MikroTik. The other thirteen show nothing rather than an empty box. The help text also stopped selling the feature short, and stopped promising switch ports for every brand, because only UniFi reports them. What you get is devices the scan cannot reach at all (sleeping phones, anything behind a firewall, other VLANs), the names from the router's DHCP table, and whether an address is a lease or a fixed reservation.

The phone says the same thing in the same words. It has its own router client and its own catalogue, so it had kept answering "check the credentials or the router type" for every failure. Someone holding both devices would have been told two different stories about one router.

All seventeen brands now have recorded answers on file, replayed through the Go and the Dart implementation alike, and that turned up three defects. A Peplink client that is not connected no longer counts as present. A Netgear device whose MAC cannot be read no longer disappears from the list. And a UniFi controller on Network 9.x reports the switch port it actually uses, rather than the field older firmware used.

Threshold checks work like every other setting now. They used to sit idle for a full monitor interval after each restart. At a fifteen-minute cadence that is fifteen minutes of a check which looks armed, measures nothing, and cannot raise the alarm it exists for. They also had a Save button nothing else has, so an edit you typed but did not confirm was thrown away, in the one place where losing an edit means an alarm quietly stops watching. Fields save as you leave them now, and the status line is read out to a screen reader.

A check also records what it measured. The result used to be evaluated and dropped, so a check row sat at a dash with a grey bar forever and reported itself up whatever it found. And in the monitoring list a check no longer poses as a device: someone asked about a device called Test that does not exist on any network, because a check pointing at localhost sat between wlan0 and a NAS, carrying a device icon and nothing to mark it. Checks have their own group now, their own icon, and their type written next to the name, in text, because colour alone reaches neither a screen-reader user nor anyone with a colour deficiency.

Desktop and server are 1.7.9, the mobile apps 1.3.9. Existing licences carry over; nothing in the data formats changed.

DeviceShelf 1.7.8 — the ranges you configure are the ranges it scans A subnet typed into the scan-range field used to change nothing at all; on the server it could even replace your own network. Both fixed, and the app now says when it dropped part of a scope. Alarms are muted instead of acknowledged, the macOS window keeps its toolbar on screen, and both device drawers work by keyboard and screen reader. The post also catches up on 1.7.4 to 1.7.7, which taught the list to show one row per machine.

Ranges you configure are finally scanned. A subnet typed into the scan-range field did nothing at all: the run finished in seconds and found nothing, with no hint that the field had been ignored. On the server the same setting had the opposite defect: a configured range replaced the machine's own network instead of adding to it, so entering a routed subnet made the server stop seeing the network it sits on. Both are fixed. And when a scope is too large or holds an entry that cannot be read, the app says so and names what it dropped, instead of quietly scanning less than you asked for.

The window no longer scrolls. On macOS the toolbar could ride off the top edge, taking the Scan button with it, and there was no scrollbar to bring it back. The dashboard also stops asking for a login you already typed.

Alarms are muted now rather than acknowledged. A muted alarm leaves the list instead of sitting in it, there is a mute-all, and the list stops reshuffling while you work in it. Both device drawers take keyboard input and read correctly to a screen reader, and closing one returns focus to the row you came from.

Four point releases went out between 1.7.3 and this one without a post, all on the same theme: one machine, one row. 1.7.4 started asking devices for their own names, so a phone on a private Wi-Fi address or a laptop with sharing switched off shows a name instead of a bare address, and the OS column says iOS, iPadOS, macOS, tvOS or Android where it used to lump them all together. 1.7.5 through 1.7.7 folded a machine's several addresses into a single row (a computer running virtual machines, a NAS answering from its container interfaces) and made that hold no matter who saw the device: the local scan, a collector, or both. Your names, comments and tags survive the folding, and a machine on your own network keeps Wake-on-LAN and its other actions even when a collector reports it too.

Desktop and server are 1.7.8, the mobile apps 1.3.8. Existing licences carry over; nothing in the data formats changed.

DeviceShelf 1.7.3 — one device list, and you pick whose network it shows The source pill in the toolbar now governs the device list instead of jumping to a second screen. Tick this computer's scan, any of your collectors, or several at once; origin becomes a column you can sort and filter by. The security analysis follows the same choice and says how many devices it could actually examine.

There used to be two device tables. The main one had configurable columns, filtering, favourites and sorting, and it showed this computer's scan. The second lived inside the remote view, had seven fixed columns and no actions, and clicking the source pill took you there. From 1.7.3 there is one table. The pill is a set of toggles: this computer's scan, any collector you have configured, any combination of them, with a filter box once the list passes eight entries. Picking a source changes the rows in place, every row carries where it came from, and that origin is a column you can sort and filter by. Turning the last source off falls back to the local scan instead of leaving an empty table with nothing to explain it. A device a collector reported stays view-only: waking it, scanning its ports or connecting to it would reach whatever holds that address on the network you are sitting on, not the machine you are reading about.

The security analysis follows the same choice. It had kept asking the backend for "the devices", meaning this computer's own scan, while the list was pointed at a collector. A report about one network sat above a list of another, with nothing to tell the reader which was which. Two counts in its summary were wrong as well. "Devices with port data" accepted any evidence at all, an mDNS service name or a certificate included, so a device nobody had port-scanned still counted as carrying port data, and a zero read as bad luck when the honest answer was that nothing had looked. Port-scanned devices are counted separately now, and the view names why there are none. The risk score also used to drop when you added a collector, because its devices had never been examined for ports and were counted in the denominator as though they had come back clean. Looking at more of your network cannot make it safer, so devices nobody examined are reported as skipped rather than quietly improving the figure.

On the server, "Update available" read the same whether a release tidied up a label or the version you are running is defective. 1.7.2 is the case in point: it shipped a CVE database missing all of 2025, so it reported fewer findings and looked healthier than it was. The manifest now carries that judgement in two independent fields: how much the new release matters, and which installs below it have a known defect. The notice says which of the two applies. The update panel used to offer docker compose pull with a footnote for the .deb, which left the macOS .pkg and the Windows service with no command at all. The server now works out how it was installed from what each package leaves behind and shows the one command that applies. The push notification uses the same logic, since an operator reading it over ntfy has no dashboard in front of them.

Pressing Scan on iPhone or iPad while not on Wi-Fi did nothing at all. The start path returned silently on a missing network, so the button could be pressed forever with no message, no error and no change on screen. The app now records why a scan could not start, says there is no local network to scan, and offers to try again; the header says it before the tap. A scan range holding no addresses is reported too, instead of ending quietly. Both apps also gained an indicator naming whose data is on screen: the local network, or the collector's name with its connection state.

Desktop and server are 1.7.3, the mobile apps 1.3.3. Existing licences carry over; nothing in the data formats changed.

DeviceShelf 1.7.2 — editing devices in the server dashboard The server dashboard can now set a device's type, tags, note, favourite and mute state, and say which machine a container runs on. Renaming no longer clears the note and type override, and one machine answering on several MAC addresses is one row again.

Until now the server dashboard could only rename a device. Everything else a person might want to record was stored, synced and displayed, yet could only be entered in the desktop app: the device type when detection guesses wrong, tags, a note, a favourite mark, muted notifications. 1.7.2 puts all of it in the dashboard's device drawer. Virtual devices get a host picker too. For a container behind NAT nothing on the network reveals which machine it runs on, so somebody stating it is the only answer there is; the server already honoured such a statement and simply had no way to take one.

Renaming a device in the dashboard used to clear its note and its type override. The dashboard sent only the new name, the server read the missing fields as emptied ones, and the metadata sync then carried that deletion to every other client. The endpoint now patches field by field: an omitted field is left alone, an explicitly emptied one is a deliberate clear. Two related defects came out with it. A statement about a container's host was filed under a differently spelled key than the same device's name and type, so forgetting the device removed one and left the other behind. And an unparseable address sent to the host endpoint was stored as given, matched nothing afterwards, and still reported success.

The device list no longer repeats itself. A NAS answering on its own network card plus a handful of container interfaces used to fill the dashboard with near-identical rows, because the server served the raw per-address inventory while only the desktop app folded them together. That folding now runs on the server as well, in the read path alone. Availability, alerts and history stay keyed per address, where they belong.

Checkboxes in the dashboard also stopped growing on their first click.

DeviceShelf 1.6.24 — router imports respect your scan range Devices imported from the router's client table or SNMP now stay inside the configured scan range, self-assigned 169.254.x addresses no longer appear as permanently-down ghosts, and the trial gives an honest heads-up before it ends.

When a router login is configured, DeviceShelf reads the router's own client table and adds hosts the local scan missed. Until now that import ignored the scan range set in the app. A Wi-Fi client that had failed to get a DHCP lease showed up under its self-assigned 169.254.x address: unreachable, 0% uptime, first seen on the nonsense date 01/01/1. 1.6.24 bounds the import to what your scan settings actually cover. If you configured a range or picked interfaces, only hosts inside that scope are adopted. Without a configured range the app uses every private LAN the machine sits on, so multi-homed setups keep their second segment.

Junk addresses are now rejected outright, from every import path. Router client tables and the ARP tables read over SNMP can contain self-assigned link-local rows (169.254.x, fe80::), loopback, multicast or 0.0.0.0. None of these is a real device. And since the monitor probes adopted addresses, a misreporting device could point probes at addresses that should never be targets. The server already blocked these address classes for SNMP targets; the same block now applies to adopted hosts, on desktop and server alike. Imported devices also get a real first-seen timestamp.

Ghost entries created by earlier versions are not deleted automatically. Remove them once and they will not come back.

The desktop app now warns before a trial runs out. On the last two trial days a dismissible notice with a buy link appears; previously the only purchase hint sat in the Settings panel. The expiry screen wording was corrected along the way: after the trial only scanning stops on desktop, and the text now says exactly that, including that collected data stays on your machine.

DeviceShelf 1.6.23 — the sync no longer eats your device names A full re-pull from a remote server could overwrite freshly written names, tags and types with stale empty records. The sync now merges by revision instead of replacing, and the monitor list learns sorting and filtering.

If the desktop app syncs device metadata with a server, certain events made it re-read the server's entire record feed: enabling the sync, re-adding a server, a server reinstall. The desktop applied every record from that feed as delivered. A record that predated your latest edits carried empty fields, and those empty fields replaced whatever you or the AI identification had just written. The AI result text survived, because it is not part of the sync. The name, tags, type and note it had filled in did not. From the outside it looked like the app forgetting your labels after a restart or a rescan.

The rebuilt pull path is deliberately clock-free, since comparing wall-clock timestamps across machines is how sync systems lose data. The desktop now remembers which server revision it has already seen and skips re-deliveries outright; a cursor reset carries no new information and can no longer touch anything. It also tracks, per server, which local change was last acknowledged. When local state has edits a server never saw, a pulled record merges field by field instead of replacing: queued edits stay untouched, a non-empty local name beats a stale empty one and gets pushed back to the server, and only genuinely newer server values are adopted. A deliberate clear made on another client still comes through, because it arrives with a newer revision.

Two smaller holes closed along the way. A sync conflict used to freeze the affected edit until you touched the field again; conflicted changes now re-base onto the server's current revision and retry, with a bound so a misbehaving server cannot loop them forever. And a transient failure reading the stored server list no longer causes an edit to be quietly skipped by the outgoing queue.

The fix is entirely on the desktop side. Servers need no update; 1.6.23 server builds exist for version parity only.

Separately, the monitoring list is now sortable and filterable. Devices with problems sort to the top by default, and a search box, sort options (name, uptime, type) and a down-only filter appear once the list has six or more entries. This applies to the local monitor and to remote server views alike.

DeviceShelf 1.6.22 — presence Home Assistant can actually use The export shipped presence as a binary sensor, which no person entity can read. It now also publishes a device tracker, one problem sensor per monitored check, and the vitals of every polled machine.

The Home Assistant export in 1.6.21 published each device as a binary sensor. That is an honest reading of what the scan measured, and it is fine on a dashboard. It also cannot drive anything: Home Assistant only attaches a device_tracker to a person, so "the phone answers on the LAN" never became "she is home", and none of the presence automations people already have could see it.

Every exported device now gets a tracker as well. Both read the same state topic, so the two views cannot disagree, and source_type says the presence was inferred from the network rather than from GPS. The binary sensor stays for dashboards and templates.

The second gap was services. Home Assistant can tell whether a machine answers a ping; it cannot tell whether the database on it is healthy, which is why people keep a second uptime tool running next to it. Each enabled check now becomes a problem sensor, reading the same alarm state that sends the notification. What turns red in HA is what triggers an alert, not a second opinion assembled elsewhere.

Then the numbers the server already collects. Each SNMP-polled machine appears as its own device with CPU, memory, disk, temperature and fan; Docker containers share one device with a running sensor each. "Notify me when the NAS disk passes 90%" is a two-line automation once the sensor exists, and impossible without it.

Some care went into what happens when a source goes quiet, because the obvious implementation is destructive. An empty list is ambiguous: Docker being switched off and the socket not answering for one cycle both arrive as zero containers. Treating the second one as "there are none" removes the entities from Home Assistant's registry, and they come back a minute later as new entities. The names you gave them, the areas you assigned and the dashboard cards pointing at them are gone. Sources now say whether they reported at all, and one that stayed silent keeps what it published.

The same applies to a failed poll. The SNMP layer reports minus one for every metric when a host times out, so skipping those metrics would have deleted CPU, memory, disk, temperature and fan on each hiccup, recorded history included, for exactly the disk sensor the feature exists for. Once a sensor has been published it stays; the state carries the gap as null, and Home Assistant renders that as unknown rather than as a plausible zero.

Turning the health watch off removes the host entities instead of freezing them. An entity that is no longer being evaluated but keeps reporting its last value is worse than one that is gone, because nothing about it looks wrong.

DeviceShelf 1.6.21 — the server talks to Home Assistant The server edition can now publish its inventory to Home Assistant over MQTT. Presence was never the interesting part; knowing that an unrecognized device just joined is.

The server edition can now publish what it finds to Home Assistant. It uses HA's own MQTT discovery protocol, so there is nothing to install on the Home Assistant side beyond the MQTT integration and a broker. No add-on, no custom component, no HACS release.

Writing a real Home Assistant integration was the obvious alternative, and the worse one. It would have meant a Python component and a review cycle, and underneath all that it would still have needed a transport. Discovery is the supported way for an outside daemon to contribute entities. The daemon writes retained JSON; Home Assistant builds the entities from it.

Each exported device arrives as one HA device. It carries a connectivity sensor plus IP and latency as diagnostics, with vendor, model, device type, operating system, first and last seen, and the open ports as attributes. Home Assistant already knows how to tell whether a phone is home, so presence alone would have been a thin reason to build any of this. The attributes are what it cannot derive on its own. So is the event entity: the server fires new_device, device_online, device_offline and new_port, each with MAC, IP, name and vendor attached. An automation can finally react to an unrecognized device joining the network. No amount of device tracking will tell you that.

Not every host gets exported. Favorites and infrastructure do, meaning the gateway, routers, switches, access points, firewalls, NAS boxes, servers and printers. Everything else waits for an explicit opt-in, device by device. A /24 with 150 hosts would otherwise produce several hundred entities on first connect, most of them the short-lived privacy MACs that modern phones rotate through. That is noise. An integration which floods someone's entity list gets uninstalled the same evening.

The bookkeeping matters more than it sounds. Discovery payloads and states are retained, so Home Assistant repopulates after a restart instead of showing nothing until the next scan, and they are rewritten only when something actually changed. A device that leaves the export has its retained config cleared, which is how Home Assistant deletes an entity rather than leaving it behind as permanently unavailable. The collector registers a last will, so a crash greys its entities out instead of freezing them on a stale "home". A broker outage is logged and otherwise ignored. Scanning and every other alert channel carry on.

Testing this against a real Home Assistant, rather than only against a broker, was worth the trouble. Two defects showed up nowhere else. A NAS with two network cards produced two devices of the same name, and Home Assistant quietly appended a _2, which tells nobody which card it is; colliding names now carry the last four hex digits of their MAC. The second one was subtler. We were setting object_id on every entity, and it turns out to be ignored the moment the payload contains a named device block, because Home Assistant builds the entity ID from the device and entity names instead. Sending it anyway advertised a control we did not have, so it is gone.

The setup, the topic layout and a couple of automation examples are in the Home Assistant guide.

DeviceShelf 1.6.20 — credentials that stay put Stored API tokens could be deleted by a setting that had nothing to do with them. The earlier fix guarded the settings form, but a dozen code paths never go through the form.

Some users saw their API tokens empty after an update, retyped them, and saw it happen again later. A fix shipped for that once, and it was not enough.

Two things went wrong together. The secure store is read once at startup, and a read can fail: a keychain that has not yet granted the freshly signed binary access, or a file another instance is mid-write on. The read returned "nothing here", which is indistinguishable from "nothing was ever stored", so the settings form showed empty fields and the credentials looked gone.

They were not. But the empty values were now in memory, and that is where the second problem started. The settings form drops secret fields the user did not touch, which is what the earlier fix added. Only a dozen places in the code never touch the form at all. They read the settings, change one flag, and write everything back:

cfg := store.Settings() cfg.SyslogEnabled = true store.SetSettings(cfg)

Every secret in that struct was the empty string, and saving wrote those blanks through to the store. Switching on syslog deleted the API keys. So did accepting the AI consent. The credentials the user retyped were then genuinely gone the next time, which is why the problem kept coming back after being fixed.

The guard now sits where the writing happens rather than in the form. A non-empty value always writes. An empty value only writes when that secret's value could actually be read at startup, which is what a deliberate "clear this field" looks like. When the read failed, clearing is refused, because there is no way to tell an intentional deletion from a value we simply never saw.

Underneath that, the two cases are no longer the same case: a read failure is now reported as a failure instead of being flattened into "not found". The settings screen uses that. A field whose value could not be read is marked read-only and says "could not be read — still stored", with a note asking you not to retype it. Restarting the app is the fix, and now the app is the one saying so.

One regression from the compatibility work in 1.6.19 is also fixed: the remote server list waited for the capability check of every server before drawing anything, so a server that was unreachable, during its own update for instance, left the list blank for several seconds.

DeviceShelf 1.6.19 — the alert dialog, and knowing what a server can do The alert settings of a paired server never opened. Fixing that surfaced a quieter problem: the app assumed every server could do everything, so a missing feature looked like a working one.

Opening the alert settings of a paired server always failed with "Server alerts could not be loaded", no matter how healthy the server was. The cause was in the bridge between the Go backend and the interface: a bound method may return a value and an error, and Wails forwards the second value only when it actually is an error. Ours was a status code, a plain string, so it was dropped. The interface expected a pair, received a single object, and the resulting exception surfaced as that message. The call now returns one value carrying both, and a test refuses any bound method with the old shape.

The fix exposed something quieter. A server that predates a setting does not report it as missing. It simply leaves the field out, and the client reads its default. The master mute switch was the visible case: against a server that cannot mute, the app showed an unchecked box. Nothing failed. The switch just did nothing, and looked exactly like a switch that was off.

So clients and servers now establish what they can do before they try it. A server answers a handshake with its version and the list of features it understands, and the app gates on that list rather than guessing from a version number. A feature the server did not declare is hidden instead of offered, so the mute switch appears only where it applies. A server too old to work with is named as such, together with the version required, rather than failing one call at a time. Servers that predate the handshake are read from their version, using bounds taken from the release tags that actually contain each feature.

The handshake needs no token, like the version endpoint it sits next to, because compatibility has to be checkable before pairing. It reports only what the build understands, never how the installation is configured. That stays behind the token.

Two smaller things. The settings button in a server row used a gear emoji, which rendered as a tiny grey mark on a light panel; it is a proper icon now. And the update check misread a release candidate: a version component with a trailing suffix parsed as zero, so 1.6.19-rc1 compared as 1.6.0 and an older release could have been presented as newer. The same parser bug sat in three places and is now one function.

On phones, pulling the device list down runs a new scan. Pulling while a scan is already running joins it instead of cancelling it, and the indicator keeps turning until the sweep is actually done.

DeviceShelf 1.6.18 — keyboard, screen reader, and one set of colours The device list works without a mouse and reads aloud properly, the server dashboard gained a light theme, and all three apps now share the same tokens.

The device list was mouse-only. On the desktop a row was a plain div with a click handler, the favourite star a span, the sortable headers neither focusable nor announced. With a keyboard you could reach the sidebar, the filter, and nothing else. The server dashboard had the same gap in table form.

Both are fixed. The device name is a real button carrying a spoken summary, the star reports whether it is set, headers sort with Enter or Space, and the status dot has text behind the colour. On the server, a focused row now survives a live update instead of dropping you back to the top of the page.

The Flutter app had no semantic annotations at all. VoiceOver and TalkBack read a row as loose fragments in layout order (title, then each badge, then every port chip) while the status dot, the gateway badge and the star said nothing whatsoever. A row is now one sentence: name, gateway or self, address, vendor, port count, plus the warnings that used to be only an icon. Tag chips stay individually reachable, because tapping one filters the list. The fade-in when a device appears is skipped when the system asks for less motion.

The faintest text colour failed WCAG AA contrast in both themes: 2.24:1 in light and 3.71:1 in dark, against the 4.5:1 required, on text carrying port counts and timestamps. Raising it on its own would have collapsed it onto the next step up, so the whole ramp moved together and kept its hierarchy.

The server dashboard was dark-only. It now follows the operating system, with an Auto/Light/Dark picker beside the language selector. Anyone on a light desktop will notice the change on the next load.

Underneath, the three surfaces had drifted apart. The server kept its own stylesheet with different names for the same colours, and the Flutter app reused the light brand palette in dark mode, where the web apps brighten every hue. They share one documented token set now.

Two bugs turned up while working on this. On the server, the ports column had no minimum width, so a device with five open ports produced a five-line row with its name broken mid-word. Anyone running the port scan could see it. And the mobile list re-sorted itself on every rebuild, because Dart's sort is not stable and rows with equal keys had nothing to break the tie.

The device row on mobile also moved: the address and response time sit on the right edge, the maker on the line under the name.

DeviceShelf 1.6.17 — a mute switch, and errors that say what happened One switch silences every alert a server sends, and connection failures finally name their cause.

The per-event toggles added in 1.6.15 only covered five device events. Certificate expiry, domain expiry, WAN reachability, host resources and your own checks had no switch at all, so "make the server stop notifying me" was not something the apps could do. There is now a master switch that mutes everything the server sends. Detection and logging carry on; delivery stops.

Connection failures used to be unhelpful in a specific way. A rejected token was reported as "server unreachable, offline, on another network, or blocked by a firewall". That sent people looking at their network instead of their token. Each case now names itself: the token was refused, no DeviceShelf answers at that address, the server locked you out after repeated failures, it timed out, or it really is offline.

Behind that sat something worse. When the first request to a server failed, the client retried the same request on neighbouring ports of the same host and, on success, saved that address instead. The retry was meant for a server that had moved to a different port, but it also ran when the token was rejected. On a machine running two servers (the installed one and a hand-started build, which is a normal thing to have) you could end up looking at the other server's inventory while your token was quietly wrong. The retry now runs only when nothing answered.

On macOS the installer had three rough edges. It did not wait for the old service to stop, so the new one could race it for the port. The access sheet on your desktop hard-coded port 8088 rather than reading the port the service actually uses. And it was written in German regardless of your language. All three are fixed, and if something was already listening on the port before the install, the sheet says so.

The server list also shows each server's version now. Two servers on one machine were previously indistinguishable, which is how the ports got confusing in the first place.

Smaller: the Wi-Fi permission button on macOS did nothing, because CoreLocation does not present its prompt to a location manager that has no delegate. On mobile, a 404 from any endpoint claimed the server did not support alert settings, even when the real answer was that no DeviceShelf was at that address.

DeviceShelf 1.6.16 — alert editor repairs and MCP hardening Fixes for the remote alert editor that shipped in 1.6.15, plus a security pass over the MCP endpoint.

The remote alert editor from 1.6.15 had four defects. Saving worked exactly once per app start, because the desktop dialog left its Save button disabled after a successful write. When someone changed the policy elsewhere, the server's revision check answered 409 and the dialog kept resending the same stale revision, so no further save could ever succeed. An emptied number field stored 0 rather than leaving the value alone, which turned "offline after 0 minutes" into an alarm on the first missed scan. And the desktop dialog shipped without translations, so everyone saw German labels.

All four are fixed. Mobile and desktop now name a revision conflict for what it is, and the desktop reloads the policy so the next save goes through.

The MCP endpoint got a security pass. Device-reported text reaches an AI assistant through several tools, and the infrastructure tools were handing it over unfiltered — SNMP sysName in particular, which anything on the network can set. Those strings now go through the same filter as hostnames and banners. Monitor checks created over MCP must point at a private, loopback or link-local address, the restriction the scan tools already carried. An assistant that renames a device or edits a check no longer discards the fields it was never asked to change, and a heartbeat monitor keeps its push token.

Browser-based MCP clients could not connect at all: the CORS preflight carries no authorization header, so it was rejected before it reached the endpoint. A trailing slash in the URL used to return dashboard HTML with status 200, which clients reported as invalid JSON. Both are fixed, and the lockout after repeated bad tokens now sends Retry-After instead of leaving you guessing whether the corrected token is wrong too.

Config exports no longer contain notification targets.

DeviceShelf 1.6.15 — remote alert settings in desktop and mobile Configure the most important alert policies of a connected server from desktop and mobile.

DeviceShelf 1.6.15 makes the most important alert policies of a connected server available from desktop and mobile.

The new alert settings let users enable or disable messages for new devices, online/offline changes, new ports and mobile presence. Offline thresholds, port confirmations, digest alerts, email cooldowns, quiet hours and the timezone can also be adjusted.

Destinations, credentials and existing notification channels remain on the server. The apps receive only channel status, never SMTP, webhook or Apprise secrets. Revision checks prevent parallel changes from overwriting one another.

DeviceShelf 1.6.14 — clearer remote views and server onboarding Choose between a server-only view and a safe combined view, fix remote error handling, and get the macOS server URL and access token after installation.

DeviceShelf 1.6.14 makes remote servers easier to use across desktop, mobile and the self-hosted server edition.

Remote servers now have an explicit view choice. Use Server devices only when you want to inspect the remote inventory without mixing it with the local scan. Use Server + local devices when you need one combined view. The combined view is read-only and does not overwrite local data.

Remote error handling is more useful. A text error response from an older or unavailable endpoint is no longer reported as a confusing JSON parsing error. The client keeps optional remote sections available when one endpoint is missing.

The macOS server package explains first access. After installation, it opens an access sheet with the local dashboard URL, the LAN URL and the persistent token. Updates keep the server state and token intact.

The release also includes the current server monitoring and cross-app views described in the server guide.

DeviceShelf 1.6.11 — reliable server discovery and saved scan scope Server discovery now survives stale or non-default mDNS ports, saved remote URLs are repaired automatically, and startup scans honor the selected interface and range.

DeviceShelf 1.6.11 fixes two practical problems that showed up in real networks.

Remote server discovery no longer trusts stale ports blindly. A DeviceShelf server can run on a port other than the old default. The desktop app now reads the announced mDNS/Bonjour port, verifies it against the server API before showing it, and falls back through known working ports if the announcement is stale.

Saved remote server URLs repair themselves. If a saved server address points to the right host but the wrong port, DeviceShelf now probes the same host on the known DeviceShelf ports. When one answers correctly, the saved URL is updated instead of leaving you with a dead manual configuration.

Startup scans honor the selected interface and range. If you saved a specific scan interface or range, the first scan after app start now uses that scope immediately. It no longer falls back to scanning every interface first.

Update: use the desktop updater, download the new installer, or update the server if you rely on LAN discovery.

DeviceShelf 1.6.10 — server availability history in every client Desktop and mobile clients now show the availability history collected by a DeviceShelf server, device names are cleaner, and servers announce themselves on the LAN.

DeviceShelf 1.6.10 is about making a connected DeviceShelf server visible and useful from the clients.

Server availability history in the desktop and mobile apps. When you connect to a DeviceShelf server, each device can now show the monitoring history the server has collected: an uptime bar, response-time chart and outage list. Gaps where the monitor itself was off are marked separately, so downtime is not counted as uptime.

Cleaner names and fewer duplicates. Device names are less cluttered now. Real hostnames are preferred over IP and MAC fallbacks, router suffixes like .local and .localdomain are stripped where they do not add meaning, and the merge logic avoids duplicate rows for the same device more reliably.

LAN server discovery. DeviceShelf servers announce themselves on the local network, so the desktop and mobile apps can find them without typing the address by hand.

Update: use the desktop updater, the new mobile build, or update the server with docker compose pull && docker compose up -d, the .deb, the Windows zip, or the GHCR image.

DeviceShelf 1.6.9 — IP assignment type, steadier AI identification Every device shows how it got its IP (static, DHCP or reserved) straight from the router, AI identification holds up across providers and follows your app language, and a settings save no longer risks your stored secrets.

A smaller release: one new column, a batch of reliability work on the AI side, and a data-safety fix.

How each device got its IP. Devices now carry an assignment type, read from the router's lease table: static, DHCP, or a DHCP reservation. It answers a question the scan alone can't: is that address pinned, or could it move on the next lease? Desktop, server and mobile all show it.

Steadier AI identification. The identification panel used to occasionally leak raw JSON when a model wrapped its reply in prose, added a code fence, or ran out of room mid-answer. It doesn't anymore: the reply is parsed the same way for every provider, and a truncated one still yields a clean result. The text now follows your app language instead of the model's default. On a confident match, a device's still-empty name, tags, type and comment are filled in for you, only the empty ones, never over an edit you made. Results cached by older versions that showed a broken "(— · low)" line now render properly. And name resolution for AI calls falls back across several public resolvers, so a single blocked or hijacked one no longer breaks the request.

A settings save could drop stored secrets. After a failed secure-store read, saving settings could overwrite a stored secret (an API key, for instance) with an empty value. Fixed: a failed read no longer lets an empty value replace what was there.

Update: docker compose pull && docker compose up -d, the new .deb/.rpm, the Windows zip, or the desktop update. Details in the server guide.

DeviceShelf 1.6.7 — Fix for the app freezing over time Two resource leaks that made the app go unresponsive and load the machine after running a while, especially with live monitoring, are fixed.

If you left DeviceShelf running for a few hours, it could go sluggish and start loading the machine, most noticeably with live monitoring on. 1.6.7 fixes the two causes.

The active ARP scan leaked a packet-capture handle and a goroutine on every sweep. In live mode that's a sweep every 5 seconds, so they piled up until macOS ran out of capture descriptors. The scan now uses a bounded read that always releases the handle, so nothing accumulates.

Presence recording also rewrote the whole store to disk (two fsyncs) once per device on every scan tick. That is an I/O storm that grows with your device count and with the store file itself, and it saturated the disk over time. Those writes are batched now, so a busy network no longer thrashes it.

Update: docker compose pull && docker compose up -d, new .deb, Windows zip, or the desktop update.

DeviceShelf 1.6.6 — Router brands, sharper identification, OpenAI-compatible AI Router integration now covers 17 brands, device identification leans on self-declared signals, the AI assistant works with any OpenAI-compatible endpoint, and settings survive a reinstall.

Four larger changes this time, plus the usual fixes.

Router host tables from any brand. When we added router integration it only spoke UniFi. As of 1.6.6, desktop and server read the client list from 17 router and controller families: FRITZ!Box and generic TR-064, UniFi, Netgear, Linksys, ASUS, TP-Link, D-Link, MikroTik, FortiGate, Omada, OPNsense, pfSense, Peplink, OpenWrt, Synology SRM, plus a generic SNMP fallback. The router already knows every device from its own DHCP/ARP table, so this surfaces hosts a local scan can't reach (other VLANs, sleeping devices) and fills in the names the router assigned. Settings has a brand picker (automatic detection, or pin a brand), and a Test button reports which one answered and how many devices it found. The mobile app gets the same picker next. UniFi is the brand we've verified against real hardware; the rest are built against each vendor's documented API and fail closed, so a mismatch returns nothing and never disturbs a scan.

Sharper device identification. Classification now prefers what a device says about itself (its mDNS, UPnP and SNMP signals) over guessing from a name. A local fingerprint database (Recog) matches offline, and a batch of misreads is gone: a Mac advertising AirPlay is a computer, not a speaker; docks, NAS boxes and mesh nodes get the right label; an unknown device at least shows its manufacturer. Vendor names now also resolve for IEEE's smaller MA-M and MA-S address blocks.

An OpenAI-compatible AI provider. The AI assistant can point at any OpenAI-style endpoint: a local vLLM or LM Studio, or a private gateway. Local endpoints skip the cloud-consent prompt, since nothing leaves your network.

Settings survive a reinstall. Your configuration is mirrored out-of-band, so wiping the config folder or reinstalling no longer starts you from scratch.

Also in this release: the server's email-alert section got a Test button with an inline SMTP result, the settings save bar confirms "Saved ✓" reliably again, and a note spells out that one scan run's alerts arrive as a single bundled email. The scan dialog remembers your interface selection without a scan first, and the language catalogs are complete again.

Fingerbank note for existing users: automatic lookups are now opt-in. If you already use Fingerbank with the passive DHCP listener, tick the new automatic-lookup box once. Until you do, DeviceShelf no longer sends fingerprints on its own.

Update: docker compose pull && docker compose up -d, new .deb, Windows zip, or the desktop update. Details in the server guide.

DeviceShelf 1.6.5 — Diagnostics you can actually read The diagnostics tools and device probes stopped dumping raw JSON and now show plain readable results.

A small papercut, gone. The Network diagnostics (ping, traceroute, DNS, speed test) and the device-probe drawer used to print the raw API response as JSON. Now they read like results: the speed test shows ↓ 18.1 Mbit/s · ↑ 71.6 Mbit/s · latency 179 ms · jitter 88 ms, ping shows replies, loss and min/avg/max, traceroute lists numbered hops, and the SSH-key, SMB, traffic, HTTP and credential probes each get a readable line. Anything the UI doesn't recognize still falls back to formatted JSON, so nothing ever renders blank.

Update: docker compose pull && docker compose up -d, new .deb, Windows zip, or the desktop update.

DeviceShelf 1.6.4 — One device, one SLA row A device could appear several times in the SLA report with misleading uptime numbers. Fixed, and existing data merges itself on the first start after the update.

If your SLA report showed the same device three or four times — one row near 100%, the others near 0% and dragging the overall number into the basement — this one is for you.

The cause was subtle: our discovery paths wrote the same MAC address in different formats. ARP and SNMP produced lower-case, DHCP fingerprinting upper-case, and each spelling became its own device identity with its own availability ledger. The phantom identities then collected an offline sample on every scan they weren't "seen" by, which is where the near-0% rows came from.

As of 1.6.4 every path writes one canonical format, the store normalizes anything that reaches it, and a one-time migration merges the fragmented history you already have: availability ledgers are summed day by day, names and metadata are kept. No manual cleanup needed; the report is correct again after the first start.

Update: docker compose pull && docker compose up -d, new .deb, Windows zip, or the desktop update. Details in the server guide.

DeviceShelf 1.6.3 — Dashboard rework, metric history and a disk-full forecast The server dashboard drops from ten tabs to six, settings get grouped sections with direct links, infrastructure metrics keep a week of history, and disks warn before they run full.

We put the server dashboard through a proper usability review and rebuilt what it flagged.

Navigation. Six tabs instead of ten: Topology, Diagnostics and Bandwidth now live inside one Network view, Syslog joined Infrastructure, and the AI assistant became a drawer you can open from any view instead of a mostly empty page of its own.

Settings. One long scroll became five grouped sections (General, Scanning & discovery, Alerts & notifications, Checks & monitors, Status page) with a sticky section nav. Every section is directly linkable, and the empty states across the app now use those links: instead of "Docker monitoring is off, the socket is not mounted, or there are no containers" the page tells you the one cause that actually applies and where to fix it.

Fewer traps. Threshold fields show a live interpretation ("→ alert off", "→ default: 90%", "→ inherits the host threshold") while you type. A clean security report shows a check mark instead of a green "0 /100". The bandwidth view no longer offers a Start button in builds without packet capture. And the phone layout works now; before, tapping a right-hand tab could pan the whole page into the void.

New since yesterday's 1.6.0. Infrastructure metrics (host CPU/RAM/disk/temperature, Proxmox nodes) keep about seven days of history, drawn as sparklines with a 24h/7d switch. On top of the disk history sits a disk-full forecast: a trend line that warns when a volume is projected to be full within your horizon (default 14 days, individually switchable like every other alert). It stays quiet on flat or jittery data.

Also in this release: a hard timeout on macOS Keychain calls so a blocked authorization prompt can never stall the server.

Update: docker compose pull && docker compose up -d, new .deb, or re-run the Windows installer. Details in the server guide.

DeviceShelf 1.6.2 — Windows installer picks the Npcap build by itself Run install.exe with Npcap present and the server comes up with live bandwidth and active ARP, no manual service surgery.

Third and last cut of the day. 1.6.1 added the optional deviceshelf-server-pcap.exe to the Windows zip, but you still had to swap the service binary yourself — nobody should have to. Now install.exe checks whether Npcap is installed and, if so, installs the packet-capture build automatically. Re-running the installer over an existing setup is enough; it doubles as the updater.

No Npcap? The installer keeps the standard build, which runs everywhere. The bandwidth card in the dashboard now spells out the Windows path too.

Update: re-download the Windows zip and run install.exe again. Docker and .deb are unaffected.

DeviceShelf 1.6.1 — Server version fix for Windows and .deb The Windows and .deb server builds reported no version and never offered updates. Fixed, and the Windows zip gains an optional Npcap build with live bandwidth.

Quick patch on top of today's 1.6.0. The Windows and .deb server builds shipped without a stamped version number, so the dashboard header showed none and the update check never considered anything newer. Docker was not affected. Both builds now carry their version again.

The Windows zip also gains a second binary: deviceshelf-server-pcap.exe. If you have Npcap installed, run that one instead of the default and you get live per-device bandwidth and active ARP scanning on Windows too. Without Npcap it won't start; the default deviceshelf-server.exe keeps working everywhere.

Update: re-download the Windows zip or install the new .deb; Docker users can skip this one.

DeviceShelf 1.6.0 — Containers, hypervisors, databases and NAS health The server now watches Docker containers, Proxmox nodes and guests, database services, NAS disk/RAID health and hardware temperatures. Every alert is switchable on its own.

The server edition gets a new Infrastructure tab and watches a lot more than devices now.

  • Docker containers. Mount the socket read-only (or set DEVICESHELF_DOCKER) and you get alerts when a running container goes down, gets stuck restarting, or its healthcheck fails. A container that was already stopped when the server started never alerts.
  • Proxmox VE. Nodes and guests, via a read-only API token (PVEAuditor role). Alerts when a node goes offline, a running VM or LXC stops, or node CPU/RAM load climbs too high.
  • NAS health. On Synology, QNAP and TrueNAS the SNMP sweep now reads the vendor's disk, RAID and pool status. A volume can be half empty and still dying; this catches the dying part.
  • Temperature and fans. Hardware sensors over SNMP (ENTITY-SENSOR and LM-SENSORS), with a temperature alert at a configurable limit.

Checks got four new types: MySQL/MariaDB, PostgreSQL, SQL Server and Redis. Each one speaks the database's own wire protocol, so an open port is not enough to pass; only a real database answer counts. And since the probe needs no credentials, none are stored. The desktop can author these checks too.

Thresholds are now switchable one by one: type 0 to turn a single alert off, leave the field empty for the default. Proxmox node limits can inherit the host limits or differ from them.

For Grafana users, /metrics gained gauges for all of it, including deviceshelf_docker_api_up and deviceshelf_pve_api_up so you can tell a live reading from a stale one during an API outage.

Update: docker compose pull && docker compose up -d, or apt install ./deviceshelf-server_1.6.0_*.deb. Details in the server guide.

DeviceShelf 1.5.15 — New icon, and a real Windows server installer A refreshed icon across platforms, a status-flicker fix, persisted scan settings, and a proper install.exe for the server.

New app icon across macOS, Windows and Linux. We also fixed a status flicker where a device would bounce between "Active" and idle in the middle of a scan, and your scan depth and the UDP-service toggle now survive a restart.

On the server side, the Windows edition ships a real install.exe and uninstall.exe instead of the batch files Windows liked to block — double-click, confirm the prompt, done. And you can read the dashboard token on any platform, Windows, Docker or the .deb, with deviceshelf-server -token.

DeviceShelf 1.5.14 — English UI and router-based topology English is now the primary interface language, and topology can come straight from your UniFi or router controller.

Two bigger changes. The interface is now English-first across desktop, server and mobile — the other languages are still there, English is just the source they're built from now.

And topology no longer leans on SNMP or LLDP guesswork. Point DeviceShelf at your UniFi or router controller and it reads which device sits on which access point or switch port directly from the controller. A Test button confirms the connection before you rely on it.

DeviceShelf 1.5.13 — Fewer, better alerts on the server Alert-flood control for the server edition, more parity with the desktop, and finer scan preferences.

The 24/7 server edition can flood you when a lot changes at once. This release adds the brakes: low-priority events batch into a digest instead of arriving one by one, alerts route by severity so the urgent ones stand out, and a brief flap no longer pages you offline-then-online a second later.

Alongside that, more of the desktop's features made it into the server, and the desktop's scan settings gained finer control over how deep a scan goes.

DeviceShelf 1.5.12 — Pair your phone by QR Connect the mobile app to a desktop or server by scanning a code — no URL, no token to type.

Adding a computer or server to the mobile app used to mean copying its address and access token onto your phone by hand. Now the desktop and server show a QR code: scan it in the app and you're connected.

Same security: the token still authenticates the connection, you just don't type it in.

DeviceShelf 1.5.11 — Settings that stick Settings now save as you type, and the Fingerbank key gets a Test button.

A round of persistence fixes. If you typed an API key or changed a field and then switched tabs before it lost focus, the change could be dropped. Settings now save as you type, so nothing gets lost on the way out.

While we were in there, the Fingerbank key got a Test button — check it works right where you paste it, instead of finding out later that device fingerprinting was quietly off.

DeviceShelf 1.5.10 — Azure OpenAI as an AI provider Azure OpenAI (Microsoft) is now a selectable AI provider, in desktop, server and mobile.

The AI advisor has always been bring-your-own-key: local, optional, off by default, with Anthropic, OpenAI, OpenRouter, Mistral, Groq, Gemini, or local Ollama. New on the list: Azure OpenAI (Microsoft). Enter your Azure resource endpoint, the deployment name, and your Azure key. It's in desktop, server, and mobile.

One caveat: this is Azure OpenAI, not the M365 Copilot license. The Copilot surface in Word or Teams isn't a callable API; what you can wire in is your company's Azure OpenAI access.

DeviceShelf 1.5.9 — real device names in alerts, a clearer uptime report, and unified server management A batch of fixes from user reports across all three apps: notifications and Live Bandwidth show real device names instead of bare IPs/MACs, traceroute is fixed on networks that blocked it, the server's uptime report gets headers and a downtime duration, and the mobile app's server list is unified into one screen.

A larger batch this time, all from user reports. Desktop, server and mobile all get real changes.

Desktop

  • Online/offline alerts show the real device name. A device coming back online or dropping offline could show its bare IP ("Back online: 192.168.1.197") or even its raw MAC address in the notification, which isn't something you can act on. The name lookup now falls back through the same chain the device list already uses: known name, then the manufacturer looked up from the MAC (available as soon as the device is seen at all), and only as a last resort the address itself.
  • Live Bandwidth stopped flickering. Near-idle devices' throughput is mostly measurement noise, so the list re-sorted itself on almost every update. A bar would flash on for one tick and vanish the next. Rows now sort by cumulative traffic instead of the instantaneous rate, and each device's numbers are smoothed before they're drawn. Devices with no resolved hostname also show their manufacturer now, not a bare IP repeated twice.
  • Traceroute works on networks that silently blocked it. The classic UDP-based probing mode is dropped outright by many firewalls, VPNs and NATs — every hop timed out with 100% loss even on a perfectly fine connection. Traceroute now uses the same ICMP echo probes as a plain ping, which get through where the old mode didn't.
  • Ping, DNS lookup and traceroute now come pre-filled with a working target (1.1.1.1 / google.com), so you can check basic connectivity with one click.
  • The DHCP-fingerprinting hint no longer contradicts itself. The "needs admin rights" warning used to stay visible even after the feature was successfully turned on and running.
  • Two settings-only bugs are fixed too: a pre-existing install's port scanning could silently stay off after an upgrade, with no visible cause. And identity resolution (hostname/vendor) could wipe a device's already-known open ports, and with them the quick-connect SSH/VNC/RDP buttons, whenever that pass didn't also happen to run a fresh port scan.

Server

  • The SLA/uptime report finally explains itself. The devices/checks tables had no column headers at all: three columns of bare numbers, nothing labeling what they meant. There's now a proper header row with hover explanations for each column.
  • The percentage now comes with a concrete duration. "94.6%" forces you to do the math yourself; each row now also shows an approximate downtime ("~1h 20m down") right next to the color-coded percentage.
  • Device rows show the manufacturer, not just the IP, when no hostname is known. It's the same fallback the desktop app already uses.
  • The daily-availability heatmap no longer collapses into one meaningless solid-color block when the report's time window is set to 24h; it always shows enough days to be readable.

Mobile

"Remote servers" (a saved list, read-only view) and "Sync" (LAN discovery, a single shared access code) used to overlap without talking to each other. Both are now one screen. Every DeviceShelf server or desktop you connect to is a saved entry with its own name, address and access code; LAN discovery adds new ones to that same list instead of running a separate flow. For each saved server you can open its own read-only view, or pull its full device list (MAC, manufacturer) into your local scan. This also fixes a real limitation: with two servers on the network, there used to be no way to give each one its own access code.

DeviceShelf 1.5.8 — stable device names and a Wake-on-LAN fix Two desktop fixes: device names no longer flicker back to bare IP addresses while background monitoring runs, and Wake-on-LAN works on machines with more than one active network interface. Desktop only.

Two fixes in the desktop app, both from user reports.

  • Device names stay put during auto-scan. With background monitoring on, the device list kept snapping back to bare IP addresses, especially in live mode with its sweeps every 5 seconds or so. Hostname, MAC, vendor, OS: all gone until enrichment caught up again. The cause: each sweep first checks only who is reachable and reports devices with no identity at all. That bare result overwrote the known one. As of 1.5.8, a resolved identity survives scan ticks and is only ever replaced by a newer resolved value, never by a blank. This holds in the device list as well as in exports and the remote API. Measurements like online state and ping still update on every tick. And if an IP gets reassigned to a different device, DeviceShelf drops the old identity instead of carrying it over.
  • Wake-on-LAN works with more than one network interface. The magic packet used to leave through a socket without broadcast permission. The system may reject that outright, and on machines with several active interfaces (Wi-Fi plus VM bridges, say) the packet could also go out the wrong one. It is now sent as a directed broadcast on every active interface, so the target device gets it no matter which network it sits on. When the send fails, the app shows a proper translated message instead of a raw network error.

The server edition gets 1.5.8 only to keep the version numbers in step; nothing changes on the server. Settings, data and monitors are preserved.

DeviceShelf 1.5.7 — device list and scan range cleanup Three fixes from user feedback: a hint when a filter hides every device; the top-bar scope now follows the range dialog; and an implausible From/To range asks before scanning. Desktop only.

A small follow-up to 1.5.6. All three came from user feedback.

  • A filter that hides everything now says so. The device list used to show a blank table when a search term or the favorites star filtered out every found device — which read as "the scan found nothing", even though the counters up top still reported all devices. Now there's a hint ("‘ei’ hides all 32 devices") with a button that clears the search and the favorites filter.
  • The scope display follows the dialog. The range shown top-left only reflected the last scan and changed only on the next one. Pick a different interface in the range dialog, or type a different From/To, and the header now moves with it immediately. Cancel, and it reverts to the real network.
  • A warning before an implausible range. A From/To spanning two networks (say 192.168.1.1 to 10.37.129.254), a reversed one, or a very large one used to silently trigger a slow scan across the wrong subnet — up to 65534 addresses. Now a dialog asks first; a normal in-subnet range still scans without a prompt.

The server edition gets 1.5.7 only to keep the version numbers in step; nothing changes on the server. Settings, data and monitors are preserved.

DeviceShelf 1.5.6 — clearer notifications Collapsed alert rows now list the individual events with timestamps instead of a confusing “flapped N×” counter; the device-list SSID column is gone. Driven by user feedback.

A small update on top of 1.5.5, driven by user feedback.

  • Clearer collapsed alerts. Multiple alerts for the same device within 10 minutes are still merged into one row — but the badge now reads “N alerts” instead of “flapped N×” (which read like the IP had changed), and the row lists every merged event with its time and detail: offline/back online, port opened/closed, IP changed. You can see exactly what happened without opening the details.
  • SSID column removed. The optional device-list column could only ever show the scanning host’s own Wi-Fi (identical in every row) — a LAN scan cannot determine which SSID a remote device is connected to. That came across as “the column shows nothing”. Your own Wi-Fi name remains in the top bar and the Network view.

The server edition gets 1.5.6 as a pure version-lockstep rebuild with no functional changes. Settings, data and monitors are preserved.

DeviceShelf 1.5.5 — richer MCP tool schemas, more hardening MCP tools now declare output schemas, titles and per-field descriptions for clearer AI-client results, plus follow-up security hardening from the 1.5.4 review. Additive, no behaviour changes.

A small additive follow-up to 1.5.4.

  • Richer MCP tool schemas. Every MCP tool now declares an output schema, a human-readable title and per-field descriptions. AI clients (Claude, Cursor, VS Code and the rest) can show clearer, structured results and pick the right tool without guessing. Purely additive — existing connections keep working unchanged.
  • More hardening. A follow-up pass closing review gaps from the 1.5.4 security sweep — API auth, notifications and the mobile export path.

No behaviour changes. Settings, data and monitors carry over.

DeviceShelf 1.5.4 — security & robustness hardening A 27-fix security and robustness pass — stricter API auth (deny-by-default, brute-force backoff, role-spoof guard, request timeouts), redacted notifications, and hardening across scanning, storage, syslog and mobile. No behaviour changes.

1.5.4 is a focused security and robustness pass — 27 fixes, no new features and no behaviour changes.

API & auth (server edition)

  • Deny-by-default. The token guard now uses an allowlist: only the static dashboard shell is public; /api/*, /metrics and /mcp all require a token. (The previous blocklist had to enumerate private paths and once nearly served /mcp unauthenticated.)
  • Brute-force backoff. After repeated failed auth attempts from one IP, further requests get a 429 for a short cool-off, so a bearer token can't be guessed online.
  • Role-spoof guard. The X-DS-Role header is stripped from incoming requests and only ever set by the guard, so a client can't claim admin to downstream handlers.
  • Request timeouts. Read/header/idle timeouts protect against slow-loris-style connection holding (the SSE dashboard feed is exempt).
  • Weak-token warning at startup if the API token is shorter than 24 characters.

Everything else

  • Notifications redact secrets from payloads, and the send path is more defensive.
  • Hardening across the scanner (ping, UPnP), store, syslog receiver and SNMP discovery, plus a safe-goroutine wrapper so a background panic can't take the server down.
  • Mobile: safer desktop-sync parsing and export.

Recommended update. Settings, data and monitors carry over untouched.

DeviceShelf 1.5.3 — the MCP server ships The server edition now ships the MCP server: read-only, strictly local access to your live inventory and monitoring for AI assistants over the Model Context Protocol. Copy-paste setup for Claude, Cursor, VS Code, Windsurf, Cline and Gemini CLI.

The Model Context Protocol server we previewed is now shipping in the server edition.

  • What it is. Set DEVICESHELF_MCP_ENABLE=true and an AI assistant can query your live network in plain language: "what's online?", "which certificates expire soon?", "what's vulnerable?", all answered from your own data. 14 read-only tools (inventory, monitoring, a one-call security overview) plus guided prompts.
  • Strictly local, read-only. The endpoint runs inside your server, behind the same bearer token, reachable only on your LAN. No cloud connector. Write actions (rename, acknowledge, scan) stay off unless you set DEVICESHELF_MCP_ALLOW_ACTIONS, and device-reported strings are treated as untrusted.
  • Connect any agent. Copy-paste setup for Claude Code, Claude Desktop, Cursor, VS Code (Copilot), Windsurf, Cline and Gemini CLI is on the server page. Most connect over Streamable HTTP natively; ChatGPT needs a public HTTPS tunnel because it runs in the cloud.
  • Licensing. Bundled with any paid license and usable during the 7-day trial.

The desktop app is unchanged from 1.5.2.

DeviceShelf 1.5.2 — server version badge, clearer e-mail setup A small server-focused update. The dashboard shows the running version, e-mail/SMTP setup is clearer, and desktop backend messages are now localized in all seven languages.

A small, backward-compatible follow-up to 1.5.1:

  • Server: the dashboard header now shows the running version (plus a public /api/version endpoint).
  • Server: e-mail/SMTP alert setup is clearer. Common providers (Gmail, Yahoo, Outlook, iCloud …) are auto-detected, and a new help section explains the required app password.
  • Desktop: all backend status and error messages are now localized across the seven supported languages.

Monitors, settings and data carry over unchanged.

DeviceShelf 1.5.1 — push/heartbeat monitors, HTTP keyword checks, read-only access, uptime bars 1.5.1 extends the server edition with push/heartbeat monitors, HTTP keyword and status assertions, per-check retries, a read-only access token, daily uptime bars and JSON config backup. Desktop adds custom device types with auto-detection and a new icon set. Backward-compatible.

1.5.1 builds on the 1.5 monitoring foundation, mostly on the headless server edition, and brings the desktop's device handling up a level.

Server edition

  • Push / heartbeat monitors. A new check type for jobs that should "call home": a cron job, backup or script POSTs to a private /api/push/<token> URL on its schedule. If a heartbeat doesn't arrive within the window you set, the monitor goes down and alerts. Good for things a port check can't see.
  • HTTP keyword and status assertions. HTTP checks can now require an exact status code (e.g. 200, or 401 for an auth-gated endpoint) and assert that the response body contains — or does not contain — a given string. A page that loads fast but shows an error no longer counts as up.
  • Retries before alarm. Each check can require N consecutive failures before it raises an alarm, so a single blip doesn't page you.
  • Read-only access token. Set a second, read-only token (DEVICESHELF_API_VIEWER_TOKEN) to hand out view-only access, either over the API (GET only) or as a read-only dashboard. Every change still needs the full token.
  • Daily availability bars. The reports view now shows a per-day uptime bar for every device and check, alongside the SLA percentages.
  • Configuration backup. Export your settings and monitors as a JSON file (no passwords or tokens) and restore them on the same or another server.
  • REST API documentation. The full server API is now documented, including the new endpoints.

Desktop

  • Custom device types with auto-detection for switches, access points and firewalls, a searchable type picker, a refreshed colorful icon set, and a per-row note tooltip on hover.

Fixes

  • Removed the colored left-edge accent on dashboard cards (cosmetic).
  • The server timeline now labels monitor-check events properly instead of showing a raw key.

Compatibility

Backward-compatible; no breaking changes. Existing configuration and data are kept. The new check options and the read-only token are opt-in, so updating raises no new notifications by itself.

DeviceShelf 1.5 — threshold monitoring, dependencies, alarm lifecycle, server connection 1.5 adds threshold-based checks (ping, TCP, HTTP/JSON, SNMP), dependency-based alarm suppression, an alarm lifecycle (acknowledge, maintenance windows, quiet hours), and desktop-to-server connections. Backward-compatible.

DeviceShelf 1.5 adds monitoring beyond plain reachability. Changes:

New in 1.5

  • Threshold-based checks. Define checks per device with warning and error thresholds. Supported types: ping latency, TCP port reachability, HTTP/HTTPS status (optionally comparing a value extracted from a JSON response via a dot path), and SNMP values.
  • Dependencies. A check can depend on a parent device (e.g. a switch or gateway). When the parent is down, alarms for the dependent checks are suppressed, so an upstream outage produces one alarm instead of one per downstream device.
  • Alarm lifecycle.
  • Acknowledge: mark a known alarm as seen so it stops re-notifying.
  • Maintenance windows: scheduled time ranges in which checks do not raise alarms.
  • Quiet hours: recurring time ranges in which no push notifications are sent.
  • Desktop-to-server connection. The desktop app can connect to one or more headless DeviceShelf servers and read their inventory, subnet, online status, timeline and alarms, and acknowledge alarms remotely.

Compatibility

Backward-compatible; no breaking changes. Existing configuration and data are kept. Checks are opt-in (you create them), so updating raises no new notifications by itself.

DeviceShelf 1.4.2 — Fingerbank device ID, richer alerts & an update notice 1.4.2 adds Fingerbank-powered device identification, far more detailed alerts (IP, vendor, type, OS, ports), and an opt-in update notice, plus everything from 1.4.1 (offline devices, dashboard polish, desktop SSH).

A focused follow-up to the big 1.4.0 release: sharper identification, clearer alerts, and a friendlier update path.

✨ New in 1.4.2

  • Fingerbank device identification. Devices are now identified by their DHCP fingerprint via Fingerbank. That means better guesses for vendor, type and OS, especially on IoT gear.
  • Richer alerts. Alert messages now spell it all out: IP, vendor, device type, OS, open ports and the Fingerbank match. A notification tells you what happened without opening the app.
  • Opt-in update notice. A "check now" button (and an optional on-launch check) lets you know when a new version is out. It never auto-installs — you stay in control.

Also since 1.4.0 (shipped in 1.4.1)

  • Offline devices stay visible in the list instead of disappearing.
  • Dashboard polish: auto-save, a favicon, a clearer WAN explanation, and a live-status fix.
  • Desktop: SSH login and scan-range fixes.

🖥 Server edition (beta)

The 1.4.2 server adds the same passive DHCP fingerprinting (it listens on UDP port 67). Because the container deliberately runs as a non-root user, binding that low port needs one tightly-scoped capability: NET_BIND_SERVICE (no root, no NET_ADMIN, just opening low ports). Without it the server still runs fine, only DHCP/Fingerbank identification is skipped.

Update your compose with --cap-add NET_BIND_SERVICE and pull :1.4.2. Full steps in the server install guide. It's a beta — bug reports & feature requests very welcome.

Get it

Update from inside the app (or hit check for updates), or grab 1.4.2 from deviceshelf.app. As always: local-first, no telemetry, no account.

DeviceShelf 1.4.0 — live monitoring, notifications & a server beta A big release: a notification center, auto/live scan, a smarter device table, in-app rollback, a Windows Npcap prompt, and a pile of fixes. Plus the first beta of the headless 24/7 server edition.

1.4.0 is a big one. Here's everything that's new and fixed, plus the first public beta of the server edition.

✨ New

  • Notification center. A bell in the toolbar collects what changed while you were looking elsewhere: devices arriving and leaving, ports opening, alerts firing.
  • Auto / live scan. Turn it on and DeviceShelf watches your network continuously, refreshing every few seconds instead of waiting for a manual scan.
  • Smarter device table. Sort by any column, connect over RDP in one click, and use per-port gating so a scan does exactly what you want.
  • In-app rollback. Need the previous build? Roll back to an earlier version right from inside the app.
  • Windows Npcap prompt. The Windows installer now tells you when Npcap is needed (for live per-device bandwidth) and links you straight to it.
  • Local-API token UX. Setting up and using the local-API token is simpler and clearer.

🐛 Fixed

  • Fingerbank rate-limit handling. Device-identification lookups no longer trip the provider's rate limit.
  • Scan range / CIDR / save fixes. Custom ranges and CIDR inputs parse correctly, and saving is reliable.

🖥 The server edition enters beta

The headless 24/7 server edition ships for the first time in 1.4.0: continuous, GUI-less monitoring you run in Docker (or install the .deb, now built in CI) on a Linux box or VM. It's covered by your existing license. Same key, no extra cost.

This is a beta. Expect a few rough edges. If you hit a bug or have a feature request, please tell us — your feedback decides where it goes next. Subscribe below to follow along.

Get it

Update from inside the app, or grab 1.4.0 from deviceshelf.app. As always: local-first, no telemetry, no account.

Network tips and product updates

The occasional guide, new features and release news, straight to your inbox. No spam, unsubscribe anytime.