An experimental agent harness, headless touch driver, and screenshot feedback loop for jailbroken Amazon Kindle devices running KOReader.
KAC lets local agents and test pipelines interact with a physical Kindle over SSH. It provides touch injection, gestures, bounded lifecycle operations, and framebuffer snapshots without modifying the Kindle root filesystem.
Warning
This is a field-tested research baseline, not a consumer-ready jailbreak or remote-desktop product. It controls a real device through an SSH service that commonly runs as root. Read SAFETY.md before use.
Modern Kindles running stripped-down BusyBox lack standard Linux automation packages like evemu, xdotool, adb, or python.
KAC solves this problem by using KOReader's bundled LuaJIT runtime with
Foreign Function Interface (FFI) to dispatch Linux Multi-Touch Type B kernel
events (struct input_event) to the input device selected by the active model
profile.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β AI Agent (Claude / Codex / Antigravity / Cursor) β
βββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ
β (JSON-RPC / MCP or CLI)
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Kindle Agent Controller (Mac / PC) β
ββββββββββββββββ¬βββββββββββββββββββββββββββ²βββββββββββββββ
β (SSH / Port 2222) β (Frame Buffer SCP)
βΌ β
ββββββββββββββββββββββββββββββββ ββββββββββ΄βββββββββββββββ
β LuaJIT FFI System Calls β β /dev/fb0 Raw Dump β
β (open, write, usleep) β β (1272x1696 RGBA / L8) β
ββββββββββββββββ¬ββββββββββββββββ ββββββββββ²βββββββββββββββ
β β
βΌ β
ββββββββββββββββββββββββββββββββ β
β Linux Kernel (profiled evdev)β β
ββββββββββββββββ¬ββββββββββββββββ β
βΌ β
βββββββββββββββββββββββββββββββββββββββββββ΄βββββββββββββββ
β Physical Kindle Hardware (Colorsoft / Basic) β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- ποΈ No New Touch Binary On-Device: Uses KOReader's bundled LuaJIT FFI and a model profile instead of installing an input utility.
- ποΈ Full Multi-Touch Protocol (Type B): Supports
ABS_MT_TRACKING_ID,ABS_MT_POSITION_X/Y,SYN_REPORT, andBTN_TOUCH. - πΌοΈ Framebuffer Snapshots: Captures a profiled frame from
/dev/fb0; arbitrary partial-refresh and active-buffer reconstruction remain open work. - π Model Context Protocol (MCP) Server: Plug KAC directly into Claude Desktop or Cursor so LLMs can invoke
kindle_tap,kindle_swipe, andkindle_screenshotas native tools. - π± Profile Table: Includes Colorsoft, Basic, PW5, Oasis 3, and Scribe geometry. Physical field acceptance currently covers the Colorsoft and Basic only.
- A jailbroken Kindle with KOReader installed.
- KOReader SSH Server enabled on port
2222(passwordless or public key auth). - Python 3.9+ on your computer:
python3 -m venv .venv . .venv/bin/activate python3 -m pip install -e .
# The device profile is auto-detected from the Kindle model/framebuffer.
# Capture a live screenshot from the Kindle
python3 -m kac.cli --host KINDLE_IP screenshot --out current_screen.png
# Tap a button at coordinate (x, y)
python3 -m kac.cli --host KINDLE_IP tap 636 1600
# Swipe left (Next Page)
python3 -m kac.cli --host KINDLE_IP swipe 1000 800 200 800
# Swipe right (Previous Page)
python3 -m kac.cli --host KINDLE_IP swipe 200 800 1000 800
# Restart KOReader without leaving a stale launcher or duplicate reader
python3 -m kac.cli --host KINDLE_IP restart
# Launch through the supported package manager on a modern Kindle jailbreak
python3 -m kac.cli --host KINDLE_IP restart --launch-mode kpm
# Launch through KPM while KOReader temporarily owns the device without Amazon UI
python3 -m kac.cli --host KINDLE_IP restart --launch-mode kpm-framework-stopOn the first touch action after a Kindle reboot, KAC automatically copies its
small LuaJIT helpers into the device's temporary /tmp directory. You do not
need to stage tap.lua, swipe.lua, or longpress.lua manually. SSH/SCP
failures are surfaced instead of being treated as successful no-op gestures.
KAC preserves KOReader's live Kindle launcher flags during a normal restart.
The restart transition is detached from the SSH session, asks KOReader to exit
cleanly, waits for its wrapper to finish restoring the Kindle lifecycle, and
then launches one fresh instance. It deliberately fails closed instead of
using kill -9, because force-killing the wrapper can leave Amazon's framework
or window manager suspended. Diagnostic output is written to
/tmp/koreader-kac-restart.log on the Kindle.
Modern KindleModding jailbreaks use KPM and scriptlets; --launch-mode kpm
uses that supported path. KUAL modes remain available for older installations
and migration diagnostics, but kual-framework-stop should only be used
deliberately because it suspends the stock Kindle interface while KOReader is
running.
--launch-mode kpm-framework-stop forwards KOReader's official
--framework_stop flag through KPM. It is appropriate when KOReader should own
the framebuffer and suspend screen completely, and KOReader's launcher will
restore the Amazon framework on exit. This flag does not itself rewrite Kindle
blanket modules; device-specific blanket correction belongs in a guarded,
backed-up launcher such as the tested Basic recovery script.
If auto-detection cannot identify an unusual model, pass an explicit profile,
for example --device basic_11th.
KAC distinguishes two very different USB connections:
- USB storage/MTP can stage installers, books, configuration, and recovery files. It cannot execute root commands or inspect live processes. Newer Kindles expose MTP rather than a Finder-mounted disk on macOS, so KAC needs a libmtp-backed transport and must serialize access to the single MTP session.
- USBNetwork exposes SSH over the cable. Once installed and enabled, KAC's existing SSH controller can use it without Wi-Fi; only the host/addressing setup changes.
USBNetwork installation remains an explicit device bootstrap step. The exact package must be selected for the Kindle model, firmware, and jailbreak stack, then installed through that stack's supported package mechanism. KAC must not guess compatibility from a model nickname alone.
For development on macOS, tools/kac_mtp.c keeps one libmtp session open while
it resolves device paths and backs up exact requested files. This avoids the
Kindle disconnect/replug cycle caused by invoking several standalone libmtp
utilities. Build it against Homebrew's libmtp:
cc -std=c11 -Wall -Wextra $(pkg-config --cflags libmtp) \
tools/kac_mtp.c -o tools/kac-mtp $(pkg-config --libs libmtp)The get command requires explicit absolute device paths, rejects traversal,
and preserves those paths beneath the selected local destination. put
resolves an explicit existing parent folder; put-root is the stricter
root-only form. Both upload one or more files in one MTP session, refuse to
overwrite a mismatched existing path, reuse an exact-size staged object for
idempotent retries, and verify every resulting MTP object name, parent, and
size before reporting success. Kindle firmware may acknowledge an
MTP object before its index/storage commit is durable, so the uploader keeps
the session open briefly after each transfer; critical recovery uploads still
require a detach/reconnect read-back before execution.
For multi-step work, kac-mtp shell holds one libmtp device handle and accepts
tab-delimited find, get, put, replace, refresh, and quit commands.
This prevents the physical reconnect loop caused by releasing the Kindle after
every operation. replace remains exact-path-only and should follow a get
backup in the same session.
The recovery/ directory records the physical Basic 5 migration path. These
are dated evidence scripts, not a universal installer; read
recovery/README.md first.
install_zenos_trial_and_inventory.shinstalls a checksum-verified ZenOS bundle from a one-tap document, moving SimpleUI and Bookshelf into a dated rollback directory before extraction.tune_basic_zenos.shnarrows the library to/mnt/us/books, locks the root, removes redundant edge-brightness gestures, and collapses a verified Home/Away OPDS pair. Its expected HTTPS URL and public label are explicit environment parameters.2-basic-no-special-offers.luais retained only as superseded experiment evidence. It did not solve framebuffer ownership and is not installed by the accepted tuning path.cleanup_basic_send_to_kindle_pdocs.shprepares an exact manifest fromcc.db, then requires the expected document count and target-list SHA-256 before deleting downloadedPDOCfiles. It deliberately preserves non-PDOC KFX purchases and dictionaries and does not delete cloud/catalog records.configure_basic_sleep_overlay.shdemonstrates the maintained overlay recipe: image-mode book-cover base plus one transparent PNG overlay.configure_basic_transparent_sleep_screen.shconfigures the tested page-peek recipe: transparent random-image sleep screens, image backgroundnone, and the separate Sleep Overlay patch disabled.
These scripts are evidence-bound to the tested MT8110 Bellatrix device /
KOReader KindleBasic5. Do not reuse them on another Kindle model without
fresh live-state checks and model-specific acceptance.
Add KAC to your Claude Desktop or Cursor MCP configuration (claude_desktop_config.json):
{
"mcpServers": {
"kindle": {
"command": "python3",
"args": ["-m", "kac.mcp_server", "--host", "KINDLE_IP", "--output-dir", "/absolute/path/to/kac-captures"]
}
}
}The stdio server implements current stateless discovery plus the legacy initialization handshake. It exposes device info, confined screenshots, bounded touch gestures, and a lifecycle-aware KOReader restart. Arbitrary root shell execution is intentionally CLI-only and requires an explicit warning acknowledgement. This is not continuous screen mirroring: each capture is a snapshot, and control depends on a reachable, awake SSH service.
python3 -m unittest discover -s tests -v
python3 -m compileall -q kac tests
sh -n recovery/*.sh
cc -std=c11 -Wall -Wextra -Werror $(pkg-config --cflags libmtp) \
tools/kac_mtp.c -o /tmp/kac-mtp $(pkg-config --libs libmtp)See RETROSPECTIVE.md for the field lessons and PROJECT_HANDOFF.md for the clean starting point for a future official product.
kindle-agent-controller/
βββ README.md # Main project documentation
βββ SAFETY.md # Trust boundary and mutation requirements
βββ RETROSPECTIVE.md # Reusable lessons from the two-device deployment
βββ PROJECT_HANDOFF.md # Product directions, boundaries, and release gates
βββ ARCHITECTURE.md # Low-level evdev & framebuffer reverse engineering guide
βββ RESEARCH_NOTES.md # Session hardware logs, kernel driver notes & discoveries
βββ ROADMAP.md # Open tasks for future agents & contributors
βββ recovery/ # Guarded one-tap and SSH migration/recovery helpers
βββ tools/ # Native transport prototypes such as kac-mtp
βββ kac/ # Python package
β βββ controller.py # High-level KindleController API
β βββ display.py # Framebuffer decoder & device profiles
β βββ cli.py # Command-line interface
β βββ mcp_server.py # Model Context Protocol server
βββ scripts/ # Headless LuaJIT FFI injection scripts
βββ tap.lua # Multi-touch tap driver
βββ swipe.lua # Multi-touch gesture interpolator
βββ longpress.lua # Long-press driver
MIT License. Copyright holders are listed in LICENSE.