Pick a runtime, copy a file
Two independent implementations, flash one firmware and copy the matching file to the board. It auto-runs at power-on; once set up, the server starts itself on every boot.
| Runtime | File to copy | Notes |
|---|---|---|
| MicroPython | main.py | Fully self-contained, no libraries to install |
| CircuitPython 8+ | code.py | A few bundle libraries in /lib (asyncio, adafruit_ntp, adafruit_requests for webhooks) |
WiFi credentials live in a settings.toml on the device, the same file format both runtimes read:
CIRCUITPY_WIFI_SSID = "YourNetwork" CIRCUITPY_WIFI_PASSWORD = "YourPassword"
Same API as the Pi
- All the same REST endpoints on port 8314,
/hello,/gpio/*,/config/*,/logs,/restart, with identical request and response shapes - Outputs with pulses,
maxclamping, and reversed relay logic; inputs with pull-ups and webhook watches - Config persisted to
config.jsonon the device with an automatic backup, output values restored after power loss - Webhook POSTs on watched-pin changes (CircuitPython: via
adafruit_requests)
The read-only trick (CircuitPython)
CircuitPython exposes the Pico's filesystem over USB, but a computer and the running server
can't both write it. boot.py solves this with a jumper: hold GP1 to GND
at boot and the filesystem stays read-only for the server (your computer can edit files);
leave GP1 floating and the server can persist config, status, and logs. Read-only mode is
visible in the API, the agent tags its os field with ReadOnly.
In the family
Everything that drives a Pi agent drives a Pico agent unchanged: the HomeKit and Matter bridges, ctrlpi-mcp, and the webhook flow to ctrlpi.com.