pebble-emu
Build, run, and observe Pebble watchapps/watchfaces in the Rebble pebble-tool emulator. Captures emulator output as PNGs (and optionally VNC/noVNC) so an AI agent can see what the watch is showing and iterate on apps without a physical Pebble.
- License 许可
- MIT
- 所属仓库
- kfet/fir
- 最近更新
- 2026-11-12
- Stars
- ★ 1
- Forks
- 0
01 前言 Front Matter
- name
- pebble-emu
- override
- true
- description
- Build, run, and observe Pebble watchapps/watchfaces in the Rebble pebble-tool emulator. Captures emulator output as PNGs (and optionally VNC/noVNC) so an AI agent can see what the watch is showing and iterate on apps without a physical Pebble.
03 SKILL.md 正文
Pebble emulator — AI-friendly recipe
The Pebble platform is alive again via Rebble / Core Devices. The modern
pebble-tool (v5.x) bundles QEMU, builds C/JS apps, runs them in an emulator,
and can stream PNG screenshots or expose a VNC server — perfect for agent loops
where you build → install → look → fix.
When to use
- User asks to write, debug, or iterate on a Pebble app or watchface.
- User mentions Pebble, Rebble, Core Devices,
.pbw, aplite/basalt/chalk/diorite/emery/flint. - You need to "see" what the watch screen looks like.
Prerequisites (one-time)
The host should be macOS or Linux. Check first; only install what is missing.
command -v pebble && pebble --version # already installed?
command -v uv || brew install uv # macOS; on Linux: curl -LsSf https://astral.sh/uv/install.sh | sh
command -v node || brew install node # required for JS/PebbleKit-JS builds
Install / upgrade pebble-tool (publishes its own bundled QEMU per SDK):
uv tool install pebble-tool # or: uv tool upgrade pebble-tool
pebble sdk install latest # downloads SDK + QEMU binaries for your OS
pebble sdk list # confirm an active SDK
That gives you pebble with subcommands: build, install, logs,
screenshot, kill, wipe, emu-control, emu-tap, emu-accel,
emu-battery, emu-bt-connection, emu-compass, emu-app-config,
gdb, repl, new-project, analyze-size.
Platforms (watch hardware variants)
Pass to every emulator command via --emulator <name>:
| Name | Watch | Display | Color |
|---|---|---|---|
aplite |
Original Pebble / Steel | 144×168 | B&W |
basalt |
Pebble Time | 144×168 | Color |
chalk |
Pebble Time Round | 180×180 round | Color |
diorite |
Pebble 2 | 144×168 | B&W |
emery |
Pebble Time 2 | 200×228 | Color |
flint |
Core Devices / Time 2 | 200×228 | Color |
When in doubt, default to basalt (most common color target).
Core loop — build, run, observe
1. Create or enter a project
pebble new-project my-face # scaffolds C + package.json
cd my-face
A project is a directory with package.json (pebble.targetPlatforms,
pebble.watchapp) and src/c/main.c. Older appinfo.json projects can be
upgraded with pebble convert-project.
2. Build
pebble build
# produces build/<name>.pbw (a zip of platform-specific binaries + resources)
Build errors land on stderr with waf formatting — read them, fix the C, rebuild.
3. Install + launch emulator (with logs)
pebble install --emulator basalt --logs
This will:
- spawn a QEMU process for the platform if none is running,
- send the freshly-built
.pbwover the QEMU pebble-protocol socket, - launch the app on the emulated watch,
- stream
APP_LOG(...)output to your terminal until you Ctrl-C.
Background it for agent use so you can keep working:
pebble install --emulator basalt >/tmp/pebble.log 2>&1 &
# logs separately, non-blocking — open a tail when needed:
pebble logs --emulator basalt >/tmp/pebble-logs.log 2>&1 &
4. Observe — capture the screen as a PNG
This is the agent's eye. The screenshot is pulled live from the running QEMU over the pebble protocol — no display server needed.
pebble screenshot --emulator basalt --no-open /tmp/pebble.png
# then read it back as an attachment
Useful flags:
--no-open— don't shell-open the image (essential for headless/agent runs).--no-correction— raw framebuffer colors (skip Pebble's color correction).--scale 4— integer upscale; helpful for tiny aplite displays.
In a fir agent loop, Read the PNG path — Read sends image files as
attachments so the model can actually see the watch face.
5. Drive inputs and sensors
pebble emu-tap --emulator basalt --direction +x # tap on x axis
pebble emu-accel --emulator basalt tilt-left # canned motion
pebble emu-battery --emulator basalt --percent 20 --charging
pebble emu-bt-connection --emulator basalt --connected no
pebble emu-compass --emulator basalt --heading 90
pebble emu-app-config --emulator basalt # opens config page
pebble emu-control --emulator basalt # interactive sensor UI in browser
Buttons (back/up/select/down) are sent through emu-control or via the QEMU
console; for scripted button presses see "Direct QEMU socket" below.
6. Live VNC / noVNC (when a human or VNC client is watching)
Add --vnc to any emulator-launching command and pebble-tool will:
- start QEMU with
-vnc :1→ TCP port 5901 on localhost (RFB protocol), - spawn
websockifyon port 6080 so you can also point a noVNC web client athttp://localhost:6080/vnc.html?host=localhost&port=6080.
pebble install --emulator basalt --vnc --logs
# then, from a VNC client:
open vnc://localhost:5901 # macOS Screen Sharing
# or for a one-shot capture from the agent:
vncdo -s localhost:5901 capture /tmp/pebble-vnc.png # pip install vncdotool
Notes:
- Only one VNC-enabled emulator runs at a time (display
:1is shared).pebble-toolwill kill any other VNC emulator on launch. - VNC and
pebble screenshotwork simultaneously — keep VNC for the human, usescreenshotfor the agent. - The VNC framebuffer shows only the raw watch display, not the chrome around it.
7. Kill / reset between runs
pebble kill # stop all running emulators (and websockify)
pebble wipe # clear emulator persistent storage for current SDK
Always pebble kill at the end of a session, or you'll leak QEMU processes.
Recommended agent loop
For autonomous iteration on a watchface:
set -e
pebble build
pebble install --emulator basalt >/tmp/pebble-install.log 2>&1
sleep 1 # let UI settle
pebble screenshot --emulator basalt --no-open --scale 2 /tmp/watch.png
tail -n 200 /tmp/pebble-install.log # build/install diagnostics
Then Read /tmp/watch.png to see the result, compare to the goal, edit
src/c/main.c, repeat. After interactive moments (button press, time change,
notification) re-screenshot.
For longer interactions, leave logs streaming to a file and grep:
pebble logs --emulator basalt >/tmp/pebble.log 2>&1 &
# … exercise the app …
grep -E 'APP_LOG|ERROR|WARN' /tmp/pebble.log
Direct QEMU socket (advanced)
pebble-tool exposes the running emulator's QEMU monitor on a unix socket
under ~/Library/Application Support/Pebble SDK/SDKs/<ver>/ (macOS) or
~/.pebble-sdk/SDKs/<ver>/ (Linux). Useful when you need to inject a button
press without emu-control:
# find the socket
find "$HOME/Library/Application Support/Pebble SDK" -name 'qemu_*.sock' 2>/dev/null
# send a custom QEMU monitor command via socat / nc -U
You rarely need this — emu-* subcommands cover the common cases.
Common pitfalls
pebble: command not foundafteruv tool install— add~/.local/binto PATH (uv prints the line to add).- "No active SDK" — run
pebble sdk install latestthenpebble sdk activate <ver>. - Screenshot looks wrong color — the corrected output applies a Pebble-LCD
gamma curve. Use
--no-correctionto compare to raw rendering. - Emulator hangs after a crash —
pebble kill && pebble wipethen retry. - Two emulators of different platforms — fine; each platform has its own
QEMU process. But only one with
--vncat a time. - Apple Silicon — if you see Rosetta prompts or QEMU fails to launch, try
uv tool upgrade pebble-tool && pebble sdk install latest. - Don't commit
build/— it's regenerated. Add to.gitignoreif missing.
References
- SDK install: https://developer.repebble.com/sdk/
- pebble-tool source (when an arg surface changes, read the installed module):
python3 -c "import pebble_tool, os; print(os.path.dirname(pebble_tool.__file__))" - Older but still-useful guides: https://developer.rebble.io/guides/tools-and-resources/pebble-tool/
- QEMU fork: https://github.com/pebble/qemu
04 同仓库更多 Skills
wt
Spawn a fresh fir agent in its own tmux session on its own git worktree. Use whenever the user wants the work — or the conversation about the work — to happen over there, not here. If the user points at this skill, or has directly loaded it in the context, that alone is the cue — spawn, don't inline.
wrap-up
Wrap up work on a project branch — review, fix, and simplify in a loop until clean, then ff-merge to main.
tmux-observer
Attach a tmux window to an already-running fir session — observe its transcript and drive its input via tmux send-keys. Use when you need to watch or steer another fir agent.
tmux-driver
Drive interactive CLIs (python, gdb, etc.) via named tmux sessions with multi-window support. Falls back to fir's built-in PTY driver when tmux is unavailable.
telegram-bot-setup
Set up a new Telegram bot channel for a fir project — install the telegram MCP, create a per-project state dir, drop in the bot token, wire .fir/mcp.json with TELEGRAM_STATE_DIR, pair the user, and verify. Use when the user asks to add, configure, or onboard a Telegram bot for a fir worktree/project.
sync
Sync with an upstream source repo — detect changed files, apply equivalent downstream edits, update the baseline, and report any new features or non-trivial changes picked up.