Transform Nintendo Switch Joy-Cons and universal gamepads (Xbox, PlayStation DualSense/DualShock, Switch Pro Controller, 8BitDo) into a wireless precision desktop mouse, couch media remote, and presentation clicker with zero external dependencies.
Tip
🚀 Tested on a different Linux distro, Steam Deck, or controller?
We'd love your feedback! Open an issue or testing report to share your distro and hardware setup, or submit a custom mode PR via CUSTOM_MODES.md.
-
Zero External Dependencies: Pure Python using standard library (
fcntl,struct,select,math,os,threading,importlib). No pip dependencies or bloated wrappers. - Universal Controller & Gamepad Support: Plug-and-play support for single Joy-Cons, paired Dual Joy-Cons, and full-sized gamepads (Xbox Series X|S / One / 360, PlayStation DualSense / DualShock, Nintendo Switch Pro Controller, 8BitDo).
- Physical Haptic / Rumble Feedback: Joy-Con and gamepads provide physical vibration clicks when switching modes, capturing screenshots, or unlocking credentials.
- Dedicated Screenshot vs. Home Separation: Instant 0ms screenshot on dedicated Capture/Share buttons and instant Home/Super key on Guide/Home buttons for full controllers, with smart dual-action hold preserved on single Joy-Cons.
- Ergonomic Volume Orientation: Natural left = Volume Down, right = Volume Up across Left Joy-Con rail, Right Joy-Con rail, and D-pad.
- Universal Modular Plugin Engine: Fully decoupled mode architecture. Every mode is a standalone, hot-discoverable Python plugin.
-
Built-in & Community Modes:
-
Desktop Mouse (
modes/air_mouse.py): Precision analog stick pointer with hybrid acceleration curve ($x^{1.6}$ ) and zero drift. -
Universal Media Remote (
modes/media_remote.py): Dedicated side-rail volume (SL/SR), subtitles (C), instant rewind (-10s), and analog stick continuous seek ($\pm 5\text{s}$ ). -
Interactive Terminal Controller (
modes/terminal.py): Hands-free AI pair programming & shell companion (Enter, HistoryUp/Down,Tabauto-complete,Esc,Ctrl+Cinterrupt,Ctrl+Lclear, and smooth buffer scrolling). -
Gaming & Macro Hotkeys (
custom_modes/gaming_hotkeys.py): Quick Save/Load, Map, Inventory, and F13-F16 macro keys. -
Wireless Presentation Clicker (
custom_modes/presentation.py): Slideshow control for Google Slides, Impress, and PowerPoint.
-
Desktop Mouse (
-
CLI Mode Manager: Manage, toggle, and scaffold modes directly via CLI (
--list-modes,--enable-mode,--disable-mode,--create-mode). -
Standalone Mode Execution: Every mode script can run independently (
python3 modes/terminal.py) to output complete visual cheatsheets. -
1-Click Auto-Start Background Service: Set up automatic background startup with
joycon-mouse --install-service. -
Live Button & Stick Diagnostic Tool: Interactive diagnostic visualizer (
joycon-mouse --test-buttons). -
User Configuration File: Persistent settings in
~/.config/joycon-mouse/config.jsonfor sensitivity, speeds, deadzones, rumble, and disabled modes. -
Auto-Dormant Game Detection: Non-blocking background thread yields hardware grabbing (
EVIOCGRAB) when Steam games or emulators launch. - Dual Joy-Con Pairing: Detects simultaneously connected Left and Right Joy-Cons and prompts to bind them into a single unified desktop controller.
joycon-mouse/
├── .gitignore # Excludes credentials, caches, and local virtualenvs
├── README.md # Public documentation
├── CUSTOM_MODES.md # Modular architecture guide & custom modes manual
├── CONTRIBUTING.md # Community contribution guidelines
├── LICENSE # MIT License
├── install.sh # Interactive 1-click installer & directory manager
├── setup.sh # Interactive setup wizard launcher
├── setup_wizard.py # Visual configuration wizard (modes, speeds, rumble)
├── uninstall.sh # Clean interactive uninstaller
├── joycon-mouse.py # Main polling loop, auto-dormant manager, mode manager
├── test_buttons.py # Interactive live button and stick diagnostic tool
├── security_manager.py.example # Open-source template for security features
├── modes/ # Built-in core modes (BaseMode subclasses)
│ ├── __init__.py # Dynamic plugin auto-loader & template generator
│ ├── base.py # BaseMode abstract class & Linux keycode constants
│ ├── air_mouse.py # Mode 1: Precision Desktop Mouse & browser controls
│ ├── media_remote.py # Mode 2: Universal media remote with side-rail volume
│ └── terminal.py # Mode 3: Interactive Terminal & Shell Controller
└── custom_modes/ # Community & user custom modes (Plug-and-Play)
├── gaming_hotkeys.py # Couch gaming hotkeys & F13-F16 macro keys
└── presentation.py # Wireless slideshow presentation clicker
Paste the 1-liner for your operating system into your terminal:
curl -fsSL https://raw.githubusercontent.com/ImNotMrReaper/joycon-mouse/main/install.sh | bashirm https://raw.githubusercontent.com/ImNotMrReaper/joycon-mouse/windows/install.ps1 | iexcurl -fsSL https://raw.githubusercontent.com/ImNotMrReaper/joycon-mouse/macos/install.sh | bash🪟 Windows (Windows 10 & 11) — windows Branch
Open PowerShell (Win + X > Terminal or PowerShell) and run:
irm https://raw.githubusercontent.com/ImNotMrReaper/joycon-mouse/windows/install.ps1 | iexAuto-detects Python (installs Python 3.12 via winget if missing), creates Desktop & Start Menu shortcuts, and adds joycon-mouse to system PATH.
- Pair your Joy-Con: Hold the round Sync button on the Joy-Con side-rail until lights flash, then connect via Windows Settings > Bluetooth & devices.
- Download the Windows Branch:
- Download the ZIP from the
windowsbranch and extract it (orgit checkout windows).
- Download the ZIP from the
- 1-Click Installer (
install.bat):- Double-click
install.bat. - Auto-detects Python, sets up user settings in
%APPDATA%\joycon-mouse, and generates Desktop and Start Menu shortcuts.
- Double-click
- Launch Anytime:
- Double-click the Joy-Con Mouse icon on your Desktop or run
run_windows.bat! - Want a standalone
.exe? Double-clickbuild_exe.batto packageJoyConMouse.exein 1 click! - Uninstall: Double-click
uninstall.batanytime to cleanly remove shortcuts.
- Double-click the Joy-Con Mouse icon on your Desktop or run
🐧 Linux (Ubuntu, Debian, Fedora, Arch, Steam Deck) — main Branch
curl -fsSL https://raw.githubusercontent.com/ImNotMrReaper/joycon-mouse/main/install.sh | bash- Run Installer:
./install.sh
- Auto-resolves distro dependencies (APT, DNF, Pacman, Zypper).
- Installs global command
joycon-mouseinto your$PATH. - Optimizes BlueZ reconnection and configures uinput permissions.
- Interactive Setup Wizard:
joycon-mouse --setup
- Clean Uninstaller:
joycon-mouse --uninstall
- Manual Run & Controller Listing:
joycon-mouse -l # List detected controllers joycon-mouse # Start polling loop
🍎 macOS (Monterey, Ventura, Sonoma, Sequoia) — macos Branch
curl -fsSL https://raw.githubusercontent.com/ImNotMrReaper/joycon-mouse/macos/install.sh | bashAuto-deploys driver, generates Desktop launcher Joy-Con Mouse.command, and configures terminal command.
- Pair your Joy-Con: Hold the Sync button, open System Settings > Bluetooth, and click Connect.
- Download the Mac Branch: Download the ZIP from the
macosbranch (orgit checkout macos). - Accessibility Permission: Ensure Terminal is enabled under System Settings > Privacy & Security > Accessibility.
- Launch Anytime: Double-click
run_macos.command!
Run the driver automatically in the background on startup:
# Install and enable background service
joycon-mouse --install-service
# View live background service logs
journalctl --user -u joycon-mouse.service -f
# Uninstall service
joycon-mouse --uninstall-serviceRun the interactive button tester to inspect real-time raw scancodes, values, and mapped mode actions:
joycon-mouse --test-buttonsCustomize speeds, deadzones, and features in ~/.config/joycon-mouse/config.json:
{
"sensitivity": 1.0,
"speed_x": 36.0,
"speed_y": 36.0,
"dead_zone": 0.08,
"accel_exponent": 1.6,
"rumble_enabled": true,
"auto_dormant_enabled": true,
"scroll_repeat_ms": 70
}While Joy-Cons offer an ultra-compact split form factor ideal for one-handed couch navigation and presentation remotes, Joy-Con Mouse natively supports full-sized dual-stick gamepads (Xbox Series X|S, Xbox One / 360, PlayStation DualSense / DualShock 4, Nintendo Switch Pro Controller, 8BitDo, Logitech, and Steam Deck controllers).
Full-sized gamepads provide significant ergonomic and hardware capabilities compared to a single split Joy-Con:
-
Dual Full Analog Sticks: Instead of a single thumbstick, full gamepads deliver independent dual-axis control:
-
Left Analog Stick: Drives high-precision cursor movement with calibrated acceleration (
$x^{1.6}$ ) and configurable deadzones. -
Right Analog Stick: Drives continuous smooth 2D scrolling (vertical and horizontal in Desktop Mouse mode) or continuous media seeking (
$\pm 5\text{s}$ scrubbing in Media Remote mode).
-
Left Analog Stick: Drives high-precision cursor movement with calibrated acceleration (
-
Dedicated Screenshot vs. Home Buttons (0ms Delay):
- On single Joy-Cons, there is physically only one system button (
Homeon Right,Captureon Left), requiring a 0.38s hold timer to distinguish between opening the Application Overview (tap) and taking a screenshot (hold). -
On Universal Gamepads & Dual Joy-Cons: Both functions are separated with zero delay (0ms latency):
-
Dedicated Capture / Share Button: Immediately fires an instant screenshot (
PrintScreen/KEY_SYSRQ) with physical haptic rumble confirmation. No holding required! -
Dedicated Guide / Home Button: Immediately fires the
Super/Windowskey (KEY_LEFTMETA) to bring up your desktop dashboard, Start Menu, or GNOME Overview with 0ms delay.
-
Dedicated Capture / Share Button: Immediately fires an instant screenshot (
- On single Joy-Cons, there is physically only one system button (
-
Tactile Stepped D-Pad Navigation:
- While the analog sticks offer fluid analog movement, the 4-way digital D-pad provides tactile, discrete stepping:
-
Media Remote: D-pad
Up/Downsteps volume cleanly without accidental skips;Left/Rightsteps tracks. -
Terminal Mode: D-pad
Up/Downscrolls shell command history;Left/Rightsteps terminal cursor position.
-
Media Remote: D-pad
- While the analog sticks offer fluid analog movement, the 4-way digital D-pad provides tactile, discrete stepping:
-
Shoulder Ergonomics & Triggers:
- Ergonomic dual triggers (
LT/L2andRT/R2) and bumpers (LB/L1andRB/R1) allow natural one-finger mouse clicks, quick-tabs, and media playback control without hand strain.
- Ergonomic dual triggers (
| Hardware Feature | Single Joy-Con (One-Hand Remote) | Universal Gamepad / Dual Joy-Cons |
|---|---|---|
| Primary Use Case | Bed/couch remote, media clicker, presentation presenter | Full desktop replacement, workstation navigation, terminal shell |
| Analog Sticks | Single stick (cursor movement OR track seeking) | Dual sticks (Left: Cursor; Right: Continuous Scroll / Seek) |
| Screenshot Trigger | Hold Home / Capture button (≥ 0.38s) | Instant Capture / Share button (0ms latency) |
| Home / Overview | Tap Home / Capture button (< 0.38s) | Instant Guide / Home / PS button (0ms latency) |
| Volume Adjustment | Side rail buttons (SL / SR) |
Tactile D-Pad Up / Down + triggers |
| Track Scrubbing | Face buttons (Left/Right or Y/A) |
Right Stick Tilt or D-Pad (Left/Right) |
| Ergonomic Profile | Ultra-lightweight (49g), discrete, fits in pocket | Two-handed balanced grip with full palm support |
| Supported Devices | Nintendo Switch Joy-Con (L), Joy-Con (R) | Xbox One / Series, PS4 / PS5, Switch Pro, 8BitDo, Dual Joy-Cons |
Cycle through active modes anytime by pressing + (Right Joy-Con), - (Left Joy-Con), or Start / + on Universal Gamepads.
| Button | Right Joy-Con | Left Joy-Con | Universal Controller (Xbox / PS / Pro) | Action |
|---|---|---|---|---|
| Primary Trigger | ZR |
ZL |
RT / R2 |
Left Mouse Click |
| Primary Bumper | R |
L |
RB / R1 |
Right Mouse Click |
| Secondary Trigger | — | — | LT / L2 |
Middle Mouse Click |
| Side Rail SL | SL |
SL |
B / Circle |
Escape (ESC) |
| Side Rail SR | SR |
SR |
A / Cross |
Enter / Open (ENTER) |
| Face Up / Scroll Up | X |
Up |
Y / Triangle or D-Pad Up |
Scroll Up |
| Face Down / Scroll Down | B |
Down |
X / Square or D-Pad Down |
Scroll Down |
| Face Left / Back | Y |
Left |
D-Pad Left |
Browser Back |
| Face Right / Forward | A |
Right |
D-Pad Right |
Browser Forward |
| Left Stick Click | R3 |
L3 |
L3 |
Middle Mouse Click |
| Right Stick Click | — | — | R3 |
Cycle Controller Mode |
| Dedicated Screenshot | — | — | Capture / Share |
Instant Screenshot (0ms) |
| Dedicated Home / Guide | Home (Hold: Screen) |
Capture (Hold: Screen) |
Guide / Home / PS |
Instant Super / Home Key (0ms) |
| Button | Right Joy-Con | Left Joy-Con | Universal Controller (Xbox / PS / Pro) | Action |
|---|---|---|---|---|
| Trigger | ZR |
ZL |
RT / R2 |
Play / Pause |
| Bumper | R |
L |
RB / R1 |
Mute / Unmute Audio |
| Side Rail SL |
SL (Vol Down) |
SL (Physical Right) |
D-Pad Up |
Volume Up (Left Joy-Con & Pad) / Down (Right) |
| Side Rail SR |
SR (Vol Up) |
SR (Physical Left) |
D-Pad Down |
Volume Down (Left Joy-Con & Pad) / Up (Right) |
| Face Up | X |
Up |
Y / Triangle |
Toggle Subtitles / Captions (C) |
| Face Down | B |
Down |
A / Cross |
Instant Rewind (-10s) |
| Face Left | Y |
Left |
D-Pad Left |
Previous Track / Replay |
| Face Right | A |
Right |
D-Pad Right |
Next Track / Skip |
| Stick Click | R3 |
L3 |
L3 |
Fullscreen Toggle (F) |
| Right Stick Click | — | — | R3 |
Cycle Controller Mode |
| Analog Stick Tilt | Tilt Left / Right | Tilt Left / Right | Right Stick Tilt | Continuous Seek ( |
| Dedicated Screenshot | — | — | Capture / Share |
Instant Screenshot (0ms) |
| Dedicated Home / Guide |
Home (Hold: Screen) |
Capture (Hold: Screen) |
Guide / Home / PS |
Instant Super / Home Key (0ms) |
| Button | Right Joy-Con | Left Joy-Con | Universal Controller (Xbox / PS / Pro) | Action |
|---|---|---|---|---|
| Primary Trigger | ZR |
ZL |
RT / R2 |
Enter / Submit Command |
| Bumper | R |
L |
RB / R1 |
Tab Auto-Complete |
| Side Rail SL | SL |
SL |
LT / L2 |
Escape / Normal Mode |
| Side Rail SR | SR |
SR |
LB / L1 |
Cancel / Interrupt (Ctrl+C) |
| Face Up | X |
Up |
D-Pad Up |
Previous Command (History Up) |
| Face Down | B |
Down |
B / Circle |
Backspace / Erase Character |
| Face Left | Y |
Left |
D-Pad Down |
Next Command (History Down) |
| Face Right | A |
Right |
A / Cross |
Enter / Confirm Prompt |
| Stick Click | R3 |
L3 |
L3 |
Suspend Job (Ctrl+Z) |
| Right Stick Click | — | — | R3 |
EOF / Exit (Ctrl+D) |
| Analog Stick Tilt | Stick Up/Down | Stick Up/Down | Stick Up/Down | Smooth Terminal Buffer Scroll |
| Dedicated Screenshot | — | — | Capture / Share |
Instant Screenshot (0ms) |
| Dedicated Home / Guide | Home (Hold: Screen) |
Capture (Hold: Screen) |
Guide / Home / PS |
Instant Super / Home Key (0ms) |
| Button | Right Joy-Con | Left Joy-Con | Universal Controller (Xbox / PS / Pro) | Action |
|---|---|---|---|---|
| Trigger | ZR |
ZL |
RT / R2 |
Jump / Action (Space) |
| Bumper | R |
L |
LT / L2 |
Target / Tab (Tab) |
| Side Rail SL | SL |
SL |
— | User Macro 1 (F13) |
| Side Rail SR | SR |
SR |
— | User Macro 2 (F14) |
| Face Up | X |
Up |
Y / Triangle |
Inventory (I) |
| Face Down | B |
Down |
A / Cross |
Quick Load (F9) |
| Face Left | Y |
Left |
X / Square |
Map (M) |
| Face Right | A |
Right |
B / Circle |
Quick Save (F5) |
| Stick Click | R3 |
L3 |
— | Character Sheet (C) |
| Dedicated Screenshot | — | — | Capture / Share |
Instant Screenshot (0ms) |
| Dedicated Home / Guide | Home (Hold: Screen) |
Capture (Hold: Screen) |
Guide / Home / PS |
Instant Super / Home Key (0ms) |
| Button | Right Joy-Con | Left Joy-Con | Universal Controller (Xbox / PS / Pro) | Action |
|---|---|---|---|---|
| Trigger | ZR |
ZL |
RT / R2 |
Next Slide (Space) |
| Bumper | R |
L |
LT / L2 |
Previous Slide (Backspace) |
| Face Up | X |
Up |
Y / Triangle |
Start Slideshow (F5) |
| Face Down | B |
Down |
X / Square |
Black Screen (B) |
| Face Left / Right | Y / A |
Left / Right |
B / A |
Prev / Next Slide |
| Stick Click | R3 |
L3 |
L3 |
Exit Slideshow (Esc) |
| Dedicated Screenshot | — | — | Capture / Share |
Instant Screenshot (0ms) |
| Dedicated Home / Guide | Home (Hold: Screen) |
Capture (Hold: Screen) |
Guide / Home / PS |
Instant Super / Home Key (0ms) |
Joy-Con Mouse features a hot-discoverable plugin system. You can create custom modes, disable built-in modes you don't use, and share modes with the community.
For full architectural details, tutorials, and contribution guides, see CUSTOM_MODES.md.
# List all discovered built-in and community modes
joycon-mouse --list-modes
# Disable a mode from cycle loop (e.g. presentation)
joycon-mouse --disable-mode presentation
# Re-enable a mode
joycon-mouse --enable-mode presentation
# Scaffold a brand-new mode template in custom_modes/
joycon-mouse --create-mode my_custom_modeEvery mode script is completely standalone and runnable directly with Python without a controller:
python3 modes/terminal.py
python3 custom_modes/presentation.py
python3 custom_modes/gaming_hotkeys.pyTo use the optional local authentication / sudo injection system:
- Copy
security_manager.py.exampletosecurity_manager.py:cp security_manager.py.example security_manager.py
- Configure your secret unlock sequence:
joycon-mouse --set-code
- Credentials and local salt hashes are encrypted via
/etc/machine-idand stored strictly in your user directory~/.config/joycon-mouse/security_config.json. These files are ignored in.gitignore.
Joy-Con Mouse is expanding across operating systems while preserving its signature zero-dependency architecture!
| Operating System | Branch | Status | Setup Guide |
|---|---|---|---|
| Linux (Wayland & X11) | main |
Production (v1.1.0+) | Quick Start |
| Windows 10 / 11 | windows |
Beta Preview | Testing Guide |
| macOS (Sonoma / Ventura / Monterey) | macos |
Beta Preview | Testing Guide |
Tip
Want to help test Joy-Con Mouse on Windows or Mac?
You don't need to know how to code! Check out our friendly TESTING_GUIDE.md to get started in under 2 minutes and be recognized as an official contributor.
Special thanks to the amazing testers and contributors helping test hardware, discover edge cases, and refine controller ergonomics across platforms:
| Contributor / Tester | Platform | Focus Area |
|---|---|---|
| @ImNotMrReaper | Linux / Core | Architecture, Linux evdev/uinput engine, modular plugins |
| @Senpai59 | Windows | Windows Lead Tester & Contributor (windows branch development & bugfixing) |
| (Community Beta Testers) | Windows / Mac / Linux | Cross-platform hardware verification & UX feedback |
Want to join our testing crew? Test the driver on your system and submit a report via Beta Tester Feedback!
Contributions are warmly welcomed! Joy-Con Mouse was designed from the ground up to be modular and community-friendly. If you want to create a custom controller mode, enhance button mappings, or report hardware quirks:
- Read
TESTING_GUIDE.mdto learn how non-coders and testers can test and submit reviews. - Read
CUSTOM_MODES.mdto see how to create and submit community modes. - Read the Contributing Guide for code style and standards.
- Please review our Code of Conduct.
- Open an Issue for feature requests or gamepad compatibility.
- Submit a Pull Request to share your mode with other users!
- Releases & Changes: See
CHANGELOG.mdfor detailed version history. - Security Policy: See
SECURITY.mdfor vulnerability disclosure guidelines. - License: Distributed under the MIT License. Designed and crafted for the open-source gaming and accessibility community.