Metadata-Version: 2.4
Name: exoclaw-firmware
Version: 0.7.0
Summary: Deployable exoclaw image for MicroPython boards (ESP32-S3 and friends)
Requires-Python: >=3.11
Requires-Dist: exoclaw-conversation>=0.21.0
Requires-Dist: exoclaw-provider-openai>=0.4.2
Requires-Dist: exoclaw-subagent>=0.15.0
Requires-Dist: exoclaw-tools-cron>=0.9.0
Requires-Dist: exoclaw-tools-workspace>=0.6.0
Requires-Dist: exoclaw[http]>=0.26.4
Description-Content-Type: text/markdown

# exoclaw-firmware

Deployable exoclaw image for MicroPython boards. Bundles core
`exoclaw` + the MP-compatible plugin set (conversation, OpenAI
provider) + board-specific boot wrappers, so flashing one tree
gets you a chip that can hold a conversation with an LLM.

This is the equivalent of `exoclaw-nanobot` for the chip target —
where nanobot is "what you run on a server", `exoclaw-firmware`
is "what you flash to a board".

## Supported boards

| Board                    | RAM       | Status      | Notes                                           |
|--------------------------|-----------|-------------|-------------------------------------------------|
| ESP32-S3 (8 MB PSRAM)    | 8 MB      | Supported   | Reference target; SD card recommended.          |
| ESP32 (4 MB)             | 4 MB      | Should work | Tighter; turn off any optional plugins.         |
| Raspberry Pi Pico W      | 264 KB    | Unlikely    | RAM budget too small for an LLM agent loop.     |

Adding a new board: copy `boards/esp32_s3/` to `boards/<your_board>/`,
adapt the `boot.py` for that platform's WiFi / SD / clock APIs.

## Quickstart (ESP32-S3)

1. **Wire up an SD card** (optional but recommended for session
   storage). Default pins in `boards/esp32_s3/boot.py`:
   `sclk=12, mosi=11, miso=13, cs=10`.
2. **Flash MicroPython 1.27+** to the board (out of scope for
   this package — see the [MicroPython downloads page]).
3. **Copy `boards/esp32_s3/secrets.py.example`** to
   `boards/esp32_s3/secrets.py` and fill in `WIFI_SSID`,
   `WIFI_PASSWORD`, `OPENAI_API_KEY`.
4. **Stage and flash:**
   ```sh
   cd packages/exoclaw-firmware
   mise run flash
   ```
5. **Reset the board** (or `mise run repl` to watch output). On
   first boot you should see `boot: SD mounted`, `boot: WiFi up`,
   `boot: clock synced`, then a `you>` prompt — type a message
   and press enter to chat with the agent over USB serial.

## What's in the flash image

The `mise run stage` task assembles the deployable tree under
`.stage/`:

```
.stage/
├── boot.py                    # WiFi + SD + NTP setup
├── main.py                    # runs run_serial_chat() (USB-CDC chat loop)
├── secrets.py                 # gitignored; your credentials
├── exoclaw/                   # core (with _cpython.py stripped)
├── exoclaw_conversation/      # MP-compatible conversation plugin
├── exoclaw_provider_openai/   # MP-compatible OpenAI provider
└── exoclaw_firmware/          # this package's app.py
```

Files matching `_cpython.py` are stripped at stage time — they
hold CPython-only implementations that the MP runtime never
imports. Same trick the core MP coverage runner uses.

## Channels

The default channel after flash is **USB-CDC serial**. Plug the
board into a host, open `mpremote repl` (or `screen
/dev/cu.usbmodem* 115200`), hit reset, and you'll see:

```
boot: WiFi up: ('192.168.…', …)
boot: clock synced via NTP
main: ready — type a message and press enter (Ctrl-C to exit)
you>
```

Type, press enter, get a response. No chat-platform tokens, no
webhook URLs — just stdin/stdout over USB.

For network-side channels, swap the `run_serial_chat` call in
`main.py` for your own loop on top of `build_agent` (which returns
a `(provider, conversation)` pair). Common patterns:

- **HTTP long-poll** (Telegram-style) — easiest cloud channel; one
  outbound request per poll cycle.
- **MQTT subscriber** (`umqtt.simple`) — IoT-native, integrates
  with Home Assistant / AWS IoT / HiveMQ.
- **HTTP webhook server** (`asyncio.start_server`) — local-network
  only unless you tunnel.
- **WebSocket** — single long-lived connection, lower latency than
  long-poll, needs a WS client.
- **BLE GATT** — phone companion app pattern, range ~10m.

Pick what fits the deployment. The serial loop stays useful as a
debug channel even after you wire a cloud channel.

## mise tasks

| Task             | What it does                                              |
|------------------|-----------------------------------------------------------|
| `mise run stage` | Assemble `.stage/` from core + plugins + board files.     |
| `mise run flash` | Copy `.stage/` onto the attached board via `mpremote`.    |
| `mise run repl`  | Drop into a REPL on the board.                            |
| `mise run run`   | Exec `main.py` on the board without flashing.             |
| `mise run wipe`  | Erase the board's filesystem (destructive).               |

[MicroPython downloads page]: https://micropython.org/download/
