I had a Kindle Voyage collecting dust in a drawer. It’s one of the nicest e-readers Amazon ever made (flush glass screen, page turn buttons) but I barely use it anymore as I prefer paper books now. It always bothers me when I have unused tech, and I remembered an article by Matthew Petroff where he jailbroke his Kindle and turned it into a weather display. I wanted to do the same: an always-on weather station that sits in my kitchen near my coffeemaker so I can see the forecast in the morning. It also seemed like a good project to try using Claude Code as an assistant, since it involves a lot of SSH, shell scripting, and reading other people’s code.

In this article, I will walk through how I jailbroke the Voyage, got a standalone weather display working with automatic sleep/wake cycles, and the many dead ends I hit along the way.

Kindle Voyage displaying a 4-day weather forecast for Barcelona on its e-ink screen
The finished weather display showing the Barcelona forecast.

Jailbreaking the Voyage

The Kindle Voyage runs firmware 5.13.6, which is well within the range supported by WinterBreak. The jailbreak process itself was straightforward: fill the storage to prevent auto-updates, copy the WinterBreak files, open the Kindle Store to trigger the exploit.

After jailbreaking, I installed the hotfix (to persist the jailbreak across reboots), KUAL (the app launcher), MRPI (package installer), USBNetwork (for SSH access), and KOReader (alternative reader).

The standard workflow for installing packages on a jailbroken Kindle is: plug in USB, copy a .bin file to mrpackages/, eject, type ;log mrpi in the search bar, wait, repeat. This got old fast. Once I had USBNetwork running, I could SSH into the Kindle and do everything directly, which made the rest of the project much more pleasant. If you’re doing anything beyond basic package installs, get SSH working early.

Getting weather on screen (three bugs deep)

I started with weather_kindle by Scott Colby, which is a standalone weather display that runs entirely on the Kindle. No external server needed. It fetches forecast data from the World Meteorological Organization, fills an SVG template, and renders it to a PNG.

The problem: weather_kindle’s installer doesn’t work on the Voyage. The .bin package has device targeting that rejects PW2+ devices. So I installed it manually by copying the files directly.

The next problem: pngcrush (which converts the PNG to greyscale) was compiled against libpng12, which doesn’t exist on the Voyage. The system has libpng16. I ended up just skipping pngcrush entirely since the e-ink display handles the conversion fine.

Then the display issue. The original weather_kindle uses eips to render the image, but eips doesn’t scale. The Voyage has a 1072x1448 display, while the weather image is 600x800. Feeding a 600x800 RGB image to eips on a 1072x1448 8bpp greyscale framebuffer produces garbage.

The fix was FBInk, which handles scaling, colour conversion, and proper e-ink refresh modes. The magic incantation:

fbink -k -f -W GC16 -w
fbink -g file=weather.png,w=-2,h=-2 -f -W GC16

The first command clears the screen with a full GC16 refresh and waits for completion. The second displays the image scaled to fit. Without the -w (wait) flag on the clear, the image write would race with the clear and you’d get ghosting.

Waking up on a schedule

This was the hard part. I wanted the Kindle to sleep most of the time (for battery life) and wake itself up periodically to refresh the weather.

What didn’t work:

  • Cron jobs don’t run while the Kindle is suspended
  • lipc-set-prop com.lab126.powerd wakeUp wakes the device but the daemon script is also suspended, so it can’t react to the wake
  • lipc-wait-event com.lab126.powerd resuming blocks in userspace and gets frozen during suspend

What worked: The same approach used by kindle-clock and kindle-kt3_weatherdisplay. Set the RTC alarm, then force suspend-to-RAM:

rtcwake -d /dev/rtc1 -m no -s $INTERVAL
echo "mem" > /sys/power/state

When the RTC fires, the kernel resumes and the script continues from the next line. Simple, reliable.

What to stop (and what not to)

The Kindle’s GUI is managed by several upstart services. You need to stop the GUI so it doesn’t overwrite your weather image, but you can’t stop everything or WiFi breaks.

After reading through several projects and a lot of trial and error, here’s what you need to stop:

stop lab126_gui
stop otaupd
stop phd
stop tmd
stop x
stop todo
stop mcsd

And here’s what you must NOT stop:

  • framework: stopping this from a KUAL-launched script kills the script itself (KUAL runs under the framework)
  • powerd: breaks battery monitoring and power management
  • lab126: breaks the WiFi interface entirely

Instead of stopping powerd, disable the screensaver via its LIPC property:

lipc-set-prop com.lab126.powerd preventScreenSaver 1

Surviving your own GUI shutdown

The trickiest part was launching a long-running script from KUAL that survives the GUI shutdown. KUAL runs inside the framework’s process tree. If you stop lab126_gui, KUAL dies, and normally takes your script with it.

The solution (which I found in kindle-clock): use setsid in the KUAL menu action to create a new session:

{
    "name": "Start Weather Display",
    "action": "setsid /mnt/us/weather/bin/weather_display.sh",
    "exitmenu": true
}

setsid detaches the script into its own session. When lab126_gui dies, the script is in a separate process group and survives.

Coaxing WiFi back to life

WiFi doesn’t automatically reconnect after suspend-to-RAM. The reconnection needs a multi-stage escalation:

  1. Immediately: wpa_cli reassociate
  2. After 10 seconds: wpa_cli disconnect then wpa_cli reconnect
  3. After 30 seconds: full radio toggle via lipc-set-prop com.lab126.wifid enable 0/1
  4. After 60 seconds: give up and show the cached image

This pattern comes from nicoh88’s KT3 weather display, which has clearly been through the same pain.

The Voyage doesn’t do 5 GHz

One more gotcha: the Kindle Voyage only supports 2.4 GHz WiFi. I spent a while wondering why it couldn’t see my office network before discovering the network was 5 GHz only. I ended up using macOS Internet Sharing to create a 2.4 GHz hotspot from my wired connection.

The result

The Kindle sits in my kitchen near my coffeemaker showing the Barcelona forecast. Every 6 hours it wakes up, connects to WiFi, fetches fresh weather data, renders it, displays it with a clean e-ink refresh, and goes back to sleep. Battery should last 3-4 weeks.

To switch back to e-reader mode, I just hold the power button for 20 seconds to reboot.

The code is at cdmckay/kindle-voyage-weather on GitHub.

Conclusion

In this article we turned a dusty Kindle Voyage into a standalone weather display with automatic sleep/wake cycles. The key lessons: setsid for surviving framework stops, rtcwake + echo "mem" for reliable sleep/wake, and never stop powerd or lab126 unless you enjoy debugging WiFi failures.