PadawanKit is a Swift-native, concurrency-first interface to Apple's
GameController framework. Lifecycle changes are explicit, controller input is
exposed through shared AsyncSequence values, and the recommended API avoids
GameController types.
It requires Swift 6.2, macOS 15, iOS 18, tvOS 18, or visionOS 2.
Read the API documentation · View PadawanKit on Swift Package Index
PadawanKit: lifecycle, input, state, capabilities, discovery, recognition, haptics, and supported peripherals.PadawanUI: environment integration and view modifiers.
PadawanInterop remains an implementation target, not a published
library product.
import PadawanKit
@MainActor
func run() async {
let central = Central()
central.start()
defer { central.stop() }
for await event in central.events {
if case let .connected(controller) = event {
print(controller.metadata, controller.capabilityCatalog)
}
}
}Creating a Central has no side effects. Call start(), stop(),
startDiscovery(), and stopDiscovery() explicitly.
for await input in controller.inputEvents {
// System controller mappings are applied.
}
let current = controller.inputSnapshot()
let physical = controller.inputSnapshot(mapping: .unmapped)Each shared input stream retains its newest 64 pending events. A subscriber that cannot keep up can miss intermediate button transitions as well as analog samples. Drain events promptly into storage you own when lossless history is required, or use a snapshot when only current state matters.
for await _ in controller.sequenceEvents(for: .konamiCode) {
activateCheatMode()
}
let actions = ControllerActionMap(bindings: [
.init(action: "jump", gesture: .press(.a)),
.init(action: "sprint", gesture: .value(.leftTrigger, minimumValue: 0.8)),
])
for await action in controller.actionEvents(for: actions) {
perform(action)
}let heartbeat: HapticPattern = [
.transient(intensity: 1, sharpness: 0.7),
.transient(intensity: 0.7, sharpness: 0.5, at: 0.14),
]
try controller.haptics?.start()
try controller.haptics?.play(heartbeat)Haptic and DualSense adaptive-trigger APIs use typed errors. Haptic patterns
are Codable and can create retained players for looping, seeking, pausing,
and live parameter changes.
ContentView()
.controllerCentral(central)
.onControllerAvailable(of: DualSenseController.self) { controller in
// Existing and newly connected DualSense controllers.
}
.onControllerInput(.a) { controller, input in
// Handle input while this view is active.
}
.controllerConnectionNotice(.hud)The SwiftUI layer consumes an already-started Central; view construction
does not start controller observation or discovery.
PadawanKit includes explicitly managed keyboard, mouse, racing-wheel, iOS virtual-controller, and visionOS 26 spatial-stylus APIs. Unknown controllers remain usable through the generic capability model.
The independently buildable command-line package lives in the
padawan-cli repository. It depends
on this package and contains padawan, its bridge tests, and the browser/Wasm
experiment.
Run these commands from the repository root:
swift build -Xswiftc -warnings-as-errors
swift test -Xswiftc -warnings-as-errorsBuild DocC with:
xcodebuild docbuild -scheme PadawanKit -destination 'generic/platform=macOS'
xcodebuild docbuild -scheme PadawanUI -destination 'generic/platform=macOS'See the DocC guides for lifecycle, buffering, recorded-input testing, and the manual hardware verification matrix.
PadawanKit is available under the MIT License.