August 17, 2026 • 11 min read

How to Run Your Own Binaries on a Jailbroken Kindle Scribe

kindle scribe jailbreak right-to-repair kindlehf git ssh glinet

I own a first-gen Kindle Scribe. Firmware 5.19.5. Amazon still boots it. After the public Véra jailbreak (August 2026, Ava and sparklerfish, Kindle software 5.17.1–5.19.6) I can run my own programs on it. The stock notebook UI is bad. I want a notes app I control.

This is the home screen on this unit, pulled off /dev/fb0 over SSH. Amazon’s store still sits under my own kindle-userspace notes scriptlets.

Home screen of this Scribe: Amazon library chrome plus Notes Sync and Notes Draw

This is the pipe I used on this unit: build for kindlehf, stage over MTP, launch with a scriptlet, open a Wi-Fi shell, put git on /mnt/us, then export stock notebooks with Notes Sync. I will not unpack the jailbreak books. I will not help strip Kindle store DRM.

The Kindle userspace pipeline: build, stage over MTP, tap a scriptlet, then work over a Wi-Fi shell

You do not get a custom kernel. otaup still checks RSA-SHA256 against /etc/uks/pubprodkey01.pem and pubprodkey02.pem.

L0  Open your own files
L1  Run our userspace          ← this post
L2  Replace Amazon daemons
L4  Our kernel                 ← still signed

What you need

  • A jailbroken Kindle on ≥ 5.16.3 (hard-float kindlehf). This write-up is a 1st-gen Scribe, 5.19.5, kernel 4.9.77-lab126, glibc 2.35, armv7l.
  • Véra, or any jailbreak that leaves you KPM and scriptlets. KUAL is dead on ≥ 5.19.4. Véra does not ship MRPI. ;log mrpi prints mrpi is not installed.
  • Calibre (calibre-debug), OpenSSH, and for git: curl and tar.
  • The Kindle on a Wi-Fi you can reach.

You will end with files you own under /mnt/us, library books that run shell, ssh as root over Wi-Fi, and git version 2.47.3 if you follow that section.

The filesystem will fight you

/mnt/us (Internal Storage) is Kindle FSP (fuse.fsp). It behaves like FAT. ln -s returns Operation not permitted. chmod +x is mostly theater.

A normal Alpine miniroot will not extract. cp -a of a tree full of symlinks will not work. Worse: mount --bind /mnt/us or /proc into a directory on /mnt/us, then rm -rf that directory, deletes your library. I did this once. The jailbreak hotfix on rootfs survived. Books on the userstore did not.

Put payloads as regular files. If a package is a tarball of symlinks, flatten it on the computer first.

The /mnt/us layout used for scriptlets, USBNetLite, custom binaries, KOReader, and update packages

Build

Static Go CLI (no GTK, no FBInk):

CGO_ENABLED=0 GOOS=linux GOARCH=arm GOARM=7 \
  go build -trimpath -ldflags '-s -w' -o myapp-kindlehf ./cmd/myapp
file myapp-kindlehf
# ELF 32-bit LSB executable, ARM, EABI5, statically linked

Not darwin. Not arm64. Kernel 4.9 is new enough for current Go. Static means you do not care about soft-float vs hard-float libc.

A real e-ink UI (notes, full screen) needs koxtoolchain and kindle-sdk, target kindlehf, Meson, FBInk/GTK. Walkthrough: kindlemodding.org/kindle-dev/gtk-tutorial.

I built camp and fest with the Go recipe (21.9 MB and 29.7 MB on this unit). They print linux/arm and Go 1.26.4. They are not a Mac campaign. Do not launch a 50 MB TUI from a library book.

Stage over MTP

USB ID 1949:9981. Calibre ebook-device flakes on this unit. Use the driver, and quit the Calibre GUI first. MTP is single-client on macOS.

calibre-debug -e scripts/mtp-put-dir.py -- ./myapp-kindlehf bin myapp
calibre-debug -e scripts/mtp-put-dir.py -- ./Install-MyApp.sh documents Install-MyApp.sh

Do not full-scan the store. This unit white-screened after an MTP thrash in July. Recovery was a 40 second power hold.

Path Role
/mnt/us/documents/*.sh Scriptlets (library books)
/mnt/us/usbnetlite/ dropbear + usbnetwork (regular files)
/mnt/us/bin/ camp, fest, git, vim, start-ssh, notes-sync
/mnt/us/opt/git/ Flattened musl git
/mnt/us/koreader/ KPM payload
/mnt/us/mrpackages/*.bin Only place for unsigned update bins

A .bin on the storage root is how official OTA starts. That is how you lose the jailbreak.

Scriptlets

/mnt/us/documents/Something.sh with these headers shows up as a book. After the jailbreak, a tap runs it as root. stdout goes to FBInk unless # DontUseFBInk.

#!/bin/sh
# Name: Start SSH
# Author: lab

echo "=== starting ==="
echo DONE

Keep it short. Copy files, chmod, print DONE. If you exec a 22 MB Go binary from the book, the UI hangs and you get no log.

A Kindle library view showing packages and scriptlets presented as books

FBInk output from a USBNet bootstrap scriptlet

Search the library by name. New .sh files sometimes need a restart to appear.

KPM installs packages: ;kpm update, ;kpm install koreader. KOReader.sh without the koreader/ tree does nothing useful.

Wi-Fi SSH (do not use Toggle USBNet)

USBNetLite (khf / libcrypt.so.2) is the Scribe-correct dropbear package. notmarek/kindle-usbnetlite; khf rebuild MobileRead 369990 (Update_usbnetlite_1.2.4_install_khf.bin).

Unpack the .bin on the computer. MTP the already extracted files into /mnt/us/usbnetlite/bin/ (dropbearmulti, usbnetwork, …). Do not ask the Kindle to tar/xz if you can avoid it.

Do not tap Toggle USBNet. That script calls volumd useUsbForNetwork 1, puts the device on a USB-ethernet page, and the only reliable exit is power off. It also starts dropbear in a mode that fought OpenSSH on this Mac after a host-key rotate.

After a reboot, tap a Start SSH scriptlet or run /mnt/us/bin/start-ssh. That script copies keys into /mnt/us/.ssh/authorized_keys (dropbear -H /mnt/us), kills a wedged dropbear, then:

/mnt/us/usbnetlite/bin/dropbearmulti dropbear -R -H /mnt/us -p 22 -K 15 -s
iptables -I INPUT -i wlan0 -p tcp --dport 22 -j ACCEPT

-R generates host keys if missing. -s disables password login.

Host scribe
  HostName KINDLE_IP
  User root
  IdentityFile ~/.ssh/id_kindle_scribe
  IdentitiesOnly yes
  StrictHostKeyChecking accept-new
  HostKeyAlgorithms +ssh-rsa
  PubkeyAcceptedAlgorithms +ssh-rsa,ssh-ed25519

KINDLE_IP is whatever the tablet has on your LAN. On this bench it was 192.168.8.142. accept-new still rejects a rotated key. After a wipe:

ssh-keygen -R KINDLE_IP
ssh scribe

Connection refused means dropbear is not running. Reboot does not start it. Host key verification failed means you forgot -R cleanup. Connection closed during KEX was a wedged dropbear here; kill it and run start-ssh again.

USB gadget (192.168.15.244 on the Kindle) is optional and kills MTP while it is on. I do not use it.

kTerm on the Kindle showing USBNetLite and a shell command after the scriptlets have done their work

KOReader → Tools → More tools → SSH is a backup (v2026.07.1 on this unit).

Watch it from a travel router

I did not put the Scribe on house Wi-Fi. It joins a GL-AXT1800 (OpenWrt) so I can see what it phones home to. The AP is the tap. That is not a break of Amazon’s boot chain.

On this bench the Scribe’s lease is 192.168.8.142. The router LAN is 192.168.8.1. The Mac stays on house ethernet and adds a second address:

sudo ifconfig en0 alias 192.168.8.179 netmask 255.255.255.0
ssh gl-axt1800   # [email protected]
ssh scribe

If the GL LAN is also on the house switch, unplug it when you are done. Two DHCP servers on one L2 will NAK each other’s clients. Do not factory-reset the GL if you care about the lab SSH key.

DNS sinkhole. dnsmasq maps a short list to 0.0.0.0: api.amazon.com, unagi-na.amazon.com, cde-ta-g7g.amazon.com, www.amazon.com, audible.com, images-amazon.com, a2z.com, and a few more from captures. Jailbreak hosts (tene7.com, repo.kindlemodding.org) still resolve.

The list does not cover all of Amazon. todo-ta-g7g.amazon.com and softwareupdates.amazon.com still return public A records. This does not block Settings → Update. Airplane mode, or staying off house Wi-Fi, is what keeps this unit off official OTA. After you change the list, toggle Kindle Wi-Fi so it drops cached answers.

Captures. tcpdump is on the GL. I ran time-boxed dumps on the LAN, filtered to the Scribe, then pulled DNS and SNI into a host inventory and decided what to add. Query logging is not on all the time. You do not install a sniffer on the Kindle.

I own the path off the device. I do not own the boot chain.

Debian armhf git drags half of gnutls. Alpine-in-chroot wants binds. Both are the wrong first move.

Working recipe on this Scribe (2026-08-17): git 2.47.3, musl, armv7, no chroot.

On the computer, from Alpine v3.21 armv7:

  1. Download git-2.47.3-r0.apk, git-init-template-2.47.3-r0.apk, pcre2, libexpat (the expat APK is only xmlwf), libcurl, brotli-libs, c-ares, libidn2, libunistring, nghttp2-libs, libpsl, zstd-libs, libcrypto3, libssl3, ca-certificates-bundle, libgcc. The Kindle’s own wget reset on that CDN. Download here.
  2. Extract each APK (tar -xzf; skip .PKGINFO / .SIGN.*).
  3. Build a flat directory:
    • lib/ld-musl-armhf.so.1 from the musl package
    • copy the same file to lib/libc.musl-armv7.so.1 (no symlinks)
    • copy each .so.* under the soname git DT_NEEDEDs (libpcre2-8.so.0, libz.so.1, libcurl.so.4, …)
    • bin/git (the real ELF)
    • only regular files from usr/libexec/git-core (do not dereference the 141 copies of git)
    • copy git-remote-http to git-remote-https
    • CA bundle → ssl/cert.pem
  4. find flat -type l must print nothing. Pack git-kindlehf.tar.gz.

On the Kindle, once SSH works:

scp git-kindlehf.tar.gz scribe:/mnt/us/
ssh scribe
mkdir -p /mnt/us/opt/git /mnt/us/bin
tar -xzf /mnt/us/git-kindlehf.tar.gz -C /mnt/us/opt/git

Wrapper /mnt/us/bin/git:

#!/bin/sh
ROOT=/mnt/us/opt/git
export GIT_EXEC_PATH="$ROOT/libexec/git-core"
export GIT_TEMPLATE_DIR="$ROOT/share/git-core/templates"
export SSL_CERT_FILE="$ROOT/ssl/cert.pem"
export GIT_SSL_CAINFO="$ROOT/ssl/cert.pem"
exec "$ROOT/lib/ld-musl-armhf.so.1" --library-path "$ROOT/lib" "$ROOT/bin/git" "$@"
chmod 0755 /mnt/us/bin/git
export PATH=/mnt/us/bin:$PATH
git --version
# git version 2.47.3
mkdir /tmp/t && cd /tmp/t
git init && echo hi > README && git add README
git -c user.email=you@local -c user.name=you commit -m test

That is the proof. HTTPS remotes use the CA file in the wrapper.

Notes Sync (stock notebooks → git)

Amazon still draws the notebook. I still want the ink in a repo I control.

Notes Sync is a scriptlet. Write in the stock Notebook tab, close the notebook, tap Notes Sync. The device copies what is already on disk under /mnt/us/notes and git pushes to a private remote. Start SSH is not required for that tap.

It is not a replacement notes app. Amazon still owns the UI and the .nbk format. Cloud-only notebooks stay MISSING until you open them once so the .nbk lands on disk. On this unit (2026-08-18) that was 2 of 15 notebooks until I opened the rest.

Notes Draw on the home screen is a different experiment: a framebuffer probe. It crashed KPPMainAppV2. Do not use it as the product.

See the panel from the desk

I cannot see the e-ink from SSH. mmap + FBInk refresh on this Scribe paints a black panel. eips row/col text stacks on one line. The path that actually shows is a full-screen PNG via:

eips -g /mnt/us/root-log.png -f -w gc16

A still poster is not the loop. The loop is: SSH a real command, render 1860×2480 of the session so far, eips -g it, look at the desk.

The desk camera is an Insta360 Link 2 (ffmpeg avfoundation index 0, pixel format uyvy422). From the campaign root:

just cam-list
just cam                      # lab/cam/latest.jpg
just cam-live                 # SSH to the Scribe, each command re-paints

DeskView in Insta360 Link Controller aims the gimbal at the table. There is no CLI for DeskView yet. If tracking is on, the cam stares at a face instead of the Scribe. Do not commit those stills.

If a JPEG of black e-ink looks empty, dump /dev/fb0 (1860×2480 Y8, stride 1872) and read the buffer.

What I ran on this unit

Serial G0922707251300S0. Véra: Font Calibration is supposed to be blank. Save theme (Bookerly, bold 0, max size, spacing 2), open the Véra book. Success string: RESTARTING GUI. Then ;kpm install koreader.

USBNetLite unpacked on the Mac, pushed as a flat tree. After reboot, /mnt/us/bin/start-ssh. ssh scribe as root. Selected Amazon names sinkholed on the GL; tene7.com left open. camp / fest / git 2.47.3 / vim 9.1 / notes-sync under /mnt/us/bin.

Pen: /dev/input/stylusevent3 (WacomDigitizer). Touch: /dev/input/touchevent4 (pt_mt).

If it breaks

What you see What it is
;log mrpi does nothing / “not installed” Véra has no MRPI. Do not wait.
Install USBNet hangs On-device xz/tar of the package. Push the extracted usbnetlite/ tree instead.
Stuck on a USBNet / RNDIS page You tapped Toggle USBNet or plugged USB with gadget on. Power off. Do not use that book.
ssh: Connection refused Dropbear is not running. Run /mnt/us/bin/start-ssh.
REMOTE HOST IDENTIFICATION HAS CHANGED New host key. ssh-keygen -R <ip>.
Connection closed in KEX Wedged dropbear. Kill it, run start-ssh, do not Toggle.
KOReader book does nothing KOReader.sh without /mnt/us/koreader/. ;kpm install koreader again.
Scriptlet missing from library Search. Restart once. Confirm the file is in documents/ and has # Name:.
Application Error dialog A library book stole /dev/fb0 (eips/mmap) while KPP still owned the booklet. Tap the dialog. If it loops, 40s power hold. Do not paint the panel from a scriptlet. Use SSH (just cam-live) after Start SSH.
Extract “can’t create symlink” Flatten on the computer.

Don’t

  • Official Settings → Update (Véra ceiling here is 5.19.6).
  • Factory reset (kills the hotfix).
  • Put an install .bin on the Kindle root.
  • Expect KUAL.
  • rm -rf anything that might have /mnt/us or /proc bind-mounted.
  • Extract Alpine onto /mnt/us/alpine.
  • Run a 20+ MB TUI inside a scriptlet.
  • Store Véra *-jb.azw3 in git.

Notes Sync is the export pipe. A kindlehf notes surface that reads the Wacom node and writes SVG/PNG I own is still a different product. Amazon’s notebook format can stay Amazon’s.