All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

0.1.0 - 2026-08-03

Four mesh-daemon strategies and their shared discovery pipeline.

Added

  • Cluster.Strategy.TailscaleLocal — peer discovery via tailscale status --json, working with Tailscale and with Headscale-based control servers, and needing no API key
  • Cluster.Strategy.LolipopZTL — peer discovery via ztlctl status
  • Cluster.Strategy.Netbird — peer discovery via netbird status --json
  • Cluster.Strategy.WireGuard — peer discovery via wg show <if> dump for plain WireGuard meshes, selecting members by IPv4 CIDR and treating peers with a recent handshake as online
  • cidr member selection (LibclusterMesh.CIDR) alongside hostname prefixes
  • LibclusterMesh.Runner, a behaviour for running the mesh CLI, with a timeout-guarded port-based default that reports a missing binary or a hung daemon rather than raising, and signals a command outliving its timeout so that a wedged daemon cannot leave one behind on every poll
  • Config validated at startup by LibclusterMesh.Config.new!/3

Notes

  • Publishing is triggered by pushing a v* tag. The workflow refuses a tag whose version disagrees with mix.exs, or one with no section in this file, because a version on hex cannot be corrected or reused.
  • A config key a strategy does not support raises ArgumentError at startup rather than being ignored. This is the failure that is hardest to diagnose otherwise: a mistyped or misplaced key means no peer ever matches, so the cluster never forms and nothing says why. socket is part of that — only Cluster.Strategy.LolipopZTL takes one.
  • A daemon that answers with the right key and the wrong shape is an error, not an empty peer list. A strategy that keeps polling and finds nobody looks exactly like a mesh with nothing on it, so each parser guards its "no peers" clause on the key being absent rather than letting it catch everything — %{} matches every map in Elixir.