Use your Nintendo Switch Online GameCube controller, Nintendo Switch 2 Pro Controller, and Joy-Con 2 in apps and games.
Switch2Kit provides controller support that any app can integrate on a supported platform. These Dolphin and Cemu forks are maintained reference apps with Switch2Kit already built in: get the app, connect your controller, and play. You do not need to install or run Switch2Kit separately.
You do NOT need this repo to play games; go straight to the forked projects above.
Continue reading to add Switch2 controller support to your apps.
Those maintained forks embed Switch2Kit on macOS 15+, Linux, and Windows x64. Linux and Windows support is experimental.
| Your games | App with Switch2Kit built in | Get started |
|---|---|---|
| GameCube and Wii | Dolphin fork | Download, connect, and play |
| Wii U | Cemu fork | Download, connect, and play |
- Get a controller-enabled app from the linked fork's README. Use the platform-specific Switch2Kit GitHub Actions build linked in that README; downloading artifacts requires signing in to GitHub. Only successful runs with an application artifact provide a download. These are development builds, not published releases. Each README also includes build-and-launch instructions when a download is unavailable.
- Connect over Bluetooth. Open Controllers in Dolphin or Options > Input settings in Cemu, click Find Switch 2 Controllers, allow Bluetooth access, and hold the controller's Sync button. Close other apps managing the same controller first.
- Select your controller and play. For GameCube games in Dolphin, select the GameCube or Pro controller beside the desired GameCube port. In Cemu, select it beside Emulated controller. The forks apply the recommended button and stick mappings automatically. Their guides cover rumble, reconnecting, and controller-specific limitations; Wii Remote setup in Dolphin remains separate.
Switch2Kit is not limited to Dolphin and Cemu. Apps can embed the same support directly, and the optional macOS Switch2Kit dashboard provides output paths for compatible SDL3 games, Chromium browser games, and RetroArch.
For an app without built-in support, follow the dashboard setup guide and the instructions for its output path. Installing Switch2Kit alone does not make a controller appear in every app: it is not a universal system-wide controller driver.
| Controller | Controls | Rumble |
|---|---|---|
| Nintendo Switch Online GameCube controller | Buttons, two sticks, analog L/R trigger travel and separate full-click buttons | On/off motor |
| Nintendo Switch 2 Pro Controller | Buttons and two sticks; ZL/ZR are digital, not analog GameCube triggers | Independent HD motors |
| Joy-Con 2, left or right | Buttons and one stick per half | Single HD motor per half |
This is support for the wireless NSO GameCube controller, not an original wired GameCube controller or USB adapter. Feature availability also depends on the app and its mappings. See controller and feature coverage for battery, raw motion, Joy-Con optical counters, output details, and physical-testing limits.
| Platform | Current Switch2Kit support |
|---|---|
| macOS 15+ (Apple Silicon and Intel) | Live Bluetooth controller support, the maintained Dolphin/Cemu reference forks, Swift and C/C++ hosts, and the optional dashboard. |
| Linux / BlueZ (experimental) | Native Bluetooth controller engine, Swift/C/C++ hosts, and the maintained Dolphin/Cemu forks. Requirements and setup. |
| Windows x64 / WinRT (experimental) | Native Bluetooth LE controller engine, Swift/C/C++ hosts, and the maintained Dolphin/Cemu forks. Requirements and setup. |
| Android | No Switch2Kit controller backend. |
The sections below cover adding Switch2Kit to an app, building the optional dashboard, and working on the library. To use an existing controller-enabled emulator, start with Start playing.
Use the C ABI and CMake integration to embed the same controller engine in a native host. The host does not need to be written in Swift and does not require the dashboard.
The maintained Dolphin and Cemu forks demonstrate complete app integrations. The separate emulator integration guide documents pinned source patches, builds, controller bindings, and motion-profile configuration for the SDK's reference integrations. Those patches and the maintained forks can differ in UI, supported platforms, and features; use each fork's README for its end-user setup.
The SDL3 integrations run in the emulator's existing input backend. The emulator owns discovery, Bluetooth permissions, and controller lifecycle; no network bridge, second SDL instance, or system virtual controller is required. Disabled builds retain the emulator's upstream platforms and deployment targets.
Requires Swift 6.2+. macOS hosts require macOS 15+ and Xcode 26+; Linux hosts use BlueZ and the native Swift toolchain; Windows hosts use WinRT and the x64 Swift toolchain.
.package(url: "https://github.com/jmonster/Switch2Kit.git", branch: "main")Add .product(name: "Switch2Kit", package: "Switch2Kit") to your target dependencies. For a local checkout, use .package(path: "/path/to/Switch2Kit").
import Switch2Kit
@MainActor
final class ControllerInput {
let manager = Switch2ControllerManager()
private var observation: Switch2ControllerObservation?
func start() throws {
observation = try manager.observe(on: .main) { event in
if case .input(let controller) = event {
print(controller.state.buttons)
}
}
manager.start()
try manager.discover(for: 60)
}
func stop() async {
await manager.stop()
observation?.cancel()
observation = nil
}
}On macOS, the host provides NSBluetoothAlwaysUsageDescription and, when sandboxed, com.apple.security.device.bluetooth. In-process input needs neither Accessibility permission nor CoreHID. Hold the controller's Sync button while discovery is active.
Raw motion telemetry is available through the library. Calibrated SDL motion requires an explicitly selected physical motion profile; no measured built-in profiles are supplied. NSO GameCube's soft/strong firmware feedback clips are separate from its on/off game rumble. See controller and feature coverage for transport, output, and physical-qualification boundaries.
Library guide · API · SwiftUI · AppKit · Bluetooth lifecycle · Application actions
The optional macOS dashboard displays live input and manages multiple controllers, Joy-Con pairs, player indicators, rumble, and mappings. It is not needed by the Dolphin and Cemu forks above.
With the macOS/Xcode requirements above installed, clone this repository and run:
git clone https://github.com/jmonster/Switch2Kit.git
cd Switch2Kit
bash scripts/build-app.sh
open build/Switch2Kit.appChoose an output for the intended game: SDL, browser, or RetroArch. Keyboard, mouse, gestures, and optional virtual HID are application features, not library dependencies. Follow the output-specific requirements rather than enabling every output.
Setup · Rumble · Application configuration · Troubleshooting
Package and regression checks (automated tests do not establish physical radio or gameplay acceptance):
swift build
swift test
bash tests/run.sh
# Linux radio integration tests:
bash tests/linux-bluez/run.sh
# macOS application and independent Swift consumer checks:
bash scripts/build-switch2kit-demo.sh
bash scripts/verify-switch2kit-consumer.shThe standalone demo shows live controller input and local semantic navigation. Swift consumers use SwiftPM source integration; the independent consumer check needs no prebuilt framework. The distribution note covers migration from the standalone Swift XCFramework. The optional C/C++ integration retains its native library build and validation.