Push live data to the user's ai-desk-card M5Paper e-ink companion display.
Use whenever the user asks to show todos, calendar, weather, AI status,
inbox counts, next meeting, or any glanceable info on their card / ๅก็ /
ๅฏๅฑ / ๅขจๆฐดๅฑ / e-ink display. 16 widget types available; AI picks slot
+ widget type, fills data, POSTs to the local card daemon (default
127.0.0.1:9877). Communicates over loopback, so individual widget writes
don't trigger AI agent approval prompts.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Push live data to the user's ai-desk-card M5Paper e-ink companion display.
Use whenever the user asks to show todos, calendar, weather, AI status,
inbox counts, next meeting, or any glanceable info on their card / ๅก็ /
ๅฏๅฑ / ๅขจๆฐดๅฑ / e-ink display. 16 widget types available; AI picks slot
+ widget type, fills data, POSTs to the local card daemon (default
127.0.0.1:9877). Communicates over loopback, so individual widget writes
don't trigger AI agent approval prompts.
The card is a 540 ร 960 e-ink panel sitting next to the user's monitor.
You push 1-4 widgets and the daemon renders a single frame; transfer
time depends on the transport.
Transport & latency (v0.8)
The daemon auto-picks Wi-Fi > USB > BLE at startup. Each path has
different per-push characteristics โ be aware:
Transport
Single-widget update
Full frame
Power use
Wi-Fi (HTTP)
~0.2 s
~2 s
high while connected
USB serial @ 115200
~1 s region / ~32 s full
32 s
n/a
BLE (small cmds only)
works for commands; frame data hangs
broken
low
The daemon also runs a dirty-region diff so unchanged pixels don't
re-transmit โ typical "one widget updated" push is 5-30 KB instead of
the 250 KB full frame. You don't manage this; the daemon decides per
push.
Per-keystroke streaming: NO. Each push triggers e-ink refresh which
damages the panel over time.
ai-status taking off / completion: one push at start, one at end.
For sub-minute "live" info (timer countdowns, music progress):
push at most every ~30 s.
If the user's on USB (1-32 s) instead of Wi-Fi (0.2 s), strongly suggest
configuring Wi-Fi via /card-wifi-setup โ it's a quality-of-life upgrade.
Layout cheat-sheet
Four slots. Narrow slots (top-left, top-right) are 270 px wide; wide
slots (middle, bottom, full) span the full 540 px. Some widgets only
shine when wide โ see the catalog below.
inbox vs messages: inbox is counts per source; messages is
named senders' previews. Use inbox for "how much is waiting", messages
for "who's poking me".
next-meeting vs calendar: next-meeting is THE next event (big
countdown); calendar is today's schedule (list).
deadlines vs todo vs calendar: deadlines = multi-day countdown;
todo = today's tasks; calendar = today's schedule.
focus vs todo: focus = ONE active task; todo = a list. If user
has one main task and 3 background items, push focus middle + todo
bottom.
ttl โ seconds; 0 = no expiry. Use ~1800 for ephemeral info.
stale_after โ seconds; widget gets a "stale" badge but stays visible
theme โ "" default. Don't set unless user asks.
Failure modes
Schema mismatch โ daemon returns HTTP 400 with the failing field.
Fix and re-push.
Daemon unreachable โ run /card-onboard to diagnose.
Widget shows but text is truncated โ you sent too much. Fewer items,
shorter strings. The card is glanceable, not a Kindle.
Pushed but nothing changed on screen โ daemon debounces by ~1.5 s.
Wait. If 30 s passes and still no change, check tail /tmp/ai_desk_card_daemon.log.
If transport.connected is false โ run /card-onboard first; don't try
to push.
Sleep-frame (name card)
The device has a "digital business card" mode: when it deep-sleeps the
e-ink panel retains the last frame at 0 W until power-cycled. To push the
card and put the device to sleep:
/card-sleep
The card content comes from ai-desk-card/assets/profile.yaml. When the
user asks to update their card, edit the YAML directly:
name:"..."# Big name (โค ~10 chars wide ideal)tagline:"..."# One short subtitle (โค 36 chars)bio_lines:# 2-5 lines, auto-wrap. Empty string = half-gap.-"..."tags:# Up to 4 chips-icon:"Job"text:"..."qr_image:"qr.png"# Optional; placeholder if missingqr_label:"..."# One line under QRavatar_image:"avatar.png"footer:"..."
Avatar + QR are PNGs in ai-desk-card/assets/. If user wants a custom
image, ask them to provide it; don't try to generate emoji or scannable
QR โ Pillow's bundled fonts lack emoji and we use image-based QR
intentionally. Tag icons should be plain short labels (Job / City /
Web), not emoji.
When to push proactively
Starting a non-trivial task: push ai-status with session_name +
task. Once per task, not per action โ e-ink doesn't like frequent
refreshes.
Long-running operation finishes: push scratch with a success
line ("PR opened: #1234"). User glances at card and knows.
Don't push for trivial state changes or every tool call.
Auto-refresh (every 2 hours)
If the user has set up the cron-driven refresh (see /card-refresh skill
REFRESH.md), the cron job will re-invoke a headless AI CLI every 2
hours to refresh widgets with fresh data. You don't need to manually
poll โ just push widgets when relevant during the conversation.