Use a Nintendo Switch 2 Joy-Con (R) as a mouse and keyboard on a Mac, Windows or Linux: slide it on a desk to move the pointer, click with the shoulder buttons, scroll with the stick, and map the other buttons to keys.
It runs as a normal app, with no driver, kernel extension or root access.
Download from the latest release:
| Runs on | Download |
|---|---|
| Apple Silicon Macs, macOS 13 or later (tested on 26) | Deskpuck-<version>-macos-arm64.dmg |
| Windows 10 and 11 on x86-64 (tested on 11) | Deskpuck-<version>-setup.exe |
| Linux on x86-64 with BlueZ (tested on CachyOS, KDE Plasma on Wayland) | Deskpuck-<version>-linux-x86_64.tar.gz |
SHA256SUMS on the same page lists each file's checksum. To check that a Windows or Linux download was built from this repository by its release workflow, run gh attestation verify <file> --repo Pyronewbic/deskpuck with the GitHub CLI.
- Open the disk image and drag Deskpuck to Applications. Open Deskpuck; macOS blocks it the first time because it is not notarized by Apple. Click Done, open System Settings > Privacy & Security, and click Open Anyway next to the Deskpuck message.
- When asked, allow Bluetooth and Accessibility access. Accessibility is what lets Deskpuck move the pointer and press keys.
- Choose Pair New Joy-Con... from the menu bar icon, then hold the SYNC button on the Joy-Con until its lights flash, within 60 seconds. From then on only this Joy-Con connects; hold SYNC to reconnect it.
No Open Anyway button?
Run this in Terminal, then open Deskpuck again:
xattr -dr com.apple.quarantine /Applications/Deskpuck.app- Run the installer. Windows warns that it protected your PC, because Deskpuck is not code-signed: click More info, then Run anyway. It installs for you alone, without admin rights. To skip the installer, unzip
Deskpuck-<version>-windows-x86_64.zipanywhere and rundeskpuck.exe. - Right-click Deskpuck's icon in the system tray (it may be under the ^ arrow), choose Pair New Joy-Con..., then hold SYNC on the Joy-Con within 60 seconds. Do not pair the Joy-Con in Windows Settings.
- Unpack the archive and run
./install.shin its folder. It installs Deskpuck for you alone, in~/.local, and adds it to the app menu;./install.sh --uninstallremoves it. - Start Deskpuck from the app menu. On GNOME, its tray icon needs the AppIndicator extension. Right-click the icon, choose Pair New Joy-Con..., then hold SYNC within 60 seconds.
The pointer does not move?
Moving the pointer needs write access to /dev/uinput. Some systems give it already (Steam's controller support does); if not, allow it once, as root. This gives the person at the screen access to /dev/uinput only, not to other input devices:
sudo tee /etc/udev/rules.d/60-deskpuck-uinput.rules <<'EOF'
KERNEL=="uinput", SUBSYSTEM=="misc", TAG+="uaccess", OPTIONS+="static_node=uinput"
EOF
sudo udevadm control --reload-rules && sudo udevadm trigger --name-match=uinput| Joy-Con (R) | Default |
|---|---|
| Slide on a surface | Move the pointer |
| R / ZR | Left click / right click |
| Stick up and down | Scroll |
| Stick click | Return |
| X / B / Y / A | Up / Down / Left / Right arrows |
Change the key mappings, pointer speed, scrolling, key repeat and theme in Settings..., from the menu bar icon on a Mac or a left click on the tray icon elsewhere. A button can also press a recorded shortcut such as Control+C, or act as a modifier: held, or latched on with one tap and off with the next. Settings are saved in config.json (modifier names keep the Mac spelling: option is Alt, command the Super or Windows key), with the pairing beside it: in ~/Library/Application Support/Deskpuck on a Mac, %APPDATA%\Deskpuck on Windows and ~/.config/deskpuck on Linux.
Pause Mouse Control stops all input from the Joy-Con but keeps it connected, so resuming is instant; quit Deskpuck to release it completely. Start at Login starts Deskpuck when you log in. To use a different Joy-Con, choose Pair New Joy-Con... again; it replaces the paired one.
Once a day Deskpuck asks github.com for the latest release, sending only its version number (github.com sees your IP address, as with any request). Update to X.Y.Z in the menu downloads a newer one, checks the maintainer's signature, installs it and restarts Deskpuck. Turn the check off under General > Updates in Settings, or set DESKPUCK_NO_UPDATE_CHECK=1.
With Reconnect with a button press on under General > Joy-Con in Settings, the next Pair New Joy-Con... teaches the Joy-Con this computer, and it then reconnects when you press a button instead of SYNC. The Joy-Con remembers one computer or console at a time, so this unpairs it from a Switch 2; attach it to the console to use it there again.
Is the Joy-Con in the system's Bluetooth settings?
Not as a paired device: a Joy-Con 2 refuses the pairing that Bluetooth settings start, so Deskpuck pairs it in the app and the Joy-Con itself remembers the computer. A Mac does not list it; a Linux Bluetooth panel may show it, unpaired, while Deskpuck looks for it or is connected. Do not pair or connect it from there.
A button press does not reconnect it?
Pair it again with the setting on if it has since been used with a console or another computer. Button reconnect is not yet tested on Windows, and on Linux only with BlueZ's default settings: with LE privacy on, the computer's address changes and it may not work.
Only Update Available, which opens the release page?
That copy cannot replace itself: a portable Windows copy, a Linux copy not installed by install.sh, or an app folder you cannot write to. Installs under /usr, such as the AUR package, update through your package manager.
- The pointer does not move (Mac): check that Deskpuck is on in System Settings > Privacy & Security > Accessibility. If it is on but still nothing happens, reset the permission and allow it again:
tccutil reset Accessibility com.pyronewbic.deskpuck - The pointer does not move (Linux): Deskpuck needs write access to
/dev/uinput(Install, Linux). - The Joy-Con does not connect: if the menu says Not paired, pair it first (see Install). Otherwise hold SYNC until the lights flash, and make sure it is not connected to a Switch or another computer at the same time. If the menu says the Joy-Con is in use by another app, quit that app (for example
deskpuck-cli). - Linux: the pointer feels choppy: at BlueZ's default connection interval a Joy-Con sends about 21 reports a second. A shorter default doubles that; see below. (Windows asks for a short interval itself.)
- Windows: the Joy-Con stops working in an admin window: Windows does not let ordinary apps send input to apps running as administrator (such as an admin PowerShell). Switch away with the mouse, the keyboard or Alt+Tab, and the Joy-Con works again.
Linux: a shorter Bluetooth connection interval
Set a shorter default once, as root. It applies to every Bluetooth LE device on the machine. Reconnect the Joy-Con afterwards; the first connection after the change can still use the old interval. With 15-30 ms the Joy-Con sent about 45 reports a second; shorter intervals failed to connect several times in testing.
sudo sed -i -e 's/^#MinConnectionInterval=$/MinConnectionInterval=12/' -e 's/^#MaxConnectionInterval=$/MaxConnectionInterval=24/' /etc/bluetooth/main.conf
grep -E '^(Min|Max)ConnectionInterval=' /etc/bluetooth/main.conf
sudo systemctl restart bluetooth
# To undo:
sudo sed -i -e 's/^MinConnectionInterval=12$/#MinConnectionInterval=/' -e 's/^MaxConnectionInterval=24$/#MaxConnectionInterval=/' /etc/bluetooth/main.conf && sudo systemctl restart bluetoothThe grep should print both lines; if it does not, your main.conf lacks the commented defaults, so set them by hand under [LE]. Running the commands twice changes nothing, and the undo touches only those two lines.
See CONTRIBUTING.md. How the code is laid out: ARCHITECTURE.md.
Deskpuck learned a great deal from the following projects.
ndeadly/switch2_controller_research
We thank the authors for their work on the Joy-Con 2 Bluetooth protocol.
Deskpuck is not affiliated with or endorsed by Nintendo. Nintendo Switch and Joy-Con are trademarks of Nintendo.
MIT. See LICENSE.