Rayfish Dev
xyz.rayfish.android.dev
Zapstore _@zapstore.dev Republished from GitHub / F-Droid by the Zapstore main account.
First release: Aug 15, 2026, 8 total releases.
Most recent release: Sep 28, 2026.
Appears in 0 app stacks.
0 sats / 0 zaps received in the past year.
Sats Received
Underlying data available via MCP: app_zaps, app_releases.
Zap Count
Underlying data available via MCP: app_zaps, app_releases.
Releases
- Sep 28, 2026 0.5.3### Features - Add firewall rules to desktop UIs ### Bug Fixes - Serve macOS app SSH outside the tunnel extension - Align firewall rule controls - Prevent duplicate daemon from creating a tunnel
More…
- **dns**: Configure Magic DNS on FreeBSD - **dns**: Stop FreeBSD configuration retries - Enter Tokio runtime before opening Apple TUN ### Performance - Clarify direct TUN ingress benchmarks - Use NetworkExtension utun directly ### Refactor - Simplify request and interface parsing - **dns**: Simplify FreeBSD resolver state ### Documentation - Scope firewall changelog entry ### Miscellaneous - Release - Merge latest master into FreeBSD DNS work - Merge latest master into FreeBSD DNS work - Merge master into FreeBSD DNS work - Merge latest master into Apple direct TUN work - Merge latest master into Apple direct TUN work - Merge master into Apple direct TUN work **Full Changelog**: https://github.com/rayfish/rayfish/compare/v0.5.2...v0.5.3 - Sep 25, 2026 0.5.2### Features - Restore Intel macOS support ### Bug Fixes - Update Windows SSH server stub - Correct mesh authorization and add macOS access controls
More…
### Testing - Tolerate slow Windows process startup - Skip Unix SSH checks on Windows ### CI - Update actions to Node.js 24 ### Miscellaneous - Release - Release **Full Changelog**: https://github.com/rayfish/rayfish/compare/v0.5.1...v0.5.2 - Sep 25, 2026 0.5.1### Features - **desktop**: Add start at login setting - **windows**: Match macOS desktop UI - **windows**: Add desktop app - Recover machine inventory with signed enrollment receipts ### Bug Fixes
More…
- **mesh**: Retry when a replacement connection never arrives - **mesh**: Allow immediate rejoin after kick - **mesh**: Revoke kicked peers immediately - **mesh**: Remove kicked networks locally - **release**: Keep desktop installers stable-only - Retain management v1 support alongside receipt recovery - Resolve user targets by name ### Refactor - **macos**: Simplify Apple tunnel bridge (#186) ### Documentation - Simplify project readme - Update changelog for v0.5.0 ### Miscellaneous - Release - Merge origin master - Merge master into connection recovery fix - Merge master into Windows desktop branch **Full Changelog**: https://github.com/rayfish/rayfish/compare/v0.5.0...v0.5.1 - Sep 24, 2026 0.5.0### Features - **macos**: Add native app and signed installers (#180) - **macos**: Show controlled machines and add peer and DNS controls - Add delegated machine control - **macos**: Automate notarized releases and add branded installer - **macos**: Integrate native app with original Rust CLI - **macos**: Install bundled ray command - **macos**: Add tunnel-backed ray command
More…
- **macos**: Approve join requests from dashboard - **macos**: Rename hosts from network cards - **macos**: Refresh dashboard tunnel status - **macos**: Leave networks from dashboard - **macos**: Create network invites from dashboard - **macos**: Show live devices and connection state - **macos**: Migrate legacy daemon state on connect - **macos**: Add safe legacy state migration - **macos**: Wire dashboard to tunnel provider - **macos**: Activate system extension before connect - **macos**: Add native tunnel app foundation - **pair**: Add 1Password identity backup ### Bug Fixes - **macos**: Align DNS switches to the right - **macos**: Pass the binary before lipo architecture checks - **dns**: Update live_upstreams doc for the two-timeout dead set - **dns**: Address review feedback - **dns**: Keep Magic DNS up when the router drops root-NS probes - **macos**: Keep tray open when toggling the connection - **dns**: Enable Magic DNS on fresh installs - Accept network keys in delegated joins - **config**: Address account lookup review - **config**: Use reentrant user/group lookups (musl heap crash) - Flush management replies before closing - Correct managed control edge cases - Exclude unix update label on windows - **ssh**: Offer no compression, so zlib clients keep their sessions - **macos**: Use provider messaging and correct open shortcut - **macos**: Open the dashboard on the active desktop - **macos**: Refresh open menus and hide the dashboard on close - **macos**: Improve tray controls and concurrent shutdown - **macos**: Use valid system extension entitlement - **macos**: Use production bundle identifiers - **macos**: Install xcodegen for local builds - **macos**: Support macos 13 empty states - **macos**: Start tunnel system extension - **windows**: Gate update label test - **macos**: Link tunnel extension dependencies - **macos**: Pass tunnel packet data directly - **macos**: Match packet flow callback - **macos**: Expose uniffi module map - **windows**: Gate unix update label - **macos**: Compile generated bridge inline - **macos**: Use tunnel provider sessions - **macos**: Use explicit command entry point - **ci**: Generate macos project in its directory - **cli**: List dns in help - **macos**: Preserve hostnames during onboarding - **macos**: Reject linked migration directories - **macos**: Require shared extension storage - **macos**: Preserve packet address families - **cli**: Clarify backup and nightly update errors - **pair**: Store backups in secure notes - **pair**: Rely on 1Password vault encryption ### Refactor - Format machine state directly - Use standard string conversions - Use typed enrollment tickets - **macos**: Simplify app internals ### Documentation - Preserve wire protocol rules in project instructions - Consolidate project instructions in AGENTS.md ### Testing - **macos**: Avoid opening a listener for stale IPC socket fixture ### CI - **macos**: Run checks without building the full app - **macos**: Limit DMG builds to versioned and manual releases - Use Ubuntu 20.04 for the old-glibc installer smoke test - **macos**: Build notarized DMGs for nightly and manual CI runs - Allow manual validation runs - **macos**: Build native app and bindings ### Build - **macos**: Publish app and daemon for Apple Silicon only - **macos**: Bundle ray command ### Miscellaneous - Release - Release - Ignore local macOS signing entitlements - Merge master into macOS app branch - Merge master into macOS app branch ### Other - Update update.rs Fix build on FreeBSD - Add DNS toggle - Fix network handle announcements after stopped reconnect replies - Forward queries to mesh peer resolvers - Test universal mesh connection selection and reconnect reuse - Select mesh connections by a shared TLS session ID - Fix CI checks for file transfer cancellation - Allow cancelling active file sends - Fix CI platform and truncation checks - Extract Android idle transport supervisor - Fix platform-specific atomic import - Keep suspend state Android-only - Avoid transport state swap on active packets - Suspend idle Android mesh transport - Extract SSH session runners - Simplify core runtime modules - Fix simultaneous peer connection selection - Fix peer connection replacement **Full Changelog**: https://github.com/rayfish/rayfish/compare/v0.4.2...v0.5.0 - Sep 19, 2026 0.4.2### Features - Keep mesh protocol 5 peers compatible - **mesh**: Raise the tunnel MTU to 1500 bytes - **tun**: Name the Linux interface rayfish0 instead of tun0 ### Bug Fixes - Support longer LAN discovery cadence and format Kotlin bindings
More…
- **android**: Retry file notification reconciliation failures - **android**: Skip unsupported desktop DNS setup - **android**: Regenerate identity backup bindings - **android**: Filter network updates that waste battery - Restore paired device state from identity backups - **ssh**: Keep idle sessions alive with keepalives - **ci**: Skip retired Android SDK tools package - **mesh**: Fall back to a 1280-byte TUN and honor peer MTU limits - **mesh**: Fragment packets that exceed the QUIC datagram limit - **dns**: Treat a loopback upstream as a possible loop back into us - **dns**: Re-point the forwarder at resolvers that still answer - **dns**: Name our interface in the macOS Setup: store - **ssh**: Drop a mesh SSH connection that never authenticates - **windows**: Decode the installer checksum response before parsing - **join**: Report why fetching the group blob failed - **windows**: Stop the five-second network-record republish loop - **macos**: Keep the mesh alive under another VPN's kill switch - **dns**: Stop the OS-DNS retry loop when the node goes offline - **transport**: Drop direct-address candidates the host cannot route - **tun**: Set the Linux TUN link state over netlink - **dns**: Re-assert macOS DNS after another VPN deletes it ### Performance - **android**: Observe file changes instead of polling while idle - Reduce background mDNS traffic and duplicate events - Make per-packet TUN logging opt-in - **forward**: Batch datagram reads and lazy-dial flushes ### Refactor - Split DNS, exit node, and daemon modules ### Documentation - **mesh**: Explain why QUIC datagrams need fragmentation - **changelog**: Cut the 0.4.1 section ### CI - Cut duplicate compiles and stop PR runs from evicting the cache ### Build - Use pinned mDNS fork instead of vendored source ### Miscellaneous - Release ### Other - Add opt-in periodic Android diagnostics - Alias - Profile high-rate latency tails **Full Changelog**: https://github.com/rayfish/rayfish/compare/v0.4.1...v0.4.2 - Sep 1, 2026 0.4.1### Features - **cli**: Mark the coordinator in status and add `ray s` - **cli**: Confirm a kick that removes a whole user - **cli**: Add `ray files reject` - **install**: Add a Windows installer - **status**: Show a saved group before its coordinator answers - **android**: Offer the identity restore before first run - **android**: Back up and restore the identity from a file
More…
### Bug Fixes - Scope DHT relay and bound forwarding work - **android**: Tighten the extracted string catalogs - **mesh**: Seat a member's paired devices and kick by identity - **e2e**: Stop the harness clobbering $KEY and sharing one tracefs - **clippy**: Group the bind and member-restore parameters - **forward**: Bound the lazy-dial packet buffer - **android**: Keep saved networks listed while they reconnect - **cli**: Keep styled values readable on light terminals - **android**: Keep identity keys out of Android Auto Backup - **android**: Let an inbound firewall rule name a peer ### Documentation - **ssh**: Say why a node cannot SSH to its own mesh address ### Testing - **e2e**: Cover unprivileged-client authority with an operator scenario ### CI - Key every rust-cache by the target triple - Fold the Windows workflow into CI - **nightly**: Publish the ARM64 Windows binary - **windows**: Build ray.exe for arm64 on a native runner ### Miscellaneous - Release - Release ### Other - V0.4.0-android-i18n - Optimize peer membership and firewall reads - Speed up warm peer resume **Full Changelog**: https://github.com/rayfish/rayfish/compare/v0.4.0...v0.4.1 - Aug 26, 2026 0.4.0### Features - **windows**: Sign the msi and the ray.exe inside it on release - **bridge**: Take listener changes from the kernel, not a poll - **bridge**: Reach IPv4-only listeners over the mesh - **hostname**: Join under this machine's name, not a random noun - **cli**: Complete the ids printed in a listing - **android**: Notify about an incoming file offer - Delete the ipv6-only setting
More…
- **dns**: Answer on the IPv6 magic address only - **mesh**: Mesh protocol 4, drop the IPv4 from the roster - **exit-node**: A tunnel carries what both ends carry, and says which - **exit-node**: Make the family claim answer for the return path - **proto**: Array-encode the network wire, mesh protocol 3 - **exit-node**: Support exit nodes in IPv6-only mode - **dns**: Decline off-mesh names on a shared resolv.conf instead of relaying - **cli**: Group nested help pages and collapse four commands (#127) - **dns**: Route the other VPN's domains to the other VPN's resolver - **dns**: Share resolv.conf with another VPN instead of standing down - **cli**: Add `ray logs` to read the daemon log without root - **windows**: Align MSI builds with release parity - **windows**: Add console-free desktop gui launcher - **windows**: Add Windows x64 desktop port ### Bug Fixes - **windows**: Open IPC reads to any local user - **status**: Do not report a reachable daemon as down - **windows**: Put the install dir on PATH - **windows**: Reject a group as the operator account - **dns**: Coerce Windows NRPT NameServers to strings - **windows**: Build the msi when the output path is a drive root - **windows**: Correct what the port claims about completions and reuse - **report**: Keep one principal's bundle out of another's sweep - **windows**: Ask for the service access the restart policy needs - **build**: Gate the listener module on the desktop feature - **windows**: Reserve a stack ray.exe can start on - **windows**: Install no completions where no shell reads them - **windows**: Correct two tests that had never run on Windows - **windows**: Compile the test target on Windows - **windows**: Ask for no more service access than the change needs - **windows**: Make the Windows target compile - **windows**: Close the review items left open on PR 117 - **mobile**: Publish the config dir without writing the environment - **completions**: Install the zsh stub where zsh actually looks - **config**: Put settings.toml under the transaction boundary - **mesh**: Restore coordinators from durable snapshots - **report**: Keep a diagnostic bundle private to whoever asked for it - **config**: Fsync config writes and give each one its own temp file - **config**: Make network updates transactional - **android**: Resolve .ray names in Chrome on an IPv4-only network - **android**: Send the diagnostics with the diagnostics report - **status**: Register a version-incompatible network instead of dropping it - **android**: Stop an offer notification outliving or misnaming its file - **android**: Require Android 8.0, where the notification APIs exist - **test**: Three harness bugs that lost fleets or passed on nothing - **dns**: Finish aborting a takeover when restoring resolv.conf fails - **firewall**: Refuse every fragment, not only the ones after the first - **mesh**: Tell a kicked member which network it left - **dns**: Two strikes before the NetworkManager takeover latches off - **firewall**: Walk the IPv6 extension-header chain to the real protocol - **mesh**: Announce handles to the address the peer is registered under - **forward**: Count the outbound packets the parser refuses - **dns**: Three ways the resolver outlived what it was pointing at - **exit-node**: A gateway is not a way onto the gateway's own network - **firewall**: Refuse IPv6 extension headers instead of misreading them - **cli**: Stop fail_unexpected abandoning the two loops written to continue - **dns**: Restore the cfg the NmQuietOutcome enum was inserted under - **cli**: Exit non-zero on a reply the command cannot read - **dns**: Re-check the upstream after quieting NetworkManager - **exit-node**: Stop a gateway claiming the IPv4 the overlay dropped - **macos**: Dial the exit peer by its mesh IPv6 - **dns**: A resolver on a mesh peer is an upstream, not a loop - **cli**: Do not abandon a loop's remaining work on the first rejection - **cli**: Exit non-zero when the daemon rejects a command - **dns**: Restore the macOS AAAA marker and the foreign-resolver loop guard - **test**: Repair three harness bugs the IPv6-only cutover left behind - Repair what round 3 found, including two tests that proved nothing - **tun**: Put the ExitFamilies import under the right cfg - **exit-node**: One rule for the mirrored prefixes, and track convergence by what we accepted - Say when a selection is not in effect, and correct the wire docs - Repair what round 2 found, including two broken round-1 fixes - Repair what round 1 of review found - **proto**: Repair the unknown-variant probe under array encoding - **exit-node**: Make the IPv6 claim three-valued and rescue the peer VPN's own traffic - **exit-node**: Address review of the IPv6-only exit-node support - **ipc**: Fill the new exit-node status fields in ray-proto's own test - **exit-node**: Keep the missing-gateway warning per family - Include timestamp in report names - Secure diagnostic report creation - **dns**: Don't share resolv.conf from an address the other VPN filters - **dns**: Stop feeding a resolver that forwards back at us - **dns**: Import strip_our_resolv_entries for every test target - **macos**: Build the SCDynamicStore search domain as a SearchDomain - **dns**: Finish the stand-down path's cleanup obligations - **dns**: Stop taking resolv.conf from a VPN that started second - **mesh**: Refuse a replayed record, expire the pairing window - **mesh**: Authenticate the sender of a control frame - **metrics**: Bind the exporter to loopback, skip it on Android - **mesh**: Don't route over a network the peer no longer shares - **dns**: Resolve the daemon's own names without the host's resolver - **windows**: Address PR 117 hardening feedback - **windows**: Close PR review follow-ups - **windows**: Verify detached updater readiness - **windows**: Tolerate stale Wintun addresses - **windows**: Enforce protected ACLs by handle - **windows**: Preserve trusted config owners - **windows**: Guard DNS rollback with CAS - **windows**: Guarantee updater artifact cleanup - **windows**: Preserve concurrent DNS state - **windows**: Finalize updater cleanup and reboot state - **windows**: Serialize DNS and contain process trees - **windows**: Secure all config staging - **windows**: Make DNS rollback exact and bounded - **windows**: Discover local WiX toolset - **windows**: Preserve concurrent operator changes - **windows**: Secure detached MSI staging - **windows**: Close bootstrap and ACL races - **windows**: Harden MSI identity and updater - **windows**: Make DNS and tunnel lifecycle async - **windows**: Harden service bootstrap and IPC - **ci**: Reuse preinstalled wix on runners - **ci**: Match wix package version on hosted runners - **ci**: Allow pinned wix downgrade on runners - **ci**: Avoid unix-only lint reachability - **ci**: Keep platform-specific IPC paths lint-clean - **windows**: Make MSI service-only and auto-start - **windows**: Unblock service startup and preserve host DNS - **windows**: Hide helper process consoles ### Performance - **mobile**: Stop re-resolving the signed record every minute ### Refactor - **mesh**: Derive a peer's address rather than passing it - **cli**: Config_row has no "no value" case to return - **connect**: Carry a message, not a whole reply, out of target resolution - Delete what the IPv6-only cutover left behind - **ipc**: Report the mesh IPv6 as the node's address - **peers**: Key the data plane on the mesh IPv6 - Name the mutexes and the search domains ### Documentation - **changelog**: Cut 0.4.0 - **claude**: Cut CLAUDE.md to rules, scope the wire ones by path - **cli**: Use a fabricated id in the completion test comment - **changelog**: The review round - Correct what the cutover left stale, and drop a real hostname - **changelog**: Use a placeholder hostname in the macOS AAAA entry - **changelog**: The round-two fixes - Four more mesh-IPv4 references in the registry - The last of the mesh-IPv4 and IPv6-only-mode wording - Drop the mesh-IPv4 wording the cutover left behind - Correct what the cutover left pointing at a deleted setting - The e2e harness, invariants and changelog for an IPv6-only overlay - State the named-vs-compact trade honestly - Say why the control wire stays named-encoded - Cut CLAUDE.md back to the register it asks for ### Styling - Rustfmt - Import Mutex/RwLock/black_box instead of inlining the full path ### Testing - **windows**: Give the descendant test time to publish its pid - **e2e**: Cover the IPv4-only listener bridge end to end - **e2e**: A churn scenario for flap, kick and nuke - **e2e**: Keep a partial fleet, and restore what deleting step 9 took - Stop three more e2e paths from asserting less than they report - Say what the DropReason tripwire actually catches - Guard two more e2e paths that pass without asserting anything - Pin the three behaviours the last round changed but left unasserted - Stop three checks from passing when they should not - Provision e2e fleets with doctl instead of scw - **e2e**: Cover the IPv6-only exit-node client - Wait for the gc sweep instead of a fixed budget - **windows**: Add zombie ddd contract coverage ### CI - **windows**: Gate MSI packaging on a label, not a variable ### Build - Accept `just android` as a name for the apk recipe - Give cross builds their own target dir ### Miscellaneous - Release - Release - **android**: Regenerate the UniFFI bindings - **windows**: Remove BMAD artifact from PR - **windows**: Remove deferred work artifact **Full Changelog**: https://github.com/rayfish/rayfish/compare/v0.3.0...v0.4.0 - Aug 15, 2026 0.3.0### Features - **android**: Add a quick settings tile for toggling the tunnel - **cli**: Group `ray -h` and scope `--json` to the commands that emit it - **ipc**: Add network-scoped config set/get - **ipv6-only**: Switch to the mode when another VPN holds the CGNAT range - **android**: IPv6-only mode as a toggle in You - **mesh**: Carry an ipv6-only claim on the signed roster - **dns**: Answer AAAA only when the data plane is ipv6-only
More…
- **net**: Ipv6-only data plane so rayfish can share a host with another VPN - **completions**: Tab completion that knows your networks and peers - **ssh**: Hand interactive sessions to login(1) - **ssh**: Complete the mesh SSH feature surface - **ssh**: Support port forwarding over mesh SSH - **status**: List nearby LAN peers instead of counting them - **mdns**: List LAN neighbours and connect to one directly - **mesh**: Keep every saved network live instead of restoring once at boot - **android**: Report how the previous process died - **service**: Support OpenRC and SysV init, not just systemd - **android**: Cancel a queued send from the app - **android**: Show the transfer percentage next to the progress bar - **gui**: Searchable command templates - **gui**: Share services toggle per network card - **gui**: Redesign the dashboard around live status - **config**: Honor RAYFISH_CONFIG_DIR on every platform - **invite**: Checksum invite codes so a mangled one fails cleanly ### Bug Fixes - **macos**: Write the service rank before anything routable - **macos**: Make configd ask our resolver for AAAA - **macos**: Publish the service's IPv6 so the resolver is asked for AAAA - **hostfw**: Gate fix_command to Linux, where its only callers are - **macos**: Scope the DNS resolver to the utun so it is asked for AAAA - **android**: Import anyhow's Result outside the desktop cfg - **android**: Regenerate the UniFFI bindings for the ipv6-only tri-state - **config**: List every settings key instead of a hand-kept five - **ipc**: Log the real decode reason and finish the exhaustive matches - **ipc**: Bound the decode-error reply and keep it out of the log's blind spot - **ipc**: Answer an undecodable request instead of hanging up - Settings collapse review cleanup - **ipc**: Restore the confirmation and error text the settings collapse moved - **config**: Drop side-effecting keys from the global settings registry - **transport**: Bind an IPv6 underlay socket - **compat**: Audit the feature surface against a coexisting VPN - **dns**: Reach magic dns over IPv6 when the data plane is ipv6-only - **dns**: Stop leaking a tailnet address and stop fighting over resolv.conf - **mobile**: Let a disabled node come back, and rebind when the phone moves - **dns**: Answer `.ray` misses locally instead of forwarding them upstream - **dns**: Fall back to the system resolver for names the mesh doesn't hold - **dns**: Drop the stale argument in the macOS DNS writer - **ssh**: Key session state by channel, not by connection - **dns**: Only answer names under .ray - **ssh**: Serve the sftp subsystem so scp works - **join**: Box the TryJoin reply to keep clippy green - **ssh**: Say when an allow rule is stored but the server is off - **mesh**: Keep retrying a network restore that was queued for approval - **android**: Identify the build a Sentry report came from - **android**: Survive Android refusing a background foreground start - **android**: Stop a failed tunnel start from leaving a VPN connected - **android**: Confirm the copy on the QR code sheet - **boot**: Recover when the daemon starts before the network is ready - **build**: Keep the host-firewall warning out of the Android build - **ssh**: Tell a refused mesh SSH client why it was refused - **peers**: Attach a live connection to networks its handshake missed - **ssh**: Warn when the host firewall blocks the mesh SSH port - **dns**: Use resolved only when it is in the resolution path - **android**: Retire a send notification that can never resolve - **android**: Stop a failed send from stranding its notification - **android**: Let the share picker reach idle peers - **build**: Import IpAddr on macOS without the desktop feature - **android**: Stop a late DNS answer from killing the app on teardown - **dht**: Keep the cause when a record lookup fails - **dns**: Never forward to an unverified DNS upstream - **firewall**: Reject IPv4 headers shorter than five words - **android**: Derive app version from the crate version ### Performance - **ssh**: Set TCP_NODELAY on sockets carrying SSH - **files**: Stream transfers instead of buffering whole files - **forward**: Cache the TUN sender per peer reader ### Refactor - **ipv6-only**: One Auto/On/Off enum instead of two booleans - Delete the code the dead_code allows were hiding - **ipc**: Make settings keys typed instead of stringly-typed - **ipc**: Collapse the settings variants into the config registry - **config**: Register the per-network toggles as settings keys - **config**: Register the firewall toggles as settings keys - **config**: Route every global setting through the registry - **config**: Add the settings key registry - **android**: Hold the prefs file once and cache the hot flags ### Documentation - **changelog**: Cut 0.3.0 - **changelog**: Separate the config-key bullet from the one after it - Document the settings registry and fix the stale ssh login note - Correct why the ipv6-only TUN keeps a v4 /32 - Ipv6-only mode in the changelog, readme and CLAUDE.md - **claude**: Document the mobile client - **changelog**: Record the DNS, mesh SSH and peer-table fixes ### Styling - Drop the reformatting of connect.rs from the merge ### Testing - **e2e**: Run the functional scenarios on local docker containers - Property tests for the data path, membership, and encodings - **dns**: Cover the forward-to-upstream path end to end ### CI - **nightly**: Give each target its own cache key ### Build - **android**: Compile the Android target in CI and locally - Add a just local-dev recipe ### Miscellaneous - Release - Release - Add `just fmt-changed` to format only touched files ### Other - Fmt **Full Changelog**: https://github.com/rayfish/rayfish/compare/v0.2.1...v0.3.0