I built a Software KVM in Rust instead of paying for Synergy
The problem
I had a MacBook and a Windows desktop on the same desk. Two mice, two keyboards, arms reaching back and forth all day. I wanted one of each.
The fix is a software KVM, a tool that lets you move your cursor from one machine to the next as if they share a single desktop. I tried the existing options:
- Synergy: paid, constant disconnects
- Barrier: dead fork, same disconnect bug
- Mouse Without Borders: Windows-only
- Hardware KVM: works, but breaks multi-monitor setups
Nothing fit. So I built my own. It's called CursorHop and the core engine is written in Rust.
Why Rust
Three reasons, in order of importance.
1. Latency is the whole game
A software KVM lives or dies by input latency. Any noticeable delay breaks the illusion and the tool feels broken. My target was under 1ms of software overhead, leaving the rest of the budget for network round-trip time.
Rust gives you that budget. No GC pauses. No runtime overhead. Deterministic allocations. For input-path code, nothing else comes close.
2. Memory safety without a runtime
A KVM app runs 24/7 with low-level access to your input devices. A crash here isn't just annoying. It can take down your desktop session.
Rust's ownership model eliminates entire classes of bugs at compile time: use-after-free, data races, null pointer dereferences, buffer overflows. The compiler refuses to build broken code.
3. Native cross-platform binaries
One Rust codebase compiles to Windows and macOS. Binaries are small (under 10MB), start instantly, and don't ship an embedded browser runtime with every install.
Architecture
The hot path looks like this:
-
Capture: OS-specific hooks grab mouse and keyboard events.
SetWindowsHookExon Windows,CGEventTapon macOS. - Encrypt: Events go over the Noise protocol (same family as WireGuard). Mutual auth, forward secrecy, low overhead.
- Transport: UDP over LAN. No TCP handshake tax on every packet.
- Discovery: mDNS. Machines find each other automatically, no IP configuration.
-
Inject: Events replayed on the target machine via
SendInputorCGEventPost.
End-to-end latency is well under 1ms on a wired LAN. 2 to 4ms on Wi-Fi. Humans can't perceive either.
What surprised me
mDNS is still weird in 2026. Different OSes handle multi-interface responses differently, especially when machines have both Wi-Fi and Ethernet active. I ended up writing a minimal mDNS responder because the existing Rust crates had edge cases that bit me.
Mac and Windows key mapping is genuinely hard. Cmd to Ctrl mapping works most of the time, except when it doesn't. Dead keys and international layouts took longer than I'd like to admit.
Clipboard sync is a minefield. Text is easy. Images are okay. Rich content like tables from Excel or styled HTML from a browser is a nightmare because every OS represents it differently. I ended up normalizing to a handful of canonical formats.
Users hate subscriptions more than I expected. I priced CursorHop as a one-time purchase because it's what I'd want as a buyer. The response has been overwhelmingly positive.
Why paid, not open source
This is the question I get most.
Short answer: I want to keep building CursorHop for years, not abandon it in six months. Paid means I can justify spending time on it. Most open-source projects in this specific space have died because nobody wants to handle the long tail of OS quirks alone.
There's a 7-day free trial with core features. Pricing is one-time, starting at $10 for the basic tier and up to $35 for the multi-machine version.
Try it
If you have more than one computer on your desk, try it for a week. I'd genuinely love feedback, especially on edge cases I haven't hit yet.
๐ cursorhop.com
Questions about the Rust architecture, the Noise integration, or the pricing tradeoff? Ask in the comments, I'll answer everything.
Top comments (2)
The latency analysis here is spot-on. Your reasoning about why Rust was the right choice โ deterministic allocations, no GC pauses, sub-1ms software overhead โ maps exactly to what I've been hitting when building storage systems for edge devices.
The mDNS weirdness you mentioned is real. Multi-interface behavior on macOS in particular has some dark corners. Did you end up implementing fallback manual IP entry for cases where mDNS discovery fails on complex network setups?
Also curious about the Noise protocol choice over TLS โ I've seen similar decisions made for IoT/embedded contexts where every handshake cycle matters. The forward secrecy without certificate infrastructure is a genuinely underrated tradeoff.
What's your plan for the Windows screen scaling issue with mixed DPI setups? That seems like it could be the hardest edge case to get right without having physical access to reproduce it.
1) mDNS & Connectivity
mDNS discovery is stable on macOS and Windows. If it fails, users can connect via a predefined PIN or device IP. Tested on four devices and working reliably. Since this is a beta, further improvements will come from user feedback. Beta users will get lifetime access for free once the product becomes paid.
2) Security (Noise Protocol)
The Noise protocol was chosen for its speed and stability. Unlike TLS, it avoids drops and stutters while still providing encryption. Since the app runs only on local networks, the risk is minimal, and Noise adds no noticeable overhead.
3) Mixed DPI
Mixed DPI is still being improved. For now, cursor movement scales proportionally between screens, similar to Windows. More customization options will be added later.
Launch
The product launches in 3 days.
Use code betatesting123 for 100% off for a limited time. Just sign up, go to checkout, and apply the code.