Claude-skills wendy-lite
Expert guidance on building WASM apps for Wendy Lite MCU firmware on ESP32-C6. Use when developers mention: (1) Wendy Lite or wendy-lite, (2) WASM apps on ESP32 or microcontrollers, (3) WendyLite Swift package or import WendyLite, (4) building C/Rust/Swift/Zig apps for ESP32, (5) WAMR runtime on embedded devices, (6) GPIO/I2C/SPI/UART/NeoPixel from WASM, (7) Embedded Swift on WASM or wasm32-none-none-wasm, (8) BLE provisioning on ESP32-C6, (9) uploading WASM binaries to MCU, (10) TLS/networking on ESP32 from Swift.
git clone https://github.com/wendylabsinc/claude-skills
T=$(mktemp -d) && git clone --depth=1 https://github.com/wendylabsinc/claude-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/wendy-lite" ~/.claude/skills/joannis-claude-skills-wendy-lite && rm -rf "$T"
wendy-lite/SKILL.mdWendy Lite
Wendy Lite is a WebAssembly (WASM) runtime firmware for ESP32-C6 microcontrollers. It enables developers to write apps in C, Rust, Swift, Zig, TypeScript, or WAT, compile them to WASM, and run them on the device with full hardware access.
Key Concepts
- WAMR Runtime: Uses WebAssembly Micro Runtime to execute WASM binaries
- Host Imports: WASM apps import functions from the
module to access hardware"wendy" - Callback System: Async events (GPIO interrupts, timers, BLE) dispatched via exported
wendy_handle_callback - Flash Persistence: WASM binaries stored in flash partition
(2MB), auto-loaded on bootwasm_a - Multi-language: Apps can be written in C, Rust, Swift 6.0+, Zig, TypeScript, or raw WAT
Project Structure
wendy-lite/ ├── main/wendy_main.c # Firmware entry point, WASM lifecycle manager ├── components/ │ ├── wendy_wasm/ # WAMR integration (load, run, stop modules) │ ├── wendy_hal/ # Hardware: GPIO, I2C, RMT, NeoPixel, Timer │ ├── wendy_hal_export/ # Registers HAL as WASM host imports │ ├── wendy_usb/ # USB CDC wire protocol for app upload │ ├── wendy_wifi/ # WiFi station + HTTP binary download │ ├── wendy_ble_prov/ # BLE WiFi provisioning ("Wendy-XXXX") │ ├── wendy_cloud_prov/ # Cloud device certificate provisioning │ ├── wendy_callback/ # Async ISR-safe event dispatch (max 32 handlers) │ ├── wendy_storage/ # NVS key-value storage for apps │ ├── wendy_uart/ # UART serial communication │ ├── wendy_spi/ # SPI bus master │ ├── wendy_sys/ # System: reboot, uptime, device ID │ ├── wendy_otel/ # OpenTelemetry: logs, metrics, traces │ ├── wendy_ble/ # BLE peripheral/central (optional) │ ├── wendy_net/ # TCP/UDP sockets, DNS, TLS (optional) │ ├── wendy_wasi_shim/ # WASI compatibility layer │ ├── wendy_safety/ # Memory safety │ └── wendy_app_usb/ # USB from WASM app perspective (optional) ├── wasm_apps/ # Example WASM applications │ ├── include/wendy.h # App API header (all host imports) │ ├── Makefile # Build system for all app languages │ ├── blink/ # C: GPIO LED blink │ ├── i2c_sensor/ # C: BMP280 I2C sensor reader │ ├── swift_display/ # Swift 6.0+ embedded WASM app │ ├── rust_blink/ # Rust WASM app │ ├── zig_blink/ # Zig WASM app │ └── wat_blink/ # Raw WebAssembly Text ├── partitions.csv # Flash layout (nvs, factory, wasm_a, storage) ├── sdkconfig.defaults # ESP-IDF + WAMR + feature flags └── diagram.json # Wokwi simulator circuit
Writing WASM Apps
C (Recommended for Getting Started)
#include "wendy.h" void _start(void) { gpio_configure(2, WENDY_GPIO_OUTPUT, WENDY_GPIO_PULL_NONE); for (int i = 0; i < 10; i++) { gpio_write(2, 1); timer_delay_ms(500); gpio_write(2, 0); timer_delay_ms(500); } }
Build:
cd wasm_apps make blink
Or manually:
clang --target=wasm32 -O2 -nostdlib -I include \ -Wl,--no-entry -Wl,--export=_start -Wl,--allow-undefined \ -o app.wasm app.c
Swift (Recommended for App Development)
Swift apps use the WendyLite Swift package from https://github.com/wendylabsinc/wendy-lite, which provides type-safe wrappers around all WASM host imports.
See
for the complete Swift API reference, Package.swift setup, and examples.references/swift-sdk.md
Key points:
- Requires Swift 6.0+ with Embedded Swift support
- Uses
for the WASM entry point@_cdecl("_start") - No heap allocation — use stack-allocated tuple buffers
only — no runtime string constructionStaticString- Cast
toUnsafePointer<UInt8>
viaUnsafePointer<CChar>
for API callsUnsafeRawPointer - Build and deploy with
wendy run
Quick start:
import WendyLite @_cdecl("_start") func start() { GPIO.configure(pin: 2, mode: .output) GPIO.write(pin: 2, level: 1) System.sleepMs(1000) GPIO.write(pin: 2, level: 0) }
Other Languages
| Language | Build Command | Requirements |
|---|---|---|
| Rust | | rustup (not Homebrew Rust) |
| Zig | | Zig 0.13+ |
| WAT | | WABT (wat2wasm) |
App Requirements
- Export a
function as the entry point_start - Import host functions from the
module"wendy" - For async callbacks, export
wendy_handle_callback(int handler_id, int arg0, int arg1, int arg2) - Call
to allow callback dispatchsys_yield()
Hardware Access Summary
| Subsystem | Key Functions | Notes |
|---|---|---|
| GPIO | , , , , , | Supports input, output, PWM, ADC, interrupts |
| I2C | , , , , | Bus 0 pre-initialized by firmware |
| NeoPixel | , , | WS2812 RGB LEDs via RMT |
| Timer | , , , | Blocking delay + async callbacks |
| UART | , , , | Serial ports with callbacks |
| SPI | , , | Full-duplex master |
| Storage | , , , | Persistent NVS key-value |
| System | , , , | Device info and control |
| OTel | , , | Structured logging, metrics, tracing |
| BLE | , , , | Optional, disabled by default |
| WiFi | , , , | App-facing WiFi control |
| Sockets | , , , | TCP/UDP, optional |
| TLS | , , | Secure connections |
| Console | | Output to UART + USB |
Boot & Lifecycle
- Firmware initializes NVS, WAMR pool, HAL, USB, BLE provisioning, WiFi
- WASM manager thread starts, registers all HAL exports
- Auto-loads WASM from flash partition
(if present)wasm_a - Runs WASM
in dedicated thread (8KB stack)_start() - Event loop handles: upload, run, stop, reset requests
Uploading WASM Binaries
- WiFi: HTTP download via UDP listener after WiFi provisioning
- USB CDC: Wire protocol with PING, UPLOAD (START/CHUNK/DONE), RUN, STOP, RESET messages
- Flash: Written to
partition with 4-byte size header, persists across rebootswasm_a
BLE Provisioning
Device advertises as "Wendy-XXXX" over BLE. A client can:
- Discover the device via BLE scan
- Send WiFi SSID/password via GATT characteristics
- Device connects to WiFi and starts mDNS + UDP listener
Building the Firmware
# Requires ESP-IDF (v5.x) with ESP32-C6 support idf.py set-target esp32c6 idf.py build idf.py flash monitor
Wokwi Simulator
The project includes
wokwi.toml and diagram.json for hardware simulation without a physical board.
Memory Constraints
- WAMR pool: 229KB (pre-allocated before WiFi/BLE)
- WASM stack: 8KB, heap: 8KB
- Flash: 4MB total (1.875MB firmware, 2MB WASM, 64KB app storage)
- WiFi/PHY IRAM offloaded to flash to free ~15-25KB DIRAM
Reference Files
Load these files as needed for specific topics:
- WendyLite Swift package: Package.swift setup, complete Swift API reference, Embedded Swift constraints, stack buffer patterns, code examplesreferences/swift-sdk.md
- Complete WASM app API: all host imports, constants, callback system, per-subsystem function signatures and usage (C-level)references/wasm-api.md
- ESP-IDF sdkconfig options, partition table, feature flags, memory tuning, component enable/disablereferences/firmware-config.md