Skip to content

synalysis/elm-pebble

Repository files navigation

elm-pebble

This is the Elm-based Pebble development platform.

Current Scope Kept In Repo

  • elmc/ - Elm-to-C compiler, runtime, and conformance tests.
  • ide/ - Phoenix LiveView IDE app (Phases 1-3 baseline).
  • packages/elm-pebble/elm-watch/ - watch-side Elm package API surface.
  • packages/elm-pebble-companion-core/ - companion-side Elm package API surface.
  • shared/ - cross-target Elm protocol modules (watch + companion).
  • ide/priv/pebble_app_template/ - Pebble app template/shim used by IDE publish builds.

Docker (persistent by default)

Run the IDE container with persistent storage:

docker compose up -d

This starts elm-pebble-ide on http://localhost:4000/projects and stores all runtime data in the named volume elm_pebble_ide_data:

  • SQLite database (/var/lib/ide/ide_prod.db)
  • project workspace files (/var/lib/ide/workspace_projects)
  • user settings (/var/lib/ide/config/settings.json in local mode, or /var/lib/ide/users/<id>/settings.json per user in public mode)
  • Pebble SDK state (/var/lib/ide/.pebble-sdk)

Container image includes required toolchain binaries:

  • elm (installed globally via npm)
  • pebble CLI (pebble-tool)
  • gif2apng 1.9 (built from SourceForge sources for animated bitmap GIF upload)
  • Pebble SDK installed on first container start into the persistent volume (PEBBLE_SDK_VERSION, default latest, currently v4.17)
  • embedded emulator runtime support (qemu-pebble from the installed SDK, pypkjs from pebble-tool, QEMU keymap data, and bzip2 for flash images)

On first startup, the container installs the Pebble SDK into the persistent volume (if missing) and starts the Phoenix server immediately. On later starts, the entrypoint upgrades the active SDK when PEBBLE_SDK_VERSION=latest and a newer release is available (for example v4.17 replacing v4.9.169). SDK install runs in the background by default. To wait for the SDK before serving traffic:

PEBBLE_SDK_BLOCKING_INSTALL=1 docker compose up -d

To pin a specific SDK version at runtime:

PEBBLE_SDK_VERSION=4.9.169 docker compose up -d

The embedded emulator uses these container paths by default:

  • ELM_PEBBLE_SDK_INSTALL_ROOT=/var/lib/ide/.pebble-sdk/SDKs/current
  • ELM_PEBBLE_QEMU_BIN=/var/lib/ide/.pebble-sdk/SDKs/current/toolchain/bin/qemu-pebble
  • ELM_PEBBLE_PYPKJS_BIN=/opt/pipx/venvs/pebble-tool/bin/pypkjs
  • ELM_PEBBLE_QEMU_IMAGE_ROOT=/var/lib/ide/.pebble-sdk/SDKs/current/sdk-core/pebble
  • ELM_PEBBLE_QEMU_DATA_ROOT=/usr/share/qemu

If QEMU flash images are not present in the active SDK, the IDE downloads them on demand into ELM_PEBBLE_QEMU_IMAGE_ROOT.

Browser WASM Emulator Runtime

The browser WASM emulator runtime is not built automatically by the IDE. Build it once on a machine with Docker, then copy the assets into the IDE data volume (/var/lib/ide/wasm_emulator by default):

docker compose run --rm wasm-emulator-builder
docker compose restart elm-pebble-ide

Or from a repo checkout:

ELM_PEBBLE_WASM_OUTPUT_DIR=/tmp/wasm-out ./scripts/build_wasm_emulator_runtime.sh

The builder downloads QEMU 10.1 source, clones ericmigi/pebble-qemu-wasm, applies the local control-bridge patch, builds qemu-system-arm.js, qemu-system-arm.wasm, and qemu-system-arm.worker.js, then copies all available Pebble SDK QEMU firmware images from the active SDK into per-platform directories under /var/lib/ide/wasm_emulator/firmware/sdk.

By default the builder uses emery as the legacy single-image fallback. Override that fallback with:

PEBBLE_WASM_FIRMWARE_PLATFORM=basalt docker compose run --rm wasm-emulator-builder

The IDE serves WASM assets from ELM_PEBBLE_WASM_EMULATOR_ROOT, which defaults to /var/lib/ide/wasm_emulator in Docker. Firmware binaries and built WASM artifacts are not committed to the repository.

To skip automatic SDK installation/activation:

INSTALL_PEBBLE_SDK=0 docker compose up -d

To use an external disk path instead of a Docker-managed volume:

cp docker-compose.external-disk.example.yml docker-compose.override.yml
# edit the host path in docker-compose.override.yml
docker compose up -d

PostgreSQL (optional)

Production releases support SQLite (default) or PostgreSQL. The adapter is selected at runtime via IDE_REPO_ADAPTER or by setting DATABASE_URL (which implies Postgres). Both adapters are included in the same release image.

cp docker-compose.postgres.example.yml docker-compose.override.yml
# set POSTGRES_PASSWORD, SECRET_KEY_BASE, PHX_HOST, etc.
docker compose up -d --build

Or run a Postgres-backed container manually:

docker build -t elm-pebble-ide .
docker run --env DATABASE_URL=postgres://user:pass@host:5432/ide_prod elm-pebble-ide

Environment variables:

Variable SQLite (default) PostgreSQL
IDE_REPO_ADAPTER sqlite (optional) postgres
DATABASE_PATH SQLite file path not used
DATABASE_URL must be unset required (also selects Postgres when adapter unset)
DATABASE_SSL off (plain TCP) true when the server requires TLS
POOL_SIZE connection pool (default 10) same

Project source files still live on disk under PROJECTS_ROOT; only users, login tokens, and project metadata move to Postgres.

The image build pipeline is defined in .github/workflows/docker-image.yml. On pushes, GitHub Actions publishes images to GitHub Container Registry as ghcr.io/<owner>/<repo>.

To run a published image directly:

ELM_PEBBLE_IMAGE=ghcr.io/synalysis/elm-pebble:latest docker compose up -d

Next Direction

The target architecture and staged execution plan for the IDE are captured in:

  • docs/IDE_ROADMAP.md

About

IDE for developing Pebble apps and watch faces in Elm

Topics

Resources

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Contributors