MeshMonitor

MeshMonitor · Releases

from GitHub · updated 2026-08-05

20 releases

  1. v4.14.1-rc1 # Pre-release 3 days ago · 2026-08-05 18:02 UTC

    MeshMonitor v4.14.1-rc1

    ⚠️ Pre-release. This is a release candidate for 4.14.1. It ships on the :dev Docker tag, not :latest. Run it if you want the fixes early and can tolerate rough edges; report anything you hit.

    Summary

    This candidate is mostly MeshCore work plus two map-interaction fixes. The headline feature is strict receive-only mode for MeshCore Companion sources — a per-source switch that holds every transmitting command, scheduler and automation while leaving receive, the packet log, the Analyzer Observer and local serial configuration fully working. Because MeshCore firmware has no radio-level transmit switch, this is enforced in software; link-layer acknowledgements and any advert schedule configured outside MeshMonitor are unaffected, and the UI says so plainly. The Analyzer Observer gained battery, uptime and noise-floor reporting, and it now hot-swaps its publisher when you import a signing key instead of demanding a source disable/re-enable cycle. On the permissions side, MeshCore contact positions now honor canViewOnMap, matching how Meshtastic nodes have always behaved — a migration backfills the flag so no existing user loses map access on upgrade. Two map fixes: clicking a marker now zooms in first only when the marker is genuinely crowded (isolated markers open their popup immediately at any zoom), and the threshold that governs it is configurable rather than hardcoded at z13. The zoom-to-fit button also stopped wearing a crosshair icon, which everyone reasonably read as "center on my GPS location."

    Features

    • MeshCore strict receive-only mode — per-source enforcement (#4550), UI (#4552), and Virtual Node gating plus docs (#4555). Closes #4547.
    • Analyzer Observer publishes battery, uptime and noise floor in its status payload (#4557). Closes #4556.

    Bug Fixes

    • MeshCore map positions now require canViewOnMap instead of only nodes:read, so a read-only user can see the contact list without learning where those nodes are (#4560). Closes #4559.
    • Marker clicks gate on density, not zoom alone — an isolated marker opens its popup on the first click at any zoom, and the crowding threshold is now a setting (#4563). Closes #4551.
    • Zoom-to-fit no longer uses the locate-me crosshair icon (#4564). Closes #4562.
    • MeshCore contact Last Heard updates on incoming direct messages (#4554). Closes #4553.
    • Analyzer Observer hot-swaps its publisher on a signing-key change — no more disable/re-enable dance after importing a key (#4544). Closes #4543.
    • DeviceMetadata arriving before MyNodeInfo is buffered rather than dropped (#4548).
    • Remote admin stops implying it knows a remote node's favorite/ignored state — the admin protocol has no readback for those flags, so the UI no longer pretends otherwise (#4542). Closes #4511.

    Documentation

    • Documented the new Map Click Zoom Gate setting and the MeshCore canViewOnMap change, including the upgrade backfill (#4565).
    • Site gallery: added Norway Østlandet Mesh (#4546). Closes #4545.

    Tests / CI

    • System tests moved off the v1 API root paths removed in 4.14 (#4565). The /api/v1/nodes-style root paths were deleted in 4.14 (#4117); because a 404 body isn't JSON, every assertion was dying inside jq with an opaque parse error. The same change corrects /api/upgrade/* from the transitional 410 to its post-removal 404. Nothing user-facing — but the suite is honest again.

    Translations

    • Weblate updates (#4541, #4252) — thank you to everyone translating.

    Upgrade Notes

    • Migration 135 backfills canViewOnMap on existing nodes grants for MeshCore sources that already had read access, so current users keep map visibility across the upgrade. New grants must set the flag explicitly.
    • Receive-only mode is per source and defaults to off. Nothing changes unless you turn it on.

    Thanks

    • @wilhel1812 for reporting the zoom-to-fit icon confusion in Discord (#45 …
  2. v4.14.0 # 4 days ago · 2026-08-03 18:26 UTC

    MeshMonitor v4.14.0

    The first stable release since v4.13.2 — the 4.13.3 release candidates were folded into this minor instead, because the work that landed is a minor's worth, not a patch's. The headline is the MeshCore Analyzer Observer: publish what your Companion hears to a regional analyzer without a second app fighting for the serial port, observation-only by design. Meshtastic and MeshCore sources now share one navigation system, which on phones means a bottom bar that scrolls sideways with readable labels instead of eleven crushed icons. Remote admin gained distinct ACK outcomes — rejected reads differently from timed out — plus opt-in auto-retry, and commands no longer die when the browser navigates away. MeshCore messages carry SNR and RSSI when heard directly, "Discover Nodes" now lists who answered with signal in both directions, and per-channel permissions finally do what they say. Node Details shows where a position came from and how precise it is, and Null Island estimates are no longer passed off as real fixes. The Packet Monitor's node filters became searchable comboboxes, which matters most on a phone and on a large mesh. Under the hood, the database driver moved to better-sqlite3 13 (N-API), verified at runtime on amd64, arm64 and armv7 before shipping.

    ⚠️ Breaking Change: v1 API root paths removed

    4.13 moved the v1 mesh-data endpoints under /api/v1/sources/{sourceId}/… and kept the old root paths alive for one release behind a Warning: 299 header. That grace period ends here — these paths now return 404:

    /api/v1/nodes      /api/v1/telemetry     /api/v1/network
    /api/v1/messages   /api/v1/traceroutes   /api/v1/status
    /api/v1/channels   /api/v1/packets       /api/v1/position-history
    

    Migrate by moving the source into the path:

    # Before (4.13, deprecated)
    curl -H "Authorization: Bearer mm_v1_…" "https://host/api/v1/nodes?sourceId=abc123"
    
    # After (4.14)
    curl -H "Authorization: Bearer mm_v1_…" "https://host/api/v1/sources/abc123/nodes"
    

    GET /api/v1/sources lists your source ids, or use the literal default to target the primary source. The /api/upgrade/* endpoints, returning 410 Gone since 4.13, are also removed.

    If you script against the REST API, check for these paths before upgrading. Everything else is drop-in; the database schema migrates automatically on first boot.

    Full details in the release announcement.

    Features

    • feat(analysis): show node names in the ok_to_mqtt violations report (#4343)
    • feat(i18n): localize the MapStyleManager settings component (#4363)
    • feat(meshcore): serve ExportPrivateKey over the Virtual Node behind an "Allow PKI export" gate (#4366)
    • feat(automations): hop-count tapback + {{ trigger.hopEmoji }} (#4340 phase 1) (#4390)
    • feat(traceroute): visual node strip on the Node Details panel (#4392)
    • feat(automations): per-node cooldown scope (#4340 phase 2) (#4396)
    • feat(meshcore): add per-node ignore list to the auto-responder (#4402)
    • feat(map): per-overlay toggle to disable the GeoJSON click popup (#4403)
    • feat(meshcore): add zero-hop ping action (#4404)
    • feat(tx-guard): allow sends when UDP Broadcast can relay for a TX-disabled node (#4405)
    • feat(waypoints): let the user pick the broadcast channel (#4406)
    • feat(automations): Auto-Ack parity conditions (#4340 phase 3) (#4407)
    • feat(automations): Auto-Acknowledge → Automation converter (#4340 phase 4) (#4408)
    • feat(settings): per-source settings foundation and guardrails (#4412 Phase 1) (#4417)
    • feat(traceroute): interactive strip — node popup More Details action + link tooltips (epic phase 1) (#4424)
    • feat(settings): read Node Display settings per-source (#4412 Phase 2) (#4425)
    • feat(traceroute): participation picker on all sources — brings the strip to MQTT (epic phase 2) (#4427)
    • feat(traceroute): Copy Forward/Return/Both text links with insecure-context fallback (#4429) …
  3. v4.13.3-rc5 # Pre-release 6 days ago · 2026-08-01 18:42 UTC

    Release candidate 5 for 4.13.3. Twelve changes since rc4.

    Remote administration no longer blocks on the mesh

    Issue #4482 — a single remote admin action could legitimately hold a browser HTTP request open for up to 75 seconds (up to 45s acquiring the session passkey, plus up to 30s awaiting a routing ACK). Behind a reverse proxy or CDN that surfaced as an upstream 502 with an unhelpful "Request failed".

    Remote admin commands, session-passkey acquisition, and remote config import now return 202 Accepted with an operation id and complete in the background, polled via GET /api/admin/operations/:id. Local-node commands stay synchronous — they have no passkey step and no ACK wait.

    • Remote ignore/unignore now confirm. They wait for the routing ACK exactly as favorites do, so a remote ignore can be verified rather than "succeeding" instantly with no way to check.
    • Partial config imports report what failed, not just what landed — "1 channel" is now distinguishable from "1 of 2 channels".

    (#4485, #4486; documented in #4490)

    Admin messages honor the configured hop limit

    Admin packets were built with a hardcoded hopLimit: 3 — the firmware default, not the user's setting. Anyone who raised their node's LoRa hop limit to reach a deeper mesh still had every remote admin command expire 3 hops out, with no indication why. They now use the node's configured value, matching how the Meshtastic Python client behaves. (#4479)

    Fixes

    • GET /stats returned 500 whenever sourceId was omitted — the cross-source aggregate path had never worked (#4470)
    • MeshCore: anon auth banner, channel-sync data loss, reply/trigger ordering (#4491)
    • MeshCore: channel view now opens at the top, and Delete no longer appears to do nothing (#4488)
    • MeshCore: hop/route/scope info preserved in channel message history (#4475)
    • Older-message loads no longer force-scroll the view to the bottom (#4477)
    • Restored the send-message button icon (#4480)

    Navigation

    • Unified Meshtastic/MeshCore per-source navigation (#4481)
    • Meshtastic phone navigation moved to the shared bottom bar (#4484)

    Validation

    Full system-test suite passed on hardware — all 12 legs, including Configuration Import, which exercises the newly-async /api/admin/import-config path and the hop-limit change against a real device. This is the first build to put the async remote-admin work in front of hardware; it shipped on unit and route coverage alone.

    🚀 MeshMonitor v4.13.3-rc5

    📦 Installation

    Docker (recommended):

    docker run -d \
      --name meshmonitor \
      -p 8080:3001 \
      -v meshmonitor-data:/data \
      ghcr.io/Yeraze/meshmonitor:4.13.3-rc5
    

    🧪 Testing

    ✅ All tests passed ✅ TypeScript checks passed ✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7

    📋 Changes

    See commit history for detailed changes.

  4. v4.13.3-rc4 # Pre-release 7 days ago · 2026-07-31 22:43 UTC

    MeshMonitor v4.13.3-rc4

    ⚠️ Pre-release. This is a release candidate for testing. It does not carry the :latest Docker tag. Run it in production only if you are ready to report bugs.

    Summary

    This candidate is built around two threads: the MeshCore Analyzer Observer epic (#4457) landing in full across three phases, and a chain of position-trust fixes that started with a protobuf refresh and ended up closing a security hole plus a long-standing data bug.

    The position thread is worth reading in order. Refreshing the Meshtastic protobufs picked up MeshPacket.rx_rssi gaining explicit presence — which turned a latent ambiguity into a live defect. Every rx_rssi != 0 guard had been treating a genuine 0 dBm reception as "no data", and in the local-node spoof detector that meant a 2.8 node transmitting at point-blank range was classified as our own outgoing message. Fixed, with a regression test on that exact case.

    Next, estimated positions were made honest. A trilaterated estimate used to be indistinguishable from a device GPS fix once it reached the client, because only one of the three position sources set a flag. Node Details now carries a GPS / Estimated / Override pill and a ± accuracy radius. On a typical install that relabels several hundred nodes that were quietly presenting guesses as fixes.

    That pill immediately exposed a real bug it had been hiding. Migration 107 once cleared bogus (0,0) fixes from nodes, but never swept estimated_positions — so a node whose Null Island fix had been cleared fell through to a Null Island estimate, re-substituting the exact coordinates the migration removed. Migration 134 purges those rows, the estimator no longer generates them, and the display gate now accepts a genuine equator or prime-meridian coordinate instead of reading a zero as "unpositioned".

    Features

    • MeshCore Analyzer Observer — backend foundation (#4457 phase 1) — #4464
    • MeshCore Analyzer Observer — publisher service (phase 2) — #4468
    • MeshCore Analyzer Observer — UI and docs (phase 3, final) — #4471
    • Position provenance in Node Details: GPS / Estimated / Override pill plus a ± accuracy radius (#4432) — #4467
    • DeviceMetadata.has_xeddsa surfaced in Admin Commands, distinguishing "cannot sign" from "did not sign" (#3923) — #4466

    Bug Fixes

    • Local-node spoof detection failed open on a 0 dBm reception. With firmware 2.8's explicit rx_rssi presence, a spoofed packet at point-blank range was classified as a genuine local transmission — #4466
    • Null Island estimates presented as real positions; migration 134 purges the stored rows, the estimator stops producing them, and a genuine equator / prime-meridian fix is no longer overwritten by an estimate — #4469
    • PWA notification clicks now deep-link to the source route (#4463) — #4465
    • MeshCore channel message history: infinite-scroll pagination — #4461
    • Traceroute node picker: relayed participation is MQTT-only — #4459
    • Per-node uptime graphs humanized (#3261); sidebar controls no longer overlap the shared footer (#4436) — #4458

    Protocol / Internals

    • Protobufs refreshed to develop@6ceceae (61 upstream commits). HardwareModel 141–143 (HELTEC_RC32 / RC52 / RCC6), PortNum.LORA_OTA_APP = 79, UA_868 marked deprecated — #4466
    • CI/release watcher scripts retry transient GitHub API errors — #4462

    Still no upstream 2.8 protobufs tag (newest remains v2.7.26), so the pin is a develop preview and the 2.8 tracking issues stay open.

    Upgrade Notes

    • Migration 134 runs automatically on first boot and deletes Null Island rows from estimated_positions. Any affected node loses its bogus estimate; the scheduled recompute recreates a row if a legitimate solve still exists.
    • Nodes that were displaying an estimated position will now show an ESTIMATED pill. That is the estimate becoming visible, not a new estimate.

    🚀 MeshMonitor v4.13.3-rc4

    📦 Installation

    Docker (recommended):

  5. v4.13.3-rc3 # Pre-release 8 days ago · 2026-07-30 21:27 UTC

    MeshMonitor v4.13.3-rc3

    ⚠️ Pre-release. This is a release candidate for testing. It does not carry the :latest Docker tag. Run it in production only if you are ready to report bugs.

    Summary

    This candidate closes out two epics and sweeps up the defects they exposed. The traceroute epic gains a statistical route view: route segments now aggregate across many traceroutes, a union layout engine draws the merged graph, and the result renders in the Node Details strip. The strip also picks up interactive node popups, link tooltips, Copy Forward/Return/Both text links, and a participation picker that finally brings the strip to MQTT sources. The per-source settings epic (#4412) lands in three phases — backend foundation, per-source reads, then the frontend — and ends with MeshCore node-age filtering built on top of it.

    That second epic uncovered a cluster of permission bugs worth calling out. Two divergent source-scoped resource lists meant per-source scoping was silently ignored for settings, dashboard, info, audit, and security (#4416), and new-user default grants were written globally when four of six are per-source resources, leaving them inert (#4448). Both are fixed. On the data side, Meshtastic 2.8's periodic rebroadcast of cached packets was inflating node "Last Heard" (#4192), and nodes without a real fix were appearing on the map — position estimates built from a single anchor are now excluded by default (#4450). MeshCore gets guards against overlapping auto-pathfinding calls and a DM permission leak to anonymous users.

    Features

    • Statistical route aggregation + union layout engine (traceroute epic phase 1) — #4444
    • Statistical route view in the Node Details strip (phase 2) — #4451
    • Interactive strip: node popup More Details action + link tooltips — #4424
    • Participation picker on all sources, bringing the strip to MQTT — #4427
    • Copy Forward/Return/Both text links, with an insecure-context fallback — #4429
    • Per-source settings foundation and guardrails (#4412 phase 1) — #4417
    • Read Node Display settings per-source (phase 2) — #4425
    • Per-source Node Display frontend (phase 3) — #4431
    • MeshCore per-source node-age filtering and Node Display settings — #4433

    Bug Fixes

    • Guard lastHeard against replayed position/telemetry packets — #4446
    • Exclude single-anchor position estimates by default — #4455
    • Purging position history now also clears the global position estimate — #4452
    • Make settings a per-source permission resource — #4443
    • Close five defects the per-source epic uncovered (#4442, #4437, #4438, #4449, #4448) — #4453
    • Close the per-source settings defects: global current-value compare, full-table scan — #4441
    • Scope MeshCore /snapshot messages field to messages:read — #4423
    • Guard MeshCore startAutoPathfinding() against overlapping calls — #4435
    • Disable Convert-to-Automation button for MeshCore sources — #4421
    • Route strip edges and labels around unrelated node glyphs — #4430
    • Bound geofenceState and autoAckCooldowns growth — #4413
    • Guard MQTT handleUplink against a client nulled mid-flight — #4414
    • Virtual node: fall back to persisted modem preset for the slot-0 channel name — #4415
    • Virtual node: stop duplicate MQTT client-proxy publishing — #4418
    • Humanize the Dashboard uptime widget and align DM chart padding — #4439
    • Unify the sidebar footer across dashboard and per-source views — #4440
    • Pass showList from every back-to-dashboard button — #4454

    Chores

    • Bump version to 4.13.3-rc3 — #4456

    Issues Resolved

    #3261, #4037, #4192, #4399, #4411, #4412, #4416, #4419, #4420, #4422, #4426, #4428, #4434, #4436, #4437, #4438, #4442, #4445, #4447, #4448, #4449, #4450

    Upgrade Notes

    No schema migrations and no breaking API changes in this candidate.

    One behavior change worth watching: map pins may thin out after upgrading. Position estimates derived from a single anchor are now excluded by default, so nodes that previously showe …

  6. v4.13.3-rc2 # Pre-release 10 days ago · 2026-07-29 04:35 UTC

    MeshMonitor v4.13.3-rc2

    ⚠️ Pre-release. This is release candidate 2 for 4.13.3. It is published for testing and does not update the :latest Docker tag. Use :4.13.3-rc2 explicitly if you want to try it.

    The headline is that Auto-Acknowledge now lives in the Automation Engine. A four-phase epic gave the engine everything Auto-Ack could do — hop-count reactions, per-node cooldowns, node-completeness and ignore-list conditions — and then added a converter that turns an existing Auto-Ack config into a real, editable automation. That means per-channel acknowledgement bodies, the thing #4340 asked for, are now just two rules rather than a second configuration axis bolted onto Auto-Ack.

    Alongside it: waypoints can pick their broadcast channel, MeshCore gains a zero-hop ping action and a per-node ignore list for the auto-responder, TX-disabled nodes can still send when UDP Broadcast can relay for them, and the Node Details panel gets a visual traceroute strip. No migrations, no configuration changes, no breaking changes.

    Auto-Acknowledge → Automation Engine (#4340)

    Four phases, each independently shippable:

    • #4390 — Hop-count tapback. Send a tapback (reaction) gained an Emoji source option: a fixed emoji, or the message's hop count (*️⃣ direct, 1️⃣7️⃣ above), using the same table Auto-Ack uses. Also adds the {{ trigger.hopEmoji }} token and a general showIf mechanism for conditional builder fields.
    • #4396 — Per-node cooldown scope. Triggers gained Cooldown applies to: the whole automation (unchanged default), each node separately, or each node per source. Previously a cooldown on a busy channel suppressed acks to every other sender.
    • #4407 — Auto-Ack parity conditions. A node.completeness tri-state field, is one of / isn't one of string operators, isDM/viaMqtt in the condition picker, and an optional DM resend cap. A machine-enforced parity table now proves the engine can express every Auto-Ack setting.
    • #4408 — The converter. A Convert to an Automation… button previews exactly what will be created, shows an honest report of what did and did not convert, and writes only on confirmation. Turning off Auto-Ack afterwards is opt-in (checked by default) and touches only the on/off switch — every other setting is preserved, so you can switch back.

    Upgrade note: nothing changes unless you use the converter. Existing Auto-Acknowledge configs keep working exactly as before, and existing automations are untouched — every new option defaults to the previous behaviour.

    Features

    • #4341 — Waypoints: pick which channel the waypoint broadcasts on
    • #4393 — MeshCore: zero-hop ping action
    • #4391 — MeshCore: per-node ignore list for the auto-responder
    • #4381 — Traceroute: visual node strip on the Node Details panel
    • #4344 — Map: per-overlay toggle to disable the GeoJSON click popup
    • TX guard: allow sends when UDP Broadcast can relay for a TX-disabled node

    Bug Fixes

    • MeshCore: sign-extend traceContactPath per-hop SNR bytes (negative SNR was being read as a large positive value)
    • #4389 — Map legend gets a usable mobile presentation
    • #4395 — Every dashboard sidebar link gets an icon
    • Traceroute: portal the strip hover popup and show the Map node card

    Known follow-ups filed during this cycle

    • #4399 — geofenceState and autoAckCooldowns are unbounded maps
    • #4400 — an ok_to_mqtt fail-closed test that flakes open under different test ordering

    🚀 MeshMonitor v4.13.3-rc2

    📦 Installation

    Docker (recommended):

    docker run -d \
      --name meshmonitor \
      -p 8080:3001 \
      -v meshmonitor-data:/data \
      ghcr.io/Yeraze/meshmonitor:4.13.3-rc2
    

    🧪 Testing

    ✅ All tests passed ✅ TypeScript checks passed ✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7

    📋 Changes

    See commit history for detailed changes.

  7. v4.13.3-rc1 # Pre-release 11 days ago · 2026-07-28 14:52 UTC

    MeshMonitor v4.13.3-rc1

    ⚠️ Pre-release. This is release candidate 1 for 4.13.3. It is published for testing and does not update the :latest Docker tag. Use :4.13.3-rc1 explicitly if you want to try it.

    A maintenance candidate focused on the map surfaces. The Map Analysis 3D view now has the view-state, follow, and layer-switching plumbing that the 2D view already had, and its basemaps actually load — the CSP was blocking several built-in tileset hosts. The tile selector gets a real mobile bottom sheet instead of a popover that mobile users could never reach, and the "Show ATAK Contacts" toggle finally survives a reload after being silently dropped by /map-preferences. On the Nodes list, Node Details is now a distinct labeled button on every row rather than an icon-click affordance people had to discover. Rounding it out: news-feed links to meshmonitor.org are absolutized, stable releases publish to the :dev tag alongside :latest, the unit suite runs roughly 2.5× faster, and a flaky packet-log test is fixed. No migrations, no configuration changes, no breaking changes.

    Bug Fixes

    • #4373 — Map Analysis 3D view gets the view-state, follow, and layer plumbing 2D has; layer gating keyed on the effective view mode; CSP connect-src widened so every built-in tileset host loads 3D basemaps (#4371)
    • #4383 — Tile selector renders as a mobile bottom sheet (#4380)
    • #4384 — "Show ATAK Contacts" map toggle persists (#4378)
    • #4385 — Every node row gets a distinct, labeled Node Details button (#4379)
    • #4377 — News-feed links to meshmonitor.org are absolutized
    • activeStyleJson wired into the MapAnalysis and MeshCore BaseMap consumers

    CI / DevOps

    • #4372 — Unit suite parallelized (~17.5 min → ~6.6 min) and the duplicate CI workflow retired
    • #4382 — Stable releases publish to the :dev tag as well as :latest
    • #4386 — De-flaked the packet-log since-timestamp filter test
    • #4388 — Version bump to 4.13.3-rc1

    Issues Resolved

    • #4371 — Map Analysis 3D view missing view-state, follow, and layer-switching plumbing that 2D has
    • #4378 — "Show ATAK Contacts" map toggle never persists
    • #4379 — Replace icon-click affordance for Node Details with a distinct labeled button
    • #4380 — Tile selector popover hidden on mobile with no fallback UI

    Upgrade Notes

    None. No database migrations and no configuration changes — upgrade in place from 4.13.2.

    Full changelog: https://github.com/Yeraze/meshmonitor/compare/v4.13.2...v4.13.3-rc1

    🚀 MeshMonitor v4.13.3-rc1

    📦 Installation

    Docker (recommended):

    docker run -d \
      --name meshmonitor \
      -p 8080:3001 \
      -v meshmonitor-data:/data \
      ghcr.io/Yeraze/meshmonitor:4.13.3-rc1
    

    🧪 Testing

    ✅ All tests passed ✅ TypeScript checks passed ✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7

    📋 Changes

    See commit history for detailed changes.

  8. v4.13.2 # 11 days ago · 2026-07-27 21:21 UTC

    MeshMonitor v4.13.2

    This release finishes the ATAK / CoT work, teaches MeshMonitor to respect a node that cannot transmit, adds a 3D terrain view, and catches gateways that uplink traffic their senders asked to keep off MQTT.

    If you run PostgreSQL or MySQL, take this release. Those two backends re-ran every migration on each boot, and migration 030 rebuilds route_segments from scratch — 865k rows deleted and reinserted on every restart for one reporting install. SQLite was never affected.

    See the release blog post for the narrative walkthrough, and the CHANGELOG for all 49 entries.

    Fix first: PostgreSQL / MySQL migration ledger

    • The settingsKey idempotency guard was SQLite-only, so PostgreSQL and MySQL replayed all 128 migrations at every start. Both backends now record applied migrations in a ledger. (#4233)

    ATAK / CoT

    • Packet decoding for ATAK plugin portnum 72 (TAKPacket) and portnum 78 (TAKPacketV2, zstd-compressed against the vendored TAKPacket-SDK dictionaries) — position, GeoChat, markers, routes, CASEVAC, emergency. GeoChat messages persist into Messages. (#3691 Phase 1, #4317)
    • ATAK contacts on every map — team-colored callsign markers with a Show ATAK Contacts toggle, STALE badge after 15 minutes, purge after 24 hours. (#3691 Phase 2)
    • CoT TCP feed for ATAK / WinTAK — settings-gated, streams Cursor-on-Target XML covering ATAK contacts plus every positioned Meshtastic and MeshCore node from every source. No authentication or encryption; trusted-network only. (#3691 Phase 3)

    Receive-only nodes

    • MeshMonitor now honors lora.tx_enabled. A central server-side guard rejects every transmit path, the UI disables transmit-dependent controls with an explanation instead of failing at the radio, and config import reads live remote LoRa config so it cannot flip TX back on by accident. New Receive-only mode guide. (#4294, #4315)

    MQTT

    • ok_to_mqtt violation detection — flags gateways that uplink packets from nodes that opted out, with 90 days of history and an ok_to_mqtt Violations report (per-gateway and per-packet views, node names, CSV export, SQL-side paging). (#4114, #4330, #4343)
    • Configurable downlink hop-limit override (0–7) on the embedded broker, replacing the zero-hop toggle. (#4081)
    • Auto-delete-by-distance applies at ingest, so an out-of-radius node never reaches the map. (#3900)

    Maps

    • 3D terrain view on Map Analysis (MapLibre + server-side DEM proxy), with node markers, neighbor links, and traceroute paths in 3D and a clean fallback without WebGL. (#3826)
    • Terrain Link Profile refinements — antenna AGL seeded from node altitude, clickable thin neighbor links, terrain analysis on route segments. (#4253, #4254)
    • ROUTER_LATE is distinguishable from ROUTER, unmessageable nodes show a badge, and the Nodes tab is now called Map. (#4295, #4325)

    Also in this release

    • Share a node as a Meshtastic contact — QR code plus a meshtastic.org/v/#… contact link. (#4327)
    • NodeInfo Enrichment report — finds fields one source could fill from another and applies the fix; Copy NodeInfo gained per-field selection and overwrite. (#3837, #4244)
    • MeshCore Virtual Node "Allow PKI export" — a separate, default-off gate serving ExportPrivateKey(23) for tools that authenticate as the node itself. The VN port has no client authentication and the private key lets a client permanently become your node, so this is deliberately not folded into admin commands. See Virtual Node docs. (#3933, #4366)
    • Every PKI DM was favoriting its recipientadd_contact was pushed before every PKI direct message, and the firmware's addFromContact() sets is_favorite to sh …
  9. v4.13.2-rc4 # Pre-release 13 days ago · 2026-07-25 19:47 UTC

    Pre-release. Rolls up the complete ok_to_mqtt violation-detection feature and its pagination follow-up.

    Detect MQTT gateways that ignore ok_to_mqtt

    Meshtastic packets carry an ok_to_mqtt bit by which the originating node signals whether it consents to its traffic being uplinked to MQTT. Firmware only enforces it when a gateway relays other nodes' packets, and it skips the check entirely whenever the gateway believes its broker address is private — a plain IP-range test with no awareness of NAT or port forwarding. A gateway reaching its broker through a LAN-literal address that is also port-forwarded gets misclassified as private and silently relays opted-out traffic to what is effectively a public broker.

    MeshMonitor now detects that. When a received packet's bit is explicitly clear and the publishing gateway is not the originator, it is a provable violation — and it is recorded.

    Important: a violation is almost certainly a gateway misconfiguration, not malice. Treat it as something worth flagging to the gateway's operator.

    Where you see it

    • Packet Monitor — a violation badge on affected packets, and a per-gateway ok_to_mqtt column in the packet detail view showing which gateway violated (a packet can be relayed by many). Four states are distinguished: violation, allowed, opted out, and unknown (bit unreadable).
    • Analysis & Reports → ok_to_mqtt Violations — a cross-source report with a per-gateway summary (violation count, distinct originators affected, sources, first/last seen), drill-down to individual violating packets, window presets (24 h / 7 / 30 / 90 days) or an explicit date range, CSV export, and an optional "include unproven" toggle.

    Behaviour worth knowing

    • Recording is on by default. Violation history is kept ~90 days in its own store, independent of the MQTT Packet Monitor's much shorter window — so the report works out of the box. The per-packet badge, however, reads the Packet Monitor's capture log, which is opt-in and off by default; the Packet Monitor now says so explicitly when capture is off, so an absence of badges is never mistaken for an absence of violations.
    • Forward-only. Detection covers traffic received after upgrading. No backfill is possible — the bit was never previously stored — so expect an empty history at first.
    • Confirmed vs. suspected. Rows whose bit could not be read (undecryptable, or captured before this feature existed) are reported as unknown/suspected, never as confirmed violations, and they come from a much shorter retention window.

    Included changes

    • #4324 — Phase 1: backend detection, migration 128, durable history, cross-source endpoints
    • #4328 — Phase 2: Packet Monitor badge + per-gateway attribution
    • #4331 — Phase 3: the ok_to_mqtt Violations report
    • #4332 — fixes #4330: SQL sorting/paging so large result sets page correctly and ascending sorts are accurate

    Upgrade notes

    Migration 128 adds columns to mqtt_packet_log and creates the violation-history table. It is idempotent and was verified against SQLite, PostgreSQL 16 and MySQL 8.4. The new table is included in migrate-db, so backend-to-backend migrations carry violation history across.

    No configuration is required.

    🚀 MeshMonitor v4.13.2-rc4

    📦 Installation

    Docker (recommended):

    docker run -d \
      --name meshmonitor \
      -p 8080:3001 \
      -v meshmonitor-data:/data \
      ghcr.io/Yeraze/meshmonitor:4.13.2-rc4
    

    🧪 Testing

    ✅ All tests passed ✅ TypeScript checks passed ✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7

    📋 Changes

    See commit history for detailed changes.

  10. v4.13.2-rc3 # Pre-release 15 days ago · 2026-07-24 13:14 UTC

    MeshMonitor v4.13.2-rc3

    ⚠️ Pre-release — this is a release candidate for testing. Docker images are not tagged :latest.

    This release candidate lands two major feature epics plus targeted fixes. The ATAK/CoT integration epic (#3691) arrives in full: TAKPacket V1 decoding with Packet Monitor previews and GeoChat messages, per-source ATAK contacts with a dedicated map layer, and a CoT TCP feed that ATAK/WinTAK clients can connect to directly. The TX-disabled epic (#4294/#4308) makes MeshMonitor a proper citizen on receive-only (listen-only) nodes: lora.txEnabled=false is now honored by a central server-side TX guard, transmit-dependent UI controls are gated, automations get a TX-disabled badge, and configuration import no longer silently forces TX back on. MQTT ingest now applies auto-delete-by-distance inline at ingest time rather than waiting for the periodic sweep (#3900). A touch-device layout bug that visually detached a sender's long name from its message bubble is fixed (#4311).

    Features

    • #4307 feat(atak): TAKPacket V1 decode, Packet Monitor previews, GeoChat messages (#3691 Phase 1)
    • #4310 feat(atak): per-source ATAK contacts + map layer (#3691 Phase 2)
    • #4314 feat(atak): CoT TCP feed for ATAK/WinTAK clients (#3691 Phase 3)
    • #4309 feat(server): honor lora.txEnabled with central TX-disabled guard (#4294)
    • #4313 feat(ui): gate transmit-dependent controls when TX is disabled (#4294)
    • #4316 docs+feat: TX-disabled polish — automations badge, API docs, receive-only guide (#4294)
    • #4306 feat(mqtt): apply auto-delete-by-distance inline at ingest (#3900)

    Bug Fixes

    • #4312 fix(channels): tie long name to its bubble on touch devices (#4311)

    Chores

    • #4318 chore: bump version to 4.13.2-rc3

    Issues Resolved

    • #3691 Feature: ATAK / CoT integration for Meshtastic ATAK plugin packets
    • #4294 [BUG] Local Configuration tab silently forces LoRa txEnabled=true, breaking intentional TX-off (listen-only) nodes
    • #4308 Epic: Properly support LoRa tx_enabled=false (receive-only mode)
    • #3900 [FEAT] Apply auto-delete-by-distance inline at MQTT ingest, not just on periodic interval
    • #4311 [BUG] Long name visually detached from its message bubble on touch devices

    Full Changelog: https://github.com/Yeraze/meshmonitor/compare/v4.13.2-rc2...v4.13.2-rc3

    🚀 MeshMonitor v4.13.2-rc3

    📦 Installation

    Docker (recommended):

    docker run -d \
      --name meshmonitor \
      -p 8080:3001 \
      -v meshmonitor-data:/data \
      ghcr.io/Yeraze/meshmonitor:4.13.2-rc3
    

    🧪 Testing

    ✅ All tests passed ✅ TypeScript checks passed ✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7

    📋 Changes

    See commit history for detailed changes.

  11. v4.13.2-rc2 # Pre-release 16 days ago · 2026-07-23 16:02 UTC

    MeshMonitor v4.13.2-rc2

    ⚠️ Pre-release (Release Candidate). This build is for testing ahead of the v4.13.2 stable release. Docker :latest tags are not updated. Report any issues you hit.

    This release candidate closes out the large multi-phase remediation epic (#3962) and the server-route extraction effort (#3502), decomposing the monolithic server.ts into focused route and service modules, migrating the frontend onto real routes + TanStack query hooks, and driving raw fetch() usage to zero. On the feature side it adds cross-source NodeInfo Enrichment (analysis report + apply API, #3837), a Portainer Stack export format in the configurator (#3724), richer MeshCore route popups (packet-flow mini map, {ROUTE_NAMES}/{HASH_SIZE} tokens, accessible detail modals), a per-trigger pre-send delay for the MeshCore Auto-Responder (#3953), configurable Auto-Ack DM resend attempts (#4266), and a map distinction between ROUTER_LATE and ROUTER with an unmessageable badge (#4295). Security fixes suppress a false-positive duplicate-key warning on the Meshtastic 2.8 NodeNum renumber (#4251) and add a self-service Clear action for stale security-risk warnings (#4302). CI hardening pins all GitHub Actions to commit SHAs. This is a testing build ahead of v4.13.2 stable.

    ✨ Features

    • NodeInfo Enrichment — cross-source analysis + apply API (#4287) and a report under Analysis & Reports (#4289) — resolves #3837
    • Portainer Stack export format in the configurator (#4282) — resolves #3724
    • Map: distinguish ROUTER_LATE from ROUTER, add unmessageable badge (#4303) — resolves #4295
    • MeshCore: {ROUTE_NAMES} / {HASH_SIZE} tokens + clickable route-detail popup (#4276)
    • MeshCore: packet-flow mini map in route popup + accessible detail modals (#4277)
    • MeshCore: per-trigger pre-send delay for the Auto-Responder (#4281) — resolves #3953
    • Automation: configurable Auto-Ack DM resend attempts (#4273) — resolves #4266

    🐛 Bug Fixes & Security

    • Security: self-service Clear action for stale security-risk warnings (#4304) — resolves #4302
    • Security: suppress false-positive duplicate-key warning for the Meshtastic 2.8 NodeNum renumber (#4272) — resolves #4251

    ♻️ Refactoring

    server.ts route extraction (#3502):

    • Extract settings + admin routes (#4263)
    • Extract nodes routes + composition-root teardown (#4265)

    Remediation epic — finish the half-migrated abstractions (#3962):

    • 4.2a — retire meshcoreRegistry shim + meshtasticManager Proxy alias, and extract services: MQTT bridge/NodeDB, announce scheduler, admin-ack + favorites, device/remote-admin (#4267, #4268, #4269, #4270, #4271)
    • 4.2b — explicit connection state machine for meshtasticManager (#4274)
    • 4.3 — split meshcoreRoutes into concern modules (#4275)
    • 5.1–5.2 — memoize context providers + TanStack version-check (#4280)
    • 5.3 — SettingsTab draft-object rewrite (#4284)
    • 5.4 — router scaffold + full tab-to-route migration (#4285, #4286, #4288, #4290, #4291, #4292, #4293, #4296)
    • 5.5 — migrate raw fetch() sites to ApiService, baseline to zero (#4297, #4298)
    • 5.6 — nodes.css cascade-order fix + CSS containment convention (#4299)

    🔧 CI / DevOps

    • Pin all GitHub Actions to commit SHAs (#4283)

    📝 Docs

    • Epic #3962 Phase 4+5 close-out (#4300)
    • Add MeshEC to the Site Gallery (#4279)
    • Record the two verification gaps from the session (#4264)

    ✅ Issues Resolved

    #3502, #3724, #3837, #3953, #3962, #4251, #4266, #4278, #4295, #4302

    🙏 New Contributors

    • @mirkosalvato1-ctrl — first contribution in #4283 (pinning Actions to SHAs). Welcome!

    Full changelog: https://github.com/Yeraze/meshmonitor/compare/v4.13.2-rc1...v4.13.2-rc2

    🚀 MeshMonitor v4.13.2-rc2

    📦 Installation

    Docker (recommended):

    docker run -d \
      --name meshmonitor \
      -p 8080:3001 \
      -v meshmonitor-data:/data \
      ghcr.io/Yeraze/meshmonitor:4.13.2-rc2
    

    🧪 Testing

    ✅ All tests passed ✅ …

  12. v4.13.2-rc1 # Pre-release 17 days ago · 2026-07-21 20:59 UTC

    ⚠️ Pre-release (Release Candidate 1 for 4.13.2). Not marked latest; no :latest Docker tags are published. For testing ahead of the 4.13.2 release — please report issues.

    Summary

    Release candidate 1 for 4.13.2. The headline is the completion of the 3D Map & Elevation effort (issue #3826): Map Analysis gains a real 2D/3D toggle backed by a standalone MapLibre GL terrain view, a DEM tile proxy that hides the configured elevation source, and neighbor-link/traceroute layers with full selection parity in 3D (#4235, #4239, #4242). The Link Profile tool now seeds antenna heights from node-reported altitude, and neighbor links are finally clickable with terrain analysis available on route segments (#4253, #4254). Unified Messages shows sender short-names alongside long names, emoji reactions show the reactor's short name, and Copy NodeInfo gains per-field selection with a MAC-address fix (#4257, #4247, #4249). A security fix lets Bearer API tokens work on the legacy /api/* endpoints instead of only /api/v1/* (#4262, closes #4259). This RC also lands a PostgreSQL/MySQL migration ledger that stops migrations replaying on every boot (#4236), a batch of MeshCore hardware system-tests (#4232, #4241, #4248), and a round of follow-up fixes to the UI icon migration and map-visibility handling. Server routing was refactored out of the monolithic server.ts as the first step of a larger cleanup (#4260).

    Features

    • 3D Map & Elevation epic (#3826): neighbor-link terrain integration (#4235), 3D terrain view + DEM tile proxy (#4239), 3D neighbor/traceroute layers + selection parity (#4242)
    • Link Profile antenna AGL seeded from node-reported altitude (#4254)
    • Unified Messages: show short name alongside long name on sender labels (#4257)
    • Channels: show reactor's short name next to emoji reactions (#4247)
    • Per-field Copy NodeInfo with overwrite + MAC address display fix (#4249)
    • Unified Messages: reply box shows "Unknown message" when the parent is missing (#4246)
    • Consistent Lucide/emoji icon style across the full UI (#4217, @wilhel1812)

    Bug Fixes

    • Clickable neighbor links + terrain analysis on route segments (#4253)
    • Restore compact glyphs in the channel dropdown options after the icon migration (#4258)
    • Repair text spacing left behind by the icon migration (#4238)
    • Close the status-glyph gap in the no-hardcoded-ui-glyph rule (#4255)
    • Per-transport last-seen timestamps with decay + unstick visibility toggles (#4250, #4240)
    • Stop discarding MeshCore favorites in the node projection (#4256)
    • Fix MeshCore marker keying to prevent ghost markers across sources (#4237)
    • PostgreSQL/MySQL migration ledger — stop replaying migrations (and rebuilding route_segments) on every boot (#4236)

    Security

    • Accept Bearer API tokens on legacy /api/* endpoints, not just /api/v1/* (#4262, closes #4259)

    Refactoring

    • Extract messages/poll/config/user routes from server.ts (#4260, first step of #3502)

    Tests / CI

    • MeshCore hardware system-tests — Phase 1 connect/handshake (#4232), Phase 2 companion channel + repeater DM auto-ack (#4241), Phase 3 repeater remote-admin login + telemetry poll (#4248)

    Chore

    • Version bump to 4.13.2-rc1 (#4261)

    Issues Resolved

    • #3826 — 3D map mode for elevation display
    • #4259 — Bearer API tokens silently rejected on legacy endpoints
    • #4245 — Unified Messages "Unknown message" reply indicator
    • #4244 — Copy NodeInfo per-field selection + MAC address
    • #4243 — reactor short name on reactions
    • #4240 — favorited/freshly-heard node missing from map + stuck hide-from-map toggle
    • #4234 — MeshCore nodes visible on every map
    • #4233 — PostgreSQL/MySQL migrations replaying every boot
    • #4215 — expand Lucide/emoji icon style across the UI
    • #4193 — short name alongside long name for message senders

    Full changelog: https://github.com/Yeraze/meshmonitor/compare/v4.13.1...v4.13.2-rc1

    🚀 MeshMonitor v4.13.2-rc1

    📦 Installation

    Docker (recommended):

  13. v4.13.1 # 19 days ago · 2026-07-20 16:45 UTC

    MeshMonitor v4.13.1

    Building on 4.13's unified map core, this release adds a suite of Link Quality tools for the RF-minded, an early preview of several Meshtastic 2.8 features, and a broad round of map, MQTT, and messaging fixes.

    Highlights: a Terrain Link Profile tool (elevation cross-section, Fresnel zone, and link-budget verdict) on Map Analysis; a per-node signal-trend / link-attenuation badge; Noise Floor on the Node Detail card; and position accuracy + location source surfaced in node popups. The Map Analysis toolbar is now icon-based with Show RF / UDP / MQTT transport toggles, and obscured markers offset intelligently by cell occupancy. On the 2.8 front (an early preview — 2.8 is not officially released yet, so this is built against the firmware development branch and is subject to change), MeshMonitor now decodes the XEdDSA signing shield, MeshBeacon packets, and the MEDIUM_TURBO preset. Also notable: telemetry requests now auto-recover from an upstream firmware NeighborInfo-hijack, a new noindex/robots.txt privacy toggle, and a gateway-aware MQTT Packet Monitor.

    See the release blog post for the narrative walkthrough.

    Link Quality & Terrain Link Profile

    • Terrain Link Profile tool: elevation cross-section + Fresnel zone + link-budget verdict, auto-frequency by region, DEM-void handling, map-mirrored graph cursor (#4143, #4147, #4151, #4170, #4156)
    • Derived signal-trend / link-attenuation badge per node (#4204)
    • Noise Floor on the Node Detail quick-stats card (#4201)
    • Position accuracy + location source in node popups, map & chat (#4188)
    • Latitude/longitude/elevation shown as text in Node Info / Node Details (#4134)

    Map Analysis

    • Icon-based toolbar with labels in tooltips (#4171)
    • Show RF / UDP / MQTT transport toggles (#4135)
    • Occupancy-scaled, distance-capped obscured-node precision offset (#4164, #4168, #4181)
    • "Discard invalid positions" setting, honored on ingest and render (#4158, #4182)
    • Per-theme (light/dark) tileset preferences (#4118)
    • Keep router short-name visible in Official pin style (#4184)
    • Honor Default Map Center on Unified/Dashboard maps (#4128)
    • Fixes: spiderfy opens the correct node (#4203), SNR overlay pins to merged marker (#4169), no route/heatmap render for marker-less or deleted nodes (#4167, #4175)

    Meshtastic 2.8 — Early Preview

    ⚠️ Meshtastic 2.8 is not officially released. This support is built against the firmware development branch and is subject to change as 2.8 evolves.

    • Pin 2.8-preview protobufs (develop@ba16bfc) with a 2.7 TrafficManagement compat shim (#4205)
    • XEdDSA packet-signing shield in the Packet Monitor (#4209)
    • MeshBeacon (MESH_BEACON_APP) decode + firmware-verified preset channel names (#4207)
    • MEDIUM_TURBO modem preset + 2.8 opt-in FAQ (#4200)

    MQTT

    • Gateway-aware MQTT Packet Monitor — per-gateway reception capture + UI (#4127, #4138)
    • Geo-ignore epic: fail-open geo filter, per-source ignore list, retroactive purge/sweep, observability (#4123, #4131, #4132, #4136)
    • Route directed MQTT messages to the DM view, not their channel (#4161)
    • Guard MQTT POSITION ingestion against Null Island fixes (#4150)

    Messages, Nodes & Automation

    • Auto-retry telemetry requests hijacked by the firmware NeighborInfo behavior (#4214)
    • Stop unsynced-clock nodes rendering chat at ~1970 (#4208)
    • MeshCore own-node messages show name, not public key (#4197)
    • Short name shown alongside long name on message senders (#4196)
    • "Message anyway" override for unmessageable nodes (#4187), and clearer hidden-composer messaging (#4140)
    • Remote-admin (non-local) reboot target for the device-reboot automation (#4186)
    • Compose draft scoped per-conversation (#4185)
    • Reliably un-hide nodes from the map across sources (#4141)
    • Traceroute no longer sends on a DISABLED channel slot (#4180)
    • Reject precision-obscured Null Island fixes on ingest (#4149)

  14. v4.13.1-rc4 # Pre-release 20 days ago · 2026-07-19 13:15 UTC

    MeshMonitor v4.13.1-rc4

    ⚠️ Pre-release (release candidate). This build is for testing ahead of the v4.13.1 stable release. Not recommended for production deployments.

    This fourth release candidate continues the Meshtastic 2.8 readiness work and lands a mix of node-detail and map improvements on top of rc3. It adds a noIndexEnabled privacy toggle so a publicly-exposed dashboard can serve X-Robots-Tag: noindex, nofollow headers plus a disallow-all /robots.txt (belt-and-suspenders for Cloudflare-tunnel setups that strip custom headers). On the 2.8 front, it decodes MESH_BEACON_APP with firmware-verified preset channel names, pins the 2.8-preview protobufs with a 2.7 TrafficManagement compat shim, adds an XEdDSA signature shield in the Packet Monitor, and ships the MEDIUM_TURBO preset with 2.8 opt-in docs. Node detail gains a derived signal-trend / link-attenuation badge and a Noise Floor quick-stat. Two bug fixes round it out: chat from unsynced-clock nodes no longer renders at ~1970, and cluster spiderfy no longer opens the popup for a nearby unrelated node.

    Features

    • Privacy: noIndexEnabled toggle serving X-Robots-Tag: noindex, nofollow + disallow-all /robots.txt (#4212, closes #4202)
    • 2.8 / Packet Monitor: XEdDSA signature shield for firmware 2.8 packets (#4209)
    • 2.8 / MeshBeacon: decode MESH_BEACON_APP + firmware-verified preset channel names (#4207)
    • 2.8 / Protobufs: pin 2.8-preview develop@ba16bfc with 2.7 TrafficManagement compat shim (#4205)
    • Nodes: derived signal-trend / link-attenuation badge per node (#4204, closes #4110)
    • Nodes: show Noise Floor on the Node Detail quick-stats card (#4201, closes #4109)
    • 2.8: MEDIUM_TURBO preset, MESH_BEACON_APP portnum, traffic-management & 2.8 opt-in docs (#4200)

    Bug Fixes

    • Messages: stop unsynced-RTC nodes rendering chat at ~1970 (rxTime now clamped to receipt time) (#4208, closes #4206)
    • Map: spiderfy no longer selects a nearby unrelated node instead of fanning the cluster (#4203, closes #4199)

    Issues Resolved

    • #4202 — [FEAT] Robots.txt / X-Robots-Tag toggle to discourage crawlers/bots
    • #4206 — [BUG] Chat from unsynced-clock nodes renders at ~1970
    • #4199 — [BUG] Spiderfy click opens popup for wrong nearby node
    • #4109 — [FEAT] Show Noise Floor on Node Detail quick-stats card
    • #4110 — [FEAT] Derived signal-trend / link-attenuation indicator per node
    • #4074 — Modem preset tables missing MEDIUM_TURBO (enum 16)
    • #3999 — [2.8 tracking] Position & telemetry broadcast now opt-in by default
    • #3547 — Docs: Traffic Management module documentation

    Full changelog: https://github.com/Yeraze/meshmonitor/compare/v4.13.1-rc3...v4.13.1-rc4

    🚀 MeshMonitor v4.13.1-rc4

    📦 Installation

    Docker (recommended):

    docker run -d \
      --name meshmonitor \
      -p 8080:3001 \
      -v meshmonitor-data:/data \
      ghcr.io/Yeraze/meshmonitor:4.13.1-rc4
    

    🧪 Testing

    ✅ All tests passed ✅ TypeScript checks passed ✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7

    📋 Changes

    See commit history for detailed changes.

  15. v4.13.1-rc3 # Pre-release 20 days ago · 2026-07-18 19:43 UTC

    MeshMonitor v4.13.1-rc3

    ⚠️ Pre-release (release candidate). Rolls up 13 PRs merged since rc2 — position-quality & Map Analysis refinements plus a cluster of messaging correctness fixes. Please test and report issues before the stable 4.13.1.

    Highlights

    This RC sharpens position quality and node identity. Node popups now show position accuracy and GPS location source; the "Discard invalid positions" toggle is honored on the render side (not just ingest); and the obscured-node precision offset is occupancy-scaled and distance-capped. On the messaging side it fixes several real correctness bugs: compose drafts no longer leak across conversations (a message meant for one node could be sent to another), MeshCore own-node messages show the node's name instead of a raw public key, and message senders now display their short name alongside the long name. Rounding it out: automations can now target a remote node for admin reboot, unmessageable nodes get a "Message anyway" override, traceroute no longer fails with NO_CHANNEL on a disabled channel slot, and the v1 default source alias scopes correctly.

    Features

    • #4188 — Position accuracy + location source in node popups (chat & map), migration 124
    • #4187 — "Message anyway" override for unmessageable-node DM banner
    • #4186 — Automation: remote-admin reboot target for the device-reboot action
    • #4196 — Show short name alongside long name on message senders (Unified Messages)
    • #4182 — Honor the "Discard invalid positions" toggle on the render side
    • #4181 — Occupancy-log-scaled, distance-capped precision offset for obscured nodes

    Bug Fixes

    • #4197 — MeshCore: own node's messages show the name, not a public key
    • #4191 — v1 default source alias deep-scopes by the resolved id (mergeParams re-derivation)
    • #4185 — Scope the compose draft per-conversation (prevents wrong-recipient sends)
    • #4184 — Keep router short-name visible in the Official pin style
    • #4180 — Traceroute no longer sends on a DISABLED channel slot (NO_CHANNEL)
    • #4175 — Drop heatmap/coverage density for deleted nodes

    Docs

    • #4179 — Meshview Link Responder added to the User Scripts Gallery

    Full changelog: https://github.com/Yeraze/meshmonitor/compare/v4.13.1-rc2...v4.13.1-rc3

    🚀 MeshMonitor v4.13.1-rc3

    📦 Installation

    Docker (recommended):

    docker run -d \
      --name meshmonitor \
      -p 8080:3001 \
      -v meshmonitor-data:/data \
      ghcr.io/Yeraze/meshmonitor:4.13.1-rc3
    

    🧪 Testing

    ✅ All tests passed ✅ TypeScript checks passed ✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7

    📋 Changes

    See commit history for detailed changes.

  16. v4.13.1-rc2 # Pre-release 21 days ago · 2026-07-17 20:04 UTC

    MeshMonitor v4.13.1-rc2

    ⚠️ Pre-release (release candidate). For testing ahead of the 4.13.1 final. No :latest Docker tags are published for RC builds.

    This RC is a Map Analysis release: it lands the full Terrain Link Profile tool and a wave of map-accuracy improvements on top of v4.13.1-rc1. Plan a link between two points and MeshMonitor now profiles the terrain between them, draws the Fresnel zone, computes a link budget, and colors a clear/marginal/obstructed verdict — with per-source auto-frequency and RX-sensitivity defaults. As you scrub the elevation graph, a marker now tracks the matching spot on the map so you can see exactly where a given point on the profile sits. Obscured-GPS (reduced precision_bits) markers are now decluttered intelligently — a node alone in its accuracy cell stays centered, and only nodes that actually share a cell are spread — applied consistently across the Dashboard, Nodes, and Map Analysis maps from one shared implementation. Position quality also got a hard look: Null Island (0,0) fixes are now rejected on ingest across Meshtastic, MeshCore, and MQTT (including the precision-obscured (0,0) fixes that used to slip through as ~0.013°), with a new Discard invalid positions Map setting to control it. The Map Analysis toolbar was tidied into icons (labels move to tooltips) to cut clutter, MQTT-sourced direct messages now render in the DM view instead of as broadcasts, and several map layers stopped drawing artifacts for marker-less nodes. Internally, the CI pipeline's Node-24 coverage hang was eliminated so future builds are faster and don't wedge.

    ✨ Features

    • Terrain Link Profile tool — profile terrain, Fresnel clearance, and link budget between two points, with clear/marginal/obstructed verdict coloring, per-source auto-frequency + RX-sensitivity defaults, DEM-void handling, and a settings UI (#4147, #4151)
    • Link Profile graph → map hover marker — moving the cursor over the elevation graph drops a marker on the map at the corresponding geographic point along the link (#4170)
    • Smarter obscured-node decluttering — the within-cell offset for low-precision_bits markers now only spreads nodes that actually share an accuracy cell; a lone node stays at its reported center (#4164, closes #4155)
    • Discard invalid positions — a new global Map setting to control whether Null Island / invalid GPS fixes are discarded on ingest (default on = current behavior) (#4158)
    • Icon toolbar for Map Analysis — action and layer buttons are now icons with the text as tooltip/aria-label, decluttering the top bar (#4171)

    🐛 Bug Fixes

    • Reject precision-obscured Null Island fixes on Meshtastic ingest — a true-(0,0) node on a reduced-precision channel arrives re-centered as ~(0.013°, 0.013°) and used to slip past the filter (#4149, #4150, #3763)
    • Route MQTT-sourced direct messages to the DM view instead of rendering them as channel/broadcast messages (#4161, closes #4152)
    • Stop drawing route segments & heatmap density for marker-less (position-stripped) nodes (#4167, closes #4162 / #4163)
    • Pin the SNR overlay dots to the merged marker position for multi-source nodes (#4169, closes #4166)

    ♻️ Refactoring

    • Consolidate the obscured-GPS within-cell offset into one shared occupancy-gated implementation used by every map surface — no more per-map "snowflake" behavior (#4168)

    🔧 CI / DevOps

    • Remove the unused coverage/Codecov runner that hung @vitest/coverage-v8 for 30+ min on Node 24, repeatedly blocking merges — CI is now faster and hang-free (#4172)

    📝 Docs

    • Link Profile documentation accuracy pass — multi-source auto-frequency, REST API reference, anchor fixes (#4156)

    Issues Resolved

    #4111 (Terrain Link Profile epic — Phases 2 & 3) · #3763 (Null Island filtering) · #4152 (MQTT directed-message rendering) · #4155 (lone-node offset) · #4162 · #4163 · #4166

    Upgrade Notes

    No breaking changes and no manual migration …

  17. v4.13.1-rc1 # Pre-release 23 days ago · 2026-07-16 17:43 UTC

    MeshMonitor v4.13.1-rc1

    ⚠️ Pre-release / Release Candidate. This build is for testing. It ships no :latest Docker tags. Please report any issues before the final 4.13.1 release.

    Summary

    This release resolves the long-running #4115 investigation where specific nodes produced zero data over MQTT: the geo filter is rearchitected from a fail-closed membership gate (which permanently blackholed GPS-less nodes and froze on encrypted feeds) to a fail-open, per-source ignore-list model with retroactive purge, automatic reappearance when a node comes back in-bounds, and a start/config-change sweep — shipped across four phases (#4123, #4131, #4132, #4136). A new MQTT Packet Monitor lands (per-gateway reception capture backend #4127 plus a gateway-aware UI #4138). Map and node UX improvements include lat/lon/elevation shown as text in Node Info/Details (#4134), Show RF/UDP/MQTT transport toggles in Map Analysis (#4135), per-theme light/dark map tilesets (#4118), and a backend elevation service for upcoming terrain link profiles (#4143). Two reported bugs are fixed: nodes can now be reliably un-hidden from the map across sources (#4141), and the Conversation page explains why the DM composer is hidden for unmessageable nodes (#4140). Also fixed: a Default Map Center regression on the Unified/Dashboard map (#4128), MeshCore-only installs whose global schedulers never started (#4146), and a stale-config Docker armv7 build (#4122). Finally, two latent cross-platform bugs surfaced during release validation were fixed: a directory case-collision that broke the macOS/Windows desktop build (#4144), and a MySQL 8 collation mismatch that aborted a migration on MySQL deployments (#4145).

    Features

    • MQTT geo-ignore rearchitecture (fixes #4115): fail-open ingestion with a per-source ignore list, retroactive purge, and auto-reappearance — #4123 (data layer), #4131 (fail-open gating), #4132 (retroactive sweep), #4136 (observability + docs)
    • MQTT Packet Monitor: per-gateway packet reception capture — #4127 (backend), #4138 (gateway-aware UI)
    • Show latitude/longitude/elevation as text in Node Info & Node Details — #4134
    • Map Analysis: Show RF / UDP / MQTT transport toggles — #4135
    • Per-theme (light/dark) map tileset preferences, including custom tiles — #4118
    • Backend elevation service for terrain link profiles (Phase 1) — #4143

    Bug Fixes

    • Reliably un-hide nodes from the map across sources; consolidate orphaned rows from removed sources — #4141
    • Explain the hidden DM composer for unmessageable nodes — #4140
    • Honor the Default Map Center setting on the Unified/Dashboard map — #4128
    • Keep global schedulers alive on MeshCore-only installs — #4146
    • Migration 122: fix illegal collation mix on MySQL 8 — #4145
    • Consolidate Mqtt/ into MQTT/ to fix the desktop-build case-collision on macOS/Windows — #4144
    • Drop deleted watchdog scripts from the armv7 Dockerfile — #4122

    Chore

    • Bump version to 4.13.1-rc1 — #4142

    Issues Resolved

    #4115, #4137, #4139, #4130, #4129, #4125, #4124, #4096, #4020

    Full changelog: https://github.com/Yeraze/meshmonitor/compare/v4.13.0...v4.13.1-rc1

    🚀 MeshMonitor v4.13.1-rc1

    📦 Installation

    Docker (recommended):

    docker run -d \
      --name meshmonitor \
      -p 8080:3001 \
      -v meshmonitor-data:/data \
      ghcr.io/Yeraze/meshmonitor:4.13.1-rc1
    

    🧪 Testing

    ✅ All tests passed ✅ TypeScript checks passed ✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7

    📋 Changes

    See commit history for detailed changes.

  18. v4.13.0 # 23 days ago · 2026-07-15 18:35 UTC

    MeshMonitor v4.13.0

    MeshMonitor 4.13.0 is the largest release of the 4.x line, stabilized through three release candidates. The headline is the Map Consolidation epic: every map surface — Dashboard, Nodes, Map Analysis, MeshCore, Unified, and embeds — now shares one rendering core, one layer library, and one popup family, so features and fixes land everywhere at once. On top of that come node selection and Follow mode, a distance-measurement tool, a polar grid overlay, and a long list of map interaction fixes. MeshCore gains message delete/purge, automatic send retries, Auto-Pathfinding target filtering, a configurable CLI timeout, and a completed Virtual Node command surface. Automations pick up multi-channel triggers, a scheduled device-reboot action, and per-source tapback routing. The long-standing "low-battery alerts silently never fire" bug — reported five separate times — is fixed at its root. Under the hood, a major architecture remediation unified the source-manager registry, moved fresh installs to migration-replay bootstrap, and deleted the legacy synchronous database API. Three deliberate breaking changes ship in this release: auto-upgrade is retired, TRUST_PROXY defaults to false, and source-scoped API endpoints require an explicit sourceId — see Upgrade Notes below. Docker users: :latest now only moves on stable releases like this one; RCs publish to :dev.

    📖 Release announcement · Full changelog

    Features

    Maps

    • Map Consolidation epic: shared BaseMap shell, layer library, unified node-marker factory, one popup family, canonical traceroute rendering on all maps including embeds — #4049, #4051, #4057, #4060, #4064, #4065, #4066, #4067, #4068 (epic #4047)
    • Node selection, emphasis & Follow mode with auto-zoom on Map Analysis — #4010, #4012 (#3788)
    • Node-to-node line-of-sight distance measurement tool on all maps — #4013 (#3636)
    • Polar grid overlay (Map Analysis, Unified, MeshCore) — #3983, #4071 (#3971)
    • Pan/zoom/spiderfy interaction polish: zoom clamp, scaled animations, zoom-gated spiderfy — #4072 (#4046)

    MeshCore

    • Delete/purge messages: per-message, per-conversation, purge-all — #3984 (#3981)
    • Automatic DM retry via same-path + flood cadence; opt-in auto-retry for automated channel sends — #3980, #3988 (#3977, #3979)
    • Auto-Pathfinding target filtering: allowlist, name regex, last-heard, hops, signal — #4039 (#4024)
    • Configurable remote/local CLI reply timeout — #4033 (#4027), honored in VN relay via #4107
    • Virtual Node: relay status requests & neighbour queries — #3991, #3993 (#3904)
    • Collapsible node list for mobile map access — #4079

    Automation

    • Multi-channel message trigger OR-list — #3982 (#3974)
    • Scheduled device-reboot action — #4002 (#3995)
    • "Send via sources" selector on the tapback action — #3997 (#3996)

    Other

    • UDP Broadcast network setting (enabled_protocols) exposed — #4113 (#4112)
    • Update-available notifications with per-deployment upgrade instructions (replaces auto-upgrade) — #4108

    Bug Fixes

    • Low-battery/inactive-node alerts lost to split per-source notification preferences — #4035 (#3417, #3462, #3671, #3884, #4020); leftover UNIQUE(user_id) autoindex dropped — #4045 (#4044)
    • Map: popup/spiderfy decoupling + obscured-marker declutter on all maps — #4022, #4028 (#4015, #4016)
    • Map: click no longer snaps view back or freezes interaction; wheel zoom, zoom-to-node, chunk-reload self-heal — #4071, #4080, #4082, #4098
    • Map: Null Island / out-of-range positions filtered from markers and line endpoints — #4077, #4078, #4099, #4101, #4103
    • Map: ROUTER_LATE renders as repeater tower — #4076 (#4075); tileset switch no longer remounts/flickers the raster layer — #4097
    • Dashboard map: neighbor lines honor the configured map endpoint — #4055 (#4042), thanks @temalo
    • MeshCore: automation DM triggers populate …
  19. v4.13.0-rc3 # Pre-release 26 days ago · 2026-07-13 18:11 UTC

    MeshMonitor v4.13.0-rc3

    ⚠️ Pre-release (Release Candidate). This build is for testing the 4.13.0 map-consolidation and MeshCore work ahead of the stable release. Not recommended for production; back up your database before upgrading.

    This release candidate builds on rc2 with a focused round of map interaction fixes and a MeshCore Virtual Node correctness fix. The map work resolves several regressions from the map-consolidation epic: click-to-pan now targets the actual node marker instead of the raw center, user gestures (zoom/pan) correctly cancel node-centering instead of snapping back and freezing, and raster tile layers no longer remount and flicker when the tileset changes. Null Island (0,0) coordinates are now filtered from both markers and line endpoints, and out-of-range/invalid node positions are detected and trimmed. Pan/zoom/spiderfy behavior was polished with a zoom clamp, scaled animations, and zoom-gated spiderfy. ROUTER_LATE nodes again render as repeater-tower icons on the NodesTab and Dashboard maps. On MeshCore, the Virtual Node login now relays the admin flag and firmware level, and the mobile node list is collapsible so the map is reachable without selecting a node. This candidate also folds in a large batch of dependency updates and a translations refresh.

    Features

    • Map: pan/zoom/spiderfy interaction polish — zoom clamp, scaled animations, zoom-gated spiderfy, re-spiderfy on zoom (#4072, resolves #4046)
    • MeshCore: collapsible node list — reach the map on mobile without selecting a node (#4079)

    Bug Fixes

    Map

    • Click pans to the node marker, not the raw center, for obscured nodes (#4082)
    • User gesture cancels node-centering — zoom no longer snaps back (#4098)
    • Fixed map snapping back to node on click and freezing interaction (#4080)
    • Stopped raster tile layer remounting on tileset change (abort/flicker) (#4097)
    • Detect and trim out-of-range (invalid) node positions (#4099)
    • Widen Null Island radius + skip it in the unified merge (#4077)
    • Null-island filter for line endpoints — routes + neighbors no longer run to 0,0 (#4078)
    • ROUTER_LATE renders as a repeater-tower icon on NodesTab + Dashboard maps (#4076, resolves #4075)
    • Integrate resolveMapEndpoint into DashboardMap neighbor lines (#4055, resolves #4042)
    • Post-epic fixes: wheel zoom, zoom-to-node, chunk-reload self-heal; MeshCore polar grid + map loading states (#4071)

    MeshCore

    • Relay admin flag + firmware level in Virtual Node login (#4095, resolves #4094)

    Translations

    • Translations update from Hosted Weblate (#4006)

    Dependencies

    • Bump the production-dependencies group with 9 updates (#4084)
    • Bump the development-dependencies group with 3 updates — @types/node, eslint, vitest (#4083)
    • Bump protobufjs 8.6.6 → 8.7.0 (#4090)
    • Bump helmet 8.2.0 → 8.3.0 (#4092)
    • Bump lucide-react 1.22.0 → 1.24.0 (#4085)
    • Bump re2 1.25.0 → 1.26.0 (#4088)
    • Bump @typescript-eslint/eslint-plugin 8.62.1 → 8.63.0 (#4089)
    • Bump @typescript-eslint/parser 8.62.1 → 8.63.0 (#4087)

    Issues Resolved

    • #4094 — MeshCore: Virtual Node functionality still does not work correctly
    • #4093 — MeshCore: Channels no longer marked unread
    • #4075 — ROUTER_LATE renders as generic pin (not repeater tower icon) on NodesTab and Dashboard maps
    • #4046 — Map UI: improve pan/zoom-to-center behavior and its interaction with marker spiderfy
    • #4042 — Dashboard Unified map: neighbor-info lines don't follow merged node marker position

    Full changelog: https://github.com/Yeraze/meshmonitor/compare/v4.13.0-rc2...v4.13.0-rc3

    🚀 MeshMonitor v4.13.0-rc3

    📦 Installation

    Docker (recommended):

    docker run -d \
      --name meshmonitor \
      -p 8080:3001 \
      -v meshmonitor-data:/data \
      ghcr.io/Yeraze/meshmonitor:4.13.0-rc3
    

    🧪 Testing

    ✅ All tests passed ✅ TypeScript checks passed ✅ Docker images built for linux/amd64, linux/arm64, linux/arm/v7

    📋 Changes

    See commit history for detailed changes.

  20. v4.13.0-rc2 # Pre-release 27 days ago · 2026-07-12 04:36 UTC

    MeshMonitor v4.13.0-rc2

    ⚠️ Pre-release — release candidate for testing; not recommended for production deployments. Docker images are not tagged :latest.

    Summary

    This release candidate lands the Map Consolidation epic (#4047): MeshMonitor's ten independent Leaflet map implementations are now one shared BaseMap shell, one composable layer library, one popup family, and one marker-icon factory. Traceroutes render identically on every surface — one canonical 4-band SNR color scale (previously three different scales), unified MQTT dashing and coloring, and the Dashboard finally renders return legs. Node markers, popups, neighbor links, and accuracy regions are likewise single-sourced, so future fixes apply to every map at once, and public embed maps now show the same canonical traceroute visuals as the app. The epic also surfaced and fixed several latent bugs, including a hidden-node position leak in the public embed traceroutes endpoint and Dashboard coloring segments with unscaled SNR values. On top of the epic, this RC brings map interaction polish (#4046): center-on-node never zooms out and its target zoom is user-configurable, pan/zoom animations scale with distance, clicking a marker at low zoom now zooms in instead of exploding a giant spiderfy fan, and open fans survive zoom changes. Live testing fixes include restored wheel/double-click zoom, correct zoom-to-node for one-way traceroutes, loading indicators on initial map data fetch, a polar grid for MeshCore maps, and a self-healing reload when a stale cached page requests rotated asset chunks after an upgrade.

    Map Consolidation Epic (#4047)

    • #4068 — Epic integration: one shell, one layer library, one popup family (phases below)
      • #4049 Phase 1 — shared BaseMap shell; pickers and editors migrated
      • #4051 Phase 2 — Map Analysis legend/polar-grid/trails reconciliation
      • #4057 Phase 3 — unified traceroute rendering across all app maps
      • #4060 Phase 4 — unified node-marker factory + shared NodeMarkersLayer
      • #4064 Phase 5 — one popup family with composable source-tech sections
      • #4065 Phase 6 — public embeds adopt canonical traceroute rendering (includes a hidden-node position leak fix 🔒)
      • #4066 / #4067 Phase 7 — shared neighbor-links/accuracy/waypoints layers; all maps on BaseMap

    Features

    • #4072 — Map interaction polish: zoom clamp with configurable target (default 17), distance-scaled animations, zoom-gated spiderfy with zoom-in-first clicks, re-spiderfy after zoom (#4046)
    • #4071 — MeshCore map polar grid; map loading indicators during initial fetch

    Bug Fixes

    • #4071 — Wheel/double-click zoom restored on all maps; zoom-to-node no longer hijacked by route-fit on one-way traceroutes; one-time reload on stale-chunk load failures after upgrades
    • #4055 — Dashboard neighbor-info lines follow the merged node marker position (#4042) — thanks @temalo!
    • #4045 — Notifications: drop inline autoindex UNIQUE(user_id) missed by migration 079 (#4044)

    Issues Resolved

    • #4047 — Consolidate 10 independent Leaflet maps into a shared BaseMap shell + composable layer library
    • #4046 — Map UI: improve pan/zoom-to-center behavior and its interaction with marker spiderfy
    • #4042 — Dashboard Unified map: neighbor-info lines don't follow merged node marker position
    • #4044 — Can't configure Apprise Notifications for a second source

    Upgrade Notes

    • Map visuals converge to one canonical look: the per-source Nodes map moves from a 3-band to the 4-band SNR color scale, no-data segments render dashed gray, the Dashboard gains traceroute return legs, the traceroute widget's legs use the theme color, and embeds show SNR-colored traceroutes instead of uniform mauve.
    • New per-user setting: Settings → Map → center-on-node target zoom (default 17).

    Full Changelog: https://github.com/Yeraze/meshmonitor/compare/v4.13.0-rc1...v4.13.0-rc2

    🚀 MeshMonitor v4.13.0-rc2

    📦 Installation

    Docker (recommended):

    docker run
    …