# AI Desk Card Β· An AI-Driven Desk Companion Skill ![GitHub stars](https://img.shields.io/github/stars/op7418/ai-desk-card?style=flat-square) ![License](https://img.shields.io/github/license/op7418/ai-desk-card?style=flat-square) ![Skill](https://img.shields.io/badge/Skill-Agent-111111?style=flat-square) ![M5Paper](https://img.shields.io/badge/M5Paper-V1.1-0A7CFF?style=flat-square) ![Claude Code](https://img.shields.io/badge/Claude%20Code-Supported-6B5B95?style=flat-square) ![Codex](https://img.shields.io/badge/Codex-Supported-222222?style=flat-square) > πŸ‡¨πŸ‡³ **δΈ­ζ–‡η‰ˆοΌˆδΈ»ζ–‡ζ‘£οΌ‰: [README.md](./README.md)** A Skill that turns an [M5Paper V1.1](https://docs.m5stack.com/en/core/m5paper) e-ink panel into a desk companion driven by an AI agent (Claude Code, Codex, Cursor, etc.). The agent decides what to push: weather, calendar, todos, PR queue, AI session status, break reminders… **Once you install the Skill, the agent walks you through firmware flashing, Wi-Fi provisioning, and daily widget pushes** β€” you don't run a single `pio` or `curl` command by hand. ![AI Desk Card hero](https://github.com/user-attachments/assets/b4777ba7-d668-42c1-9920-3e6d8bef534e) ``` You ──ask naturally──▢ AI Agent ──triggers──▢ Skill ──auto-runs──▢ M5Paper ``` ## 30 seconds to start ```bash npx skills add https://github.com/op7418/ai-desk-card --skill ai-desk-card ``` Or paste this to any AI Agent with shell access: ```text Install the ai-desk-card Skill. Clone https://github.com/op7418/ai-desk-card into ~/.claude/skills/ai-desk-card. After install, verify SKILL.md, flows/, daemon/, src/, assets/ all exist. ``` To update an existing install: ```text Update ai-desk-card. cd into ~/.claude/skills/ai-desk-card, git pull, and tell me the latest commit. ``` Then assuming you have an M5Paper V1.1 and a USB-C data cable, just say: ```text Help me set up ai-desk-card. I have an M5Paper V1.1 plugged in over USB-C. ``` The Skill will automatically: 1. Probe current state (PlatformIO, USB device, daemon, Wi-Fi) 2. Install what's missing (`pipx install platformio` if needed) 3. Compile + flash CJK font + flash firmware (~1 minute) 4. Start the daemon 5. Ask for your Wi-Fi password β†’ provision 6. Push the first widget After that, daily use is a natural conversation: ```text Show today's Beijing weather on my card. Refresh weather and unread mail every 30 min on workday 8am-10pm. What's on my card right now? Auto-sleep at 11pm and show my business card. ``` ## What you get - πŸ–₯ **Ambient desk display**: a 540Γ—960 e-ink panel sits next to your monitor β€” glance, don't context-switch - πŸ€– **AI-pushed content**: the agent decides what widget to send and when; you don't open a browser for weather - πŸ“¦ **16 widget types**: weather / calendar / todo / focus / inbox / pr-queue / ai-status / git-status / now-playing / break-reminder / scratch / messages / deadlines / next-meeting / system / ai-tasks - 🎨 **Server-side render**: daemon uses Python + Pillow; want a new widget? Edit Python, no C++ - πŸ”Œ **Three power modes auto-switch**: USB-powered / USB-data-only / battery + BLE standby (months of life) - 🌐 **Wi-Fi LAN, 0.2 s per frame**: local HTTP, no cloud - πŸ’€ **Sleep at zero watts, last frame retained**: e-ink physics; ~6 months on a charge in arch C - πŸ‘† **Tappable bottom-bar chips**: "Sleep" β†’ push business card + deep sleep; "Settings" β†’ settings page. 150 ms tap-ack flash - ⏰ **Auto-sleep at quiet hours**: daemon flips to business card without needing the agent online ## When it fits / when it doesn't **βœ… Good fit if**: - You want an always-on side display but don't want another bright monitor - You already use Claude Code / Codex / Cursor and want an ambient physical output - You like e-ink's low-strain feel (not glaring, not distracting) - You accept a ~10 min one-time hardware setup (then zero maintenance) **❌ Not a fit if**: - You need fast-refresh content (stock tickers, video, animation) β€” e-ink can't - You don't want to buy hardware or flash firmware - You need rich touch interaction (touch works but e-ink is slow) ## Common scenarios | You say | Agent does | |------|------| | "Help me set up ai-desk-card" | Full onboarding: probe β†’ flash firmware β†’ start daemon β†’ provision Wi-Fi | | "Show today's weather on my card" | Push weather widget | | "Put my schedule on it" | Push calendar widget, auto-read macOS Calendar | | "Show what I'm working on" | Push focus widget | | "Refresh every 30 min" | Write `~/.ai-desk-card/interests.yaml` + register loop | | "Auto-sleep at 11pm with my business card" | Configure quiet_hours, daemon handles it | | "Card won't connect" | Run diagnostic flow β†’ locate issue β†’ suggest fix | | "I changed Wi-Fi" | Run wifi-setup flow | | "What's on my card now?" | curl the daemon for a current-frame PNG preview | ## Platform support | Agent | Status | Notes | |------|------|------| | Claude Code | βœ… Primary | Native Skill + slash command convenience layer | | Codex CLI | 🟑 Same SKILL.md format | Should work, not deeply tested | | Gemini CLI | 🟑 Should work | Same | | Cursor | 🟑 Works | Needs shell permission | | Aider | 🟑 Works | Same | | Self-built agent | βœ… | Any agent that recognizes SKILL.md + has shell access | ## Hardware you need | Item | Notes | |------|------| | **M5Paper V1.1** | Primary target. ~Β₯600 / $90. [Official store](https://shop.m5stack.com/products/m5paper-v1-1) / Amazon / AliExpress | | M5Paper V1.0 | Likely works, battery threshold (`4150 mV`) may need tuning | | M5Paper S3 | Needs porting (1-2 days, BLE stack differs) | | USB-C **data cable** | Used once for flashing. Charge-only cables don't work | | (optional) USB-C charger | Needed for always-on Wi-Fi mode | > ⚠️ **You don't need to pre-install PlatformIO / compilers / Python** β€” if the Skill detects something missing, it lets the agent install it. ## Install ### Option 1: One-line install (recommended) ```bash npx skills add https://github.com/op7418/ai-desk-card --skill ai-desk-card ``` ### Option 2: Ask the AI to install Copy this and paste to Claude Code / Cursor / any AI Agent with shell access: > Install the `ai-desk-card` Skill. Steps: > > 1. Ensure `~/.claude/skills/` exists (create if not) > 2. Run `git clone https://github.com/op7418/ai-desk-card.git ~/.claude/skills/ai-desk-card` > 3. Verify: `ls ~/.claude/skills/ai-desk-card/` should show `SKILL.md`, `flows/`, `plugin/`, `daemon/`, `src/`, `assets/` > 4. Tell me when done; from then on saying "set up the card" will trigger this Skill ### Option 3: Manual clone ```bash git clone https://github.com/op7418/ai-desk-card.git ~/.claude/skills/ai-desk-card ``` ### Trigger keywords After install, the agent auto-triggers the Skill when you mention any of: - "card" / "desk card" / "e-ink display" / "secondary display" - "show X on my card" - "just got an M5Paper" / "first-time setup" / "flash firmware" - "refresh every N min" / "auto-refresh" - "sleep the card" / "show business card" - "ai-desk-card" ## How it works The Skill is a structured workflow; the agent steps through it automatically: 1. **Onboarding (flow 01)** β€” probe PlatformIO + USB β†’ walk through firmware flash 2. **Transport diagnosis (flow 02)** β€” locate issues when device is unreachable 3. **Wi-Fi setup (flow 03)** β€” provision credentials into device NVS 4. **Interests (flow 04)** β€” first-time "what do you want to see, how often" 5. **Push widget (flow 05)** β€” daily hot path 6. **Schedule (flow 06)** β€” agent's own loop / cron registration 7. **Sleep (flow 07)** β€” business card + deep sleep at zero watts Full sub-flows live in [`flows/`](./flows/). Main routing in [`SKILL.md`](./SKILL.md). ## 16 widget types **Work staples**: - `weather` Β· `calendar` Β· `next-meeting` - `todo` Β· `focus` Β· `deadlines` - `inbox` Β· `messages` Β· `pr-queue` - `git-status` Β· `system` Β· `now-playing` **Notes / pacing**: - `scratch` Β· `break-reminder` **AI monitoring**: - `ai-status` Β· `ai-tasks` **4 slots / 2-1-1 layout**: ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ top-left β”‚ top-right β”‚ ← 270Γ—280 each β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ middle β”‚ ← 540Γ—340 full-width β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ bottom β”‚ ← 540Γ—280 full-width β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ β”‚ bottom bar (chips) β”‚ ← 60 px, "Sleep" + "Settings" β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` Plus `full` (540Γ—960) which takes over the whole screen β€” used for the business card / boot splash. Full schema in [`plugin/skills/card-widget/schemas/`](./plugin/skills/card-widget/schemas/). ## Auto-refresh (optional) When the Skill first asks "which widgets do you want, how often", it writes `~/.ai-desk-card/interests.yaml`: ```yaml version: 1 slots: top-left: weather top-right: calendar middle: todo bottom: inbox schedule: cadence: "30m" # 5m / 15m / 30m / 1h / 2h hours: "08-22" days: "mon-fri" timezone: "Asia/Shanghai" data_sources: weather: city: "Beijing" calendar: source: "macos" # or google / ics-url todo: source: "reminders" # or things3 / todoist git_status: repo: "/Users/you/code/main-project" # At quiet_hours.start, switch to business card + deep sleep. # Daemon handles this in the background β€” agent doesn't have to be online. quiet_hours: enabled: true start: "23:00" end: "07:00" ``` Three ways to trigger the refresh: - **Agent's native loop (recommended)**: Claude Code's `/loop 30m`, `ScheduleWakeup`, etc. - **cron**: `crontab -e` line: `*/30 8-21 * * 1-5 bash /path/to/ai-desk-card/plugin/skills/card-refresh/scripts/refresh_loop.sh` - **No-AI fallback**: weather / system / git don't need AI β€” run `fallback_refresh.py` directly ## Three power-mode architectures | Mode | State | Push latency | Battery | |------|------|---------|------| | **A** Always plugged | USB-C power + Wi-Fi always on | 0.2 s | n/a (powered) | | **B** USB only | USB data cable (no Wi-Fi yet) | 1 s region / 32 s full | n/a (powered) | | **C** Battery + BLE standby | Wi-Fi off, daemon wakes via BLE | 5 s wake + 0.2 s push | ~6 months | Arch C is the favorite: the panel sits on your desk for months without charging; when the agent has something to push, BLE wake β†’ bring up Wi-Fi β†’ HTTP push β†’ 30 s linger β†’ drop Wi-Fi. ~0.2 mAh per push Γ— 24 pushes/day Γ— 6 months = 1150 mAh battery. ## Directory structure ``` ai-desk-card/ β”œβ”€β”€ SKILL.md ← Agent entry point (any-agent) β”œβ”€β”€ scripts/state.sh ← State probe β€” JSON: daemon / transport / wifi / device / interests β”œβ”€β”€ flows/ ← 7 sub-flows (~60-100 lines each) β”‚ β”œβ”€β”€ 01_install.md Zero-state hardware + firmware flash β”‚ β”œβ”€β”€ 02_transport.md Daemon-can't-reach-device diagnostic β”‚ β”œβ”€β”€ 03_wifi.md Wi-Fi provisioning β”‚ β”œβ”€β”€ 04_interests.md interests.yaml guided setup β”‚ β”œβ”€β”€ 05_push.md Widget push hot path β”‚ β”œβ”€β”€ 06_schedule.md Scheduled-push protocol β”‚ └── 07_sleep.md Business card + deep sleep β”œβ”€β”€ plugin/ ← Claude Code convenience layer (slash + shared scripts) β”‚ β”œβ”€β”€ plugin.json β”‚ β”œβ”€β”€ commands/ ← /card-* commands β”‚ β”œβ”€β”€ scripts/ ← start.sh / stop.sh / status.sh β”‚ └── skills/ ← Sub-skills, called indirectly by main SKILL.md β”œβ”€β”€ daemon/ β”‚ β”œβ”€β”€ card_daemon.py ← HTTP bridge + transport layer + background loops β”‚ β”œβ”€β”€ card_render.py ← Widget view renderer β”‚ β”œβ”€β”€ card_render_settings.py β”‚ └── card_render_sleep.py ← Business card renderer β”œβ”€β”€ src/ ← Firmware (frame_receiver / wifi / http / ble / touch poll) β”œβ”€β”€ assets/ β”‚ β”œβ”€β”€ profile.yaml ← Your business-card info (shown when sleeping) β”‚ β”œβ”€β”€ qr.png ← Optional QR β”‚ └── avatar.png ← Optional avatar β”œβ”€β”€ data/cjk.ttf ← CJK font (flashed to LittleFS once) β”œβ”€β”€ platformio.ini β”œβ”€β”€ partitions.csv β”œβ”€β”€ HANDOVER.md ← Engineering handover └── PRODUCT.md ← Product narrative ``` ## How it really works (one diagram) ``` You speak M5Paper β”‚ β–² β–Ό β”‚ AI Agent ──────┐ β”‚ β”‚ triggers Skill β”‚ β–Ό β”‚ SKILL.md routing β”‚ β”‚ β”‚ β”‚ scripts/state.sh probes: β”‚ β”‚ Β· pio / firmware / daemon β”‚ β”‚ Β· device.alive / wifi β”‚ β”‚ Β· interests.yaml β”‚ β”‚ β”‚ └─▢ picks one of 7 sub-flows β”‚ β”‚ β”‚ β–Ό β”‚ Agent executes β”‚ β”‚ β”‚ β–Ό β”‚ POST to daemon (127.0.0.1:9877) β”‚ β”‚ β”‚ β–Ό β”‚ daemon renders (Python + Pillow) β”‚ β”‚ β”‚ β–Ό β”‚ HTTP / USB / BLE push β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ## FAQ **Q: I really don't need to flash firmware myself?** No. After install, just say "set up the card" β€” the agent probes state, installs PlatformIO (if missing), runs `pio run -t upload`, flashes the CJK font, and tells you what it's doing at each step. **Q: I don't have M5Paper V1.1 β€” anything else?** M5Paper V1.0 likely works. M5Paper S3 needs porting (BLE stack differs). Inkplate / Waveshare / etc. aren't supported yet β€” roadmap item. **Q: Do I have to use Claude Code?** No. `SKILL.md` is agent-agnostic β€” any agent that recognizes the format + has shell permission works (Codex / Cursor / Aider / self-built). The `plugin/` slash commands are a Claude Code convenience layer, not the core. **Q: What about network?** All local. Daemon runs on your machine (127.0.0.1:9877). Device and computer are on the same Wi-Fi LAN. **ESP32 only supports 2.4 GHz** β€” 5 GHz-only SSIDs won't connect. **Q: Chinese characters show as tofu boxes?** You skipped the LittleFS font flash. Ask the agent to "run uploadfs again". **Q: How do I update the firmware?** Say "update ai-desk-card and re-flash". The Skill pulls new code + builds + uploads. **Q: Does it work outside macOS?** Daemon should work on Linux (not deeply tested). Windows needs WSL2. PlatformIO is cross-platform. **Q: Does any data go to the cloud?** No. Daemon binds 127.0.0.1 by default (deviceβ†’daemon status_report goes over LAN). Wi-Fi credentials live in device NVS, never in daemon logs or git. ## Roadmap - M5Paper V1.0 / S3 port verification - Inkplate / Waveshare / other e-ink board support - Captive portal Wi-Fi provisioning (no daemon needed) - Hardware power-button intercept (long-press 2s β†’ render business card before deep sleep) - More widget schemas (Feishu / WeChat / Linear / Notion) - Multi-device dashboard sync ## Contributing Issues and PRs welcome at https://github.com/op7418/ai-desk-card. Most valuable contributions: - Hardware photos / videos (helps new users see the form factor) - Linux / Windows daemon testing reports - M5Paper V1.0 / S3 firmware port verification - New widget schemas + renderers - Translation / docs improvements ## License GPL-3.0 with attribution clause Β· see [LICENSE](./LICENSE) Vendored EPDGUI framework (from upstream M5Paper_FactoryTest): MIT, Β© 2020 m5stack.