# Operations runbook This runbook covers private Reachy Mini deployments using the Reachy daemon, a Hermes host, and the companion bridge. ## Service map | Component | Default location | Port/service | |---|---|---| | Reachy daemon | Reachy/Pi | `8000`, `reachy-mini-daemon.service` | | Reachy Hermes settings | Reachy app process | `8042` | | Hermes API Server | Hermes host | `8642`, Hermes gateway | | Reachy companion bridge | Hermes host | `8643`, `hermes-reachy-bridge.service` | ## Pre-deployment checks On the development/Hermes host: ```bash uv run ruff check . uv run pytest uv build --wheel ``` Confirm no production configuration, `.env`, captured audio, or provider key is included in the wheel or Git diff. On Reachy: ```bash systemctl is-active reachy-mini-daemon.service curl -fsS http://127.0.0.1:8000/api/daemon/status ``` Stop any running app before replacing its installed package: ```bash curl -X POST http://REACHY_HOST:8000/api/apps/stop-current-app ``` ## Wheel deployment Copy the wheel to Reachy, then install it into the same Python environment used by the Reachy daemon: ```bash scp dist/reachy_mini_hermes-*.whl REACHY_HOST:/tmp/ uv pip install \ --python /path/to/reachy_mini/.venv/bin/python \ --reinstall \ --no-deps \ /tmp/reachy_mini_hermes-*.whl ``` `--no-deps` is appropriate only after verifying that the Reachy environment already satisfies the package requirements. In particular, Realtime mode needs `websockets>=15,<17`. Start the app: ```bash curl -X POST http://REACHY_HOST:8000/api/apps/start-app/reachy_mini_hermes ``` Wait for both conditions: ```bash curl -fsS http://REACHY_HOST:8000/api/apps/current-app-status curl -fsS http://REACHY_HOST:8042/api/status ``` The app manager may report `running` several seconds before the settings server and media pipeline are ready. ## Companion bridge deployment The bridge normally runs directly from the checked-out repository. After bridge code or Hermes-host credentials change: ```bash systemctl --user restart hermes-reachy-bridge.service systemctl --user status hermes-reachy-bridge.service ``` Validate with the private bearer token: ```bash curl -H "Authorization: Bearer $API_SERVER_KEY" \ http://127.0.0.1:8643/health ``` For Realtime mode, require: - `hermes_api: true`; - `realtime_available: true`; - `realtime_model: gpt-realtime-2.1`. For Kids Mode, additionally require: - `kids_chat_available: true`; - `kids_tts_streaming_available: true`; - successful authenticated `/v1/kids/chat` moderation/chat and `/v1/kids/speech/stream` PCM probes. ## Health checks ### Reachy app ```bash curl -fsS http://REACHY_HOST:8042/api/status ``` Important fields: - `runtime.state`; - `runtime.power_mode`; - `runtime.last_error`; - `runtime.audio_frames_processed`; - `runtime.turns_completed`; - `runtime.interruptions`; - `config.conversation_mode`; - `config.camera_enabled`, `runtime.camera_captures`, and `runtime.camera_last_error`. Test one local camera frame without returning its image content: ```bash curl -X POST http://REACHY_HOST:8042/api/camera/test \ -H 'Content-Type: application/json' \ -d '{"confirm":"camera"}' ``` In Standby, `audio_frames_processed` should increase while daemon motor mode remains `disabled`. In Meeting or Sleep, the frame count should stop increasing. ### Reachy daemon ```bash curl -fsS http://REACHY_HOST:8000/api/daemon/status systemctl show reachy-mini-daemon.service -p ActiveState -p NRestarts ``` Check: - daemon state is `running`; - motor mode matches the requested app power state; - control-loop error count remains zero; - restart count does not increase unexpectedly. ### Logs ```bash journalctl -u reachy-mini-daemon.service -f journalctl --user -u hermes-reachy-bridge.service -f ``` Expected startup milestones include: - app process started; - settings server listening on `8042`; - Reachy Hermes audio input/output rates logged; - motors disabled when entering Standby. Treat tracebacks, `Reachy voice runtime failed`, repeated WebSocket closures, and increasing daemon restarts as failures. Hardware GPU-device discovery warnings from ONNX Runtime may be harmless on a Pi when CPU inference continues successfully. ## Bluetooth and controller checks This procedure applies only to **Reachy Mini Wireless**. Reachy Mini Lite and wired-only installations do not expose this Bluetooth controller feature as supported hardware. 1. Verify the adapter and BlueZ service: ```bash systemctl is-active bluetooth bluetoothctl show sudo rfkill list bluetooth ``` 2. Verify the Reachy app service account belongs to `input` and can run `bluetoothctl show` through the target image's BlueZ D-Bus/polkit policy. Do not assume a `bluetooth` Unix group exists. Restart the Reachy daemon after changing groups. 3. Put the controller in pairing mode and use **Robot → Bluetooth gamepad → Scan**. Confirm Pair, Trust, and Connect all succeed. 4. Confirm the kernel created `/dev/input/js0` (or another `js*` device) and the app reports **Controller ready**. 5. With clear space and controller movement enabled, test one input at a time: D-pad look, Cross center, Square Happy, Triangle Surprised, Circle Stop. 6. Enter Meeting, Sleep, and Kids Mode and confirm movement inputs are rejected. Disconnect the controller and confirm the UI returns to Waiting/Disconnected without moving Reachy. 7. Do not map power, shutdown, dance, camera, agent, smart-home, or raw joint operations to the controller. Useful diagnostics: ```bash bluetoothctl devices Paired bluetoothctl devices Connected jstest /dev/input/js0 journalctl -u bluetooth -n 100 --no-pager ``` ## Power controls Use the settings UI where practical. API equivalents: ```bash curl -X POST http://REACHY_HOST:8042/api/power \ -H 'Content-Type: application/json' \ -d '{"mode":"standby"}' curl -X POST http://REACHY_HOST:8042/api/power \ -H 'Content-Type: application/json' \ -d '{"mode":"meeting","duration_minutes":60}' curl -X POST http://REACHY_HOST:8042/api/power \ -H 'Content-Type: application/json' \ -d '{"mode":"sleep"}' ``` Stop only the voice app: ```bash curl -X POST http://REACHY_HOST:8042/api/app-off \ -H 'Content-Type: application/json' \ -d '{"confirm":"off"}' ``` The Pi shutdown endpoint intentionally requires `{"confirm":"shutdown"}`. Do not call it as a routine health test. ## Cooling-maintenance acceptance checklist After installing or changing a heatsink/fan: 1. Inspect that no cable, camera ribbon, speaker lead, or motor path is pinched. 2. Confirm the heatsink does not contact exposed components or obstruct Reachy's movement. 3. Power on the Pi and verify the fan physically spins under its configured trigger condition. 4. Check current temperature: ```bash vcgencmd measure_temp cat /sys/class/thermal/thermal_zone0/temp ``` 5. Check Raspberry Pi throttling history: ```bash vcgencmd get_throttled ``` A clean result is `throttled=0x0`. Nonzero values can include historical undervoltage or thermal events; decode them before concluding that the current state is bad. 6. Start the Reachy daemon and voice app. 7. Confirm daemon restart count, control-loop errors, motor mode, and app status. 8. Leave the robot operating long enough to observe steady-state temperature. 9. Perform the human audio acceptance sequence below. ## Human audio acceptance 1. Leave Reachy in Standby and confirm motors are relaxed. 2. Say **“Hey Hermes”** once at normal speaking volume and distance; repeat the initial-wake check with **“Okay Nabu”** and **“Hey Reachy.”** 3. Ask a simple social question; verify the native Realtime response begins promptly. 4. Interrupt Reachy naturally while it is speaking; verify playback clears and the new turn is heard. In pipeline mode, confirm each configured wake phrase can also interrupt playback. 5. Ask a non-consequential Hermes tool question, such as checking a sensor state. 6. With on-demand camera enabled, ask **“What do you see?”** and verify one camera capture is logged. 7. Start a supervised Kids Mode session, verify the parent lock, one moderated child turn, Flash PCM streaming, parent stop, safe fold, and continued transcript/status redaction. 8. Verify the final answers match the fresh image or Hermes tool result rather than an unverified claim. 9. Exercise Meeting, Standby, and Sleep from the UI. 10. Review logs for tracebacks and record temperature after the test. ## Soak test Before declaring a deployment stable: - issue at least 30 app-status requests; - issue at least 30 daemon-status requests; - ping Reachy at least 20 times and report packet loss; - confirm zero new daemon or bridge restarts; - confirm zero new runtime tracebacks; - verify the final power state and motor mode. ## Rollback Keep the previous known-good wheel until acceptance passes. ```bash curl -X POST http://REACHY_HOST:8000/api/apps/stop-current-app uv pip install --python /path/to/reachy_mini/.venv/bin/python \ --reinstall --no-deps /path/to/previous/reachy_mini_hermes.whl curl -X POST http://REACHY_HOST:8000/api/apps/start-app/reachy_mini_hermes ``` The user configuration is stored separately from the wheel, so rollback normally preserves settings. If a future release changes the configuration schema incompatibly, back up `~/.local/share/reachy_mini_hermes/config.json` before deployment.