Skip to content

Repository files navigation

opencode_esp32_client

A physical OpenCode entry point built on M5StickS3. Press a button, speak, and the device records, transcribes, and sends your prompt to a self-hosted OpenCode server. Results are read on your phone.

Why

OpenCode already has an iOS client and a Web UI, but both require pulling out a phone, unlocking it, opening an app, and tapping into a session. This project reduces that to: pull a keychain-sized device out of your pocket, press one button, speak. The ESP32 sits in deep sleep at microamps and wakes on a GPIO button press, so it can stay with you for weeks on a coin battery without charging.

The device fills the "physical entry point" layer for an OpenCode-based personal agent setup: the agent interacts with you through your phone when it needs to, and you trigger the agent through the ESP32 when you want to. The two are complementary, not redundant.

Hardware

  • M5StickS3 (ESP32-S3-PICO-1-N8R8): 8MB Octal Flash, 8MB Octal PSRAM, 135x240 LCD, BMI270 IMU, ES8311 codec + MEMS mic, 250mAh battery, USB-C
  • Front button BtnA (GPIO11) for record / send; side button BtnB (GPIO12) for status and debugging
  • Stays in deep sleep (~10µA) between uses; wakes on button press

How it works

  1. Device is in deep sleep on your keychain
  2. Press the front BtnA — it wakes, connects to your configured WiFi in the background, and starts recording immediately
  3. Speak — audio is encoded as Ogg/Opus in PSRAM while the LCD shows a live volume meter
  4. Press the front BtnA again (or wait for the recording timeout) — the recording is uploaded to the REST STT backend
  5. A new OpenCode session is created and the text is sent via POST /session/:id/prompt_async
  6. LCD shows Sent for 10 seconds, then the device returns to deep sleep
  7. Open the OpenCode app on your phone to see the AI response

Every recording creates a new OpenCode session in the server's current project. Start the server from the workspace you want this device to target; the device does not send a per-request directory.

The default request model is OpenAI GPT-5.6-SoL (openai / gpt-5.6-sol). Both model fields can be changed from the device dashboard.

Pressing the side BtnB wakes a read-only status screen for debugging. It does not record or submit a task, and all credentials remain redacted.

Setup

Prerequisites

  • An M5StickS3
  • A self-hosted OpenCode server reachable from your local network (opencode serve --hostname 0.0.0.0 --port 4096)
  • An AI Builders Space token for the REST STT endpoint (see Configuration)
  • ESP-IDF (tested with 5.5.5; see docs/rfc.md for the full stack)

Configure WiFi and STT defaults

Copy the compile-time template and fill in WiFi and STT credentials. main/secrets.h is gitignored:

cp main/secrets.example.h main/secrets.h
# edit main/secrets.h

After the device joins WiFi, open its port 80 dashboard to store the OpenCode server URL, Basic Auth credentials, agent, and model in NVS. Credential values are never returned by the status API.

Build and flash

. "$IDF_PATH/export.sh"
idf.py set-target esp32s3
idf.py build
idf.py -p /dev/cu.usbmodemXXX -b 115200 flash

Development mode is enabled by default so USB Serial/JTAG remains available for repeated autonomous flashing. After a 10-second result window it turns off the backlight without sleeping; BtnA or BtnB turns the backlight on again. Disable OPENCODE_DEV_MODE in idf.py menuconfig for the battery-powered build that returns to deep sleep after the same window.

The production profile keeps the device awake for at least 60 seconds after flashing or any non-deep-sleep reset so macOS can enumerate USB. Normal BtnA/BtnB wake cycles return to deep sleep after the 10-second interaction window.

idf.py -B build-production \
  -D SDKCONFIG=sdkconfig.production \
  -D 'SDKCONFIG_DEFAULTS=sdkconfig.defaults;sdkconfig.production.defaults' \
  build
idf.py -B build-production \
  -D SDKCONFIG=sdkconfig.production \
  -D 'SDKCONFIG_DEFAULTS=sdkconfig.defaults;sdkconfig.production.defaults' \
  -p /dev/cu.usbmodemXXX -b 115200 flash

See docs/rfc.md for the full architecture and docs/test.md for verification.

Status

The v1 firmware builds and its microphone-to-STT-to-OpenCode path has been validated on M5StickS3 hardware. See docs/test.md for the remaining production power and endurance checks.

License

MIT (see LICENSE).

Related

About

M5StickS3 voice entry point for OpenCode

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages