# APESS onboarding — fully containerized A team needs two things running: the **APESS stack on their laptop** and the **ZeroClaw node on their Uno Q**. Both are containers. Nothing installs to a host. ``` LAPTOP: docker compose up → apess-api + apess-web (deploy/lan) BOARD : App Lab → Run → ONE container = daemon + relay + responder ``` Everything a team does — say-hi, the module chat, Refine, Telegram, the LED matrix, the I2C scan — runs through this. The board never needs the Zephyr flash toolchain or Linux `/dev/i2c`: the matrix is driven by a resident responder and I2C is scanned on the MCU (Wire), both over the RouterBridge relay. ## 1. Instructor — build the distributable app (once) Bake the cloud token + all assets into a shareable App Lab app: ```sh export ANTHROPIC_OAUTH_TOKEN=sk-ant-oat01-… # baked into the bundle ./deploy/uno-q/package-onboard-app.sh # → deploy/uno-q/dist/apess-onboard ``` The bundle contains: the ZeroClaw binary (matrix_text + i2c_scan), the single-`default`-agent config (matrix + i2c_scan allowlisted, Telegram-ready), the skills, the responder sketch, and the baked token. It ships **without** a `.secret_key` (each board mints its own on first Run) and **without** any team's Telegram token. The `dist/` output is gitignored (it holds the token). Import it once to smoke-test, or share it to students: ```sh arduino-app-cli app new --from-app deploy/uno-q/dist/apess-onboard # instructor test # then in App Lab: open the app → Share → QR ``` ## 2. Student — bring up their board (fresh OR pre-existing) 1. Open **App Lab** on the Uno Q (it ships with the board). 2. **Import** the "APESS Onboard" app (scan the QR). 3. Click **Run**. The node comes up in one container: it flashes the resident responder, launches the cloud agent, mints its `.secret_key`, self-registers to the team's APESS laptop, and scrolls a **claim code** on the LED matrix. Fresh or pre-existing board is identical — Run is idempotent; it just (re)starts the node. ## 3. Student — the wizard (laptop) - Open `http:///` → **Start the workshop**. - **Phase 1:** team name + members → type the **claim code** the matrix is scrolling → board bound (state persists in `localStorage`; a Disconnect button is the only thing that drops it). - Say hi to the agent, optionally set up **Telegram** (writes the token to the node and reloads it), toggle **Voice**. - **Phase 2:** open the node, name the domain. Then the modules. ## `APESS_URL` — how the board finds the laptop The board self-registers to `APESS_URL` (default `http://apess-api.local:3000`). Options, easiest first: - **mDNS:** have the `deploy/lan` box advertise `apess-api.local` (zero-config for students). - **Per-team:** set `APESS_URL` in the app's `.zeroclaw/apess-node.env`, or pass `APESS_URL=http://:3000` when packaging. ## Reachability The laptop's API must reach the board over the workshop WiFi. Verify the AP allows **client-to-client** traffic (many guest networks isolate clients). See `deploy/lan/README.md`.