First-frame latency drops by another 1-2 s on cold-cache plays: 1. HLS segment duration halved from 4 s to 2 s. seg-0 lands in ~half the wait time — the player paints the first frame as soon as it arrives. Software encodes on 4K go from ~3 s wait to ~1.5 s; HW encoders shave ~0.5 s. Trade-off: 2× segment count per source (~3600 segments for a 2 h movie instead of ~1800), but each is half the size on disk. Within HLS spec — Apple recommends 6 s, but 2 s is valid; LL-HLS uses 1-2 s. 2. Cache from 0.9.9 self-heals: cached entries used 4 s segments; VerifyComplete now expects a different highest segment index and invalidates them, triggering a re-encode on next play. No manual cleanup needed. 3. OnStreamSession daemon callback now runs StartHLSSession in a goroutine. Sync HTTP responses return immediately (~50 ms instead of waiting for the ~0.3-1 s ffprobe). Other pending actions in the same sync cycle (new tasks, deletes) no longer wait for the transcoder warmup. Browser HEAD probes already have a 30 s retry budget that covers the brief gap between playerSessionRegistry.add and streamSrv.HLS().Register. Helpers added (engine.segmentDurationFor / segmentStartSec / segmentCountForDuration) so a future short-first-segment variant or non-uniform layout can slot in without touching every call site. Internal: -hls_init_time was investigated but discarded — ffmpeg's implementation treats it as a min duration, not a target, so it couldn't deliver a uniformly 2 s first segment on top of a 4 s steady state. Uniform 2 s is simpler and gets the same first-frame win.
23 KiB
23 KiB
Changelog
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.9.10] - 2026-05-27
Changed
- HLS segments halved from 4 s to 2 s. seg-0 now lands in ~half the
cold-cache wait time, so the player paints the first frame ~1-2 s
sooner on software encodes (~0.5 s sooner on HW encoders). Trade-off:
2× more segments per source (a 2 h movie produces ~3600 segments
instead of ~1800), but each is half the size. Well within HLS spec
— Apple recommends 6 s but 2 s is also valid; LL-HLS uses 1-2 s.
Existing 0.9.9 cache entries fail
VerifyComplete(the new segment count expects different file names at the boundary) and are invalidated + re-encoded transparently on next play. Self-healing, no manual cleanup needed. OnStreamSessiondaemon callback now runsStartHLSSessionin a goroutine instead of blocking the sync HTTP loop on ffprobe (~0.3-1 s typical). Net: sync responses return immediately, and any other pending actions in the same response (new tasks, deletes) no longer wait for ffmpeg to warm up. Browser HEAD probes already have a 30 s retry budget that absorbs the brief window betweenplayerSessionRegistry.addandstreamSrv.HLS().Register.
[0.9.9] - 2026-05-27
Added
- per-session encoder log: every HLS session start now logs
encoder=… accel=… preset=…so a "preparando sesión" complaint can be triaged from the journal alone. Cache-HIT sessions keep the existing simpler log (no ffmpeg involved). - probe cache:
engine.ProbeFileis memoised by(path, mtime, size)for 30 minutes. A second play of the same file skips ffprobe entirely — saves 1-3 s on first-segment latency for 50+ GB MKVs. Cache key changes immediately on any file rewrite (mtime or size delta). - agents tab transcoder row: the web profile → agents tab now shows
each agent's selected encoder (
NVIDIA NVENC,Intel Quick Sync,VA-API,macOS VideoToolbox, orSoftware (libx264)in amber) plus the comfortable transcode-resolution cap. Surfaces the same diagnostic the daemon log carries.
Changed
- HLS encoder presets biased for first-start latency:
- libx264: default
veryfast→superfast(~15-20% faster encode; marginal quality loss at 5-25 Mbps target bitrates). Users wanting the previous quality can setdownload.transcode.preset = "veryfast"inconfig.toml. - NVENC:
-preset p4 -tune hq→-preset p3 -tune ll. First-segment encode drops from ~1.5 s to ~0.8 s on RTX-class GPUs. - QSV:
-preset medium→-preset veryfast. Keeps-look_ahead 0for low-latency rate control. - VideoToolbox (macOS): adds
-realtime 1 -q:v 50(was unset). Therealtimeflag steers VideoToolbox into the low-latency code path.
- libx264: default
- Encoder + preset selection moved into
engine.ResolveEncoderProfileso the same logic drives both argv construction and the log line. download.transcode.presetis now libx264-only. The configured preset is honoured on software encode (libx264 vocabulary: ultrafast → veryslow); HW backends ignore it and use vendor-specific defaults (NVENC p3, QSV veryfast). Passing a libx264 preset to NVENC / QSV was previously rejected by ffmpeg; the documentation now reflects what was always the only correct usage.- Default
download.transcode.presetis empty (was"veryfast"). The engine fills in"superfast"for libx264 — latency-biased. Users who want better quality at slower first-play should set it explicitly inconfig.toml:"veryfast"(previous default) /"faster"/"fast"/"medium". Range documented in the TranscodeConfig struct.
[0.9.8] - 2026-05-27
Fixed
- auto-upgrade restart loop: when the server signal arrived for a version
the daemon was already running (e.g. flag still set after a previous
upgrade),
applyAutoUpgradewould callupgrade.Execute(which no-ops), thenos.Exit(0)anyway — systemd respawned, the flag was still set, the cycle repeated. Now: no-op case is detected up front, the daemon clears the server flag via/api/internal/agent/upgrade-resultand stays alive. - upgrade flag stuck after success: the CLI never reported the upgrade
outcome, so
upgrade_requestedstayedtruein the DB forever. The daemon now calls/api/internal/agent/upgrade-resulton every applyAutoUpgrade branch (success, failure, no-op) — server clears the flag, restart loops end.
Added
- New
Client.ReportUpgradeResult(agentID, success, version, error)HTTP method wrappingPOST /api/internal/agent/upgrade-result.
[0.9.7] - 2026-05-26
Added
- hls cache: persistent fMP4 segment cache keyed by
(source, quality, audio_index). After a successful encode the segmentsinit.mp4are kept under~/.cache/unarr/hls-cache/{key}/with a.completemarker. A second play of the same file at the same quality skips ffmpeg entirely (smoke-tested 23–31× faster than re-encode). LRU- size-budget eviction; pinned during active play; per-key writer-lock
prevents two concurrent encodes from corrupting each other. Startup
reaps orphan dirs without
.completeolder than 10 min so a daemon crash doesn't leak disk indefinitely. New[downloads.hls_cache]block inconfig.toml:enabled(default true),size_gb(default 5, min 1),dir(default~/.cache/unarr/hls-cache).
- hls cache integrity check: on HIT, the daemon stats
init.mp4+ last segment before reporting cache reuse — if a file was externally deleted, the entry is invalidated and re-encoded transparently. - hls cache stats: hit/miss counters surface via
cache.Stats()(Hits,Misses,EntryCount,TotalBytes) and the sweeper logs a daily summary line[hls_cache] day-stats: hits=N misses=M ratio=X% entries=Y size=ZMB. - subtitle integrity for cached replay:
Closewaits up to 15 s for the subtitle extractor goroutine before sealing.completeso a HIT never serves half-written.vttfiles. Timeout invalidates instead of sealing.
Changed
[daemon] auto_upgradenow appears in freshconfig.tomlfiles astrue(it was always the implicit default; this just makes it visible in default-generated configs).
[0.9.6] - 2026-05-26
Added
- auto-upgrade: when the web flags the agent for upgrade
(
POST /api/internal/agent/upgradeor the "Force update now" button), the daemon now downloads and replaces the binary in-place, then exits so the service supervisor (systemd Restart=alwayson Linux, the equivalent on macOS/Windows) respawns on the new version. Nounarr updatestep required from the user. Still opt-in — only fires when the server sends the upgrade signal.
Changed
- The
OnUpgradedaemon callback no longer just logsrun unarr self-update; it now triggers the actual upgrade in a background goroutine.
[0.9.5] - 2026-05-26
Added
- funnel: optional CloudFlare Quick Tunnel subprocess.
unarr funnel onspawnscloudflaredas a child process and registers an anonymoushttps://<random>.trycloudflare.comhostname tunnelled to the daemon's HLS server. The hostname is reported back to the web on every sync so the in-browser player picks it up automatically — cross-network playback now works on torrentclaw.com without Tailscale or port forwarding. Bytes proxy through CloudFlare; TorrentClaw still doesn't relay content. - funnel: on by default for fresh installs (NAS/Docker get cross-network
HTTPS automatically); existing configs that pre-date the feature stay
off until the operator runs
unarr funnel on. - funnel: auto-downloads cloudflared to the unarr data dir when not on
PATH (Linux amd64/arm64/armhf/386). ELF magic + size sanity check on the
download;
O_EXCLpartial-write so concurrent daemons don't clobber each other. - funnel: subprocess supervisor keeps the tunnel up across cloudflared crashes + CF's ~6h Quick Tunnel rotation. Exponential backoff (2 s → 5 min) on persistent failures. The web's reported URL is cleared the moment cloudflared exits so an outdated hostname doesn't keep handing out 502s.
- funnel:
unarr funnel statusshows the live URL once registered. See README §[downloads.funnel]for the throughput / latency caveats of CF's free Quick Tunnels. - docker: the official
torrentclaw/unarrimage now bundlescloudflaredso the funnel works the moment the container starts — no first-run download.
Fixed
- hls/libx264: bump the H.264 level we hint to libx264 by one tier so
anamorphic (>16:9) sources stop emitting unplayable streams. 720p at
level 3.1 silently rejected 1728×720 cinemascope frames with
frame MB size > level limit; 720p now ships at level 4.0, 1080p at 4.1. Decoder compatibility is unaffected — every device that handles 1080p already handles ≥ 4.1.
[0.9.4] - 2026-05-26
Removed
- streaming: retire the custom WebRTC DataChannel pipeline. The daemon no longer ships pion/webrtc, the WSS signaling client, or the wire framing package — every in-browser session now uses HLS over HTTP from the daemon (Tailscale / LAN / UPnP). Browser P2P (WebTorrent) bytes never re-enabled.
- config:
[downloads.webrtc]block removed from the TOML schema; existing config files with the section parse cleanly because go-toml ignores unknown sections. - seed_file:
mode=seed_filetask handler +engine.SeedFilehelper dropped — the last in-browser caller was retired with the WebRTC player. - wstracker-probe: standalone probe binary removed.
Changed
- agent wire:
SyncResponse.WebRTCSessions(JSON:webrtcSessions) renamed toStreamSessions(JSON:streamSessions). The Go typeagent.WebRTCSessionis nowagent.StreamSession. Wire-incompatible with web < 2026-05-26. - torrent:
buildMagnetno longer accepts anextraTrackersvariadic — the default tracker list is the only set used.
Fixed
- hls: clamp the ffmpeg
-b:vto the bitrate cap derived from the EFFECTIVE output height instead of the requested quality. Previously asking for "2160p" on a 1080p source overshot the H.264 level we resolved from the effective height (4.0, max 20 Mbps) and made libx264 abort withVBV bitrate > level limit.
[0.9.2] - 2026-05-21
Added
- vpn:
unarr vpncommand (status,enable,disable) to manage the managed WireGuard split-tunnel, withvpn status --checkto verify provisioning. - vpn: report split-tunnel state (active, exit server) to the web on register
- every sync, so the dashboard shows which agent holds the single WireGuard slot.
- vpn: send the agent id when fetching the VPN config so the web can arbitrate the single WireGuard slot — the first agent claims it; the rest are told to run OpenVPN on their own host (1 agent on WireGuard + up to 9 on OpenVPN).
[0.9.1] - 2026-05-21
Added
- mirror: update fallback URLs to use IPFS and remove GitHub Pages
Fixed
- security: bump golang.org/x deps and add container CVE scan gate
[0.9.0] - 2026-05-21
Added
- agent: add mirror failover, agent client refactor, status 401 detection
- vpn: local config_file for self-hosted/personal VPN testing
- vpn: split-tunnel torrent traffic through managed WireGuard
Documentation
- docker: refresh Docker Hub README + sync description in CI
Fixed
- security: CORS allowlist, URL scheme guard, state perms, ZIP slip, mirror docs
- security: UPnP opt-in, bounded SSE reader, signed self-update
- security: harden HLS session IDs, /health disclosure, archive password handling
- upgrade: fetch releases from TorrentClaw app, not GitHub
Other
- release: 0.9.0
[0.8.1] - 2026-05-08
Added
- config: set default values for WebRTC and transcoding in minimal TOML config
- transcode: dynamic H.264 level + HW probe + capability reporting
Changed
- streaming: improve signal handling and remove unused components
Fixed
- self-update: auto-restart live daemon after upgrade
- streaming: allow HLS sessions when webrtc disabled
Other
- gitignore: add dist-ffbinaries to ignored files
- release: 0.8.1
[0.8.0] - 2026-05-08
Added
- mediainfo: ResolveFFmpeg + DownloadFFmpeg mirroring ffprobe pattern
- release: bundle ffmpeg + ffprobe in tarballs and Docker image
- seed-file: unarr-side handler for browser-on-demand seeding (Fase 4.7.c)
- stream: per-session quality cap from web
- stream: real-time transcoding for non-browser-decodable codecs
- stream: pion-based WebRTC byte streamer for browser playback
- streaming: seek-restart, single-session, idle sweeper, probe.json
- streaming: add HLS transport pipeline (daemon side)
- streaming: ffmpeg transcoding pipeline (direct play / fMP4 / HW accel)
- torrent: act as WebTorrent peer for browser ↔ unarr P2P streaming
- wstracker-probe: -seed FILE mode for browser ↔ unarr e2e validation
Fixed
- streaming: bounded ffmpeg auto-restart + tmpdir gc + probe/stderr safety
- transcoder: force aac stereo 48khz + frag_duration for mse compat
- transcoder: force main profile + setparams Rec.709 + serveRange wait
- transcoder: correct scale filter + always force yuv420p
Other
- release: 0.8.0
- streaming: post-review fixes — race lock, dead branch, stderr cap
- torrent: bump anacrolix log level Critical → Warning for visibility
[0.7.0] - 2026-04-10
Added
- daemon: enhance service management with start, stop, restart, and status commands for Windows
Other
- release: 0.7.0
[0.6.8] - 2026-04-10
Added
- library: add server-driven file deletion with allow_delete config
Other
- release: 0.6.8
[0.6.7] - 2026-04-10
Added
- scan: always scan downloads + organize dirs, deduplicate child paths
Other
- release: 0.6.7
[0.6.6] - 2026-04-09
Fixed
- docker: switch ffprobe download from johnvansickle.com to BtbN/FFmpeg-Builds
- stream: fix black screen on remote/Tailscale streaming
Other
- release: 0.6.6
[0.6.5] - 2026-04-09
Fixed
- upgrade: retry download on transient network errors with user feedback
Other
- release: 0.6.5
[0.6.4] - 2026-04-09
Fixed
- daemon: report error status when stream path is rejected
Other
- release: 0.6.4
[0.6.3] - 2026-04-09
Fixed
- library: use native arm64 ffprobe on Apple Silicon (osx-arm-64)
Other
- release: 0.6.3
[0.6.2] - 2026-04-09
Added
- library: resilient scan for large libraries and better ffprobe errors
Other
- release: 0.6.2
- ignore local config/ directory
[0.6.1] - 2026-04-08
Added
- wake: long-poll wake listener for instant CLI sync
Fixed
- resolve deadlock, data races and path traversal vulnerabilities
[0.6.0] - 2026-04-08
Added
- sync: replace WS+DO transport with unified HTTP sync
Fixed
- ws: add ping/pong keepalive and read deadline to detect zombie connections
Other
- release: 0.6.0
[0.5.5] - 2026-04-07
Added
- agent: send stream port and IPs in register request
- stream: report duration and position in watch progress
- stream: trackingReader with byte-based progress and rate limiting
Fixed
- daemon: cancel watch reporter on stream switch and re-notify ready
Other
- release: 0.5.5
[0.5.4] - 2026-04-07
Fixed
- stream: use platform-specific socket options for Windows cross-compilation
Other
- release: 0.5.4
[0.5.3] - 2026-04-07
Added
- stream: persistent stream server with file swapping
Other
- release: 0.5.3
[0.5.2] - 2026-04-07
Added
- stream: report multi-network URLs for smart resolution
Other
- release: 0.5.2
[0.5.1] - 2026-04-07
Added
- daemon: add on-demand library scan via heartbeat and WebSocket
Fixed
- agent: add retry with backoff and WebSocket connect for daemon registration
- daemon: report failed status on stream request errors
- daemon: use correct systemd user target and isolate test cache
- stream: prevent duplicate events from killing active stream server
Other
- release: 0.5.1
[0.5.0] - 2026-04-06
Added
- organize: use server metadata for file organization and subtitle handling
- stream: add NAT-PMP port mapping for remote downloads
Other
- release: 0.5.0
- release: add changelog generation and release automation
[0.4.1] - 2026-04-01
Added
- cli: add login command and refactor shared helpers
- stream: report watch progress to API via HTTP Range tracking
Fixed
- ci: fix lint errors and pin CI to Go 1.25
- lint: remove unused newStubCmd function
Other
- cli: remove moreseed stub command
- cli: remove redundant stub commands (monitor, open, add, compare)
[0.4.0] - 2026-03-31
Added
- cli: upgrade command, rich status, and version cache
Fixed
- progress: always report status transitions and poll for control signals
[0.3.7] - 2026-03-31
CI/CD
- docker: remove dockerhub-description sync step
[0.3.6] - 2026-03-31
CI/CD
- deps: bump docker/metadata-action from 5 to 6
- deps: bump docker/setup-qemu-action from 3 to 4
- deps: bump docker/login-action from 3 to 4
- deps: bump docker/build-push-action from 6 to 7
- deps: bump codecov/codecov-action from 5 to 6
- docker: add Docker Hub description sync and DOCKERHUB.md
Fixed
- ci: upgrade golangci-lint to v2.11.3 for Go 1.25 support
- docker: upgrade alpine packages to patch CVE-2025-60876 and CVE-2026-27171
- lint: use default:none to disable errcheck, fix all gofmt and exhaustive
- lint: disable errcheck, tune gosec/exclusions for codebase state
- lint: configure linters for codebase maturity, fix gofmt and ineffassign
- lint: exclude common fire-and-forget patterns from errcheck
- lint: resolve errcheck and bodyclose warnings for golangci-lint v2
[0.3.5] - 2026-03-30
Changed
- migrate lint config to v2, remove daemon auto-upgrade, add trust badges
[0.3.3] - 2026-03-30
Fixed
- ci: remove go-client checkout steps
[0.3.2] - 2026-03-30
Added
- init: add 60s countdown, skip key, and cancel detection to browser auth
CI/CD
- release: add Docker Hub publish and VirusTotal scan jobs
Documentation
- add beta notice, fix install URLs to get.torrentclaw.com
Fixed
- ci: fix virustotal job condition syntax
- docker: simplify Dockerfile for CI builds (no local go-client)
- release: disable homebrew tap (needs PAT, not GITHUB_TOKEN)
Other
- re-enable homebrew tap in goreleaser
[0.3.1] - 2026-03-30
Fixed
- build: unused variable in Windows process check
- release: disable homebrew tap until repo is created
Other
- rename module from torrentclaw-cli to unarr
Build
- remove UPX compression (antivirus false positives, startup penalty)
[0.3.0] - 2026-03-29
Added
- agent: add WebSocket transport with HTTP fallback
- auth: browser-based CLI authentication (like Claude Code)
- daemon: add auto-scan, force start, and stall timeout default
- debrid: add HTTPS downloader for debrid direct URLs
- stream: UPnP port forwarding for remote video playback
- usenet: implement full NNTP download pipeline
- add migrate command, media server detection, and debrid auto-config
- replace setup with init wizard + interactive config menu
- add clean command to remove temp files, logs, and cached data
- add Sentry error reporting
- improve daemon resilience, streaming, and usenet downloads
- initial commit — unarr CLI
Changed
- extract BuildSyncItems to library package, remove duplication
Documentation
- improve CLI help, shell completion, and README
Fixed
- torrent: expand tracker list, add DHT persistence and configurable timeouts
- force-start tasks bypass HasCapacity check in dispatch loop
- add panic recovery to auto-scan, cap DHT nodes at 200
- harden usenet/debrid downloaders from critico review
Build
- add -s -w -trimpath to Makefile, add build-small target with UPX [0.9.1]: https://github.com/torrentclaw/unarr/compare/v0.9.0...v0.9.1 [0.9.0]: https://github.com/torrentclaw/unarr/compare/v0.8.1...v0.9.0 [0.8.1]: https://github.com/torrentclaw/unarr/compare/v0.8.0...v0.8.1 [0.8.0]: https://github.com/torrentclaw/unarr/compare/v0.7.0...v0.8.0 [0.7.0]: https://github.com/torrentclaw/unarr/compare/v0.6.8...v0.7.0 [0.6.8]: https://github.com/torrentclaw/unarr/compare/v0.6.7...v0.6.8 [0.6.7]: https://github.com/torrentclaw/unarr/compare/v0.6.6...v0.6.7 [0.6.6]: https://github.com/torrentclaw/unarr/compare/v0.6.5...v0.6.6 [0.6.5]: https://github.com/torrentclaw/unarr/compare/v0.6.4...v0.6.5 [0.6.4]: https://github.com/torrentclaw/unarr/compare/v0.6.3...v0.6.4 [0.9.10]: https://github.com/torrentclaw/unarr/compare/v0.9.9...v0.9.10 [0.9.9]: https://github.com/torrentclaw/unarr/compare/v0.9.8...v0.9.9 [0.9.8]: https://github.com/torrentclaw/unarr/compare/v0.9.7...v0.9.8 [0.9.7]: https://github.com/torrentclaw/unarr/compare/v0.9.6...v0.9.7 [0.9.6]: https://github.com/torrentclaw/unarr/compare/v0.9.5...v0.9.6 [0.9.5]: https://github.com/torrentclaw/unarr/compare/v0.9.4...v0.9.5 [0.9.4]: https://github.com/torrentclaw/unarr/compare/v0.9.2...v0.9.4 [0.9.2]: https://github.com/torrentclaw/unarr/compare/v0.9.1...v0.9.2 [0.9.1]: https://github.com/torrentclaw/unarr/compare/v0.9.0...v0.9.1 [0.9.0]: https://github.com/torrentclaw/unarr/compare/v0.8.1...v0.9.0 [0.8.1]: https://github.com/torrentclaw/unarr/compare/v0.8.0...v0.8.1 [0.8.0]: https://github.com/torrentclaw/unarr/compare/v0.7.0...v0.8.0 [0.7.0]: https://github.com/torrentclaw/unarr/compare/v0.6.8...v0.7.0 [0.6.8]: https://github.com/torrentclaw/unarr/compare/v0.6.7...v0.6.8 [0.6.7]: https://github.com/torrentclaw/unarr/compare/v0.6.6...v0.6.7 [0.6.6]: https://github.com/torrentclaw/unarr/compare/v0.6.5...v0.6.6 [0.6.5]: https://github.com/torrentclaw/unarr/compare/v0.6.4...v0.6.5 [0.6.4]: https://github.com/torrentclaw/unarr/compare/v0.6.3...v0.6.4 [0.6.3]: https://github.com/torrentclaw/unarr/compare/v0.6.2...v0.6.3 [0.6.2]: https://github.com/torrentclaw/unarr/compare/v0.6.1...v0.6.2 [0.6.1]: https://github.com/torrentclaw/unarr/compare/v0.6.0...v0.6.1 [0.6.0]: https://github.com/torrentclaw/unarr/compare/v0.5.5...v0.6.0 [0.5.5]: https://github.com/torrentclaw/unarr/compare/v0.5.4...v0.5.5 [0.5.4]: https://github.com/torrentclaw/unarr/compare/v0.5.3...v0.5.4 [0.5.3]: https://github.com/torrentclaw/unarr/compare/v0.5.2...v0.5.3 [0.5.2]: https://github.com/torrentclaw/unarr/compare/v0.5.1...v0.5.2 [0.5.1]: https://github.com/torrentclaw/unarr/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/torrentclaw/unarr/compare/v0.4.1...v0.5.0 [0.4.1]: https://github.com/torrentclaw/unarr/compare/v0.4.0...v0.4.1 [0.4.0]: https://github.com/torrentclaw/unarr/compare/v0.3.7...v0.4.0 [0.3.7]: https://github.com/torrentclaw/unarr/compare/v0.3.6...v0.3.7 [0.3.6]: https://github.com/torrentclaw/unarr/compare/v0.3.5...v0.3.6 [0.3.5]: https://github.com/torrentclaw/unarr/compare/v0.3.3...v0.3.5 [0.3.3]: https://github.com/torrentclaw/unarr/compare/v0.3.2...v0.3.3 [0.3.2]: https://github.com/torrentclaw/unarr/compare/v0.3.1...v0.3.2 [0.3.1]: https://github.com/torrentclaw/unarr/compare/v0.3.0...v0.3.1 [0.3.0]: https://github.com/torrentclaw/unarr/releases/tag/v0.3.0