Way back when (circa 2015), I made some watchfaces for Pebble Watches. You can still access them today thanks to the Rebble project. It’s recently been announced that the original creators will launch a new device that will run the recently open-sourced version of Pebble OS.
However, the SDK has not been updated in about 10 years. It relies on Python 2, and the code doesn’t work on Python 3. You typically would need an emulator, or some other tool to allow you to install and build the old dependencies to develop watchfaces and apps.
That is… until now! I’ve been hacking on this for the past week and it seems to be in a very good place, I have tested it on my Apple Silicon Mac, My Arch Linux machine, and my old x86 Mac. I can build and install my old watchfaces and make upgrades.
If you’re looking to install rebbletool
- visit the README on Github - the setup section will walk you through getting started.
Disclaimer: This tool is very experimental. Although I have tested it to work on my devices and it works well for me, it might not work on yours or could break things. Use at your own risk!
Running the CLI
Now, onto the fun part.
The first thing, was to get the pebble
(renamed to rebble
) command line tool to run, and install the last available SDK. This was actually pretty easy, just migrating Python 2 code to Python 3. Since I wanted to make this something you could clone + install, I also modified it to download the correct SDK containing the toolchain and set those up locally. On macOS, this process also makes gatekeeper not complain about all the files.
Then, I ran rebble build
. And, it crashed. It became apparent this was not going to be as easy as I thought it would be.

Getting it to build
Most of this is boring. But, in short - we’ve got a small set of patches that will allow things to build, and the command line tool will automatically detect this and apply them on top of the installed SDK to allow it to run using Python 3.
One important note - all of the binaries provided with the SDK were made before Apple Silicon, so you will need to make sure Rosetta 2 is installed. You can do so via running softwareupdate --install-rosetta
.
Installing to Phone
This part, was pretty easy! I enabled the developer connection on my phone, fixed a couple more crashes in the CLI tool, and it installed!
This shows a full SDK install, patch, and build of a watchface, which I then installed to my phone!:
Getting the emulator to run
On my Mac, I tried to run rebble install --emulator basalt
next. No luck.
On Linux, it started but would crash because we had disabled pypkjs (which fails to build at this point in the adventure).
Since We have Rosetta 2 on the Mac, so it should work and fail in the same manner as on Linux, but upon further inspection it’s looking for some dylibs we don’t have the proper versions of.
If you try to brew install
these, like the original instructions suggest, this will still fail, instead complaining it’s not x86 (our Apple Silicon Mac is arm
, not x86_64
). I decided to fire up my (2012) Macbook pro, and install the libraries on there. The hope was, I can get those built & installed, then bundle them up and put them somewhere the system would look for them.
I bundled them up, and modified the SDK install to detect an Apple Silicon Mac, then it puts them in the rebbletool project directory alongside lib/
. Then, I updated it to include the correct PATH
to the emulator, and the DYLD_FALLBACK_LIBRARY_PATH
pointing to our lib file with the x86 dylibs.
These are the libraries needed:
libglib-2.0.0.dylib
libintl.8.dylib
libpixman-1.0.dylib
libgthread-2.0.0.dylib
libpcre2-8.0.dylib
This worked!
Installing faces & apps on the emulator
From here, I turned to look into the next part. Upon emulator start, it informs us pypkjs
is not able to be found. I disabled this when originally getting the cli tool to run, since it would not build.
I forked pypkjs, and disabled everything v8 related - it depended on PYv8
which has not been maintained, and the fork STPYv8
, doesn’t support the JSExtension
mechanism that pypkjs uses.
Upon disabling that, and after patching a single line of byte handling code in libpebble2
, I was greeted with this on my mac:
Success! 💯
Emulator GDB
Unfortunately, the gdb
provided by the SDK on macOS is linked to the old Python2
framework. Thankfully, this isn’t a huge problem - homebrew actually has a compatible arm version ready to go! After running brew install arm-none-eabi-gdb
, and altering the CLI tool to find it - gdb works!
What about PKJS?
This is where it gets more “fun”. And by that, I mean writing a bit more code than I thought I would. It turns out the best way to get this to work was to figure a way to make pypkjs run under STPYv8
. There’s likely no porting PYv8
to modern systems, and we should use the latest fork.
It looked like I could pretty easily call functions/return data from js -> python, so I built a table of external functions, and provided a mechanism within the JS vm to call them. I then refactored the code to use that instead of the native methods JSExtension uses.
This plus-side of doing it this way, is that we can also log all of the back & forth between pypkjs and the js code the user writes!
This also enables the rebble emu-app-config
command to work, provided your page implements the return_to
query param as described in the docs
pypkjs
running and running things like GeoLocation, XHRThe future
That’s all for now! I’ll be slowly refining things. There’s a few parts that aren’t working fully yet, including localStorage persistence and the Websockets APIs in pypkjs
, but those are a work in progress!
I’m looking into seeing if we can rebuild the tools and/or make some of the homebrew versions of the cross-compiler work, so that we don’t need to rely on Rosetta. There’s other people on the Rebble Discord already looking into rebuilding the emulator to work on macOS natively, so good things might be coming!