[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-11757":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":13,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":15,"stars7d":16,"stars30d":17,"stars90d":14,"forks30d":14,"starsTrendScore":18,"compositeScore":19,"rankGlobal":9,"rankLanguage":9,"license":20,"archived":21,"fork":21,"defaultBranch":22,"hasWiki":23,"hasPages":21,"topics":24,"createdAt":9,"pushedAt":9,"updatedAt":25,"readmeContent":26,"aiSummary":27,"trendingCount":14,"starSnapshotCount":14,"syncStatus":28,"lastSyncTime":29,"discoverSource":30},11757,"cardputer-claude-os","dakshaymehta\u002Fcardputer-claude-os","dakshaymehta","DIY OS bundle for the M5Stack Cardputer: Claude Buddy (BLE), Push-to-Claude (voice + chat with memory via a Cloudflare Worker), and a flash-and-go installer skill for Claude Code. Forked from moremas\u002Fbuild-with-claude.",null,"Python",163,17,1,0,10,14,103,30,3.77,"Apache License 2.0",false,"main",true,[],"2026-06-12 02:02:33","# Cardputer Claude OS\n\nA DIY \"OS\" bundle for the [M5Stack Cardputer](https:\u002F\u002Fshop.m5stack.com\u002F) —\nflash UIFlow firmware, install a launcher, and ship a tiny suite of apps\nthat turn the Cardputer into a hand-held Claude device:\n\n- **Claude Buddy** — pair the Cardputer with Claude Code over BLE; watch\n  agent runs, token spend, and queue depth from your pocket.\n- **Push to Claude** — hold SPACE to record a voice question, release to\n  send. Whisper transcribes, Claude Haiku 4.5 replies on the LCD, and a\n  per-device 24-hour memory keeps context across turns. Type-mode also\n  available for noisy rooms.\n- **Claude Pager** — type a task on the QWERTY, fire it off as a\n  long-running [Managed Agents] session in the cloud, and watch live\n  status (`bash: pytest …`, `wrote auth_test.py`, `idle ✓`) on the LCD.\n  Inbox lists active sessions; Detail screen lets you reply, interrupt,\n  or approve pending tool calls from your pocket. Pairs with the\n  **Central Console** browser UI on your Mac and the `claude-pull`\n  artifact sync.\n- **Cardputer MCP** — turn the device into a pocket pager for any\n  Model-Context-Protocol-speaking agent (Claude Code, Cursor,\n  Claude Desktop, Managed Agents, etc.). The agent can buzz you\n  with a colored banner + speaker chirp (`notify`), ask a\n  multiple-choice question you answer on the QWERTY (`ask`), or\n  demand a physical gesture for destructive operations (`confirm`).\n  Local stdio MCP server + BLE-GATT peripheral — no cloud, no\n  Wi-Fi required.\n- **Hello \u002F Snake** — minimal example app + a snake game so the bundle\n  isn't all serious business.\n\n[Managed Agents]: https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fmanaged-agents\u002Foverview\n\n> **Forked from** [`moremas\u002Fbuild-with-claude`](https:\u002F\u002Fgithub.com\u002Fmoremas\u002Fbuild-with-claude).\n> This fork adds the `worker\u002F` directory (a Cloudflare Worker that\n> handles voice STT + Claude chat with conversation memory) and the\n> `Push to Claude` device app that talks to it. Everything else\n> originates from upstream — credit and thanks to the original authors.\n\n## What's new in this fork\n\n| Addition                         | Where                                                                                     | What it does                                                                                                                                                                                                 |\n| -------------------------------- | ----------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| **Cardputer MCP (host bridge)**  | [`mcp\u002F`](mcp\u002F)                                                                            | Stdio Model Context Protocol server (`bleak`-based) that any Claude or MCP client can register. Three tools: `notify`, `ask`, `confirm`. Talks BLE to the device app — no cloud, no Wi-Fi required.          |\n| **Cardputer MCP (device app)**   | [`buddy\u002Fdevice\u002Fapps\u002Fcardputer_mcp.py`](buddy\u002Fdevice\u002Fapps\u002Fcardputer_mcp.py)                | BLE GATT peripheral on a fresh service UUID block (`a5cd0001-…`), distinct from Buddy's NUS. Renders notifications, ask-question modals, and a hold-Y confirmation gesture; sends acks via TX notifications. |\n| **Cloudflare Worker relay**      | [`worker\u002F`](worker\u002F)                                                                      | Auth-gated edge endpoint. Whisper for STT, Claude Haiku 4.5 for the reply, Workers KV for per-device conversation memory (last 8 messages, 24 h TTL).                                                        |\n| **Voice + chat app**             | [`buddy\u002Fdevice\u002Fapps\u002Fpush_to_claude.py`](buddy\u002Fdevice\u002Fapps\u002Fpush_to_claude.py)              | On-device client. Streams WAV to the Worker as it records (flat RAM footprint), text-fallback mode, scrollable replies, `\u002Freset` shortcut.                                                                   |\n| **Pager device app**             | [`buddy\u002Fdevice\u002Fapps\u002Fpager.py`](buddy\u002Fdevice\u002Fapps\u002Fpager.py)                                | Three-screen UI (Compose \u002F Inbox \u002F Detail) for firing and triaging Managed Agents sessions from the QWERTY. Long-polls the Worker for live event ticker.                                                     |\n| **SessionRouter Durable Object** | [`worker\u002Fsrc\u002Frouter.do.js`](worker\u002Fsrc\u002Frouter.do.js)                                      | One DO per Anthropic session. Lazily polls the Managed Agents `events.list` endpoint, mirrors events into DO storage, and serves both the Pager (poll) and Console (SSE).                                    |\n| **Central Console (browser)**    | [`worker\u002Fsrc\u002Fconsole.html`](worker\u002Fsrc\u002Fconsole.html)                                      | Single-file dark-theme HTML console served from the Worker. Live event stream, syntax-highlighted bash, inline diffs for `str_replace`, file pills, interrupt + reply. Token-gated, no build step.           |\n| **Mac artifact sync**            | [`mac\u002Fclaude-pull`](mac\u002Fclaude-pull) + [`launchd plist`](mac\u002Fcom.claude.pager.pull.plist) | Stdlib Python script run every 60 s by launchd. Pulls each session's `\u002Fworkspace\u002Fout\u002F` files into `~\u002FClaudeRuns\u002F\u003Ctitle>-\u003Cid>\u002F` and posts a banner notification when a session completes.                     |\n| **Externalized device config**   | [`buddy\u002Fdevice\u002Fapps\u002Fconfig.example.py`](buddy\u002Fdevice\u002Fapps\u002Fconfig.example.py)              | Worker URL + device secret loaded from a gitignored `config.py` so secrets never enter the repo.                                                                                                             |\n\nSee [`worker\u002FREADME.md`](worker\u002FREADME.md) for the full Cloudflare deploy\nguide.\n\n## Buy a Cardputer\n\nThe bundle targets the **M5Stack Cardputer-Adv** (the version with PDM\nmic + speaker, required for Push to Claude). Get one direct from\n[shop.m5stack.com](https:\u002F\u002Fshop.m5stack.com\u002F) — search \"Cardputer\".\nThe original Cardputer (non-Adv) works for everything except the voice\napp.\n\n## Quick start — flash a Cardputer\n\n1. Clone this repo locally — anywhere is fine:\n   ```bash\n   git clone https:\u002F\u002Fgithub.com\u002Fdakshaymehta\u002Fcardputer-claude-os.git\n   ```\n   The skill auto-detects the buddy bundle relative to its own install location, so the clone path doesn't matter. `~\u002FDownloads\u002Fm5stack\u002F` and `~\u002FDesktop\u002Fm5stack\u002F` are also checked as conventional fallbacks.\n2. Plug the Cardputer into your laptop via USB-C\n3. Open Claude Code and start a new chat\n4. Point Claude Code to the repo folder\n5. Type `m5-onboard go`\n\nThat's it — Claude will automatically flash the firmware and push the apps onto the device.\n\n### When Claude prompts you to put the device into download mode\n\nHalfway through, Claude will pause and ask you to do this on the **back** of the device:\n\n1. Hold down the **G0** button on the Cardputer\n2. While still holding G0, press the **Reset** button\n3. Release Reset first, then release G0\n4. The screen goes dark — device is in download mode\n\nClaude takes over from there.\n\n### What happens next\n\n- **Firmware writes to the device** (~180 seconds)\n- **Apps push to the device** (~100 seconds)\n- **Device reboots** straight into the launcher — pick an app and go\n\nDone. Power the device on\u002Foff with the side switch.\n\n---\n\n## Quick start — Cardputer MCP (let any agent reach the device)\n\nTurn the Cardputer into a pocket pager that any MCP-speaking client\n— Claude Code, Claude Desktop, Cursor, Codex, Managed Agents (via\nthe future HTTPS bridge), or anything that supports the Model\nContext Protocol — can reach. Three tools land on first connect:\n\n- `cardputer.notify(title, body, urgency)` — flash a banner on the\n  device and chirp the speaker. Urgency colors the header\n  (info=dark, warn=yellow, crit=red) and varies the beep pattern.\n  Returns once the banner is shown; auto-clears after 5 s.\n- `cardputer.ask(question, choices, timeout_s)` — show a numbered\n  multiple-choice question; the user presses 1–4 on the QWERTY;\n  the chosen string returns to the agent. Blocks the agent until\n  the user answers, ESCs, or `timeout_s` elapses.\n- `cardputer.confirm(title, timeout_s)` — display a red danger\n  banner and demand a physical gesture before resolving as\n  `confirmed`. The whole point is that a prompt injection cannot\n  synthesize a sustained physical keypress. Reserve this for\n  irreversible operations (deploys, force pushes, DROP TABLE,\n  charges, etc.). See _Known limitations_ in\n  [`mcp\u002FREADME.md`](mcp\u002FREADME.md) for the current gesture\n  caveat — the screen says \"HOLD Y\" but on this build you tap Y\n  rapidly to advance the timer.\n\nThe whole stack is local — stdio MCP between your client and the\nhost-side `bleak` bridge, then BLE-GATT to the device. No cloud\ntrip, no Wi-Fi required. Pairing cache lives at\n`~\u002F.cardputer-mcp\u002Fpaired.json` so reconnects skip the BLE scan.\n\n### Setup\n\n1. **Push the device app** (no firmware re-flash needed if you've\n   already onboarded the device):\n\n   ```bash\n   python3 .claude\u002Fskills\u002Fm5-onboard\u002Fscripts\u002Finstall_apps.py \\\n       --port \u003CPORT> --src buddy\n   ```\n\n2. **Set up the host bridge:**\n\n   ```bash\n   cd mcp\n   python3 -m venv .venv\n   source .venv\u002Fbin\u002Factivate\n   pip install -r requirements.txt\n   ```\n\n3. **Register the MCP server with Claude Code:**\n\n   ```bash\n   claude mcp add cardputer \\\n       \"$(pwd)\u002F.venv\u002Fbin\u002Fpython\" \\\n       \"$(pwd)\u002Fserver.py\"\n   ```\n\n   (Cursor, Codex, Claude Desktop, etc. each have their own\n   MCP-server registration UI; point them at the same\n   `.venv\u002Fbin\u002Fpython server.py` pair.)\n\n4. **On the device:** boot the launcher, pick **cardputer_mcp**\n   from the menu. The screen will read `waiting for bridge` and\n   display the device's `CardputerMCP_XXXXXX` BLE name. First\n   tool call from the agent triggers a scan + connect; the\n   screen flips to a green `READY`.\n\n5. **Try it.** In a fresh Claude Code session:\n\n   > Buzz the Cardputer with title \"tests passing\" and body\n   > \"127 ok in 4.2s\".\n\n   You should see the banner flash on the device, hear a chirp,\n   and Claude gets back `\"shown\"`. The whole round trip is\n   sub-second after the first connect.\n\n### macOS Bluetooth permission\n\nThe first BLE scan from the bridge triggers a macOS permission\nprompt. Approve it once; `bleak` caches the grant. If Claude Code\nruns inside a sandboxed terminal multiplexer that's not seeing\nthe prompt, grant Bluetooth to the terminal app itself under\n**System Settings → Privacy & Security → Bluetooth**.\n\n### Verifying without an MCP client\n\n[`mcp\u002Fsmoke_test.py`](mcp\u002Fsmoke_test.py) exercises the bridge\ndirectly (imports `Bridge` and calls the tools as Python), with\nno MCP registration needed. Useful for confirming BLE\nconnectivity, debugging gesture handling, and validating new\nfirmware before plugging it into a real session:\n\n```bash\ncd mcp && .venv\u002Fbin\u002Fpython smoke_test.py\n```\n\nIt runs a `notify`, then an `ask` (you press 1–3 on the device),\nthen a `confirm` (you tap Y rapidly per the caveat above).\n\nSee [`mcp\u002FREADME.md`](mcp\u002FREADME.md) for the full architecture\nnotes, wire-protocol pointer, known limitations, and roadmap;\nthe BLE wire format lives in\n[`buddy\u002Freferences\u002Fmcp_protocol.md`](buddy\u002Freferences\u002Fmcp_protocol.md).\n\n---\n\n## Quick start — Push to Claude (voice + chat)\n\nThe voice app needs a Cloudflare Worker you control. Roughly 10 minutes\nof one-time setup; after that every voice\u002Ftext turn is a single tap.\n\n1. Deploy the Worker — follow [`worker\u002FREADME.md`](worker\u002FREADME.md). You'll end up with a Worker URL and a `DEVICE_SECRET` you generated.\n2. Point the device at it:\n   ```bash\n   cp buddy\u002Fdevice\u002Fapps\u002Fconfig.example.py buddy\u002Fdevice\u002Fapps\u002Fconfig.py\n   ```\n   Edit `config.py`, paste in your `WORKER_BASE` and `DEVICE_SECRET`.\n3. Push the apps to the Cardputer (no firmware re-flash needed):\n   ```bash\n   python3 .claude\u002Fskills\u002Fm5-onboard\u002Fscripts\u002Finstall_apps.py --port \u003CPORT> --src buddy\n   ```\n4. Boot the device → **Push to Claude** → tap SPACE.\n\n`config.py` is gitignored — your secret stays on your machine.\n\n---\n\n## Quick start — Claude Pager + Central Console (cloud agents)\n\nThe Pager turns the Cardputer into a remote control + status display\nfor [Anthropic Managed Agents] sessions. Type a task on the QWERTY,\nfire it, and watch the device tick through `bash`, `write`, `idle ✓`\nin real time. A self-contained HTML console on your Mac mirrors the\nsame sessions with a full terminal-style event log; a launchd job\nsyncs artifacts the agent saves into `~\u002FClaudeRuns\u002F`.\n\n[Anthropic Managed Agents]: https:\u002F\u002Fplatform.claude.com\u002Fdocs\u002Fen\u002Fmanaged-agents\u002Foverview\n\nThe Pager rides on the same Worker as Push to Claude — finish that\nquick start first. Then:\n\n1. **Provision an extra KV namespace** for the session index:\n\n   ```bash\n   cd worker\n   npx wrangler kv namespace create INDEX\n   ```\n\n   Paste the returned id into `worker\u002Fwrangler.toml`, replacing\n   `REPLACE_WITH_YOUR_INDEX_KV_ID`.\n\n2. **Add the Durable Object migration** (already in `wrangler.toml`)\n   and redeploy:\n\n   ```bash\n   npx wrangler deploy\n   ```\n\n   First deploy registers the `SessionRouter` DO via the v1 migration\n   block; subsequent deploys are normal.\n\n3. **Open the Central Console** at\n   `https:\u002F\u002F\u003Cyour-worker>.workers.dev\u002Fconsole`. On first load it asks\n   for your `DEVICE_SECRET` (same value as the Cardputer); the secret\n   is stored in browser localStorage and never sent anywhere except\n   your Worker. Hit `+ New`, type a task, watch it run.\n\n4. **Push the Pager app** to the Cardputer. It ships as pre-compiled\n   bytecode (`.mpy`) because the source-form is too large to parse\n   inside the launcher's residual heap:\n\n   ```bash\n   pip3 install --user --break-system-packages mpy-cross\n   python3 buddy\u002Fscripts\u002Fpush_pager_mpy.py --port \u003CPORT>\n   ```\n\n   Reboot the device and pick **Pager** from the launcher menu.\n\n5. **(Optional) Mac artifact sync.** Agents save user-facing\n   artifacts into `\u002Fworkspace\u002Fout\u002F` inside their container. The\n   `mac\u002Fclaude-pull` script mirrors them to `~\u002FClaudeRuns\u002F\u003Ctitle>-\u003Cid>\u002F`\n   on a 60-second launchd schedule and pings you with a banner when\n   a session completes.\n   ```bash\n   .\u002Fmac\u002Finstall_launchd.sh        # writes a stub config and exits\n   $EDITOR ~\u002F.config\u002Fclaude-pager\u002Fconfig.json   # paste worker_base + device_secret\n   .\u002Fmac\u002Finstall_launchd.sh        # second run actually loads launchd\n   ```\n   Logs land at `\u002Ftmp\u002Fclaude-pull.{out,err}.log`. Run manually with\n   `.\u002Fmac\u002Fclaude-pull -v`.\n\n### Using the Pager\n\nThree screens, switched with the arrow cluster:\n\n```\nCOMPOSE   ← →   INBOX   →   DETAIL\n                            (Enter on a row)\n```\n\n- **Compose** — type a task and Enter to launch. `→` jumps to Inbox\n  without sending.\n- **Inbox** — live list of recent sessions with status pip + last-tool\n  subline. Refreshed every 4 s. Up\u002FDown to scroll, Enter to drill into\n  Detail, `D` to delete, `N` to jump back to Compose.\n- **Detail** — live ticker for one session. Long-polls the Worker so\n  deltas show within ~1 s of the agent acting.\n  - `R` reply (sends a follow-up message)\n  - `I` interrupt (sends `user.interrupt`)\n  - `Y\u002FN` approve\u002Fdeny pending tool confirmation (when present)\n  - `Esc` back to Inbox\n\nNotifications fire across **every** screen — the Pager polls the\nWorker every 15 s in the background. When an agent transitions:\n\n| Trigger                   | Beep               | Banner                        |\n| ------------------------- | ------------------ | ----------------------------- |\n| `running` → `idle`        | A5 → E6 chirp      | green **DONE: \u003Ctitle>**       |\n| pending tool confirmation | triple D6 urgent   | yellow **NEEDS YOU: \u003Ctitle>** |\n| → `terminated`            | A4 → A3 descending | red **ERROR: \u003Ctitle>**        |\n\nState is persisted to `\u002Fflash\u002F.pager_notif.json` so the same DONE\ndoesn't re-fire after a reboot.\n\n### Using the Central Console\n\nBrowser tab at `\u003Cyour-worker>\u002Fconsole`. Token-gated, dark theme,\nmonospace. Left rail = sessions, main pane = event stream with:\n\n- syntax-highlighted bash blocks\n- inline diffs for `str_replace` tool calls\n- collapsible tool-result blocks\n- pending-confirmation `y`\u002F`n` buttons in the composer\n- file pills along the bottom — click to download\n\nPress `n` (when no input is focused) to fire a new task. Use `⌘\u002FCtrl-Enter`\nin the composer or the spawn modal to send.\n\n### Cost guard\n\nEach Managed Agents session keeps a cloud container hot for its\nlifetime — typically a few cents to a couple of dollars per task.\nThe Worker enforces a per-device daily spawn cap (`PAGER_DAILY_SPAWN_CAP`\nin `wrangler.toml`, default 30). Bump or lower it to taste.\n\n---\n\n## Using Claude Buddy (BLE)\n\n1. Power on the Cardputer\n2. Pick **Claude Buddy** from the launcher menu\n3. In Claude Desktop: **Help → Troubleshooting → Enable Developer Tools** (one-time, persists)\n4. Then **Developer menu → Hardware Buddy → Connect**\n\n## WiFi auto-connect\n\nThe launcher tries to bring up WiFi on every boot and shows the result\non screen — `Connected · IP: 192.168.x.x` on success, `WiFi: offline`\non failure (the launcher always continues either way). Out of the box\nthe credentials in [`buddy\u002Fdevice\u002Fwifi_event.py`](buddy\u002Fdevice\u002Fwifi_event.py)\nare blank, so you'll see `WiFi: offline`. Edit that file to fill in\nyour own SSID + password, or remove the `_connect_wifi_with_splash()`\ncall near the top of `main()` to skip the auto-connect entirely.\n\n## Adding your own app\n\n1. Drop a `.py` file into `buddy\u002Fdevice\u002Fapps\u002F`\n2. Push just the apps without re-flashing:\n   ```bash\n   python3 .claude\u002Fskills\u002Fm5-onboard\u002Fscripts\u002Finstall_apps.py --port \u003CPORT> --src buddy\n   ```\n3. The launcher auto-discovers the new app on next boot\n\nCrib from `buddy\u002Fdevice\u002Fapps\u002Fhello_cardputer.py` — it's the smallest example of the conventions (keyboard polling, font, exit behaviour).\n\n## Getting back to stock UIFlow\n\nThe buddy bundle takes over the boot flow via `\u002Fflash\u002Fmain.py`. Remove\nthat file and UIFlow's stock launcher boots normally on the next reset.\nFrom the device REPL:\n\n```python\nimport os\nos.remove('\u002Fflash\u002Fmain.py')\nimport machine; machine.reset()\n```\n\nTo also drop the apps under `\u002Fflash\u002Fapps\u002F`, walk that directory the\nsame way and remove what you don't want.\n\nIf you want a fresh UIFlow firmware on top, re-run `m5-onboard go`\n_without_ `--apps`: the skill flashes UIFlow and stops, leaving the\nfilesystem alone.\n\n---\n\n## Prerequisites\n\nYou need **Python 3.10+**, **git**, and **Claude Code** on your laptop. `pyserial` ships vendored inside `.claude\u002Fskills\u002Fm5-onboard\u002Fscripts\u002Fvendor\u002F`. `esptool` is GPL-licensed and is **not** vendored — the skill auto-installs it via pip on first run if it isn't already in your environment, so the user-facing experience is still a single command. To pre-install explicitly: `python3 -m pip install --user -r requirements.txt`.\n\nFor the Push-to-Claude Worker you also need **Node.js 18+** and a\nCloudflare account; full instructions in [`worker\u002FREADME.md`](worker\u002FREADME.md).\n\nBootstrap if needed:\n\n- **macOS** — `python3` usually pre-installed; if not, `brew install python`\n- **Linux (Debian\u002FUbuntu)** — `sudo apt-get install -y python3 python3-pip git`\n- **Windows** — `winget install -e --id Python.Python.3.13` and `winget install -e --id Git.Git`\n\n**Windows + older boards only:** the CH9102 USB-UART driver is needed for Basic \u002F Fire \u002F Core2 \u002F StickC. Download from [WCH](https:\u002F\u002Fwww.wch.cn\u002Fdownloads\u002FCH343SER_EXE.html). Cardputer-Adv and CoreS3 use the in-box composite-USB driver and need nothing extra.\n\n**Want `--apps buddy` to point at a different bundle?** The default resolves to the `buddy\u002Fdevice\u002F` directory next to the skill in this repo, with `~\u002FDownloads\u002Fm5stack\u002F` and `~\u002FDesktop\u002Fm5stack\u002F` checked as fallbacks. To override (e.g. you maintain a fork or have a customized bundle elsewhere), set `M5_BUDDY_DIR`:\n\n```bash\nexport M5_BUDDY_DIR=\u002Fpath\u002Fto\u002Fbuddy\u002Fdevice\n```\n\n## Troubleshooting\n\n- **Download-mode prompt keeps retrying** — you're releasing G0 too early. Release Reset first, keep holding G0 for about a second, then release.\n- **\"No USB-UART bridge found\" (older boards)** — install the CH9102 driver on Windows; on macOS\u002FLinux, unplug and replug.\n- **Claude Buddy never connects over BLE** — make sure the buddy launcher (not UIFlow's) owns `\u002Fflash\u002Fmain.py`. The skill handles this automatically on install.\n- **Push to Claude shows \"Not configured\"** — copy `config.example.py` to `config.py` and fill in `WORKER_BASE` + `DEVICE_SECRET`, then re-push the apps.\n- **Push to Claude returns \"unauthorized\"** — the `DEVICE_SECRET` in `config.py` doesn't match the one set on the Worker. Re-run `wrangler secret put DEVICE_SECRET` and update `config.py` to match.\n- **Something else feels broken** — run `python3 .claude\u002Fskills\u002Fm5-onboard\u002Fscripts\u002Fsmoke_test.py --port \u003CPORT>` for an I2C + LCD + speaker + button check.\n\n## What's in this repo\n\n- **`.claude\u002Fskills\u002Fm5-onboard\u002F`** — the Claude Code skill. Detect port, flash UIFlow, install apps. See [`.claude\u002Fskills\u002Fm5-onboard\u002FSKILL.md`](.claude\u002Fskills\u002Fm5-onboard\u002FSKILL.md) for the full playbook and every gotcha baked into the scripts.\n- **`buddy\u002F`** — the MicroPython app bundle that gets installed. See [`buddy\u002FREADME.md`](buddy\u002FREADME.md) for device-side layout and iteration tooling.\n- **`worker\u002F`** — the Cloudflare Worker that powers Push to Claude (voice + chat memory). See [`worker\u002FREADME.md`](worker\u002FREADME.md) for deploy instructions.\n\nThe three are decoupled by design: the `m5-onboard` skill can install any bundle via `--apps \u003Cpath>`, `buddy` is just what ships here, and the worker is optional (only the Push-to-Claude app uses it).\n\n## Contributing\n\nPRs welcome — especially new launcher apps, new boards, and improvements\nto the onboarding flow. Open an issue first if you're planning anything\nnon-trivial. The code is small and intentionally tries to stay readable\nend-to-end.\n\n## License\n\nThis project's own code is licensed under **Apache 2.0** — see [`LICENSE`](LICENSE) and [`NOTICE`](NOTICE).\n\n`pyserial` (BSD-3-Clause, Apache-compatible) is the only third-party package bundled in `.claude\u002Fskills\u002Fm5-onboard\u002Fscripts\u002Fvendor\u002F`. `esptool` (GPLv2+) is intentionally not vendored; it's declared as a pip dependency in [`requirements.txt`](requirements.txt) so the repository itself stays cleanly Apache-2.0. See [`LICENSE-THIRD-PARTY.md`](LICENSE-THIRD-PARTY.md) for details.\n\nForked from [`moremas\u002Fbuild-with-claude`](https:\u002F\u002Fgithub.com\u002Fmoremas\u002Fbuild-with-claude); upstream Apache-2.0 license preserved in `LICENSE` and `NOTICE`.\n","这是一个为M5Stack Cardputer设计的DIY操作系统包，旨在将其转变为手持式Claude设备。核心功能包括通过蓝牙低能耗技术与Claude Code配对、语音提问并通过Cloudflare Worker转录和回复、以及作为模型-上下文-协议代理的口袋传呼机使用等。此外，还支持长时间运行的任务管理，并能在LCD上实时显示状态。适合需要便携式智能助手的应用场景，如远程工作、教育辅助或个人项目开发。基于Python开发，该项目是对`moremas\u002Fbuild-with-claude`的一个扩展版本。",2,"2026-06-11 03:32:25","CREATED_QUERY"]