The Problem
Linux exposes the first‑generation Apple Siri Remote only as a raw /dev/hidraw device with a vendor‑defined report map. The remote stays silent until it is unlocked, and its reports contain touch, button, and gesture data that the OS does not interpret. A user needs a way to pair the remote, unlock it, decode its events, and optionally expose them as keyboard inputs.
What This Does
The project unlocks the remote, decodes its reports into JSON events, and can replay or expose those events as virtual key presses.
appleremote/__main__.pyimplements the CLI (list,monitor,gestures,lab,keys).appleremote/device.pyhandles HID discovery, unlocking, and raw I/O.appleremote/decode.pytranslates vendor reports into structured Python dicts.appleremote/gestures.pyaggregates touch points into tvOS‑style gestures.appleremote/keys.pymaps decoded events to Linux input events via/dev/uinput.docs/PROTOCOL.mddocuments the raw protocol.udev/71-appleremote.rulesgrants non‑root users write access to/dev/uinput.systemd/appleremote-keys.serviceshows how to run the virtual keyboard in a session.
How It Is Wired
Execution starts in appleremote/__main__.py. The main() function parses sys.argv and dispatches to one of the sub‑commands.
listcallsdevice.find_hidraw()to enumerate/dev/hidrawNnodes matching the remote’s vendor/product IDs.monitoropens the chosen node withdevice.open(), enters a loop reading reports, and for each report callsdecode.decode_report(). The resulting dict isjson.dumps()‑ed and written to stdout.gesturesruns the same read loop but feeds each decoded report intogestures.process_event(), which aggregates touch points and emits higher‑level gesture events.keysopens/dev/uinput(permissions supplied by the udev rule) and translates gesture/button events intoinput_eventstructures via the mapping defined inkeys.map. Each event is written to the uinput device.labstarts a tiny HTTP server that servesappleremote/lab.htmland streams the decoded stream to the browser via WebSocket.
The only external touch point is the HID device on /dev/hidrawN. All other I/O is either stdout (JSON) or /dev/uinput (virtual keyboard). No network or database interaction occurs.
How To Use It
Setup
git clone https://github.com/moses-y/open-appleremote
cd open-appleremote
No build or install step is required; the code uses only the standard library.
Configuration Apply the udev rule so the current user can write to /dev/uinput:
sudo cp udev/71-appleremote.rules /etc/udev/rules.d/
sudo udevadm control --reload && sudo udevadm trigger
Running
python3 -m appleremote list # find the HID node
python3 -m appleremote monitor # stream decoded JSON events
python3 -m appleremote gestures # tvOS‑style gestures
python3 -m appleremote lab # web lab on 127.0.0.1:8791
python3 -m appleremote keys # expose virtual keyboard
To replay a capture: python3 -m appleremote monitor --replay tests/sample.jsonl.
Systemd Add systemd/appleremote-keys.service to your unit directory and enable it to start the virtual keyboard automatically.
Real‑World Use
A media‑center operator can run python3 -m appleremote keys as a systemd service, turning the remote into a full keyboard for Kodi or a browser. The gestures sub‑command can feed into a custom UI that reacts to swipe gestures, while the lab web page provides an interactive debugging view during development.
Code Health & Issues
- Low (Dependency lock) –
pyproject.tomldeclares dependencies but no lockfile; builds may vary across environments. - Low (CI pipeline) – No
.github/or CI configuration; automated testing is not enforced. - Low (Testing coverage) – Three test files (
tests/test_appleremote.py) cover basic device discovery and decoding but lack end‑to‑end integration tests. - Low (Documentation) –
docs/PROTOCOL.mdis comprehensive, yet the README lacks a brief API reference.
No critical bugs were found in static analysis; the code follows a linear call path with no hidden side effects.
The Bottom Line
open-appleremote provides a lightweight, dependency‑free solution to unlock and decode the Apple Siri Remote on Linux. Its single‑script interface and clear module separation make it easy to integrate into a media‑center or remote‑control workflow. The lack of CI and lockfiles limits reproducibility, but for quick prototypes or small deployments it offers a practical, well‑documented approach.