A keyboard-first native SwiftUI remote for Apple TV. Device discovery, encrypted pairing, and Companion-protocol commands are provided by the MIT-licensed pyatv library through a bundled Python bridge.
Apple TV Remote lives in the macOS menu bar without a Dock icon. Use its status item to show or hide the remote, manage the connection, or quit. The window is the remote itself: drag its background to move it, or right-click it to choose an Apple TV, rescan, pair, and open keyboard help.
Press Control–Option–Shift once from any app to turn global remote mode on. Use the arrow keys to navigate, Return to select, Delete to go back, and − or + to change the volume. Press the modifier chord again to turn the mode off.
The app follows the same local-package structure as Progress Cocoa:
| Module | Responsibility |
|---|---|
AppleTVRemote/ |
Thin macOS app lifecycle and menu commands |
ModelKit/ |
Shared Apple TV, command, and connection domain values |
Aesthetics/ |
Shared design tokens and button styles |
AppleTVClient/ |
Apple TV discovery, pairing, command transport, and Python bridge |
GlobalRemote/ |
System-wide registered hotkeys and transient overlay |
RemoteControlView/ |
Main SwiftUI remote view, view model, and supporting views |
Each package directory is independently buildable and has Sources/<Module> and Tests/<Module>Tests.
Press Control–Option–Shift once from any app to show the global remote indicator and capture its remote keys. Press the same modifier chord again to turn the mode off. The modifiers do not need to remain held while navigating.
Global control uses macOS registered hotkeys and does not require Accessibility or Input Monitoring permission.
Open AppleTVRemote.xcodeproj in Xcode, or use the repository commands:
make test
make build
./scripts/build-app.sh
open outputs/Apple\ TV\ Remote.appRun ./scripts/generate-project.rb after intentionally changing the app target or its local-package products. The committed Xcode project is generated from that script.
This Mac uses uv to provide an isolated Python runtime for pyatv. Pairing credentials are stored by pyatv in ~/.pyatv.conf; they are never included in this repository.
