Share keyboard and mouse input from macOS to Linux over a local network.
  • Rust 42.6%
  • Swift 38.3%
  • Shell 11.9%
  • JavaScript 6.6%
  • Makefile 0.4%
  • Other 0.2%
Find a file
Erik Craddock 63555748fc
All checks were successful
CI / Rust build, lint, and test (push) Successful in 13s
CI / Swift build, lint, and test (push) Successful in 16s
Merge pull request 'Fix cursor handoff, configurable layout, and installed update reliability' (#26) from fix/cursor-height-handoff into main
Reviewed-on: #26
2026-11-07 12:31:34 -06:00
.forgejo fix: support configurable handoff layout and reliable installed updates 2026-11-07 12:19:44 -06:00
config fix: support configurable handoff layout and reliable installed updates 2026-11-07 12:19:44 -06:00
docs fix: support configurable handoff layout and reliable installed updates 2026-11-07 12:19:44 -06:00
gnome-extension/kvshare@caradoc.com fix: support configurable handoff layout and reliable installed updates 2026-11-07 12:19:44 -06:00
launchd fix: launch macOS app with application identity 2026-08-12 21:58:15 -05:00
packaging fix: support configurable handoff layout and reliable installed updates 2026-11-07 12:19:44 -06:00
protocol/fixtures feat: mirror numbers without transferring input control 2026-09-23 19:54:16 -05:00
scripts fix: support configurable handoff layout and reliable installed updates 2026-11-07 12:19:44 -06:00
src fix: support configurable handoff layout and reliable installed updates 2026-11-07 12:19:44 -06:00
swift fix: support configurable handoff layout and reliable installed updates 2026-11-07 12:19:44 -06:00
systemd fix: support configurable handoff layout and reliable installed updates 2026-11-07 12:19:44 -06:00
tests feat: package versioned releases 2026-07-22 10:35:19 -05:00
.gitignore feat: package versioned releases 2026-07-22 10:35:19 -05:00
AGENTS.md chore: remove unused Overmind scaffolding 2026-07-16 23:04:07 -05:00
Cargo.lock fix: version the incompatible protocol release as 0.2.0 2026-09-23 22:14:17 -05:00
Cargo.toml fix: version the incompatible protocol release as 0.2.0 2026-09-23 22:14:17 -05:00
clippy.toml Initial project setup 2026-07-16 21:48:04 -05:00
LICENSE Initial project setup 2026-07-16 21:48:04 -05:00
Makefile feat: package versioned releases 2026-07-22 10:35:19 -05:00
README.md fix: support configurable handoff layout and reliable installed updates 2026-11-07 12:19:44 -06:00
rustfmt.toml Initial project setup 2026-07-16 21:48:04 -05:00

kvshare

Share keyboard and mouse input from macOS to Linux over a local network.

Install

Versioned releases provide a macOS .pkg and an Arch Linux package that install without a repository checkout. Verify the published checksums, then follow the macOS installation guide and Arch Linux installation guide.

Build from source

Development requires Rust 1.88+, Swift 6.2+ on macOS, GNOME Shell on Wayland, and a fixed wired Ethernet route between the target machines.

cargo build
swift build --package-path swift --product KvshareMac

Development

Run the current Rust application directly with cargo run.

Display arrangement

Set "linuxSide": "left" or "linuxSide": "right" in the Mac’s ~/.config/kvshare/config.json, and set the same value in KVSHARE_LINUX_SIDE in Linux’s ~/.config/kvshare/receiver.env. Both default to right when omitted. With Linux on the left, cross the Mac’s left edge to enter Linux and Linux’s right edge to return. With Linux on the right, use the opposite edges. Cursor height is preserved. Restart the Mac app and Linux receiver after changing layout; after updating extension code, log out of GNOME and back in. The settings must match; layout is not negotiated over TCP.

macOS menu-bar app

For a stable release installation, permissions, optional login launch, operation, and recovery, follow docs/MACOS_APP.md.

For development, copy the receiver configuration example and replace its reserved linux-receiver.example hostname with your Linux receiver's hostname or fixed Ethernet IP address:

mkdir -p ~/.config/kvshare
cp config/kvshare.example.json ~/.config/kvshare/config.json
$EDITOR ~/.config/kvshare/config.json

Keep actual machine hostnames and IP addresses in local files under ~/.config/kvshare/, not in the repository. Configure the Linux receiver's local KVSHARE_MAC_IP for the sending Mac as described in docs/LINUX_RECEIVER.md.

Then run the menu-bar app:

swift run --package-path swift KvshareMac

Set KVSHARE_CONFIG to load a different configuration path. The app starts disabled; use its menu-bar icon to enable or disable sharing, inspect status, or quit. On first enable, grant both Input Monitoring and Accessibility access in System Settings, then disable and enable kvshare again. While Linux has control, press Control-Option-Escape to return control to the Mac.

Press Control-Shift-Backslash (Control + | on a US keyboard) to toggle number mirroring. With sharing enabled and Linux ready, unmodified top-row numbers go to both machines from either screen. Other keys and modified shortcuts retain normal routing. This requires protocol version 2 on both machines; upgrade the Mac app and Linux receiver together.

Number-mirroring regression check

  1. Open a scratch text editor on each machine. Enable sharing and number mirroring; keep control on the Mac and type 1234567890. Each editor should receive exactly one copy, without pointer movement or handoff.
  2. Transfer control to Linux and repeat. Toggle mirroring off and verify numbers reach only the controlled machine on both screens.
  3. Check modified numbers, letters, and numpad keys; they should retain normal routing.
  4. Hold a number across toggle-off, handoff, emergency return, Disable, and disconnect. No key should remain stuck. Lock Linux while Mac controls, verify Linux receives nothing, then unlock and verify a fresh number press mirrors again. Do not type sensitive information during testing.

Cursor-capture regression check

  1. Enable sharing and push through the Mac display's edge facing Linux.
  2. Move the mouse while Linux has control and verify that Linux receives movement while no cursor is visible moving on the Mac. If number mirroring is enabled, verify that unmodified top-row numbers still reach both machines.
  3. Return through Linux's edge facing the Mac and verify that the Mac cursor is visible, parked at the edge facing Linux, and moves normally.
  4. Repeat the handoff and return with Control-Option-Escape, receiver disconnect, Disable, and Quit; each path must restore normal Mac cursor visibility and movement.

Run formatting, linting, and tests before submitting changes:

make check

Run all pre-PR checks before opening a pull request:

make pre-pr

List the available Make targets with make help.

Packaging and releases

Cargo.toml is the canonical semantic version source. Run make package-macos on macOS or make package-arch on Arch Linux to build local artifacts. Tagged Forgejo releases build and publish both packages and SHA-256 checksums. See docs/RELEASES.md for versioning, release creation, signing, and verification.

Setup and verification

For a clean target-machine setup:

  1. Install the Linux receiver service, including uinput access and fixed source-IP configuration.
  2. Install the GNOME handoff extension, then log out and back in when required.
  3. Install and authorize the macOS app.
  4. Follow the smoke tests in the platform guides and compare with the MVP verification results.

License

MIT