Always-on-top desktop widget for Windows 10/11: connection status, ping, jitter/loss, adapter traffic, and on-demand speedtest via the Ookla CLI.
- Live metrics — ping to 1.1.1.1 (and to the default gateway when it answers ICMP), jitter and packet loss over a 30 s sliding window, adapter up/down traffic.
- Status at a glance — online / degraded / local-only / offline, shown as a colored dot on the widget and on the tray icon.
- Speedtest — manual (button or tray menu) and automatic when the connection degrades (with a 30-minute cooldown). Powered by the Ookla CLI.
- Three window modes — Compact strip, Expanded panel, and Locked (click-through: the widget ignores the mouse; unlock via the tray icon).
- Quality of life — drag to move (position is remembered), auto-hide while a fullscreen app is active, optional run at startup, VPN-friendly (hides the gateway row when a VPN owns the default route).
- Windows 10/11
- .NET 10 SDK to build
(
winget install Microsoft.DotNet.SDK.10) - Ookla Speedtest CLI for speed
measurements (
winget install Ookla.Speedtest.CLI) — the widget works without it, only the speedtest feature needs it
dotnet run
Release single-file exe (output in publish\NetOverlay.exe):
build.cmd
- Drag the widget to move it; click it to toggle Compact/Expanded.
- Tray menu: switch mode (Compact / Expanded / Locked), run speedtest, toggle "Run at startup", exit.
- Locked mode makes the widget click-through; left-click the tray icon (or use the tray menu) to unlock.
- The widget hides automatically while a fullscreen app is active.
If you run a default-deny firewall such as simplewall:
- Ping/status keeps working regardless — the widget sends ICMP through the Windows IP Helper API, which app-level firewalls do not filter.
- Speedtest needs an allow rule for
speedtest.exe(the widget launches it as a child process, so a rule for NetOverlay alone is not enough). The winget install path is%LOCALAPPDATA%\Microsoft\WinGet\Packages\Ookla.Speedtest.CLI_Microsoft.Winget.Source_8wekyb3d8bbwe\speedtest.exe. - Add
NetOverlay.exeitself too if you want to be explicit; a silent block shows up as "speedtest failed (blocked by firewall?)" in the widget.
%APPDATA%\NetOverlay\settings.json (created on first change; edit while the
widget is closed):
| Key | Default | Meaning |
|---|---|---|
InternetHost |
1.1.1.1 |
Ping target |
PingIntervalMs |
1500 |
Ping period |
PingDegradedMs |
250 |
Avg ping above this → degraded |
LossDegradedPercent |
5 |
Loss above this → degraded |
WindowSeconds |
30 |
Sliding window for jitter/loss and gateway-alive |
SpeedtestPath |
speedtest |
Absolute path wins; otherwise winget path, then PATH |
AutoSpeedtestOnDegradation |
true |
Auto-measure when degraded |
DegradedTriggerSeconds |
15 |
How long degradation must last before an auto-measure |
AutoSpeedtestCooldownMinutes |
30 |
Min interval between auto-measures |
HideOnFullscreen |
true |
Hide while a fullscreen app is active |
Probes/— MetricsEngine (ping/jitter/loss/traffic loop), SpeedtestRunner (Ookla CLI wrapper). No UI dependencies.ViewModels/— OverlayViewModel (MVVM), modes, auto-speedtest logic.Views/— OverlayWindow: frameless topmost window, drag/click, click-through.Services/— settings persistence, Win32 interop (click-through, fullscreen detection via SHQueryUserNotificationState).
MIT © Ivan Larin
