PyEilik
Control an Eilik desk robot from Python — its servos, its screen, and video playback with the robot dancing along.
The robot ships sealed, with an app and no documented interface. The protocol this speaks was recovered by reverse engineering and checked against real hardware; it is written up in full at eiliksdk.com/protocol.
A C core with a stable ABI does the work; the Python package is a thin wrapper over it.
macOS only, and deliberately so. The robot runs at 125000 baud, which is not a standard rate: setting it needs an Apple-specific ioctl, and there is no equivalent elsewhere. On another platform the port would open at some default rate and put garbage on the wire, which is worse than not shipping at all.
Install
pip install pyeilik
The distribution is pyeilik; the import is eilik, the way pyserial
imports as serial.
One wheel covers Apple silicon and Intel on any Python 3.9 or newer: it carries a plain shared library rather than a CPython extension, so it is not tied to an interpreter version.
Showing a PNG needs a decoder, which Python has none of built in:
pip install 'pyeilik[image]'
Quick start
import eilik
with eilik.connect() as robot:
robot.arm_left.to(1800)
robot.head.to(1600)
robot.commit() # both joints move together, in one packet
print(robot.positions())
robot.rest()
Sides are the robot's own, the way anatomy is normally named: arm_left is
the robot's left arm, which is the one you see on your right when facing it.
What it does
Servos. Four joints, with their real travel limits enforced. Targets are staged and then committed, because one packet can carry all four and that is the only way to move them in step.
The screen. 128×64, one bit per pixel, in both directions.
robot.screen.show("face.png") # scaled, thresholded, rotated for you
saved = robot.screen.read() # 1024 bytes, the panel's own order
robot.screen.clear()
Video, and dancing to it. Needs ffmpeg on PATH.
robot.play("clip.mp4") # picture and sound
robot.play("clip.mp4", dance="simple") # and the robot moves to it
robot.play("clip.mp4", dance="guitar")
Sound comes out of your computer. The robot has a speaker, but no command exists to send audio to it — not in this protocol, and not in the manufacturer's own software either.
Worth knowing
ServoFaultErrormeans a power cycle, not a bug hunt. When every joint reads position 0 the servo controller has stopped. Unplugging USB will not fix it: the robot has an internal battery, so it has to be switched off at the power switch.- Only one process can hold the port. A second connection raises
PortBusyError. Use the context manager so the port is always released. - Every command waits for its acknowledgement. Sending a second command while the firmware is still reading a 1032-byte display frame drops the device off the USB bus. The library waits so you do not have to.
Links
Not affiliated
Eilik is a product of its respective manufacturer. This project is independent, unofficial, and not endorsed by them. The name is used only to say which device the library talks to.
License
MIT.
Development
cmake -S . -B build -DBUILD_SHARED_LIBS=ON && cmake --build build
pip install -e '.[dev]'
ctest --test-dir build # C, no robot needed
pytest # Python, no robot needed
pytest -m hardware # needs a robot
The documentation site lives in site/.
Metadata
Release files for pyeilik 0.3.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pyeilik-0.3.1.tar.gz | 2.0 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pyeilik-0.3.1-py3-none-macosx_11_0_universal2.whl | Python 3 | none | macOS 11.0+ universal2 (ARM64, x86-64) | Details |
Total release size: 2.1 MB
Release files / pyeilik-0.3.1.tar.gz
| Download URL | pyeilik-0.3.1.tar.gz |
|---|---|
| Size | 2.0 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ae4e1bdde4939b95c85caeb98c07ec85bd2eb209aa5c79e713505766e1ae8d71
|
|
BLAKE2b-256 checksum How to use checksums |
1770040a59a706410a5bc18a88a6ffadff8ed79d28edfd37a85bf6c4f8e9e9c8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.
Transparency logRelease files / pyeilik-0.3.1-py3-none-macosx_11_0_universal2.whl
| Download URL | pyeilik-0.3.1-py3-none-macosx_11_0_universal2.whl |
|---|---|
| Size | 58.9 kB |
| Tags | Python 3 macOS 11.0+ universal2 (ARM64, x86-64) |
|
SHA-256 checksum How to use checksums |
68dd1983168c646bbdd137e6d178cf0c605955643397255f70817162fc13d288
|
|
BLAKE2b-256 checksum How to use checksums |
6cf74c8092d66ad5fb9fd849bcca5fc375b131dbd8193e22cd39ba189ddb4c25
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 26, 2026.
Transparency log