by op7418
桌面 AI 副屏 Skill:M5Paper 墨水屏 + AI Agent 推送 widget。装 Skill 后由 Agent 自动引导烧固件、配 Wi-Fi、推送内容。本地运行、无云依赖。
# Add to your Claude Code skills
git clone https://github.com/op7418/ai-desk-cardLast scanned: 6/8/2026
{
"issues": [],
"status": "PASSED",
"scannedAt": "2026-06-08T08:55:44.113Z",
"npmAuditRan": true,
"pipAuditRan": true
}No comments yet. Be the first to share your thoughts!
30 days in the Featured rail · terms & refunds
name: ai-desk-card description: | Drive a physical e-ink desk card (M5Paper 540×960) sitting next to the user's monitor. Use whenever the user wants to: - show / push / display ANYTHING on their card / 卡片 / 副屏 / 墨水屏 / e-ink display / desk card / glanceable display / secondary display - set up the device for the first time (flash firmware, pair, provision Wi-Fi) — phrases like "刚拿到 M5Paper", "怎么装卡片", "first-time setup", "刷固件", "卡片没反应" - schedule recurring pushes / "每小时刷一次" / "工作时间显示日历" / "auto-refresh every 30 min" - configure what the card shows (weather, todos, calendar, inbox, PR queue, AI status, focus, scratch, deadlines, messages, now-playing, git-status, system, next-meeting, break-reminder, ai-tasks) - put the device to sleep / show business card / "息屏" / "睡眠" Single Skill, agent-agnostic: probes current state, then routes to the right sub-flow. Never asks "is the daemon running" — it checks. trigger_keywords:
A 540×960 e-ink panel sitting next to the user's monitor. AI agents push widgets to it; the daemon renders frames server-side and ships pixels over Wi-Fi / USB / BLE. This Skill is the only thing an agent needs to call — it auto-detects state and routes to the right flow.
Before doing anything, run the state probe. Do not ask the user "have you done X" — find out by checking.
bash $SKILL_DIR/scripts/state.sh
($SKILL_DIR is wherever this Skill is installed. If your agent runtime
sets $CLAUDE_PLUGIN_ROOT, use that. Otherwise use the repo root.)
Output is JSON with this shape:
{
"hardware": { "pio_installed": bool, "m5paper_usb": str|null },
"firmware": { "flashed": bool, "ours": bool, "version": str|null },
"daemon": { "running": bool, "pid": int|null },
"transport": { "connected": bool, "type": "BLETransport|SerialTransport|WiFiTransport|null" },
"device": { "alive": bool, "last_seen_seconds": int|null,
"active_transport": "Wi-Fi|USB|BLE|null",
"battery_pct": int|null, "uptime": str|null },
"wifi": { "provisioned": bool, "ip": str|null },
"interests": { "configured": bool, "path": str|null }
}
The most important field is device.alive. It tells you whether the
device has sent a status report in the last ~90 s. transport.connected
only says "daemon picked a transport class"; device.alive says "we're
actually hearing back from the device right now."
The Skill supports two devices with different panels + daemons:
If GET /heartbeat returns device_status.device == "M5PaperColor"
(via color_daemon.py running), use the Color path described in
flows/08_paper_color.md:
pio run -e paper-colorpython3 daemon/color_daemon.py --device-ip <IP>cmd:wifi_set (no BLE pairing UX)top-left / top-right / bottom-left / bottom-rightambient (SHT40 temp+humid)Otherwise (default) use the V1.1 path through the routing table below.
The two daemons can't run on the same port simultaneously — pick one based on which device is in front of the user. The Skill flows below work for V1.1 unless explicitly noted.
Walk the decision tree in this order. First mismatch wins; fix it, then re-probe.
| Condition | Next action | Detail flow |
|---|---|---|
firmware.flashed == false AND no device.alive |
First-time hardware setup | flows/01_install.md |
daemon.running == false |
Start the daemon | bash $SKILL_DIR/plugin/scripts/start.sh |
device.alive == false AND transport.connected == false |
Device unreachable — could be asleep, off, BLE not paired. Tell user, suggest physical wake (tap rotary / plug USB) | flows/02_transport.md |
device.alive == false AND transport.connected == true (daemon connected something but no status_report in 90s) |
Device transport up but not responding — restart daemon, then probe | flows/02_transport.md |
wifi.provisioned == false (and user wants always-on or battery mode) |
Provision Wi-Fi | flows/03_wifi.md |
interests.configured == false AND user just asked for "auto-refresh" or "定时推送" |
Ask about interests, write ~/.ai-desk-card/interests.yaml |
flows/04_interests.md |
device.alive == true + user said "push X" |
Build widget JSON, POST to daemon | flows/05_push.md |
device.alive == true + user said "schedule" / "每 N 分钟" / "auto" |
Set up scheduled push | flows/06_schedule.md |
device.alive == true + user said "sleep" / "息屏" |
Push business card + deep sleep | flows/07_sleep.md |
Always tell the user which step you're on. Don't operate silently.
When state is OK and user asks to show something:
curl -sf -X POST "${CARD_DAEMON_URL:-http://127.0.0.1:9877}/widget" \
-H 'Content-Type: application/json' \
-d @- <<'JSON'
{
"slot": "top-left",
"type": "weather",
"data": { "city": "Beijing", "temp_c": 22, "icon": "sun", "summary": "晴" }
}
JSON
top-left (270×280) · top-right (270×280) · middle (540×340) ·
bottom (540×280) · full (540×960, takes over the whole screen).plugin/skills/card-widget/schemas/ for full
JSON schemas with examples.Full per-widget schema + theme reference: plugin/skills/card-widget/SKILL.md
If the user's request implies recurrence ("keep my calendar updated", "check email every hour", "show me today's todos throughout the day"), don't just push once. Instead:
~/.ai-desk-card/interests.yaml (see flow 04)/loop 30m or ScheduleWakeupplugin/skills/card-refresh/scripts/refresh_loop.shThe Skill provides the what (interests + push) — your agent provides the when (loop primitive).
plugin/ directory is provided for
CLIs that consume slash commands, but this SKILL.md is the agent-agnostic
entry point.127.0.0.1:9877 by default) + the device's local Wi-Fi.
🌏 English version: README.en.md
一个适配 Claude Code / Codex 等 Agent 的桌面副屏 Skill。把 M5Paper V1.1 4.7 寸墨水屏立在显示器旁边,由 AI Agent 推送 widget:天气、日程、todo、PR 队列、AI 状态、休息提醒……
装上 Skill 后,烧固件 / 配 Wi-Fi / 推内容 / 设置定时全部由 Agent 引导,你不用自己跑一行 pio 或 curl。
你 ──说自然语言──▶ AI Agent ──触发──▶ Skill ──自动执行──▶ M5Paper 屏上
npx skills add https://github.com/op7418/ai-desk-card --skill ai-desk-card
也可以把下面这段话直接发给有 shell 权限的 AI Agent:
帮我安装 ai-desk-card Skill。把 https://github.com/op7418/ai-desk-card 克隆到 ~/.claude/skills/ai-desk-card,安装完成后检查 SKILL.md、flows/、daemon/、src/、assets/ 是否存在。
已经装过想更新:
帮我更新 ai-desk-card。请进入 ~/.claude/skills/ai-desk-card 执行 git pull,然后告诉我当前最新 commit。
装完之后,假设你手上有 M5Paper V1.1 + USB-C 数据线,直接对 Agent 说:
帮我把 ai-desk-card 装上。我手上是 M5Paper V1.1,USB-C 已经插好了。
Skill 会自动:
pipx install)之后日常使用就是和 Agent 自然对话:
在卡片上显示今天北京的天气。
让卡片每 30 分钟刷新天气和未读邮件,工作日 8 点到 22 点。
现在卡片上是啥?
晚上 11 点之后自动息屏显示我的名片。
✅ 合适:
❌ 不合适:
| 你说 | Agent 干什么 |
|---|---|
| "帮我把 ai-desk-card 装上" | 完整入职流程:探测状态 → 烧固件 → 起 daemon → 配 Wi-Fi |
| "在卡片上显示今天的天气" | 推 weather widget |
| "把日程贴上去" | 推 calendar widget,自动读 macOS 日历 |
| "显示我现在在做的任务" | 推 focus widget |
| "让卡片每 30 分钟刷新" | 写 ~/.ai-desk-card/interests.yaml + 注册 loop |
| "23 点自动息屏显示名片" | 配 quiet_hours,daemon 后台自动处理 |
| "卡片连不上" | 触发诊断 flow:探测 → 定位问题 → 给修复建议 |
| "我换 Wi-Fi 了" | 重新走 wifi-setup flow |
| "卡片现在显示啥" | curl daemon 拿当前帧的 PNG 预览 |
| 平台 | 状态 | 说明 |
|---|---|---|
| Claude Code | ✅ 主力测试 | 原生 Skill 工作流 + slash 命令兼容层 |
| Codex CLI | 🟡 同 SKILL.md 格式 | 应该可用,未深度测试 |
| Gemini CLI | 🟡 应该可用 | 同上 |
| Cursor | 🟡 可用 | 需要 shell 权限 |
| Aider | 🟡 可用 | 同上 |
| 自写 Agent | ✅ | 只要识别 SKILL.md + 有 shell 权限就行 |
| 项目 | 说明 |
|---|---|
| M5Paper V1.1 | 主力支持。约 ¥600 / $90。官方店 / Amazon / AliExpress |
| M5Paper V1.0 | 大概率可用,电池阈值参数 (4150 mV) 可能要调 |
| M5Paper S3 | 需要 1-2 天移植(BLE stack 不同) |
| USB-C 数据线 | 烧固件时用一次。普通"只充电"线不行 |
| (可选) USB-C 充电器 | 想用"常插电 + Wi-Fi 常开"模式需要 |
⚠️ 不需要事先装 PlatformIO / 编译器 / Python 环境 — Skill 检测到缺什么会让 Agent 自己装。
npx skills add https://github.com/op7418/ai-desk-card --skill ai-desk-card
把下面这段话复制粘贴给 Claude Code / Cursor / 任何有 shell 权限的 AI Agent:
帮我装
ai-desk-card这个 Skill。请按下面步骤做:
- 确保
~/.claude/skills/目录存在(不存在就创建)- 执行
git clone https://github.com/op7418/ai-desk-card.git ~/.claude/skills/ai-desk-card- 验证:
ls ~/.claude/skills/ai-desk-card/应该看到SKILL.md、flows/、plugin/、daemon/、src/、assets/- 装好告诉我,之后我说"帮我把卡片装上"就会触发这个 Skill
git clone https://github.com/op7418/ai-desk-card.git ~/.claude/skills/ai-desk-card
装好后 Agent 会在你说这些时自动唤起 Skill:
Skill 是结构化工作流,Agent 会按下面顺序自动跑(你不用记每一步):
完整子流程在 flows/ 目录。Skill 主路由在 SKILL.md。
工作日常:
weather 天气 · calendar 今日日程 · next-meeting 下个会todo 待办 · focus 当前专注任务 · deadlines deadline 提醒inbox 收件箱 · messages 消息 · pr-queue PR 队列git-status git 状态 · system 系统状态 · now-playing 正在播放笔记 / 节奏:
scratch 便签 · break-reminder 休息提醒AI 监控:
ai-status 当前 AI session · ai-tasks AI 任务列表4 个槽位 / 2-1-1 布局:
┌────────────┬────────────┐
│ top-left │ top-right │ ← 270×280 各占半
├────────────┴────────────┤
│ middle │ ← 540×340 整条
├─────────────────────────┤
│ bottom │ ← 540×280 整条
├─────────────────────────┤
│ bottom bar (chip 区) │ ← 60 px,含"睡眠""设置"chip
└─────────────────────────┘
还有一个 full(540×960)覆盖全屏,用来推电子名片 / 启动 splash 等。
完整 schema 在 plugin/skills/card-widget/schemas/。
Skill 第一次问你"想看哪些卡片、什么时段刷"时,会帮你写 ~/.ai-desk-card/interests.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" # 或 google / ics-url
todo:
source: "reminders" # 或 things3 / todoist
git_status:
repo: "/Users/you/code/main-project"
# 到 quiet_hours.start 自动切到电子名片 + deep sleep
# daemon 后台自动处理,不需要 Agent 在线
quiet_hours:
enabled: true
start: "23:00"
end: "07:00"
定时触发方式:
/loop 30m、ScheduleWakeup 等crontab -e 加一行 */30 8-21 * * 1-5 bash /path/to/ai-desk-card/plugin/skills/card-refresh/scripts/refresh_loop.shfallback_refresh.py| 模式 | 状态 | 推帧延迟 | 续航 |
|---|---|---|---|
| A 常插电 | USB-C 供电 + Wi-Fi 长开 | 0.2 s | n/a(供电中) |
| B USB only | USB 数据线(还没配 Wi-Fi) | 1 s 区域 / 32 s 全帧 | n/a(供电中) |
| C 电池 + BLE 待机 | Wi-Fi 关,daemon 通过 BLE 唤醒 | 5 s 唤醒 + 0.2 s 推 | ~6 个月 |
架构 C 是最爱:屏挂在桌边几个月不充电,AI Agent 推内容时 BLE 唤醒一次 → 拉 Wi-Fi → HTTP 推帧 → 30 秒 linger 后断 Wi-Fi。一次推送约 0.2 mAh,24 次/天 × 6 个月 = 1150 mAh 电池。
ai-desk-card/
├── SKILL.md ← 任意 Agent 的入口
├── scripts/state.sh ← 状态探测:JSON 输出 daemon/transport/wifi/device/interests 状态
├── flows/ ← 7 个子流程(每个 ~60-100 行)
│ ├── 01_install.md 零状态硬件 + 固件烧录
│ ├── 02_transport.md daemon 连不上设备的诊断
│ ├── 03_wifi.md Wi-Fi 配网
│ ├── 04_interests.md interests.yaml 引导写入
│ ├── 05_push.md 推 widget 热路径
│ ├── 06_schedule.md 定时刷新协议
│ └── 07_sleep.md 电子名片 + deep sleep
├── plugin/ ← Claude Code 兼容层(slash 命令 + 共享脚本)
│ ├── plugin.json
│ ├── commands/ ← /card-* 命令
│ ├── scripts/ ← start.sh / stop.sh / status.sh
│ └── skills/ ← 子 skill,由主 SKILL.md 间接调用
├── daemon/
│ ├── card_daemon.py ← HTTP 桥 + 传输层 + 后台 loop
│ ├── card_render.py ← widget view 渲染
│ ├── card_render_settings.py
│ └── card_render_sleep.py ← 电子名片渲染
├── src/ ← 固件 (frame_receiver / wifi / http / ble / 触屏 poll)
├── assets/
│ ├── profile.yaml ← 你的电子名片信息(息屏时显示)
│ ├── qr.png ← 可选 QR
│ └── avatar.png ← 可选头像
├── data/cjk.ttf ← CJK 字体(首次烧到 LittleFS)
├── platformio.ini
├── partitions.csv
├── HANDOVER.md ← 工程交接
└── PRODUCT.md ← 产品定位
你说话 M5Paper
│ ▲
▼ │
AI Agent ──────┐ │
│ 触发 Skill │
▼ │
SKILL.md 路由表 │
│ │
│ scripts/state.sh 探测: │
│ · pio / firmware / daemon │
│ · device.alive / wifi │
│ · interests.yaml │
│ │
└─▶ 选 7 个子 flow 之一 │
│ │
▼ │
Agent 自动执行 │
│ │
▼ │
POST 到 daemon (127.0.0.1:9877) │
│ │
▼ │
daemon 渲染(Python + Pillow) │