RuView Hardware Setup
ruvnet/RuView
Brings a RuView CSI sensing node online by building ESP32-S3 or ESP32-C6 firmware, flashing the board, provisioning WiFi and checking the serial output.
Detects a newly connected M5Stack ESP32 board over USB, flashes UIFlow 2.0 firmware and installs the Claude Buddy MicroPython apps, or reruns single steps of that flow.
$ npx skills add anthropics/claude-plugins-official --skill m5-onboard -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install anthropics/claude-plugins-official m5-onboard --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/anthropics/claude-plugins-official.git skills-src && mkdir -p .claude/skills && cp -r skills-src/plugins/cwc-makers/skills/m5-onboard .claude/skills/m5-onboard && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "m5-onboard" agent skill from https://github.com/anthropics/claude-plugins-official/tree/main/plugins/cwc-makers/skills/m5-onboard into .claude/skills/m5-onboard/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "m5-onboard", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/anthropics/claude-plugins-official/tree/main/plugins/cwc-makers/skills/m5-onboardType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add anthropics/claude-plugins-official --skill m5-onboard -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install anthropics/claude-plugins-official m5-onboard --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/anthropics/claude-plugins-official.git skills-src && mkdir -p .agents/skills && cp -r skills-src/plugins/cwc-makers/skills/m5-onboard .agents/skills/m5-onboard && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "m5-onboard" agent skill from https://github.com/anthropics/claude-plugins-official/tree/main/plugins/cwc-makers/skills/m5-onboard into .agents/skills/m5-onboard/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "m5-onboard", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add anthropics/claude-plugins-official --skill m5-onboard -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install anthropics/claude-plugins-official m5-onboard --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/anthropics/claude-plugins-official.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/plugins/cwc-makers/skills/m5-onboard .cursor/skills/m5-onboard && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "m5-onboard" agent skill from https://github.com/anthropics/claude-plugins-official/tree/main/plugins/cwc-makers/skills/m5-onboard into .cursor/skills/m5-onboard/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "m5-onboard", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/anthropics/claude-plugins-official.git --path plugins/cwc-makers/skills/m5-onboard--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add anthropics/claude-plugins-official --skill m5-onboard -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install anthropics/claude-plugins-official m5-onboard --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/anthropics/claude-plugins-official.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/plugins/cwc-makers/skills/m5-onboard .gemini/skills/m5-onboard && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "m5-onboard" agent skill from https://github.com/anthropics/claude-plugins-official/tree/main/plugins/cwc-makers/skills/m5-onboard into .gemini/skills/m5-onboard/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "m5-onboard", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install anthropics/claude-plugins-official m5-onboardInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add anthropics/claude-plugins-official --skill m5-onboard -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/anthropics/claude-plugins-official.git skills-src && mkdir -p .github/skills && cp -r skills-src/plugins/cwc-makers/skills/m5-onboard .github/skills/m5-onboard && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "m5-onboard" agent skill from https://github.com/anthropics/claude-plugins-official/tree/main/plugins/cwc-makers/skills/m5-onboard into .github/skills/m5-onboard/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "m5-onboard", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add anthropics/claude-plugins-official --skill m5-onboard -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install anthropics/claude-plugins-official m5-onboard --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/anthropics/claude-plugins-official.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/plugins/cwc-makers/skills/m5-onboard .opencode/skills/m5-onboard && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "m5-onboard" agent skill from https://github.com/anthropics/claude-plugins-official/tree/main/plugins/cwc-makers/skills/m5-onboard into .opencode/skills/m5-onboard/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "m5-onboard", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
m5-onboardDetects a newly connected M5Stack ESP32 board over USB, flashes UIFlow 2.0 firmware and installs the Claude Buddy MicroPython apps, or reruns single steps of that flow.
This skill carries a freshly plugged-in M5Stack board from nothing to running software: detect it on USB, identify the model, flash UIFlow 2.0 firmware, and copy a MicroPython app bundle (Claude Buddy, Snake and Hello) to /flash/ so the device boots into it. The apps talk over BLE or USB. It works on macOS, Linux and Windows, and it was developed on an M5Stack Basic v2.6 and then generalized to the rest of the Core family, with the Cardputer-Adv as the default target.
The scripts do not ship with the skill. They live in a local clone of the build-with-claude repository, which the /maker-setup command creates, and each one is run from that clone's onboard/ directory. A fresh or unknown device gets onboard.py with the buddy apps, a flashed device that only needs apps gets install_apps.py, and a device that seems broken gets smoke_test.py, which checks I2C, the LCD, the speaker and the buttons.
The agent asks which port to use when several devices are connected. Cardputer-Adv is assumed when you name no model, but if you say Cardputer without Adv it asks first, because the two take different firmware images and the wrong one boot-loops the device. Other boards such as Core2, CoreS3, Basic or Fire need an explicit --variant.
4 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit b8e53f1. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
python3pythonwingetapt-getgitbrewbashcurldnfpipFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
raw.githubusercontent.comAlso links to:
github.comFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
M5Stack Device Onboarding loads about 5.9k tokens when it runs. Until then it costs about 85 tokens; SKILL.md has 3,204 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check noted patterns worth knowing about, such as sudo or a known installer.
missing, offer to install it via `/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/indistro package manager. Debian/Ubuntu: `sudo apt-get update && sudo apt-get install -y python3 python3-pip`. Fedora: `s`/dev/ttyUSB*` / `/dev/ttyACM*` without sudo requires group membership (`dialout` on Debian/Ubuntu/Arch, `uucp` on Fedosudo usermod -aG dialout $USER`sudo python3 scripts/onboard.py ...` works as a one-off but adding the group membership is strictly better because pyAutomated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from anthropics/claude-plugins-official at commit b8e53f1, republished under its Apache-2.0 licence (© anthropics). 3,204 words, ~5,940 tokens.
.claude/skills/m5-onboard/SKILL.md (or your agent's skills folder).This skill automates the full cold-start workflow for an M5Stack ESP32 device: detect on USB, identify model, flash UIFlow 2.0, and push a MicroPython app bundle onto /flash/ so the device boots into user software. The apps we ship (Claude Buddy, Snake, Hello) talk over BLE or USB. The workflow runs on macOS, Linux, and Windows; the skill was developed against an M5Stack Basic v2.6 (CH9102 bridge, ESP32-D0WDQ6-V3, 16 MB flash) and generalized to cover the rest of the Core family, with the Cardputer-Adv (ESP32-S3, native USB) as the current default target.
This skill ships as part of the cwc-makers plugin for reference, but the executable scripts and the buddy/ app bundle live in a local clone of https://github.com/moremas/build-with-claude (the /maker-setup command creates this clone). Run every scripts/*.py invocation below from inside that clone's onboard/ directory so --apps buddy resolves to the sibling buddy/device/ payload.
Use this when a user plugs in an M5Stack device and wants it provisioned. The decision tree:
onboard.py --apps buddy end-to-end (detect → identify → flash → install apps). This is the default path.install_apps.py --src buddy (or any --src <path> to a directory of .py files).smoke_test.py (I2C + LCD + speaker + button check).smoke_test.py.If multiple devices are plugged in, ask which port to target — don't guess. If the user is provisioning a device they previously worked with (e.g. "same thing as last time" or "another Buddy"), default to --apps buddy unless they say otherwise.
The rig this skill lives on provisions Cardputer-Adv boards overwhelmingly, so onboard.py now defaults to --variant cardputer-adv. In practice that means:
--variant explicitly — the default won't apply.detect.py won't be able to tell Cardputer from Cardputer-Adv before UIFlow is flashed (same native USB-JTAG VID, no pre-flash I2C probe). So this is a user-intent question, not a hardware-fingerprint one.The main orchestrator is scripts/onboard.py. It drives the sub-scripts in order and handles the handoffs between them (waiting for reboots, capturing MAC, reporting progress). Prefer calling it directly over stitching the sub-scripts yourself unless the user asks for a partial run.
The default provisioning command (fresh Cardputer-Adv, install the buddy bundle):
python3 scripts/onboard.py --apps buddyHow to invoke this from Claude Code's Bash tool. Do NOT call onboard.py as a foreground Bash command. The Bash tool captures output and does not stream it back to the assistant until the command exits — and this command runs 2–3 minutes. That silence looks identical to a hang, and the assistant will usually give up before the button-dance prompt ever reaches the user. Instead, always run with run_in_background: true, tee to a log file, and then use the Monitor tool (or periodic tail via Read) to surface stage banners, heartbeats, and prompts to the user in real time. 2>&1 is not the fix — all progress already writes to stderr, which a terminal shows fine. The fix is streaming semantics, not redirection. The pattern that works:
# Launch (background, tee log):
python3 scripts/onboard.py --apps buddy 2>&1 | tee /tmp/m5-onboard.log
# Monitor (surfaces key events without drowning in byte-progress spam):
tail -f /tmp/m5-onboard.log | grep -E --line-buffered \
"^====|heartbeat|Heads up|Enter download mode|download mode!|rebooted into UIFlow|Manual reset|DONE|ERROR|Error|Traceback|FAIL|failed|No USB|not detected|Attempt [0-9]|Device already in download|Download mode port|Post-flash port|Waiting for device"The flash stage cannot proceed without a manual button press on native-USB boards — there is no software path. When the monitored log shows Enter download mode (or the script appears to wait at the FLASH stage), you MUST stop and tell the user to do the following on the back of the Cardputer, in your own words, before continuing:
If the device reboots into UIFlow instead of going dark, tell the user G0 was released too early and to try again holding it longer. Do not move on, retry the script, or attempt a software workaround until the user confirms the screen is dark — the flash will not start otherwise. The same applies to any later Manual reset prompt: relay the physical step and wait for the user.
Users running onboard.py directly in their own terminal (not via Claude Code) will see all output live — no changes needed there.
If --port is omitted, detect.py picks the most likely candidate across all three OSes: native-USB ESP32-S3 (/dev/cu.usbmodem* on macOS, /dev/ttyACM* on Linux, COMx on Windows), or a CH9102/CP210x UART bridge on older boards. Bluetooth-serial ports are filtered out. If multiple candidates are present, it asks.
The known apps name buddy resolves to the buddy/device/ directory in this repo (custom launcher + Hello + Claude Buddy BLE client + Snake). Any other --apps value is treated as a filesystem path.
To skip re-flashing and just push (or refresh) the apps onto an already-provisioned device:
python3 scripts/install_apps.py --port <PORT> --src buddyWhere <PORT> is whatever detect.py printed on the last full run — for example /dev/cu.usbmodem1101, /dev/ttyACM0, or COM3.
detect.py) — enumerate serial ports, filter to USB-UART bridges (CH9102 vendor 0x1A86, Silabs CP210x 0x10C4, FTDI 0x0403) or the ESP32-S3 native USB-JTAG interface (0x303A). Probe with esptool to confirm the chip. Port names differ per OS (/dev/cu.usbmodem* on macOS, /dev/ttyACM*/ttyUSB* on Linux, COMx on Windows) but pyserial abstracts that.detect.py) — alongside port discovery, detect.py reads the factory-test partition signature and/or scans I2C once UIFlow is on, and cross-references references/hardware_signatures.md to suggest the right firmware variant (Basic-16MB, Core2, CoreS3, Cardputer-Adv, etc.). User-facing variant choice happens via onboard.py --variant; there is no separate detect.py --identify flag.fetch_firmware.py) — query the M5Burner manifest API and download the appropriate UIFlow 2.0 binary into the system temp dir. Cached between runs — safe to clear the cache anytime, it just re-downloads.flash.py) — esptool write_flash 0x0 <image> at 460800 baud for UART bridges, --no-stub at 115200 baud for native-USB S3 devices. 921600 fails intermittently on the CH9102 bridge — do not increase it. Native-USB flash can intermittently throw Lost connection, retrying mid-erase; esptool recovers. The post-flash watchdog-reset teardown step can fail even when the flash itself succeeded — flash.py parses esptool's stdout, treats that specific failure pattern as non-fatal when Hash of data verified appeared, and onboard.py falls back to flash.native_reset() and then manual-RESET coaching if needed.install_apps.py) — paste-mode REPL upload of every .py from a source directory into /flash/, then reboot via repl_reset (DTR/RTS is a no-op on native USB — don't reach for it). Source layout: root *.py → /flash/, apps/*.py → /flash/apps/ (UIFlow's stock launcher scans that). When the bundle ships a root main.py, install_apps.py also sets NVS boot_option=2 so UIFlow's own launcher doesn't run and our main.py takes over the boot flow — critical for BLE-using apps on ESP32-S3 (see gotchas below).smoke_test.py) — I2C scan, LCD test pattern, speaker beep, button read.These are things the scripts already handle correctly but which you should not override if the user asks you to "just run esptool manually" or similar:
onboard.py:_wait_for_download_port prompts for this at runtime during FLASH: press and HOLD BtnG0, briefly press BtnRST, release BtnRST first, keep holding BtnG0 for ~1 more second, release BtnG0, screen should be fully dark. If the device reboots back into UIFlow instead, BtnG0 was released too early — the coaching retries and tells the user to hold it longer. Do NOT try to automate this with esptool --before default_reset or pyserial's DTR/RTS; both are no-ops on native USB (the pins aren't wired to EN), and adding them just hides the real prompt.m5-onboard go — it's idempotent and will re-enter download mode, re-flash, re-push apps. Don't panic and don't start opening the case; the mask ROM is in silicon and survives a corrupted flash as long as the USB PHY is intact.--no-stub on native USB. Not 921600 on either. The CH9102 bridge loses sync on erase_flash at 921600 (not theoretical — it fails). Native USB's stub-baud-bump path produces "Lost connection" mid-flash; 115200 no-stub is counterintuitively faster end-to-end because it never fails.set_str, not set_blob (relevant to install_apps.py's boot_option setter). UIFlow's startup calls nvs.get_str() and ESP-IDF tags blob and string entries separately. A blob-tagged key returns ESP_ERR_NVS_NOT_FOUND to get_str, and the device boot-loops. If a prior attempt wrote a blob, call nvs.erase_key(name) before set_str.try:/except: line-by-line makes the REPL accumulate indentation forever. Use Ctrl-E to enter paste mode, send the block, Ctrl-D to execute. mpy_repl.py wraps this.mpy_repl.repl_reset() (sends machine.reset() through the REPL) for post-install reboots on those devices — install_apps.py already does this. If you bypass install_apps.py and stitch your own flow, don't reach for DTR/RTS on a usbmodem port and expect a reboot; files will be on disk but the old code will still be running. That regression bit us once.boot_option=2 + a custom main.py. UIFlow's default boot_option=1 starts a background Flow-pairing BLE advertise that wedges the NimBLE controller — subsequent gap_advertise(adv_data=...) calls from user code hit OSError(-519) "Memory Capacity Exceeded" regardless of payload shape, and the device ends up advertising with empty AD fields that iOS and the desktop Claude Buddy app filter out. The bundle's main.py lives at /flash/ and takes over the boot flow (showing a simple menu over /flash/apps/), never touches BLE itself, and leaves the controller pristine for whichever app the user picks. install_apps.py now sets boot_option=2 automatically when the bundle ships a root main.py — don't regress that behavior.Once m5-onboard go finishes at the DONE banner, the device is ready to use on its own:
.py in /flash/apps/ plus the top-level /flash/*.py entries.main.py connects to a hard-coded event WiFi (SSID cardputer) on every boot and shows the result on the LCD before the launcher menu appears. Credentials live in buddy/device/wifi_event.py; the connect is best-effort and the launcher always continues even if the connect fails. If you're using this bundle outside the event, edit wifi_event.py or remove the _connect_wifi_with_splash() call from main.py.main.py at /flash/ (no replacement boot.py), so the stock UIFlow boot.py is never touched and there's no boot_uiflow.py backup to restore. Revert by removing our main.py from the device REPL: os.remove('/flash/main.py') followed by machine.reset(). UIFlow's stock launcher takes over on the next boot. To start completely fresh including the firmware, re-run the skill without --apps.scripts/onboard.py — main orchestratorscripts/detect.py — port discovery + chip IDscripts/fetch_firmware.py — M5Burner API + downloadscripts/flash.py — esptool wrapperscripts/install_apps.py — push a directory of .py files into /flash/ via paste-mode REPL; backs up boot.py as boot_uiflow.py before overwriting; also writes the boot_option NVS key when the bundle ships a root main.pyscripts/smoke_test.py — I2C + LCD + speaker + buttonsscripts/mpy_repl.py — shared serial/REPL helpers (paste mode, hard reset, boot-log capture)references/hardware_signatures.md — chip + I2C fingerprints → model → firmwarereferences/uiflow2_nvs.md — NVS key reference with types and failure modespyserial — vendored at onboard/scripts/vendor/serial/ (pinned 3.5, BSD-3-Clause).esptool — pip dependency, declared in requirements.txt. Importable check happens via importlib.util.find_spec("esptool"); binary backstop search covers ~/Library/Python/*/bin/ on macOS, ~/.local/bin/ on Linux, %APPDATA%\Python\Python3XX\Scripts\ on Windows.onboard.py runs a preflight check at startup: if esptool (or, in the rare prune-vendor case, pyserial) is missing, it lists what's needed and asks the user whether to install now. On Y (or Enter) it runs python -m pip install --user <missing> in the current interpreter, then verifies. Inside a venv the --user flag is dropped so the install lands in the venv's site-packages. Non-interactive callers (piped stdin) get a manual-install hint instead of a prompt.
Python itself has to exist before this skill can do anything — you can't bootstrap an interpreter from inside one. git is not required — the /maker-setup command falls back to downloading the GitHub tarball with curl+tar (both pre-installed on macOS, Linux, and Windows 10+) when git --version fails. Claude's responsible for detecting Python and installing it if missing before running any scripts/*.py invocation. Detection is just running python3 --version / python --version — if it fails, Claude fetches Python with the host's native package manager before anything else.
Per-OS Python bootstrap (Claude's responsibility if missing):
winget install -e --id Python.Python.3.13 --silent --accept-source-agreements --accept-package-agreements. Takes ~30 seconds, no UI, gets PATH right. If the current shell can't see python afterwards, tell the user to close and reopen the terminal (Windows updates PATH only on new shells)./usr/bin/python3 on any current macOS (shipped by Apple). If for some reason it isn't, brew install python@3.13 via Homebrew is the go-to; if Homebrew itself is missing, offer to install it via /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" (but only if the user confirms — Homebrew is a larger commitment than winget).sudo apt-get update && sudo apt-get install -y python3 python3-pip. Fedora: sudo dnf install -y python3 python3-pip. Arch: sudo pacman -S --noconfirm python python-pip. You may need to sudo and should surface the password prompt to the user if needed.pyserial — bundled with the skill:
A pinned pyserial 3.5 ships under scripts/vendor/ (BSD-3-Clause, Apache-compatible). Every script that imports serial calls vendor_path.ensure_on_syspath() before the first third-party import, which prepends scripts/vendor/ to sys.path, so the vendored copy resolves regardless of whatever the user has system-wide. Net effect: port enumeration and REPL I/O work on a fresh clone with zero pip step. ~500 KB, pure-Python, same tree on macOS / Linux / Windows.
esptool — pip dependency, auto-installed on first run:
esptool is GPLv2+ and is intentionally not vendored — keeping the repository cleanly Apache-2.0 means the GPL bits live in the user's pip-managed environment, not in the tree. The skill's preflight checks for an importable esptool and, if missing, prompts to install it (python -m pip install --user esptool — --user dropped inside a venv so it lands in site-packages). For subprocess calls we use [sys.executable, "-m", "esptool", ...]; the subprocess inherits user-site so the pip-installed module imports cleanly. requirements.txt declares this for explicit setup; the prompt path is the default for first-time attendees who haven't run pip yet.
Non-interactive callers (piped stdin, CI) skip the prompt and get a python -m pip install --user esptool hint instead.
Fallback if someone prunes scripts/vendor/:
The same preflight path also re-installs pyserial via pip if the vendor copy is gone. This handles the case where someone downloaded a source-only zip that excluded vendor, or manually trimmed the repo to save space.
USB driver — Windows-specific, only for older boards:
The CH9102 USB-UART driver is still a manual install on Windows — WCH doesn't publish a winget manifest. Only needed for UART-bridge boards (Basic, Fire, Core2, StickC). Native-USB ESP32-S3 boards (Cardputer, Cardputer-Adv, CoreS3) enumerate as composite USB-CDC devices using Windows' in-box drivers and need no extra install.
The skill runs on macOS, Linux, and Windows. Non-obvious bits:
Port naming. pyserial abstracts the lookup but what the user sees looks different per OS. Pass whichever form detect.py reports:
/dev/cu.usbmodem1101 (native USB) or /dev/cu.usbserial-XXXX (CH9102)/dev/ttyACM0 (native USB) or /dev/ttyUSB0 (UART bridge)COM3, COM4, etc. (Device Manager → Ports if unsure)Linux permissions — read this before blaming hardware. On most distros, accessing /dev/ttyUSB* / /dev/ttyACM* without sudo requires group membership (dialout on Debian/Ubuntu/Arch, uucp on Fedora). Symptom: detect.py finds the port, but the flash step fails with Permission denied or Could not open port. Fix once, long-term:
sudo usermod -aG dialout $USER
# log out / log back in — group change only takes effect for new sessionssudo python3 scripts/onboard.py ... works as a one-off but adding the group membership is strictly better because pyserial's port-open in user mode succeeds cleanly from then on.
Windows PATH gotchas. Python's pip install --user esptool lands the executable in %APPDATA%\Python\Python3XX\Scripts\. If that directory isn't on PATH, pip prints a warning and nothing else picks up the install. detect.py looks there directly as a backstop, so the skill still works even without PATH fixed. But if you're invoking esptool outside the skill (or hitting "esptool not found" errors from other tools), either:
%APPDATA%\Python\Python3XX\Scripts to PATH via System Properties → Environment Variables, ORpython -m esptool ... which always works regardless of PATH.Windows Store Python. Newer Windows 11 machines may have Python pre-installed via Microsoft Store. It works but has quirky PATH behavior (lives under %LOCALAPPDATA%\Packages\PythonSoftwareFoundation.Python.*\). detect.py checks that location too. If you have the choice, the winget install Python.Python.3.13 version is more predictable.
Bundle path resolution. install_apps.py's --src buddy shorthand resolves in this order:
$M5_BUDDY_DIR if set — explicit override, always wins. Useful when you want to point at a fork or a customized bundle that isn't in this clone.buddy/device/ directory inside this repo, found via os.path.realpath(__file__) walking up from install_apps.py. Works for any clone location, including symlinked skill installs at ~/.claude/skills/m5-onboard/.~/Downloads/m5stack/buddy/device.~/Desktop/m5stack/buddy/device.Most installs hit (2). Set M5_BUDDY_DIR only for the unusual case of pointing at a bundle outside this clone: export M5_BUDDY_DIR=/path/to/buddy/device (Unix) or $env:M5_BUDDY_DIR="C:\path\to\buddy\device" (PowerShell).
Firmware cache. Downloaded firmware lands at ~/.cache/m5-onboard/ (or $XDG_CACHE_HOME/m5-onboard/), created at mode 0700 if missing. Cache files are MD5-verified at write time and re-verified on hit. Clearing the cache is safe; the next run re-downloads.
© anthropics, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in plugins/cwc-makers/skills/m5-onboard of anthropics/claude-plugins-official.
Open the folder on GitHubat commit b8e53f1
M5Stack Device Onboarding next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| M5Stack Device Onboarding this skillanthropics/claude-plugins-official | 38k | — | ~5.9k | Automated safety check: Notes | Apache-2.0 | |
| RuView Hardware Setupruvnet/RuView | 97k | — | ~1.8k | Automated safety check: Notes | MIT | |
| Esp32 Firmware Engineeralxv2016/folloup-sticky | 117 | 1 repos | ~3.8k | Automated safety check: Pass | GPL-3.0 | |
| RuView mmWave Radar Setupruvnet/RuView | 97k | — | ~907 | Automated safety check: Notes | MIT | |
| Embedded DebugFastLED/FastLED | 7.5k | — | ~1.4k | Automated safety check: Pass | MIT | |
| Auto EmbeddedDunCanYounG-1/MICU-auto-embedded | 253 | — | ~1.6k | Automated safety check: Pass | CC-BY-NC-4.0 |
ruvnet/RuView
Brings a RuView CSI sensing node online by building ESP32-S3 or ESP32-C6 firmware, flashing the board, provisioning WiFi and checking the serial output.
alxv2016/folloup-sticky
ESP32 firmware engineering for ESP-IDF projects. An agent skill from alxv2016/folloup-sticky.
ruvnet/RuView
Sets up and runs 60 GHz and 24 GHz mmWave radar sensing on ESP32 boards in RuView, alone or fused with WiFi CSI.
FastLED/FastLED
Firmware crash analysis, stack trace decoder, and register dump interpreter for ESP32/ARM/AVR platforms.
DunCanYounG-1/MICU-auto-embedded
全平台嵌入式 AI 开发框架(对标 Trellis):把 RIPER-5 五阶段协议 + 四文件记忆 + 分层架构门禁 + Scout/Builder/Verifier 多 Agent + 24 个工具调用技能(build/flash/debug/serial/can/modbus/visa/static/memory/rtos/scons),做成『装进工程、项目级 hook…
BlueAndi/Pixelix
A skill your agent uses when writing, reviewing, or refactoring C/C++ firmware code in this repository (src/, lib/, test/) — creating or editing .h/.hpp/.cpp files, applying MISRA-oriented and…
anthropics/claude-plugins-official
Explains how to write Claude Code plugin hooks, both prompt-based checks and bash commands, for events such as PreToolUse, Stop and SessionStart.
anthropics/claude-plugins-official
Explains how to write agents for Claude Code plugins: the markdown file with YAML frontmatter, trigger descriptions, model and color settings, and system prompt design.
anthropics/claude-plugins-official
Shows how Claude Code plugins keep per-project settings and state in .claude/plugin-name.local.md files with YAML frontmatter and a markdown body.
anthropics/claude-plugins-official
Explains how to bundle Model Context Protocol servers in a Claude Code plugin, covering config files, stdio, SSE, HTTP and WebSocket server types, and authentication.
anthropics/claude-plugins-official
Explains how to write Claude Code slash commands: Markdown files with YAML frontmatter, arguments, file references, bash context and interactive prompts.
anthropics/claude-plugins-official
Explains the directory layout, plugin.json manifest and component organization of a Claude Code plugin, including auto-discovery and portable paths.
Works with
Categories
Detects a newly connected M5Stack ESP32 board over USB, flashes UIFlow 2.0 firmware and installs the Claude Buddy MicroPython apps, or reruns single steps of that flow. 0 firmware, and copy a MicroPython app bundle (Claude Buddy, Snake and Hello) to /flash/ so the device boots into it. The apps talk over BLE or USB.
M5Stack Device Onboarding fits situations like: plugging in a new M5Stack Cardputer, Core, CoreS3 or Stick and wanting it set up; flashing or resetting an ESP32-based M5Stack board with UIFlow 2.0 firmware; reinstalling the Claude Buddy apps on a device that is already flashed; running a hardware smoke test on a board that seems broken.
Run `npx skills add anthropics/claude-plugins-official --skill m5-onboard -a claude-code`. Or copy the skill folder (plugins/cwc-makers/skills/m5-onboard in anthropics/claude-plugins-official) into .claude/skills/m5-onboard in your project. Claude Code loads it when a task matches its description.
Run `npx skills add anthropics/claude-plugins-official --skill m5-onboard -a codex`. Or copy the skill folder (plugins/cwc-makers/skills/m5-onboard in anthropics/claude-plugins-official) into .agents/skills/m5-onboard in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add anthropics/claude-plugins-official --skill m5-onboard -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/m5-onboard, .gemini/skills/m5-onboard, .github/skills/m5-onboard and .opencode/skills/m5-onboard in your project.
Going by SKILL.md and its folder, M5Stack Device Onboarding needs the command-line tools its instructions call (python3, python, winget, apt-get, git and brew). Our summary lists: An M5Stack ESP32 device connected over USB; A local clone of build-with-claude, created by /maker-setup.
SKILL.md names 2 domains. In commands or code: raw.githubusercontent.com; the agent is likely to contact it when it follows the instructions. As links in the text: github.com. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found notes only (pipes a well-known installer script into a shell; runs commands with sudo), nothing it rates as a warning. It is not a guarantee. Review the folder before installing.
M5Stack Device Onboarding is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.9k tokens (SKILL.md is roughly 24k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with M5Stack Device Onboarding: RuView Hardware Setup (ruvnet/RuView, 97k stars), Esp32 Firmware Engineer (alxv2016/folloup-sticky, 117 stars), RuView mmWave Radar Setup (ruvnet/RuView, 97k stars) and Embedded Debug (FastLED/FastLED, 7.5k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
anthropics (a GitHub organization, an official publisher) maintains it in anthropics/claude-plugins-official, which has 37,597 GitHub stars. The repository holds 29 skills in this directory. The repository was last updated on October 9, 2026.
Source: anthropics/claude-plugins-official on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.