A terminal dashboard that tracks ICMP latency, jitter and packet loss for many targets at once β a single executable with its target list built in.
Inspired by upa/deadman.
- Responsive TUI (Bubble Tea + Lipgloss) β columns adapt to the terminal width, CJK-aware, never overflow
- Socket-reuse ping engine (
pro-bing, infinite-send mode) β every probe tracked by sequence number - Metrics β loss %, last RTT, moving-average RTT, jitter, settled probe count, sparkline history
- Fallback to the OS
pingcommand when raw ICMP is unavailable - DNS resolution β give a hostname, an IP, or a display name plus
host; hostnames prefer IPv4 - 22 embedded presets (DNS, cloud, CDN, backbone, gaming, streaming, β¦) chosen at runtime (
-preset), or an external-configfile - Redraws only when data changes (max 20 fps)
Grab a zip from Releases:
| Asset | Platform |
|---|---|
go-deadman-windows-amd64.zip |
Windows x64 |
go-deadman-darwin-arm64.zip |
macOS Apple Silicon (M-series, MacBook Neo) |
Each binary contains every preset β pick one with -preset.
On macOS the binary is ad-hoc signed but not notarized, so Gatekeeper blocks it after a browser download. Clear the quarantine flag once:
xattr -d com.apple.quarantine ./go-deadman
./go-deadmanEach release ships SHA256SUMS.txt, and every binary has a GitHub build-provenance attestation, so you can prove it was built by this repository's CI from a specific commit:
gh attestation verify go-deadman.exe --repo sinnoken/go-deadmango-deadman # embedded "internet" preset
go-deadman -preset tasks # another embedded preset
go-deadman -list-presets # name, target count, description
go-deadman -config my.yaml # an external config instead
go-deadman -versionWithout -preset, a binary renamed to go-deadman-<preset> (e.g. go-deadman-tasks.exe) starts with that preset, which is handy for double-clicking on Windows.
| Key | Action |
|---|---|
β β / k j |
Scroll one row |
PgUp PgDn / b f / Space |
Scroll one page |
Home End / g G |
Jump to top / bottom |
q / Ctrl+C |
Quit (stops all probes and ping child processes) |
The list scrolls when it is taller than the terminal; the footer then shows Rows a-b/n. Targets whose hostname fails to resolve show DNS RESOLVE FAILED, retrying and are retried with backoff (5 s doubling to 60 s), so they start pinging on their own once DNS works.
| OS | Native mode needs |
|---|---|
| Windows | Nothing extra for IPv4 (uses the IcmpSendEcho API, timed with QueryPerformanceCounter); IPv6 targets need Administrator |
| Linux | Unprivileged ICMP (net.ipv4.ping_group_range), enabled on most distros |
| macOS | Nothing extra |
Without it, each target falls back to the OS ping command automatically. Native targets are marked with * after SNT.
Every binary embeds all of these. internet is the default overview and tasks is a template for your own LAN; the rest are themed lists of at most 16 targets.
| Preset | Monitors | Targets |
|---|---|---|
internet |
Overview: backbone, cloud, IX, DNS and Taiwan ISPs (default) | 31 |
tasks |
LAN template: public DNS, home gateway and 192.168.77.x hosts | 28 |
asia-pacific |
Major Asia-Pacific carriers (their public DNS / core hosts) | 11 |
backbone |
Tier-1 and major international backbone carriers | 11 |
cdn |
CDN providers (nearest edge as resolved from your network) | 12 |
china |
Mainland China carriers, DNS and major sites | 12 |
cloud |
Public cloud entry points and Asia-Pacific regions | 10 |
continents |
Latency map across continents (Vultr ping endpoints) | 16 |
dev |
Developer services and package registries | 16 |
dns |
Public recursive DNS resolvers | 16 |
gaming |
Game platforms and stores | 12 |
ipv6 |
IPv6 reachability (on Windows these need Administrator for native mode) | 9 |
ix |
Internet exchange operators (their web front-ends, not peering LANs) | 11 |
ntp |
Public NTP time servers | 9 |
root-dns |
DNS root servers a-m (g-root drops ICMP) | 12 |
saas |
Office SaaS and AI services | 14 |
social |
Social networks and messaging | 15 |
streaming |
Video and music streaming services | 11 |
taiwan |
Taiwan ISPs (their public DNS servers) | 9 |
taiwan-infra |
Taiwan Internet infrastructure and public services | 9 |
tld-dns |
Authoritative name servers of major TLDs | 16 |
transpacific |
Trans-Pacific path: East Asia, Pacific and US West (Vultr ping endpoints) | 9 |
Choose one in any of three ways:
go-deadman -preset dns # flag
go-deadman-gaming.exe # binary renamed to go-deadman-<preset> (used when -preset is absent)
go-deadman -list-presets # see what is available$ go-deadman -list-presets
asia-pacific 12 Major Asia-Pacific carriers (their public DNS / core hosts)
backbone 11 Tier-1 and major international backbone carriers
cdn 12 CDN providers (nearest edge as resolved from your network)
...
transpacific 9 Trans-Pacific path: East Asia, Pacific and US West (Vultr ping endpoints)
What these numbers mean. A reply to ICMP echo shows the network path to that address is up; it does not prove the service behind it works. Many service targets (some SaaS, game and streaming entries in particular) resolve to a CDN edge near you, so you are measuring that edge, not the origin. Services that block or rate-limit ICMP were left out. Every target was checked from Taiwan (each YAML records the date); results from other networks may differ.
Presets live in presets/ and share one schema:
description: "My targets" # optional, shown by -list-presets
interval: 1s # probe interval, Go duration, >= 100ms (default 1s)
jitter: 0.1 # Β±10% random spacing in fallback mode, 0 < jitter < 1 (default 0.1)
devices:
- name: "Cloudflare"
ip: "1.1.1.1"
- name: "---" # separator row
- name: "nas.lan" # name only β IP resolved via DNS
- ip: "192.168.1.1" # IP only β name via reverse DNS
- name: "Steam store" # display name + hostname to resolve
host: "store.steampowered.com"A device needs at least one of name, ip or host; ip and host are mutually exclusive. When a hostname resolves to several addresses, the first IPv4 address is used, because Windows has a non-admin native path only for IPv4. To monitor IPv6, write the IPv6 address in ip (as the ipv6 preset does).
The file is validated at startup (interval, jitter range, each device has a name, host or valid IP). Invalid files exit with a message; unknown keys are ignored.
| Column | Meaning |
|---|---|
| LOSS | Lost Γ· SNT. Non-zero loss is never shown as 0% (<0.1%, one decimal below 10%), and is never rounded up to 100% |
| RTT | Most recent successful RTT; FAIL (row in red) when the latest probe failed |
| AVG | Mean of the last 50 successful RTTs |
| JIT | Mean absolute difference between RTTs of adjacent successful probes (last 50 pairs); a lost probe breaks the pair. Same rule in native and fallback mode |
| SNT | Settled probes (replied or timed out). Each sequence number counts once; replies arriving after the timeout are ignored |
| HISTORY | Newest on the left. Bar height is log-scaled RTT (β β 1 ms β¦ β β₯ ~190 ms); color is the absolute latency: green < 50 ms, yellow < 150 ms, red β₯ 150 ms. A full red block β is a lost probe |
Probe timeout is max(interval, 1s) in both modes. On narrow terminals columns drop in this order: HISTORY, SNT, JIT, AVG, ADDRESS, LOSS β HOSTNAME and RTT always stay.
Requires Go 1.25+.
go build -trimpath -ldflags="-s -w" -o go-deadman ./cmd/go-deadmanEvery presets/*.yaml is embedded; adding a file there adds a preset. Each needs a description:, and TestLoadConfigPresets rejects duplicate targets and themed presets with more than 16 targets.
Windows icon and version info (optional):
go install github.com/tc-hib/go-winres@v0.3.3
go-winres make --in winres/winres.json --out cmd/go-deadman/rsrc --product-version 1.2.3 --file-version 1.2.3| Path | Contents |
|---|---|
cmd/go-deadman/ |
Entry point: flags, config source, program start |
internal/monitor/ |
Config loading/validation, ping workers (probeTracker, Windows IcmpSendEcho, fallback), per-target statistics |
internal/tui/ |
Bubble Tea model, width-aware layout, scrolling, rendering |
presets/ |
Target lists (*.yaml), all embedded and selected at runtime |
winres/ |
Windows icon and version-info manifest |
go vet ./...
go test ./... # add -race where cgo is available
go test ./internal/monitor -run '^TestProbeTracker$' -count=1CI (.github/workflows/build.yml) runs a tidy check, gofmt, vet, race tests, a coverage gate (internal/monitor β₯ 80%), golangci-lint, govulncheck and gosec on every push and PR, plus go test on Windows and macOS runners. All actions are pinned to commit SHAs and tools to fixed versions (Dependabot proposes updates). Pushing a v* tag builds every platform, attests the binaries and publishes a release; the tag becomes the app version and the Windows file version.
The ping workers are unit-tested without network access: newEchoSession, runPing and the DNS lookups are package variables that tests replace with fakes.
